Referral fees
This page is also Markdown, for agents: /intear-dex/guides/referral-fees.md, and /llms.txt lists every page.
An app can charge its own fee on the swaps it sends, with referral_fees: the accounts to pay and the fee each one gets, out of the swap’s input. The engine takes the fees before the DEX gets the input, so they work the same on every DEX, and puts them in the inner balances of the accounts. Nothing is set up in advance other than registering the input asset, so each swap can charge different fees.
"referral_fees": [["myapp.near", 5000], ["partner.near", 1000]]Each fee is a u32 out of 1000000, so 5000 is 0.5% and 1000 is 0.1%.
- At most 5 accounts, with fees that add up to at most 5% (
50000). A fee of 0 charges nothing. - The fees are in the swap’s input asset, and go to the accounts’ inner balances, to withdraw like any other asset.
- An account is only paid if the input asset is registered for it. Otherwise its fee isn’t charged, and the trader keeps it. Anyone can register the asset for it with
for. - With
ExactIn, the fees come out of the amount, each rounded down, and the DEX swaps the rest. WithExactOut, they’re added on top of what the DEX takes, rounded up, so that each fee is its fraction of the whole input. swap_simplereturns the whole input, fees included, and theconstraintof anExactOutswap limits the whole input too. The trader’s inner balance needs all of it.- In
execute_operationsand deposits, only the first swap pays them. - The DEX’s own fees, and a fee discount it gives, apply to what the DEX gets, not to the referral fees.
referreris separate: it names your app in the events and to the DEX, but doesn’t charge anything.
The DEX Aggregator puts the fees of its requests in referral_fees for Plach routes, and registers the input asset for the accounts that don’t have it.
Charge a fee
Section titled “Charge a fee”The near CLI examples below charge a 1% fee for bob.near on alice.near’s swap of 1 NEAR to USDt, after a storage deposit, registering NEAR and USDt, and depositing 1 NEAR. Together they’re one script.
bob.near is paid in NEAR, the swap’s input, so NEAR has to be registered for it first. It can do that itself, or anyone can do it for it:
# bob.near is paid in the swap's input, NEAR, so NEAR has to be registered for# it. Anyone can register it, here alice.near, from its own storage balance.near contract call-function as-transaction dex.intear.near register_assets \ json-args '{"asset_ids": ["near"], "for": {"Account": "bob.near"}}' \ prepaid-gas '30.0 Tgas' attached-deposit '1 yoctoNEAR' \ sign-as alice.near network-config mainnet sign-with-keychain sendsimulate_swap_simple takes the same referral_fees, and gives the same amounts as the swap would:
# The DEX swaps 0.99 NEAR, so simulate with the same referral feesAMOUNT_OUT=$(near contract call-function as-read-only dex.intear.near simulate_swap_simple \ json-args '{ "dex_id": "slimedragon.near/xyk", "message": "AQAAAEBCDwABAAAA3QAAAAA=", "trader": "alice.near", "asset_in": "near", "asset_out": "nep141:usdt.tether-token.near", "amount": {"ExactIn": "1000000000000000000000000"}, "referral_fees": [["bob.near", 10000]] }' \ 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": "AQAAAEBCDwABAAAA3QAAAAA=", "asset_in": "near", "asset_out": "nep141:usdt.tether-token.near", "amount": {"ExactIn": "1000000000000000000000000"}, "referral_fees": [["bob.near", 10000]], "constraint": $min_amount_out }')" \ prepaid-gas '100.0 Tgas' attached-deposit '1 yoctoNEAR' \ sign-as alice.near network-config mainnet sign-with-keychain sendThe DEX swaps 0.99 NEAR, and 0.01 NEAR goes to bob.near’s inner balance. The swap event lists the fees each account got in referral_fees_paid, and its amount_in is what the DEX got, without them.
In operations and deposits
Section titled “In operations and deposits”execute_operations takes referral_fees next to operations and referrer:
{ "operations": [{ "SwapSimple": { ... } }, { "Withdraw": { ... } }], "referrer": "myapp.near", "referral_fees": [["myapp.near", 5000]]}A deposit message takes them in its object form, the same way, except that referral_fees can’t be null there: leave it out instead. In both, only the first swap pays them: in a chain of swaps, the fee is in the first swap’s input.
The whole script
Section titled “The whole script”#!/usr/bin/env bash# Swaps 1 NEAR from the inner balance for USDt, paying bob.near a referral fee# of 1%. alice.near has never used Intear DEX, and neither has bob.near.set -euo pipefail
near contract call-function as-transaction dex.intear.near storage_deposit \ json-args '{}' \ prepaid-gas '30.0 Tgas' attached-deposit '0.01 NEAR' \ sign-as alice.near network-config mainnet sign-with-keychain send
near contract call-function as-transaction dex.intear.near register_assets \ json-args '{"asset_ids": ["near", "nep141:usdt.tether-token.near"]}' \ prepaid-gas '30.0 Tgas' attached-deposit '1 yoctoNEAR' \ sign-as alice.near network-config mainnet sign-with-keychain send
near contract call-function as-transaction dex.intear.near deposit_near \ json-args '{}' \ prepaid-gas '30.0 Tgas' attached-deposit '1 NEAR' \ sign-as alice.near network-config mainnet sign-with-keychain send
# bob.near is paid in the swap's input, NEAR, so NEAR has to be registered for# it. Anyone can register it, here alice.near, from its own storage balance.near contract call-function as-transaction dex.intear.near register_assets \ json-args '{"asset_ids": ["near"], "for": {"Account": "bob.near"}}' \ prepaid-gas '30.0 Tgas' attached-deposit '1 yoctoNEAR' \ sign-as alice.near network-config mainnet sign-with-keychain send
# The DEX swaps 0.99 NEAR, so simulate with the same referral feesAMOUNT_OUT=$(near contract call-function as-read-only dex.intear.near simulate_swap_simple \ json-args '{ "dex_id": "slimedragon.near/xyk", "message": "AQAAAEBCDwABAAAA3QAAAAA=", "trader": "alice.near", "asset_in": "near", "asset_out": "nep141:usdt.tether-token.near", "amount": {"ExactIn": "1000000000000000000000000"}, "referral_fees": [["bob.near", 10000]] }' \ 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": "AQAAAEBCDwABAAAA3QAAAAA=", "asset_in": "near", "asset_out": "nep141:usdt.tether-token.near", "amount": {"ExactIn": "1000000000000000000000000"}, "referral_fees": [["bob.near", 10000]], "constraint": $min_amount_out }')" \ prepaid-gas '100.0 Tgas' attached-deposit '1 yoctoNEAR' \ sign-as alice.near network-config mainnet sign-with-keychain send