Skip to main content

Swapping

This tutorial will walk you through Astroport's swap functionality using CosmJS.

Setup

Step 1: Import Necessary Libraries

Import the required libraries to connect to the chain and perform transactions.


_3
import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
_3
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
_3
import { GasPrice } from "@cosmjs/stargate";

Step 2: Define Constants

Specify the required constants, such as the RPC URL, mnemonic, and factory contract address.

NOTE

This tutorial includes the mnemonic directly in the code for quick setup. While convenient for testing, this exposes a sensitive piece of information and is not secure for production use. Always follow secure key management practices and never expose the mnemonic in real-world scenarios.


_3
const rpc = '<rpc-url>'
_3
const mnemonic = ''
_3
const pairContractAddress = 'neutron...'

Step 3: Create a Wallet

Create a wallet using the mnemonic for the specific chain prefix.


_4
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(
_4
mnemonic, {
_4
prefix: "neutron" // neutron, or terra
_4
});

Step 4: Retrieve Wallet Address

Get the wallet address from the wallet.


_2
const firstAccount = await wallet.getAccounts();
_2
const walletAddress = firstAccount[0].address

Step 5: Set Up the Signing Client

Configure the signing client for connecting to the chain.


_5
const signingClient = await SigningCosmWasmClient.connectWithSigner(
_5
rpc,
_5
wallet,
_5
{ gasPrice: GasPrice.fromString("0.0053untrn") }
_5
)

Step 6: Wrap Code Inside an Async Function with Error Handling

Wrap the code inside a start() function, marked as async, to handle the asynchronous operations throughout the code. Also, include a try/catch block for robust error handling. This structure enables the use of await with async functions and ensures proper management of any errors that may occur.


_12
const start = async () => {
_12
try {
_12
// Place all the code inside this try block
_12
_12
// ...
_12
_12
} catch (error) {
_12
console.error('An error occurred:', error);
_12
}
_12
}
_12
_12
start();

Swap

Astroport implements the same smart contracts API for swapping across its various pool types (xyk, stable, pcl). The swap function performs a direct swap between two assets in a liquidity pool.

Step 1: Define the Swap Message

Create the swap message with asset details.


_20
const swapMsg = {
_20
"swap": {
_20
"offer_asset": {
_20
"info": {
_20
"token": {
_20
"contract_addr": "..."
_20
}
_20
},
_20
"amount": "10000000"
_20
},
_20
"ask_asset_info": {
_20
"native_token": {
_20
"denom": "..."
_20
}
_20
},
_20
"belief_price": beliefPrice,
_20
"max_spread": "0.1",
_20
"to": "...."
_20
}
_20
};

ParamsTypeDescription
[offer_asset]AssetOffer asset
[ask_asset_info]Option<AssetInfo>Information about an asset stored in a [AssetInfo] struct
[belief_price]Option<Decimal>Belief price
[max_spread]Option<Decimal>The difference between the ask amount before and after the swap operation. If the swap spread exceeds the provided max limit, the swap will fail. If belief_price is provided in combination with max_spread, the pool will check the difference between the return amount (using belief_price) and the real pool price.
[to]Option<String>Address receiving tokens (if different from sender)

Asset

This enum contains asset info and a token amount.

json
asset.rs
Copy

_8
{
_8
"info": {
_8
"token": {
_8
"contract_addr": "..."
_8
}
_8
},
_8
"amount": "100000"
_8
}

ParamsTypeDescription
infoAssetInfoInformation about an asset stored in a [AssetInfo] struct
amountUint128A token amount

AssetInfo

AssetInfo is a convenience wrapper to represent whether a token is the native one (from a specific chain, like LUNA for Terra) or not. It also returns the contract address of that token.

asset.rs
Copy

_4
pub enum AssetInfo {
_4
Token { contract_addr: Addr },
_4
NativeToken { denom: String },
_4
}

VariantsDescription
TokenNon-native Token
NativeTokenNative token

Simulation Enpoint

Astroport's native solution for calculating the belief_price is the simulation query.

The query takes in an offer_asset which contains information about the native token and an amount to send.


_17
const simulationQuery = await client.queryContractSmart(
_17
pairContract,
_17
{
_17
"simulation": {
_17
"offer_asset": {
_17
"info": {
_17
"native_token": {
_17
"denom": "uluna"
_17
}
_17
},
_17
"amount": "100000"
_17
}
_17
}
_17
}
_17
);
_17
_17
console.log(simulationQuery);

Depending on the token decimal for the assets you are swapping, you may need to normalize the response from the simulation query before passing it into your swap message.


_1
beliefPrice = String(beliefPrice * 1000000);

Step 2: Execute Swap

Execute the swap transaction.


_9
const executeSwap = await signingClient.execute(
_9
walletAddress,
_9
pairContractAddress,
_9
swapMsg,
_9
"auto", // fee
_9
"" // memo
_9
);
_9
_9
console.log(JSON.stringify(executeSwap));