Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sicherheitslücken (CVE)5 ways AI is reshaping the cybersecurity job market(21.09.2026 um 10:25 Uhr)
IT Security NachrichtenRevoking the token didn’t kill the backdoor(21.09.2026 um 11:00 Uhr)
Malware / Trojaner / VirenChainScript-RAT per Polygon: ClickFix-Kampagnen drehen C2-Infrastruktur(21.09.2026 um 10:55 Uhr)
IT Security NachrichtenEnterprise Mobile KI: So lassen sich Shadow-AI-Risiken kontrollieren(21.09.2026 um 12:00 Uhr)
Malware / Trojaner / VirenChainScript-RAT setzt auf Polygon-Blockchain für C2-Rotation(21.09.2026 um 12:19 Uhr)
Sicherheitslücken (CVE)5 ways AI is reshaping the cybersecurity job market(21.09.2026 um 10:25 Uhr)
IT Security NachrichtenRevoking the token didn’t kill the backdoor(21.09.2026 um 11:00 Uhr)
Malware / Trojaner / VirenChainScript-RAT per Polygon: ClickFix-Kampagnen drehen C2-Infrastruktur(21.09.2026 um 10:55 Uhr)
IT Security NachrichtenEnterprise Mobile KI: So lassen sich Shadow-AI-Risiken kontrollieren(21.09.2026 um 12:00 Uhr)
Malware / Trojaner / VirenChainScript-RAT setzt auf Polygon-Blockchain für C2-Rotation(21.09.2026 um 12:19 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

How to Swap Tokens Programmatically with TypeScript

Swapping tokens programmatically with TypeScript requires three things: a swap API that returns executable calldata, a wallet library to sign transactions, and an RPC connection to broadcast them. With DEX aggregators handling over $13.5…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Swapping tokens programmatically with TypeScript requires three things: a swap API that returns executable calldata, a wallet library to sign transactions, and an RPC connection to broadcast them. With DEX aggregators handling over $13.5 billion in daily trading volume and TypeScript dominating web3 frontend and bot development, knowing how to execute on-chain swaps from code is a core skill for any DeFi developer. This guide walks you through swapping tokens on any EVM chain using TypeScript and a free API that requires no key and no SDK — just a single GET request.






What You'll Need





  • Node.js 18+ or Bun (for native fetch)


  • TypeScript (5.x recommended)


  • viem or ethers.js for signing and sending transactions

  • A wallet with a private key (testnet or mainnet)

  • No API key — the swap API used in this guide is free and requires no registration



Install the dependencies:




npm install viem typescript









Step 1: Fetch a Swap Quote



The swap API at api.swapapi.dev takes a GET request with five parameters and returns a complete transaction object. No authentication, no SDK, no POST body.




const res = await fetch("https://api.swapapi.dev/v1/swap/1?tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&tokenOut=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&amount=1000000000000000000&sender=0xYourAddress");
const quote = await res.json();






This fetches a quote to swap 1 ETH for USDC on Ethereum mainnet. The parameters are:





  • chainId (path): 1 for Ethereum, 42161 for Arbitrum, 8453 for Base, 137 for Polygon, 56 for BSC — 46 chains total


  • tokenIn: the input token address. Use 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native ETH/BNB/MATIC on any chain


  • tokenOut: the output token address. USDC on Ethereum is 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48


  • amount: the input amount in the token's smallest unit (wei). 1 ETH = 1000000000000000000


  • sender: the wallet address that will execute the swap



The response includes everything you need: the transaction object (to, data, value), expected output amounts, slippage protection, token metadata, and even recommended RPC URLs for the target chain.






Step 2: Parse the Response



The API returns a structured envelope with a status field that tells you exactly what happened.




const { success, data } = quote;

if (!success) {
console.error("API error:", quote.error.message);
process.exit(1);
}

if (data.status === "NoRoute") {
console.error("No swap route found for this pair");
process.exit(1);
}






A successful response contains these key fields:





  • data.status: "Successful" for a full fill, "Partial" if only part of the amount can be swapped, "NoRoute" if no path exists


  • data.expectedAmountOut: the best-case output in raw units


  • data.minAmountOut: the minimum output after slippage (transaction reverts below this)


  • data.priceImpact: price impact as a decimal (e.g., -0.0012 = -0.12%)


  • data.tx: the ready-to-submit transaction object


  • data.rpcUrls: ranked list of recommended public RPCs for the chain



To get the human-readable output amount, divide by the token's decimals:




const amountOut = Number(data.expectedAmountOut) / 10 ** data.tokenTo.decimals;
console.log(`Expected output: ${amountOut} ${data.tokenTo.symbol}`);









Step 3: Check Price Impact



Before executing any swap, check the price impact to avoid losing funds on low-liquidity pairs.




if (data.priceImpact < -0.05) {
console.error(`Price impact too high: ${(data.priceImpact * 100).toFixed(2)}%`);
process.exit(1);
}






A price impact of -5% or worse means you're moving the market significantly. For production bots, set a configurable threshold — most strategies use -1% to -3% as a maximum.






Step 4: Handle ERC-20 Approvals



When swapping a native token (ETH, BNB, MATIC), no approval is needed. But when swapping an ERC-20 token, you must approve the router contract to spend your tokens before the swap will succeed.




import { createWalletClient, http, parseAbi } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { arbitrum } from "viem/chains";

const account = privateKeyToAccount("0xYourPrivateKey");
const client = createWalletClient({ account, chain: arbitrum, transport: http(data.rpcUrl) });

const erc20Abi = parseAbi(["function approve(address spender, uint256 amount) returns (bool)"]);
const approveTx = await client.writeContract({ address: data.tokenFrom.address, abi: erc20Abi, functionName: "approve", args: [data.tx.to, BigInt(data.amountIn)] });






Wait for the approval transaction to confirm, then fetch a fresh swap quote before proceeding. The calldata is time-sensitive — it includes a deadline, so always re-fetch after approval.



Note: USDT on Ethereum requires setting the allowance to 0 before setting a new non-zero allowance.






Step 5: Simulate with eth_call



Before sending a real transaction and spending gas, simulate the swap using eth_call. This is free and catches most failures before they cost you money.




import { createPublicClient } from "viem";

const publicClient = createPublicClient({ chain: arbitrum, transport: http(data.rpcUrl) });

await publicClient.call({ to: data.tx.to, data: data.tx.data, value: BigInt(data.tx.value), account: account.address });






If eth_call reverts, the swap would fail on-chain. Common reasons: insufficient balance, missing ERC-20 approval, or expired deadline (quote older than 30 seconds).






Step 6: Estimate Gas and Send the Transaction



Estimate gas with a 20% buffer to avoid out-of-gas reverts on complex multi-hop routes, then send the transaction.




const gasEstimate = await publicClient.estimateGas({ to: data.tx.to, data: data.tx.data, value: BigInt(data.tx.value), account: account.address });

const txHash = await client.sendTransaction({ to: data.tx.to, data: data.tx.data, value: BigInt(data.tx.value), gas: (gasEstimate * 120n) / 100n });

console.log(`Transaction sent: ${txHash}`);






The API provides a gasPrice field as a suggestion, but viem and ethers.js automatically handle EIP-1559 gas pricing on supported chains, so you can omit it. Submit within 30 seconds of fetching the quote — the calldata includes a deadline.






Complete Example: Swap ETH for USDC on Arbitrum



Here is a full working script that swaps ETH for USDC on Arbitrum using viem:




import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { arbitrum } from "viem/chains";

const SENDER = "0xYourWalletAddress";
const PRIVATE_KEY = "0xYourPrivateKey";

const res = await fetch(`https://api.swapapi.dev/v1/swap/42161?tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&tokenOut=0xaf88d065e77c8cC2239327C5EDb3A432268e5831&amount=1000000000000000000&sender=${SENDER}`);
const { data } = await res.json();

if (data.status !== "Successful") throw new Error(`Swap failed: ${data.status}`);

const amountOut = Number(data.expectedAmountOut) / 10 ** data.tokenTo.decimals;
console.log(`Swapping 1 ETH for ~${amountOut} USDC on Arbitrum`);

const account = privateKeyToAccount(PRIVATE_KEY);
const publicClient = createPublicClient({ chain: arbitrum, transport: http(data.rpcUrl) });
const walletClient = createWalletClient({ account, chain: arbitrum, transport: http(data.rpcUrl) });

await publicClient.call({ to: data.tx.to, data: data.tx.data, value: BigInt(data.tx.value), account: SENDER });

const gas = await publicClient.estimateGas({ to: data.tx.to, data: data.tx.data, value: BigInt(data.tx.value), account: SENDER });

const txHash = await walletClient.sendTransaction({ to: data.tx.to, data: data.tx.data, value: BigInt(data.tx.value), gas: (gas * 120n) / 100n });

console.log(`TX: ${txHash}`);






This script fetches a quote, validates the response, simulates the swap, estimates gas, and submits the transaction — all in under 25 lines. The API provides the RPC URL, so you don't need to configure a separate node provider.






Swapping on Other Chains



The same code works on any of the 46 supported chains. Just change the chain ID and token addresses:



Polygon (chain 137) — swap MATIC for USDC:




const res = await fetch(`https://api.swapapi.dev/v1/swap/137?tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&tokenOut=0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359&amount=1000000000000000000&sender=${SENDER}`);






Base (chain 8453) — swap ETH for USDC:




const res = await fetch(`https://api.swapapi.dev/v1/swap/8453?tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&tokenOut=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&amount=1000000000000000000&sender=${SENDER}`);






BSC (chain 56) — swap BNB for USDT:




const res = await fetch(`https://api.swapapi.dev/v1/swap/56?tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&tokenOut=0x55d398326f99059fF775485246999027B3197955&amount=1000000000000000000&sender=${SENDER}`);






Note that USDT uses 18 decimals on BSC, unlike 6 decimals on Ethereum. The API returns tokenTo.decimals in the response, so always use that value instead of hardcoding decimals.






Using ethers.js Instead of viem



If your project uses ethers.js v6, the same flow applies with different syntax:




import { ethers } from "ethers";

const res = await fetch(`https://api.swapapi.dev/v1/swap/42161?tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&tokenOut=0xaf88d065e77c8cC2239327C5EDb3A432268e5831&amount=1000000000000000000&sender=${SENDER}`);
const { data } = await res.json();

const provider = new ethers.JsonRpcProvider(data.rpcUrl);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

const tx = await wallet.sendTransaction({ to: data.tx.to, data: data.tx.data, value: BigInt(data.tx.value) });
console.log(`TX: ${tx.hash}`);






ethers.js automatically handles gas estimation and EIP-1559 pricing, so you can send the transaction directly. For production use, add the simulation step (provider.call(...)) and gas buffer described earlier.






Handling Partial Fills and Edge Cases



The API returns three status values, all with HTTP 200. Your code should handle each:




if (data.status === "Successful") {
// Full fill — execute the swap
}

if (data.status === "Partial") {
const filled = Number(BigInt(data.amountIn)) / Number(BigInt(requestedAmount));
console.log(`Only ${(filled * 100).toFixed(1)}% of requested amount can be filled`);
}

if (data.status === "NoRoute") {
console.log("No route — try a different pair or chain");
}






For partial fills, data.amountIn and data.expectedAmountOut reflect the fillable portion, not your original request. The tx object is still executable — it just swaps the partial amount. Do not retry the same amount in a loop; the liquidity cap won't change.






Frequently Asked Questions






How do I swap tokens programmatically with TypeScript?



Fetch a swap quote from a DEX aggregator API, then sign and submit the returned transaction object using viem or ethers.js. With Swap API, a single GET request returns the complete to, data, and value fields — no SDK, no API key, no ABI encoding. The full flow (quote, simulate, send) takes under 25 lines of TypeScript.






Do I need an API key to swap tokens?



No. Swap API is free and requires no API key, no account, and no registration. It supports 46 EVM chains from a single endpoint. Other aggregator APIs like 1inch and 0x require API keys and paid plans for production use.






What TypeScript library should I use for on-chain swaps?



Both viem and ethers.js work. viem is the newer library with better TypeScript types and tree-shaking support. ethers.js v6 is more established with a larger community. Both can sign transactions, estimate gas, and interact with ERC-20 contracts. The swap API is library-agnostic — it returns raw transaction data that any wallet library can submit.






How do I handle token decimals when swapping?



Never hardcode decimals. The API response includes tokenTo.decimals and tokenFrom.decimals for every swap. Use these to convert between raw amounts and human-readable values: humanAmount = rawAmount / 10 ** decimals. For example, USDC uses 6 decimals on Ethereum and Arbitrum, but USDT uses 18 decimals on BSC.






What happens if a swap fails?



Simulate every swap with eth_call before sending a real transaction. If the simulation reverts, the swap would fail on-chain — do not submit. Common failure reasons: insufficient token balance, missing ERC-20 approval, or expired calldata (quotes are valid for 30 seconds). If eth_estimateGas fails, that also indicates the transaction would revert.






Get Started



Swap API is free, requires no API key, and supports 46 EVM chains from a single endpoint. One GET request returns everything you need: executable calldata, expected output amounts, slippage protection, and RPC URLs.



Browse the Swagger UI for interactive testing, or check the OpenAPI specification to auto-generate a typed TypeScript client.




curl "https://api.swapapi.dev/v1/swap/42161?tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&tokenOut=0xaf88d065e77c8cC2239327C5EDb3A432268e5831&amount=1000000000000000000&sender=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"


Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten How to Swap Tokens Programmatically with TypeScript

Thematisch verwandte Begriffe: Swap, Tokens, Programmatically, with · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94036 | A security flaw has been discovered in D-Link DIR-X1860 and DIR-X1860Z u…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick