Websites and apps
Linking to the web app
Section titled “Linking to the web app”The simplest integration is a link. The web app is at https://trestly.io, and opens there once the mainnet launch is
verified. Its pages are plain paths (The web app):
| Path | Opens |
|---|---|
/ |
The main page |
/bridge |
The bridge, from an EVM chain to Kaspa |
/swap |
KAS⇄kUSDT swaps |
/pool |
Liquidity in KasPool |
/portfolio |
What the connected wallets hold |
/reserves |
Proof of reserves |
/network |
The Reserves page opened at its Bridge status: each network working or paused, the contracts, the kUSDT and pool IDs |
/activity |
What the user’s wallets did |
/terms |
The Terms of Service |
Any other path opens the main page. /bridge reads two query parameters, and no page reads any other:
| Parameter | Effect |
|---|---|
from=<chain code> |
Picks the EVM chain: 1 Ethereum, 2 BNB Chain. A code the deployment does not have falls back to the first chain |
to=evm |
Opens the bridge back, from Kaspa to the chain from names. Without it the bridge goes to Kaspa |
For example, https://trestly.io/bridge?to=evm&from=2 opens the bridge back to BNB Chain. There is no
parameter for an amount or an address: the user enters them, and the page fills in the connected wallet’s address.
Links from the time of hash routes (/#/bridge?to=evm) still land on the same page.
On a first visit the web app asks the user to accept its Terms of Service (Terms of Service).
Using kUSDT Wallet from a page
Section titled “Using kUSDT Wallet from a page”kUSDT Wallet injects window.kusdt. A page connects with kaspa_requestAccounts, then asks for balances, a send, a
redemption, a swap or a liquidity change. Each of these opens the wallet’s own window for the user to approve. The
page never sees a key. See Wallet provider for the methods, the error codes and the
events, and note:
- Amounts are decimal strings (or safe integers) of the smallest unit: sompi for KAS (10⁸ in 1 KAS), base units for kUSDT (10⁶ in 1 kUSDT).
- Connections are per network.
kaspa_getNetworkanswers any page;kaspa_switchNetworkasks the user to move. - Until the user has accepted the wallet’s Terms of Service, every method but
kaspa_getNetworkis answered4100. - A site has at most 8 requests waiting at a time; past that,
-32002.
Deposits are made on Ethereum or BNB Chain, so a page uses the user’s EVM wallet for them (EIP-1193, EIP-6963 or WalletConnect).
Bridging from your own page
Section titled “Bridging from your own page”If you build the bridge into your own page instead of linking to the web app, follow what the web app does:
- To Kaspa. Approve exactly the amount, then call the vault’s
depositAtLeastwith the least kUSDT the user accepts, so a fee that rose meanwhile makes it revert instead of taking more. Ethereum’s USDT refuses to change a non-zero allowance: reset it to 0 first. Derive the Kaspa owner from the user’s own address, never from typed input: a wrong owner can’t be corrected after the mint. See Doing it without the web app and Kaspa recipients. - Follow the deposit with
GET /deposits/:chain/:nonce(Status values). - Back to an EVM chain. Before every burn, ask
GET /recipients/:chain/:addressand burn only when it sayspayable, and check that the vault can pay now (paused, backing,releaseAvailable, release capacity). A burn cannot be undone. See Redeem kUSDT. - Never send USDT to a vault’s address with a plain transfer. Only
depositanddepositAtLeastbridge; a plain transfer is lost (Known limits).
Read the vault addresses and their parameters (fees, minimum and maximum deposit, paused) from GET /status, or
from the vaults themselves, and check them against Status: Addresses, where they are
published once the launch is verified. Make them a setting rather than code. The public testnet ended on 14 November
2026; to try your page before mainnet, run the whole stack locally (Run the simnet flow).
Pool swaps
Section titled “Pool swaps”Through kUSDT Wallet
Section titled “Through kUSDT Wallet”kusdt_swap with {side: "buy" or "sell", amountIn, minOut} is the short way. The wallet builds the swap on the
pool’s newest verified state, refuses it while the pool is paused or when a sell is over the circuit breaker, and
never goes ahead on its own at a worse price than the user approved. minOut stays the hard floor
(The pool).
Building it yourself
Section titled “Building it yourself”- Read the pool.
GET /poolanswers the newest pool and reserve states, the spot prices,breaker(what sells may still take out now, and from which DAA score a pool transaction can be sent) andpaused(Coordinator API). - Check it. Recompute the pool state’s locking script and find the UTXO on your own node (Verifying answers).
- Quote.
kusdt-tx quotegives the exact output with the same core the covenant checks against (Protocol helpers); the formula is on Swap: price and fee. Asking for one base unit more is rejected. - Build.
pool-buyorpool-sell(Transactions), keeping to the input rules: at most 8 inputs, plain Schnorr P2PK funding coins already in a block. - Sign and submit. If another swap lands first, yours becomes invalid rather than worse: quote again and ask the user again before you send at a lower output (No sandwiching).
While the pool is paused, buys, sells and new liquidity stop, and removing liquidity keeps working (When the pool is paused).