@anywalletkit/protocol-swap2-omniston
v0.4.0
Published
STON.fi Omniston for Any Wallet Kit: TON swaps on the STON.fi DEX and TON ↔ EVM / EVM ↔ EVM stable orders through HTLC escrows, over the Omniston RFQ; standalone or as a provider of the swap2 router.
Maintainers
Readme
@anywalletkit/protocol-swap2-omniston
STON.fi Omniston as a swap2 module: TON ↔ TON swaps settled on the STON.fi DEX,
and TON ↔ EVM and EVM ↔ EVM stable orders settled through HTLC escrows
(resolver Arbiter), over the Omniston WebSocket RFQ. Standalone through
OmnistonSwap2Protocol, or as one provider of the router.
Install
npm install @anywalletkit/protocol-swap2-omniston @anywalletkit/core
# or: pnpm add @anywalletkit/protocol-swap2-omniston @anywalletkit/core · yarn add @anywalletkit/protocol-swap2-omniston @anywalletkit/coreOn npm: @anywalletkit/protocol-swap2-omniston, published from the release workflow with provenance.
EVM chains: Ethereum, BNB, Polygon, X Layer, HyperEVM, Robinhood, Base, Plasma, Arbitrum, Avalanche. ARC (in Omniston's matrix) waits for the asset catalog; TRON needs its own order path and is not wired yet.
Routes and their gates
Every route is fail-closed until its allowlists and validators are configured:
- TON → TON (DEX swap):
trustedSettlementContracts["ton:-239"],validateTonJettonWallet,validateTonSwapTarget. The built message's DEX call is decoded in the package (STON.fi v1/v2 incl. pTON and cross-swap, DeDust v1, DeDust CPMM v2): receiver = destination, refunds/excess = trader, on-chain minimum ≥ the quote's, no foreign referral; unknown layouts and split/multi-route quotes are refused by name.validateTonSwapLeg(supplied bycreateOmnistonTonValidators) confirms the routers' ask wallets, pTON wallet ownership and DeDust pool pairs on chain.tonSwapPayloadCheck: "report"traceston-swap-payload <reason>instead of refusing (default"enforce"). BehindremoteProvider, the app checks the built body itself:remoteProvider({name: "omniston", baseUrl, verifyBuild: omnistonVerifyBuild({...createOmnistonTonValidators()})}). A TON → TON swap body is opened withcheckTonSwapPayloadagainst the app's own request (receiver, refund, on-chain minimum, input; the quote carriesrouteSteps) and the DEX it pays is confirmed with the app's validators. A TON → EVM escrow body goes toverifyTonEscrowBuild: the jetton amount, the trader as owner, the destination chain, address and token and the quote's minimum delivery come from the app, the protocol contract fromtrustedProtocolAddresses, and the escrow code, authority key and timelocks are the audited ones. WithoutverifyBuildthe engine refuses remote cell bodies. - TON → EVM (HTLC order, the wallet pays a jetton escrow): factory
allowlisted on both chains,
validateTonJettonWallet,validateTonEscrowPayload,validateEvmOutputPosition. - EVM → TON (gasless order): the wallet approves the Omniston order
protocol (a 1inch Limit Order Protocol v4 fork,
trustedEvmOrderProtocolsper chain — a different table from the factories, since one address plays different roles on different chains) and signs an EIP-712Order;buildDepositreturns atypedDataUnsignedTxonly after the order, the pinned v1beta8 extension and the serialized order details are verified against the quote,registerSignedOrderhands the signature to Omniston, andtrackIntentdiscloses the HTLC secret only whenvalidateEvmInputPosition(finalizedSrcEscrowCreated+ escrow state) ANDvalidateTonOutputPosition(factory-deployed TON position with bound state, inside its completion window) both pass. BehindremoteProviderthe order is built on your server, so the app pins the order protocols itself:remoteProvider({name: "omniston", baseUrl, ...omnistonPins(trustedEvmOrderProtocols)})— the same audited table. The engine then signs only anOrderwhose verifying contract is a pinned spender, whose maker is this account and that sells exactly the swap's input of the source token; aPermitor any other typed message is refused. The rest of the order is the app's to check, and the engine signs a remote typed order only withverifyBuild:remoteProvider({name: "omniston", baseUrl, ...omnistonPins(AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS), verifyBuild: omnistonVerifyBuild({...createOmnistonTonValidators()})}). The build carries theorderExtensionthe order's salt commits to, andomnistonVerifyBuildopens both: the v4 domain on a trusted order protocol, the exact Order schema,takingAmountat least the quote's minimum, a single-fill order with no allowed sender and an expiry minutes away, the pinned v1beta8 auction and fee terms, one trusted escrow factory (trustedSettlementContracts, default the audited table) as the extension target, the whitelisted resolver as the order's receiver, the destination chain and token, the audited timelocks, the TON token and recipient and the quote id. The hashlock is the server's: the server holds the HTLC secret. The same applies to EVM → EVM.validateEvmTypedOrderis exported for apps that hold the settlement data. - EVM → EVM (gasless order, same order protocol as EVM → TON): the signed
extension's ExtraDataArgs name the destination chain, token and deposit and
are checked against the quote. The EVM recipient is NOT in anything the
wallet signs (it rides in the unsigned order details), so the secret is
disclosed only when
validateEvmInputPosition(source fill, including the destination complement) ANDvalidateEvmOutputPosition(an escrow the trusted factory derives from immutables that pay the recipient) both pass. The destination escrow's fee split must be exactly the quoted protocol and integrator fees, paid only to the quote'sprotocolFeeRecipientAddress/ integrator, its destination stages must be 1/120/180 s, and the secret is not released within 45 s of its cancellation stage (refusal reasons go to the validator'sonRefusal).
Validators
@anywalletkit/protocol-swap2-omniston/validators ships the RPC/indexer-backed
validators every route above needs, plus the audited contract tables:
createOmnistonEvmOutputValidator, createOmnistonEvmInputValidator,
createOmnistonTonValidators (TonAPI), createOmnistonEvmDeliveryLocator
(feeds locateEvmDelivery: a completed EVM-destination order then carries
destTxHash, the escrow's payout to the recipient — Omniston's feed names the
escrow, not that transaction), AUDITED_OMNISTON_SETTLEMENT_CONTRACTS,
AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS. No deployment env is read: pass your
own endpoints as rpcUrls (CAIP-2 → URLs, tried before the public fallbacks)
and tonApiUrl / tonApiKey. On serverless also inject durable
secretStore / quoteStore — the HTLC secret must survive to the poll that
discloses it. Give the quote store a claim (an atomic create-if-absent: Redis
SET NX, a conditional KV put): the platform picks quote ids, and a context is
never rebound to another user's quote under the same id. A secret is disclosed
only against the exact order it was locked to (its stored binding), so even a
rebound context gets nothing.
The destination-escrow proof requires the escrow immutables to be found in the
resolver's calldata AND to derive, through the trusted factory's
addressOfEscrowDst (deployedAt stamped with the block timestamp), to the
escrow address the factory announced; a decoy tuple or hidden immutables fail
closed.
Activity
describeActivity(tx, ctx) recognizes TON-side transactions by their
counterparty (compared in raw form, so EQ…, UQ… and 0:… all match), looking
at the destination contract and both sides of every transfer:
- STON.fi DEX router (
STONFI_ROUTERSinsrc/activity.ts; v2.2EQCS4UEa…cN3is what the wallet's swaps hit, v1 kept for older history) →swap, "Swapped GRAM → USD₮" / "Swapped USD₮ → GRAM", subtitle "STON.fi · TON". - Omniston HTLC escrow (
OMNISTON_ESCROWS, the Escrow MinterEQAbWJ3Y…mrZthat every live quote names assrcProtocolContractAddress) →bridge, "Bridged USD₮", subtitle "Omniston · STON.fi". The EVM leg is paid by the resolver and is not recognizable offline.
EVM → TON: the EVM leg is an off-chain signature (no transaction to
recognize); the delivery is a jetton transfer from the same escrow contract and
shows up as bridge. Nothing on EVM is recognized.
Fixtures (fixtures/activity/, test wallet UQCbXJ1-…fQaq, tonapi events):
two STON.fi swaps (GRAM → USD₮, USD₮ → GRAM) and one escrow order (1.6 USD₮);
negatives: a 1Click deposit on TON (a plain jetton transfer to a one-time
address — must stay null) and an EVM LI.FI swap.
