Dedust

Dedust SDK v2 uses different messages for native TON and jetton swaps

Last updated ยท

Dedust SDK v2 connects swap integrations to TON vaults through messages that differ with the input asset. Native TON enters through a vault swap call that includes the traded amount and execution funding. A jetton enters through its owner's token-wallet transfer, carrying a swap payload to the corresponding vault. Both paths identify a pool and require usable contracts before funds move. The integration therefore needs to distinguish the trade quantity, payment envelope and minimum acceptable output.

In short: The SDK exposes readiness checks because a resolved pool or vault address alone does not establish that the contract is usable.

Factory lookups locate the pool and its input vault

Factory lookups resolve the contract objects that a swap integration needs for its selected asset pair. Describe native TON with Asset.native() and a jetton with Asset.jetton(rootAddress) . The getPool lookup takes the pool type and asset pair. Resolve the native vault with getNativeVault or the selected jetton's vault with getJettonVault . These objects have different roles in the eventual request: the input vault receives the asset and the pool address identifies the exchange calculation.

The asset descriptor and jetton vault lookup must refer to the same token root. Keep that identity associated with the request throughout construction, including when resolving the owner's token wallet.

Which contracts must be ready before a swap?

The selected pool and input vault must report ReadinessStatus.READY before the integration sends a funded swap request. Resolving their addresses does not establish readiness, and sending funds to an inactive contract can cause irretrievable loss. Use the readiness getter on each relevant object. Set suitable execution funding and a minimum output for the intended trade; readiness alone does not establish an acceptable exchange price.

Diagram: Which contracts must be ready before a swap? (Dedust)
Visual summary: Which contracts must be ready before a swap?

Open full-size image

Native TON requests separate the trade amount from execution funds

The native vault's sendSwap method receives the TON trading amount directly, alongside the target pool and an execution allowance.

Keep the traded TON separate

The amount field specifies the TON quantity offered for exchange. The gasAmount field supplies an additional execution allowance. The SDK constructs a message value from their sum, so the payment attached to that message exceeds the trading quantity when the allowance is positive. That sum describes the attached message value; it does not establish the complete wallet debit.

Changing gasAmount changes the attached value without changing amount . Putting the combined payment into the trading field would encode a different input quantity.

Retain the pool and output condition

The poolAddress argument identifies the pool that should process the exchange. The native vault remains the destination of the funded call. Include the minimum acceptable output in limit before submitting the request. That condition concerns the asset received, while amount concerns TON sent for exchange.

Jetton requests carry the swap inside a token transfer

A jetton input uses its owner's token-wallet contract to transfer the asset, with the swap instruction embedded in that transfer. The native vault's calling pattern does not replace this token-wallet operation.

Resolve the token-specific sending wallet

Create a JettonRoot object from the selected token's root address, then resolve its wallet with getWallet(sender.address) . This gives the contract that holds that owner's balance of the selected jetton. The owner account, jetton root and resolved token wallet identify different objects. Retain those distinctions when selecting which opened contract receives sendTransfer .

Separate the destination from the swap payload

The transfer's destination is the input jetton's vault address. Build its forwardPayload with VaultJetton.createSwapPayload , supplying the intended pool address and output limit. The pool address belongs inside that instruction; it does not replace the vault destination in the enclosing token transfer.

Creating the payload produces a serialized cell. The transfer moves jettons into the vault's jetton wallet. That wallet sends the cell to the vault in a transfer notification only when a positive TON amount is forwarded.

Fund the forwarded instruction

The transfer's amount specifies the jetton quantity. The attached TON value must cover transfer costs and the forwardAmount sent with the vault notification to fund the swap. Preserve those asset units when building the call: copying the token quantity into a TON funding field changes the meaning of the request.

How does a direct swap enforce its minimum output?

A direct Protocol v2 swap is rejected if its output falls below the specified limit. The SDK accepts limit in both the native swap arguments and the jetton payload builder. Keep the limit in the output asset's units, separate from the input quantity and TON execution budget.

The pool's getEstimatedSwapOut getter accepts assetIn and amountIn , then returns assetOut , amountOut and tradeFee . Those fields identify the estimate's direction and output quantity. The estimate does not fix the later execution price. Encode the acceptable floor in the funded request itself, so acceptance depends on that condition when the pool processes the swap.

Reversing the input changes the payment structure

Consider a hypothetical integration using a ready volatile pool containing TON and a jetton. The selected pool, jetton, trade quantities and execution allowances are hypothetical inputs.

For the native-input direction, set the trading quantity to 1.375 TON and the additional execution allowance to 0.245 TON. The native SDK method attaches 1.620 TON to its message: 1.375 + 0.245. The encoded trade amount remains 1.375 TON.

For the jetton-input direction, let J denote the selected token quantity. The token wallet's transfer encodes J in amount , while its attached TON value funds execution separately. No addition between J and a TON allowance produces a meaningful combined asset quantity. The pool can remain the same while the sending contract and amount units change.

The calculation establishes the native message value, not an adequate gas budget or a quoted return. Execution still depends on the contracts being ready, sufficient TON funding and satisfaction of the specified output limit.

Pool fees and execution budgets describe different costs

The pool's getTradeFee getter reads a numerator and denominator, returning their ratio. Read the selected pool's value instead of treating one fee percentage as a constant across integrations.

Funding figures in SDK snippets are call inputs. They do not establish a universal execution cost, and a forwarded TON allowance does not describe the pool's trading fee.

The token transfer also has a responseAddress for returned excess TON. Keep that address distinct from the vault destination and the swap's output recipient. Returned execution funds and purchased tokens have different meanings even when an integration directs them to the same owner.

Can native TON and jetton swaps share integration code?

Native TON and jetton swaps can share asset selection, pool resolution and minimum-output handling, while their funded message builders remain distinct. Keep the asset associated with every amount. A native trade quantity, a jetton quantity and a TON execution allowance cannot become interchangeable because an API uses the same field name.

Readiness implementations also differ. The native vault checks whether its contract is active. The jetton vault additionally reads its readiness flag, while the pool requires an active contract and positive reserves for both assets. Calling each object's getReadinessStatus preserves those checks when shared code handles multiple input types.

Multi-hop routing can extend a swap instruction through next . Liquidity provision uses separate deposit methods and payloads. Keep those operations outside the direct-swap message builder, then choose the native-vault or jetton-wallet path from the asset that the integration will send.

Key questions about Dedust

Does SDK v2 require a package release numbered 2.x?

The SDK v2 label identifies the protocol family and does not require a matching package major version. The package declares support for Protocol v2 separately from its own release number. Match the installed package API to the integration code instead of assuming that the protocol number names a package release.

What does a zero deadline mean in swap parameters?

A zero deadline disables the deadline check in Protocol v2. A configured deadline applies when the swap reaches the pool. Submitting a wallet request before that deadline does not establish that the pool received it in time.

Is exact-output swapping available through SwapKind in Protocol v2?

Protocol v2 implements given_in, while given_out is marked as unimplemented. The swap request specifies an input quantity and can set a minimum output. That minimum does not turn the request into an exact-output swap.

Which field selects a different recipient for swap proceeds?

Set swapParams.recipientAddress to select the address that receives funds after the swap. Without an override, the protocol uses the sender's address. This parameter belongs to the swap itself; the jetton transfer's responseAddress concerns returned execution funds and does not select the purchased token's recipient.

How can a swap attach a payload to its success or rejection transfer?

Protocol v2 accepts fulfillPayload and rejectPayload in the swap parameters. The fulfillment payload accompanies the fund transfer after a successful swap, while the rejection payload accompanies the transfer after a rejected swap. These optional cells belong in swapParams, separate from the token transfer's forwardPayload.

Where can an integration inspect a resolved jetton wallet's owner and root?

The jetton wallet's getWalletData method returns ownerAddress and minterAddress alongside its balance and wallet code. Compare the owner with the intended sender and the minter with the selected jetton root. Those returned fields help identify a mismatched token-wallet contract before constructing its transfer.