Swaps
A Plach swap is an Intear DEX swap with "dex_id": "slimedragon.near/xyk". The message of the swap says which pools to go through. Everything else works as on any DEX of the engine: swap_simple, simulate_swap_simple, and SwapSimple operations, with exact input or exact output.
The examples on this page swap from alice.near’s inner balance, after a storage deposit, registering NEAR, USDT and USDC, and depositing 1 NEAR and 1 USDT. Together they’re one script.
The message
Section titled “The message”The message is a Borsh SwapArgs: a list of routes, an optional fee discount, and referral fees.
struct SwapArgs { routes: Vec<SwapRoute>, fee_discount: Option<SignedFeeDiscount>, /// Left out when empty referral_fees: ReferralFees,}
struct SwapRoute { /// Share of the amount that goes through this route, 1000000 = 100% fraction: u32, /// Pools to swap through, in order pool_ids: Vec<u32>,}
/// Accounts and their fees, 1000000 = 100%struct ReferralFees(Vec<(AccountId, u32)>);Without referral fees, the message ends after fee_discount, as it did before they existed.
For a swap of the whole amount through one pool, without a fee discount or referral fees, the message can also be just the pool ID, a little-endian u32. 3QAAAA== is pool 221, NEAR/USDT:
near contract call-function as-read-only dex.intear.near simulate_swap_simple \ json-args '{ "dex_id": "slimedragon.near/xyk", "message": "3QAAAA==", "trader": "alice.near", "asset_in": "near", "asset_out": "nep141:usdt.tether-token.near", "amount": {"ExactIn": "1000000000000000000000000"} }' \ network-config mainnet nowThrough several pools
Section titled “Through several pools”Each pool of a route swaps the output of the one before into its other asset, and the last one must output asset_out. This message goes from USDT to NEAR in pool 221, then from NEAR to USDC in pool 85:
01 00 00 00 1 route40 42 0f 00 fraction: 1000000 (100%)02 00 00 00 2 poolsdd 00 00 00 22155 00 00 00 8500 no fee discountThat’s AQAAAEBCDwACAAAA3QAAAFUAAAAA in base64:
# USDT to NEAR in pool 221, then NEAR to USDC in pool 85AMOUNT_OUT=$(near contract call-function as-read-only dex.intear.near simulate_swap_simple \ json-args '{ "dex_id": "slimedragon.near/xyk", "message": "AQAAAEBCDwACAAAA3QAAAFUAAAAA", "trader": "alice.near", "asset_in": "nep141:usdt.tether-token.near", "asset_out": "nep141:17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1", "amount": {"ExactIn": "1000000"} }' \ network-config mainnet now | jq -r '.[1]')MIN_AMOUNT_OUT=$((AMOUNT_OUT * 99 / 100))
near contract call-function as-transaction dex.intear.near swap_simple \ json-args "$(jq -n --arg min_amount_out "$MIN_AMOUNT_OUT" '{ "dex_id": "slimedragon.near/xyk", "message": "AQAAAEBCDwACAAAA3QAAAFUAAAAA", "asset_in": "nep141:usdt.tether-token.near", "asset_out": "nep141:17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1", "amount": {"ExactIn": "1000000"}, "constraint": $min_amount_out }')" \ prepaid-gas '150.0 Tgas' attached-deposit '1 yoctoNEAR' \ sign-as alice.near network-config mainnet sign-with-keychain sendUnlike several SwapSimple operations, the intermediate asset (NEAR here) doesn’t go through your inner balance, so it doesn’t need to be registered for you, and it’s one swap for the engine.
Split across routes
Section titled “Split across routes”With several routes, each takes its fraction of the amount, and the fractions must add up to 1000000. The first route also takes what’s left after rounding. This one swaps 70% of 1 NEAR to USDC in pool 85, and 30% in pool 22:
02 00 00 00 2 routes60 ae 0a 00 fraction: 700000 (70%)01 00 00 00 1 pool55 00 00 00 85e0 93 04 00 fraction: 300000 (30%)01 00 00 00 1 pool16 00 00 00 2200 no fee discount# 70% through pool 85 and 30% through pool 22, both NEAR/USDCAMOUNT_OUT=$(near contract call-function as-read-only dex.intear.near simulate_swap_simple \ json-args '{ "dex_id": "slimedragon.near/xyk", "message": "AgAAAGCuCgABAAAAVQAAAOCTBAABAAAAFgAAAAA=", "trader": "alice.near", "asset_in": "near", "asset_out": "nep141:17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1", "amount": {"ExactIn": "1000000000000000000000000"} }' \ network-config mainnet now | jq -r '.[1]')MIN_AMOUNT_OUT=$((AMOUNT_OUT * 99 / 100))
near contract call-function as-transaction dex.intear.near swap_simple \ json-args "$(jq -n --arg min_amount_out "$MIN_AMOUNT_OUT" '{ "dex_id": "slimedragon.near/xyk", "message": "AgAAAGCuCgABAAAAVQAAAOCTBAABAAAAFgAAAAA=", "asset_in": "near", "asset_out": "nep141:17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1", "amount": {"ExactIn": "1000000000000000000000000"}, "constraint": $min_amount_out }')" \ prepaid-gas '150.0 Tgas' attached-deposit '1 yoctoNEAR' \ sign-as alice.near network-config mainnet sign-with-keychain sendSplits work for exact output too: then each route delivers its fraction of amount_out.
The last created pool
Section titled “The last created pool”The pool ID 4294967295 (u32::MAX, ffffffff) means the pool created last. Use it to create a pool and swap in it in one execute_operations, before you know its ID.
Prices
Section titled “Prices”In each pool, the fees are taken from the input first. The rest goes into the pool, and the output keeps the product of the pool’s balances:
amount_out = in_after_fees * out_balance / (in_balance + in_after_fees)rounded down. For an exact output, the input is the least amount that gives at least amount_out after fees. A swap can’t take a pool’s whole balance of an asset, and fails on an empty pool.
Each pool of a route charges its own fees. See Fees for what they are and where they go.
Events
Section titled “Events”Each pool a swap goes through logs a Swap event with its amounts and fees, and a PoolUpdated event with its new balances.