STON.fi
STON.fi是一个建立在TON 区块链上的去中心化自动做市商(AMM),提供几乎零费用、低滑点、极其简单的界面以及与 TON 钱包的直接集成。
在进一步介绍之前,请自己熟悉以下内容:
Swaps
在 STON.fi 文档中阅读更多关于 Swaps 的信息。
Swaps使用 StonfiSwap
Message 和 SwapAdditionalData
Struct
/// https://docs.ston.fi/docs/developer-section/api-reference-v2/router#swap-0x6664de2amessage(0x6664de2a) StonfiSwap { // Address of the other Router token wallet otherTokenWallet: Address;
// Where to send refunds upon a failed swap refundAddress: Address;
// Where to send excesses upon a successful swap excessesAddress: Address;
// UNIX timestamp of execution deadline for the swap deadline: Int as uint64;
// Reference to another Cell with additional data, // using the Tact's greedy auto-layout mechanism additionalData: SwapAdditionalData;}
/// https://docs.ston.fi/docs/developer-section/api-reference-v2/router#additional_data-bodystruct SwapAdditionalData { // Minimum required amount of tokens to receive // Defaults to 1, which causes the swap to fail // only if no tokens are received minOut: Int as coins = 1;
// Where to send tokens upon a successful swap receiverAddress: Address;
// Forward fees for the `customPayload` if it's not `null` // Defaults to 0 fwdGas: Int as coins = 0;
// Custom payload that will be sent upon a successful swap // Defaults to `null`, which means no payload customPayload: Cell? = null;
// Forward fees for `refundPayload` if it's not `null` // Defaults to 0 refundFwdGas: Int as coins = 0;
// Custom payload that will be sent upon a failed swap // Defaults to `null`, which means no payload refundPayload: Cell? = null;
// Referral fee, between 0 (no fee) and 100 (1%) // Defaults to 10, which means 0.1% fee refFee: Int as uint16 = 10;
// Address of the referral // Defaults to `null` referralAddress: Address? = null;}
STON.fi SDK 定义了一些常量用于处理费用。 请注意这些是硬编码值,但最佳做法是用当前配置参数动态计算费用
/// Hardcoded fee value to pay for sending a message to the Jetton walletconst FeeSwapJettonToJetton: Int = ton("0.3");/// Hardcoded fee value to pay forward fees from the Jetton walletconst FeeSwapJettonToJettonFwd: Int = ton("0.24");
/// Hardcoded fee value to pay for sending a message to the Jetton walletconst FeeSwapJettonToToncoin: Int = ton("0.3");/// Hardcoded fee value to pay for sending a message to the Jetton walletconst FeeSwapJettonToToncoinFwd: Int = ton("0.24");
/// Hardcoded fee value to pay for sending a message and subsequent forwardingconst FeeSwapToncoinToJetton: Int = ton("0.01") + ton("0.3");
Jetton to Jetton
// CPI Router v2.1.0const RouterAddress: Address = address("kQALh-JBBIKK7gr0o4AVf9JZnEsFndqO0qTCyT-D-yBsWk0v");
// Router Jetton Wallet addressconst RouterJettonWallet: Address = address("kQAtX3x2s-wMtYTz8CfmAyloHAB73vONzJM5S2idqXl-_5xK");
/// NOTE: To calculate and provide Jetton wallet address for the target user,/// make sure to check links after this code snippetfun jettonToJetton(myJettonWalletAddress: Address) { // Amount of Jettons to swap let offerAmount: Int = 100_000;
// Prepare the payload let forwardPayload = StonfiSwap{ otherTokenWallet: RouterJettonWallet, refundAddress: myAddress(), excessesAddress: myAddress(), // Deadline is set to 10,000 seconds from now deadline: now() + 10_000, additionalData: SwapAdditionalData{ receiverAddress: myAddress() }, };
// Start a swap with the message to the Jetton wallet send(SendParameters{ to: myJettonWalletAddress, value: FeeSwapJettonToJetton, body: JettonTransfer{ queryId: 42, amount: offerAmount, destination: RouterAddress, responseDestination: myAddress(), forwardTonAmount: FeeSwapJettonToJettonFwd, forwardPayload: forwardPayload.toCell(), }.toCell(), });}
//// Helper Messages, Structs and constants described earlier on this page//
message(0x6664de2a) StonfiSwap { otherTokenWallet: Address; refundAddress: Address; excessesAddress: Address; deadline: Int as uint64; additionalData: SwapAdditionalData;}
struct SwapAdditionalData { minOut: Int as coins = 1; receiverAddress: Address; fwdGas: Int as coins = 0; customPayload: Cell? = null; refundFwdGas: Int as coins = 0; refundPayload: Cell? = null; refFee: Int as uint16 = 10; referralAddress: Address? = null;}
const FeeSwapJettonToJetton: Int = ton("0.3");const FeeSwapJettonToJettonFwd: Int = ton("0.24");
//// Messages from the Jetton standard//
message(0xf8a7ea5) JettonTransfer { queryId: Int as uint64; amount: Int as coins; destination: Address; responseDestination: Address?; customPayload: Cell? = null; forwardTonAmount: Int as coins; forwardPayload: Cell?; // slightly adjusted}
Jetton to Toncoin
Jetton to Toncoin swap与Jetton to Jetton swap 非常相似,唯一不同的是,RouterJettonWallet
地址被替换为 RouterProxyTonWallet
。
// CPI Router v2.1.0const RouterAddress: Address = address("kQALh-JBBIKK7gr0o4AVf9JZnEsFndqO0qTCyT-D-yBsWk0v");
// Router's pTON addressconst RouterProxyTonWallet: Address = address("kQBbJjnahBMGbMUJwhAXLn8BiigcGXMJhSC0l7DBhdYABhG7");
/// NOTE: To calculate and provide Jetton wallet address for the target user,/// make sure to check links after this code snippetfun jettonToToncoin(myJettonWalletAddress: Address) { // Amount of Jettons to swap let offerAmount: Int = 100_000;
// Prepare the payload let forwardPayload = StonfiSwap{ otherTokenWallet: RouterProxyTonWallet, refundAddress: myAddress(), excessesAddress: myAddress(), // Deadline is set to 10,000 seconds from now deadline: now() + 10_000, additionalData: SwapAdditionalData{ receiverAddress: myAddress() }, };
// Start a swap with the message to the Jetton wallet send(SendParameters{ to: myJettonWalletAddress, value: FeeSwapJettonToToncoin, body: JettonTransfer{ queryId: 42, amount: offerAmount, destination: RouterAddress, responseDestination: myAddress(), forwardTonAmount: FeeSwapJettonToToncoinFwd, forwardPayload: forwardPayload.toCell(), }.toCell(), });}
//// Helper Messages, Structs and constants described earlier on this page//
message(0x6664de2a) StonfiSwap { otherTokenWallet: Address; refundAddress: Address; excessesAddress: Address; deadline: Int as uint64; additionalData: SwapAdditionalData;}
struct SwapAdditionalData { minOut: Int as coins = 1; receiverAddress: Address; fwdGas: Int as coins = 0; customPayload: Cell? = null; refundFwdGas: Int as coins = 0; refundPayload: Cell? = null; refFee: Int as uint16 = 10; referralAddress: Address? = null;}
const FeeSwapJettonToToncoin: Int = ton("0.3");const FeeSwapJettonToToncoinFwd: Int = ton("0.24");
//// Messages from the Jetton standard//
message(0xf8a7ea5) JettonTransfer { queryId: Int as uint64; amount: Int as coins; destination: Address; responseDestination: Address?; customPayload: Cell? = null; forwardTonAmount: Int as coins; forwardPayload: Cell?; // slightly adjusted}
Toncoin 交换至 Jetton
要将 Toncoin 兑换为 Jetton,STON.fi 需要使用一种被称为代理 Toncoin 钱包(简称 pTON)的工具。 要与它进行适当的互动,我们需要引入一个 ProxyToncoinTransfer
Message
/// https://github.com/ston-fi/sdk/blob/786ece758794bd5c575db8b38f5e5de19f43f0d1/packages/sdk/src/contracts/pTON/v2_1/PtonV2_1.tsmessage(0x01f3835d) ProxyToncoinTransfer { // Unique identifier used to trace transactions across multiple contracts // Defaults to 0, which means we don't mark messages to trace their chains queryId: Int as uint64 = 0;
// Toncoin amount for the swap tonAmount: Int as coins;
// Where to send refunds upon a failed swap refundAddress: Address;
// Optional custom payload to attach to the swap // Defaults to `null` forwardPayload: Cell?;}
请注意,ProxyToncoinTransfer
与JettonTransfer
相似, 但不要求除退款地址以外的任何地址,也不要求指定任何预付金额。
// Router's pTON wallet addressconst RouterProxyTonWallet: Address = address("kQBbJjnahBMGbMUJwhAXLn8BiigcGXMJhSC0l7DBhdYABhG7");
// Router's Jetton wallet addressconst RouterJettonWallet: Address = address("kQAtX3x2s-wMtYTz8CfmAyloHAB73vONzJM5S2idqXl-_5xK");
fun toncoinToJetton() { // Amount of Toncoin to swap let offerAmount: Int = 1_000;
// Prepare the payload let forwardPayload = StonfiSwap{ otherTokenWallet: RouterJettonWallet, refundAddress: myAddress(), excessesAddress: myAddress(), // Deadline is set to 10,000 seconds from now deadline: now() + 10_000, additionalData: SwapAdditionalData{ receiverAddress: myAddress() }, };
// Start a swap with the message to the proxy Toncoin wallet send(SendParameters{ to: RouterProxyTonWallet, value: FeeSwapToncoinToJetton + offerAmount, body: ProxyToncoinTransfer{ tonAmount: offerAmount, refundAddress: myAddress(), forwardPayload: forwardPayload.toCell(), }.toCell(), });}
//// Helper Messages, Structs and constants described earlier on this page//
message(0x01f3835d) ProxyToncoinTransfer { queryId: Int as uint64 = 0; tonAmount: Int as coins; refundAddress: Address; forwardPayload: Cell?;}
message(0x6664de2a) StonfiSwap { otherTokenWallet: Address; refundAddress: Address; excessesAddress: Address; deadline: Int as uint64; additionalData: SwapAdditionalData;}
struct SwapAdditionalData { minOut: Int as coins = 1; receiverAddress: Address; fwdGas: Int as coins = 0; customPayload: Cell? = null; refundFwdGas: Int as coins = 0; refundPayload: Cell? = null; refFee: Int as uint16 = 10; referralAddress: Address? = null;}
const FeeSwapToncoinToJetton: Int = ton("0.3");
流动资金
阅读更多关于STON.fi documentation中流动资金条款的信息。
STON.fi 允许您只指定一种代币来存入流动性—池将自动执行交换并铸造流动性提供者(LP)代币。 要做到这一点,您需要将 ProvideLiquidity
Message 的 bothPositive
字段设置为 false
。
流动性存款使用 ProvideLiquidity
Message 和 ProvideLiquidityAdditionalData
Struct
/// https://docs.ston.fi/docs/developer-section/api-reference-v2/router#provide_lp-0x37c096dfmessage(0x37c096df) ProvideLiquidity { // Address of the other Router token wallet otherTokenWallet: Address;
// Where to send refunds if provisioning fails refundAddress: Address;
// Where to send excesses if provisioning succeeds excessesAddress: Address;
// UNIX timestamp of execution deadline for the provisioning deadline: Int as uint64;
// Reference to another Cell with additional data, // using the Tact's greedy auto-layout mechanism additionalData: ProvideLiquidityAdditionalData;}
/// https://docs.ston.fi/docs/developer-section/api-reference-v2/router#additional_data-body-1struct ProvideLiquidityAdditionalData { // Minimum required amount of LP tokens to receive // Defaults to 1, which causes the provisioning to fail // only if no tokens are received minLpOut: Int as coins = 1;
// Where to send LP tokens if provisioning succeeds receiverAddress: Address;
// Should both tokens in a pair have a positive quantity? // If not, then the pool would perform an additional swap for the lacking token // Defaults to `true`, which means that deposit would only go through // when both token amounts are non-zero bothPositive: Bool = true;
// Forward fees for the `customPayload` if it's not `null` // Defaults to 0 fwdGas: Int as coins = 0;
// Custom payload that will be sent if provisioning succeeds // Defaults to `null`, which means no payload customPayload: Cell? = null;}
STON.fi SDK 定义了一些常量用于处理费用。 请注意这些是硬编码值,但最佳做法是用当前配置参数动态计算费用
/// Hardcoded fee value to pay for sending a liquidity provisioning message/// when depositing a certain amount of Jettonsconst FeeSingleSideProvideLpJetton: Int = ton("1");
/// Hardcoded fee value to pay forward fees of subsequent messages for liquidity provisioningconst FeeSingleSideProvideLpJettonFwd: Int = ton("0.8");
/// Hardcoded fee value to pay for sending a liquidity provisioning message/// when depositing a certain amount of Toncoinsconst FeeSingleSideProvideLpToncoin: Int = ton("0.01") + ton("0.8");
存入 Jetton
// CPI Router v2.1.0const RouterAddress: Address = address("kQALh-JBBIKK7gr0o4AVf9JZnEsFndqO0qTCyT-D-yBsWk0v");
// Router's pTON wallet addressconst RouterProxyTonWallet: Address = address("kQBbJjnahBMGbMUJwhAXLn8BiigcGXMJhSC0l7DBhdYABhG7");
// Router's Jetton wallet addressconst RouterJettonWallet: Address = address("kQAtX3x2s-wMtYTz8CfmAyloHAB73vONzJM5S2idqXl-_5xK");
/// NOTE: To calculate and provide Jetton wallet address for the target user,/// make sure to check links after this code snippetfun jettonDeposit(myJettonWalletAddress: Address) { // Amount of Jettons for liquidity provisioning let offerAmount = 100_000;
// Prepare the payload let forwardPayload = ProvideLiquidity{ otherTokenWallet: RouterProxyTonWallet, refundAddress: myAddress(), excessesAddress: myAddress(), // Deadline is set to 1,000 seconds from now deadline: now() + 1_000, additionalData: ProvideLiquidityAdditionalData{ receiverAddress: myAddress(), bothPositive: false, // i.e. single side }, };
send(SendParameters{ to: myJettonWalletAddress, value: FeeSingleSideProvideLpJetton, body: JettonTransfer{ queryId: 42, amount: offerAmount, destination: RouterAddress, responseDestination: myAddress(), forwardTonAmount: FeeSingleSideProvideLpJettonFwd, forwardPayload: forwardPayload.toCell(), }.toCell(), });}
//// Helper Messages, Structs and constants described earlier on this page//
message(0x37c096df) ProvideLiquidity { otherTokenWallet: Address; refundAddress: Address; excessesAddress: Address; deadline: Int as uint64; additionalData: ProvideLiquidityAdditionalData;}
struct ProvideLiquidityAdditionalData { minLpOut: Int as coins = 1; receiverAddress: Address; bothPositive: Bool = true; fwdGas: Int as coins = 0; customPayload: Cell? = null;}
const FeeSingleSideProvideLpJetton: Int = ton("1");const FeeSingleSideProvideLpJettonFwd: Int = ton("0.8");
//// Messages from the Jetton standard//
message(0xf8a7ea5) JettonTransfer { queryId: Int as uint64; amount: Int as coins; destination: Address; responseDestination: Address?; customPayload: Cell? = null; forwardTonAmount: Int as coins; forwardPayload: Cell?; // slightly adjusted}
存入 Toncoin
// Router's pTON wallet addressconst RouterProxyTonWallet: Address = address("kQBbJjnahBMGbMUJwhAXLn8BiigcGXMJhSC0l7DBhdYABhG7");
// Router's Jetton wallet addressconst RouterJettonWallet: Address = address("kQAtX3x2s-wMtYTz8CfmAyloHAB73vONzJM5S2idqXl-_5xK");
fun toncoinDeposit() { // Amount of Jettons for liquidity provisioning let offerAmount = 100_000;
// Prepare the payload let forwardPayload = ProvideLiquidity{ otherTokenWallet: RouterJettonWallet, refundAddress: myAddress(), excessesAddress: myAddress(), deadline: now() + 1000, additionalData: ProvideLiquidityAdditionalData{ receiverAddress: myAddress(), bothPositive: false, // i.e. single side }, };
send(SendParameters{ to: RouterProxyTonWallet, value: FeeSingleSideProvideLpToncoin + offerAmount, body: ProxyToncoinTransfer{ queryId: 42, tonAmount: offerAmount, refundAddress: myAddress(), forwardPayload: forwardPayload.toCell(), }.toCell(), });}
//// Helper Messages, Structs and constants described earlier on this page//
message(0x01f3835d) ProxyToncoinTransfer { queryId: Int as uint64 = 0; tonAmount: Int as coins; refundAddress: Address; forwardPayload: Cell?;}
message(0x37c096df) ProvideLiquidity { otherTokenWallet: Address; refundAddress: Address; excessesAddress: Address; deadline: Int as uint64; additionalData: ProvideLiquidityAdditionalData;}
struct ProvideLiquidityAdditionalData { minLpOut: Int as coins = 1; receiverAddress: Address; bothPositive: Bool = true; fwdGas: Int as coins = 0; customPayload: Cell? = null;}
const FeeSingleSideProvideLpToncoin: Int = ton("0.01") + ton("0.8");
提取流动资金
要提取流动性,需要燃烧的 LP 代币。 您可以参考 Jettons Cookbook 页面中有关 Jetton 销毁的相关部分 的示例。 然而,应该添加比正常销毁更多的 Toncoin,因为如果添加的 Toncoin 太少,可能会导致 LP 代币被销毁,但不会从池中发送任何(或仅部分)流动性。 因此,请考虑至少附上 Toncoin - 超额部分将予以退还。