Skip to main content

Estimate → Build → Track

Both directions follow the same shape. Each section below is a complete walkthrough using only HTTP. A successful response wraps its payload as { "data": ..., "success": true }, and the fields named below live under data. An estimate for a pair that is not enabled still returns HTTP 200, with success: false. Errors return a 4xx or 5xx status with a message.

BTC → EVM​

This walks the full lifecycle of a BTC → EVM request. (The SDK does the same in a few lines.)

1. Estimate​

curl -X POST https://api.teleportdao.xyz/api/v2/teleswap/utils/wrap-and-swap-estimate \
-H "Content-Type: application/json" \
-d '{
"amountBTC": "0.001",
"networkName": "optimism",
"outputToken": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"
}'

Returns the expected outputAmount, minInputAmountBTC, maxInputAmountBTC (null when no maximum is set), and a teleswapFee breakdown.

2. Build the unsigned transaction​

curl -X POST https://api.teleportdao.xyz/api/v2/teleswap/utils/wrap-and-swap-unsigned \
-H "Content-Type: application/json" \
-d '{
"recipientAddress": "0x4e3e1807aa17aed8d1FC580dDa552079d9427ece",
"amountBTC": "0.001",
"networkName": "optimism",
"signer": {
"addressType": "p2wpkh",
"publicKey": "...",
"address": "bc1..."
}
}'

Sign the returned transaction with your Bitcoin wallet and broadcast it.

3. Track​

Poll by the Bitcoin TXID until state is Done:

curl https://api.teleportdao.xyz/api/v2/teleswap/requests/tx/<txId>
{ "state": "Pending" } // → later → { "state": "Done", "status": "Submitted", ... }

EVM → BTC​

This walks the full lifecycle of an EVM → BTC request. Both endpoints are on /api/v3 — the recommended path for this direction.

1. Estimate​

curl -X POST https://api.teleportdao.xyz/api/v3/teleswap/utils/swap-and-unwrap-estimate \
-H "Content-Type: application/json" \
-d '{
"exchangeInfo": {
"inputToken": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"inputAmount": "20000000"
},
"networkName": "arbitrum"
}'

Returns the expected outputAmountBTC, minInputAmountBTC, maxInputAmountBTC (null when no maximum is set), and a teleswapFee breakdown. inputAmount is in the token's smallest unit; omit inputToken to sell the chain's native coin.

2. Build the contract call​

Apply your slippage tolerance to outputAmountBTC and send the result as minBtcAmount — the floor the contract enforces. Use at most 8 decimals, rounded down. For a 1% tolerance, send outputAmountBTC × 0.99.

curl -X POST https://api.teleportdao.xyz/api/v3/teleswap/utils/swap-and-unwrap-inputs \
-H "Content-Type: application/json" \
-d '{
"exchangeInfo": {
"inputToken": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"inputAmount": "20000000"
},
"bitcoinAddress": "bc1...",
"networkName": "arbitrum",
"minBtcAmount": "<outputAmountBTC × 0.99>",
"userAddress": "0x..."
}'

Returns contractAddress, method, methodABI, and inputs — the params to pass and the value to send.

What userAddress is for

On cross-chain networks it is required: if the request fails, this is the address that receives the assets back.

On base networks it is not used. There the only failure mode reverts the whole transaction, so the input token never leaves the user's wallet and there is nothing to refund.

3. Approve and send​

Call method on contractAddress with inputs.params, using methodABI and passing inputs.value as the transaction value.

When inputs.value is 0 the input is an ERC-20 — approve contractAddress to spend inputAmount first. A non-zero value means the input is the chain's native coin, and there is nothing to approve.

const contract = new Contract(contractAddress, [methodABI], wallet);
const tx = await contract[method](...inputs.params, {
value: BigInt(inputs.value || "0"),
});
Read the contract and method from the response

Take contractAddress, method and methodABI from every response rather than hardcoding them. They depend on the route.

4. Track​

Poll by the transaction hash until state is Done or Failed. data is null until the request has been indexed.

curl https://api.teleportdao.xyz/api/v2/teleswap/requests/tx/<txId>
{ "data": null, "success": true } // not indexed yet
{ "data": { "state": "Pending", ... }, "success": true }
{ "data": { "state": "Done", ... }, "success": true } // or "Failed"

See the full API reference for every parameter.