TypeScript Examples - EVM
Complete TypeScript examples for trading on EVM chains (Base, Ethereum, BSC, Arbitrum, etc.)
Prerequisites
npm install ethersEnvironment Variables
export NAOS_API_KEY="your-api-key"
export NAOS_API_DOMAIN="https://api.naos.trade"
export TRADING_EVM_PKEY="your-evm-private-key"Setup
import { ethers } from 'ethers'
const API_BASE_URL = process.env.NAOS_API_DOMAIN || 'http://localhost:3001'
const API_KEY = process.env.NAOS_API_KEY || 'your-api-key-here'
const TRADING_EVM_PKEY = process.env.TRADING_EVM_PKEY
interface SwapStep {
input: string
output: string
router: string
quoter: string
fee: number
tick: number
hook: string
poolType: string
address: string
}
interface QuoteResponse {
success: boolean
path?: Array<{ step: SwapStep }>
stats?: {
valueAmountInUsd: number
amountOut: string
amountOutMin: string
priceImpact?: number
txCostUsd?: number
}
transaction?: {
trade: string
approve?: string
quoteId: string
}
error?: string
}
async function makeRequest<T>(endpoint: string, options?: RequestInit): Promise<T> {
const response = await fetch(`${API_BASE_URL}${endpoint}`, {
method: options?.method || 'GET',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
...(options?.headers as Record<string, string> || {})
},
body: options?.body
})
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`)
return await response.json() as T
}Get Quote
async function getQuote(params: {
token: string
amount: number
side: 'BUY' | 'SELL'
slippage: number
trader: string
chain: string
priority?: 'LOW' | 'MEDIUM' | 'HIGH' | 'INSTANT'
integrator?: string
fee?: number
}): Promise<QuoteResponse> {
const queryParams = new URLSearchParams({
token: params.token,
amount: params.amount.toString(),
side: params.side,
slippage: params.slippage.toString(),
trader: params.trader,
chain: params.chain
})
if (params.priority) queryParams.append('priority', params.priority)
if (params.integrator) queryParams.append('integrator', params.integrator)
if (params.fee) queryParams.append('fee', params.fee.toString())
const response = await makeRequest<QuoteResponse>(`/api/v1/quote?${queryParams.toString()}`)
if (response.success && response.stats) {
console.log('Quote received:')
console.log(` Value: $${response.stats.valueAmountInUsd.toFixed(2)}`)
console.log(` Amount Out: ${response.stats.amountOut}`)
console.log(` Price Impact: ${response.stats.priceImpact?.toFixed(2) || 'N/A'}%`)
console.log(` TX Cost: $${response.stats.txCostUsd?.toFixed(4) || 'N/A'}`)
console.log(` Quote ID: ${response.transaction?.quoteId}`)
}
return response
}Execute Transaction
async function executeTransaction(params: {
txData: string
network: string
mev: boolean
skipSimulation: boolean
quoteId: string
approveTxData?: string
}): Promise<any> {
const response = await makeRequest<any>('/api/v1/execute', {
method: 'POST',
body: JSON.stringify(params)
})
if (response.success) {
console.log('Transaction executed:')
console.log(` Status: ${response.status}`)
console.log(` TX Hash: ${response.txRes?.txHash}`)
console.log(` From: ${response.txRes?.fromToken}`)
console.log(` To: ${response.txRes?.toToken}`)
console.log(` Spent: ${response.txRes?.spent}`)
console.log(` Received: ${response.txRes?.received}`)
}
return response
}Simple Buy Example
async function simpleBuyEVM(): Promise<void> {
const wallet = new ethers.Wallet(TRADING_EVM_PKEY!)
const params = {
token: '0xFb31f85A8367210B2e4Ed2360D2dA9Dc2D2Ccc95',
chain: 'BASE',
trader: wallet.address,
amount: 0.01,
slippage: 500
}
console.log('Getting quote...')
const quote = await getQuote({
token: params.token,
amount: params.amount,
side: 'BUY',
slippage: params.slippage,
trader: params.trader,
chain: params.chain
})
if (!quote.success || !quote.transaction) {
throw new Error(quote.error || 'Quote failed')
}
console.log('Signing transaction...')
const tx = ethers.Transaction.from(quote.transaction.trade)
const signedTx = await wallet.signTransaction(tx)
let signedApproveTx
if (quote.transaction.approve) {
console.log('Signing approval transaction...')
const approveTx = ethers.Transaction.from(quote.transaction.approve)
signedApproveTx = await wallet.signTransaction(approveTx)
}
console.log('Executing transaction...')
const result = await executeTransaction({
txData: signedTx,
network: params.chain,
mev: false,
skipSimulation: false,
quoteId: quote.transaction.quoteId,
approveTxData: signedApproveTx
})
console.log('Trade completed!')
console.log(`TX Hash: ${result.txRes?.txHash}`)
console.log(`Explorer: https://basescan.org/tx/${result.txRes?.txHash}`)
}Full Trading Flow (Buy → Sell)
Complete example showing buy and then sell 50% of holdings:
async function evmFullTradingFlow(): Promise<void> {
const wallet = new ethers.Wallet(TRADING_EVM_PKEY!)
const traderAddress = wallet.address
const params = {
token: '0xFb31f85A8367210B2e4Ed2360D2dA9Dc2D2Ccc95',
chain: 'BASE',
amount: 0.001,
slippage: 500
}
console.log('='.repeat(80))
console.log('BUY STEP')
console.log('='.repeat(80))
console.log(`Token: ${params.token}`)
console.log(`Chain: ${params.chain}`)
console.log(`Trader: ${traderAddress}`)
console.log(`Amount: ${params.amount} ETH`)
console.log(`Slippage: ${params.slippage / 100}%`)
const buyQuote = await getQuote({
token: params.token,
amount: params.amount,
side: 'BUY',
slippage: params.slippage,
trader: traderAddress,
chain: params.chain
})
if (!buyQuote.success || !buyQuote.transaction) {
throw new Error(buyQuote.error || 'Failed to get buy quote')
}
console.log('\nSigning buy transaction...')
const buyTx = ethers.Transaction.from(buyQuote.transaction.trade)
const signedBuyTx = await wallet.signTransaction(buyTx)
let signedApproveTx
if (buyQuote.transaction.approve) {
console.log('Signing approval transaction...')
const approveTx = ethers.Transaction.from(buyQuote.transaction.approve)
signedApproveTx = await wallet.signTransaction(approveTx)
}
console.log('\nExecuting buy transaction...')
const buyResult = await executeTransaction({
txData: signedBuyTx,
network: params.chain,
mev: false,
skipSimulation: false,
quoteId: buyQuote.transaction.quoteId,
approveTxData: signedApproveTx
})
if (!buyResult.success) throw new Error(buyResult.error || 'Buy failed')
const tokensReceived = buyResult.txRes?.received || '0'
console.log('\nBUY COMPLETED!')
console.log(`TX Hash: ${buyResult.txRes?.txHash}`)
console.log(`Tokens Received: ${tokensReceived}`)
console.log(`ETH Spent: ${buyResult.txRes?.spent}`)
console.log(`Explorer: https://basescan.org/tx/${buyResult.txRes?.txHash}`)
console.log('\nWaiting 20 seconds before selling...')
await new Promise(resolve => setTimeout(resolve, 20000))
console.log('\n' + '='.repeat(80))
console.log('SELL STEP (50% of holdings)')
console.log('='.repeat(80))
const tokenInfo = await makeRequest<any>(`/api/v1/token-info?tokenAddress=${params.token}&chain=${params.chain}`)
const tokenDecimals = tokenInfo.decimals || 18
const balanceFormatted = Number(tokensReceived) / Math.pow(10, tokenDecimals)
const sellAmount50Percent = balanceFormatted * 0.5
console.log(`Token Balance: ${balanceFormatted.toFixed(6)} tokens`)
console.log(`Selling 50%: ${sellAmount50Percent.toFixed(6)} tokens`)
const sellQuote = await getQuote({
token: params.token,
amount: sellAmount50Percent,
side: 'SELL',
slippage: params.slippage,
trader: traderAddress,
chain: params.chain
})
if (!sellQuote.success || !sellQuote.transaction) {
throw new Error(sellQuote.error || 'Failed to get sell quote')
}
console.log('\nSigning sell transaction...')
const sellTx = ethers.Transaction.from(sellQuote.transaction.trade)
const signedSellTx = await wallet.signTransaction(sellTx)
let signedSellApproveTx
if (sellQuote.transaction.approve) {
console.log('Signing sell approval transaction...')
const sellApproveTx = ethers.Transaction.from(sellQuote.transaction.approve)
signedSellApproveTx = await wallet.signTransaction(sellApproveTx)
}
console.log('\nExecuting sell transaction...')
const sellResult = await executeTransaction({
txData: signedSellTx,
network: params.chain,
mev: false,
skipSimulation: false,
quoteId: sellQuote.transaction.quoteId,
approveTxData: signedSellApproveTx
})
if (!sellResult.success) throw new Error(sellResult.error || 'Sell failed')
console.log('\nSELL COMPLETED!')
console.log(`TX Hash: ${sellResult.txRes?.txHash}`)
console.log(`ETH Received: ${sellResult.txRes?.received}`)
console.log(`Tokens Spent: ${sellResult.txRes?.spent}`)
console.log(`Explorer: https://basescan.org/tx/${sellResult.txRes?.txHash}`)
console.log('\n' + '='.repeat(80))
console.log('TRADING FLOW COMPLETED SUCCESSFULLY!')
console.log('='.repeat(80))
console.log(`Buy TX: https://basescan.org/tx/${buyResult.txRes?.txHash}`)
console.log(`Sell TX: https://basescan.org/tx/${sellResult.txRes?.txHash}`)
}Advanced: With Custom Options
async function customBuyEVM(): Promise<void> {
const wallet = new ethers.Wallet(TRADING_EVM_PKEY!)
const params = {
token: '0xFb31f85A8367210B2e4Ed2360D2dA9Dc2D2Ccc95',
chain: 'BASE',
trader: wallet.address,
amount: 0.01,
slippage: 800,
priority: 'MEDIUM' as const,
integrator: '0x4Ff5f9bC75C29903b0EABdEc445A6621556feF73',
fee: 150
}
const quote = await getQuote({
token: params.token,
amount: params.amount,
side: 'BUY',
slippage: params.slippage,
trader: params.trader,
chain: params.chain,
priority: params.priority,
integrator: params.integrator,
fee: params.fee
})
if (!quote.success || !quote.transaction) {
throw new Error(quote.error || 'Quote failed')
}
const tx = ethers.Transaction.from(quote.transaction.trade)
const signedTx = await wallet.signTransaction(tx)
const result = await executeTransaction({
txData: signedTx,
network: params.chain,
mev: false,
skipSimulation: true,
quoteId: quote.transaction.quoteId
})
console.log('Trade completed with custom options!')
console.log(`TX Hash: ${result.txRes?.txHash}`)
}Priority Fees
Get and use priority fee information:
async function getPriority(chain: string): Promise<any> {
const response = await makeRequest<any>(`/api/v1/priority?network=${chain}`)
console.log('Priority fees:')
response.priorities.forEach((p: any) => {
console.log(` ${p.level}: ${p.params.maxFeePerGas || p.params.gasPrice}`)
})
return response
}
const priorityInfo = await getPriority('BASE')
const quote = await getQuote({
token: '0x...',
amount: 0.01,
side: 'BUY',
slippage: 500,
trader: wallet.address,
chain: 'BASE',
priority: 'HIGH'
})Token Information
Get token details before trading:
async function getTokenInfo(tokenAddress: string, chain: string): Promise<any> {
const response = await makeRequest<any>(
`/api/v1/token-info?tokenAddress=${tokenAddress}&chain=${chain}`
)
if (response.success) {
console.log('Token Info:')
console.log(` Name: ${response.name || 'N/A'}`)
console.log(` Symbol: ${response.symbol || 'N/A'}`)
console.log(` Decimals: ${response.decimals}`)
console.log(` Price: $${response.priceUsd?.toFixed(6) || 'N/A'}`)
console.log(` Liquidity: $${response.liquidityUsd?.toLocaleString() || 'N/A'}`)
console.log(` Pool: ${response.poolAddress || 'N/A'}`)
}
return response
}Balance Checking
Check native and token balances:
async function getBalance(walletAddress: string, network: string): Promise<any> {
const response = await makeRequest<any>(
`/api/v1/balance?walletAddress=${walletAddress}&network=${network}`
)
if (response.success) {
const formatted = Number(response.balance) / Math.pow(10, response.decimals || 18)
console.log(`Balance: ${formatted.toFixed(6)} ${network === 'SOL' ? 'SOL' : 'ETH'}`)
}
return response
}
async function getTokenBalance(
walletAddress: string,
tokenAddress: string,
network: string
): Promise<any> {
const response = await makeRequest<any>(
`/api/v1/token-balance?walletAddress=${walletAddress}&tokenAddress=${tokenAddress}&network=${network}`
)
if (response.success) {
const formatted = Number(response.balance) / Math.pow(10, response.decimals || 18)
console.log(`Token Balance: ${formatted.toFixed(6)}`)
}
return response
}Error Handling
async function safeTrade() {
try {
await simpleBuyEVM()
} catch (error: any) {
if (error.message.includes('Pool not found')) {
console.error('Token not found or has no liquidity')
} else if (error.message.includes('Insufficient balance')) {
console.error('Not enough ETH in wallet')
} else if (error.message.includes('Slippage')) {
console.error('Price moved too much, increase slippage tolerance')
} else if (error.message.includes('HTTP 401')) {
console.error('Invalid API key')
} else if (error.message.includes('HTTP 429')) {
console.error('Rate limit exceeded')
} else {
console.error('Unexpected error:', error.message)
}
}
}Running the Examples
Create a file evm-trading-test.ts:
import * as dotenv from 'dotenv'
dotenv.config()
async function main() {
console.log('Testing EVM Trading Flow...')
await evmFullTradingFlow()
}
main().catch(console.error)Run it:
export NAOS_API_KEY="your-api-key"
export NAOS_API_DOMAIN="https://api.naos.trade"
export TRADING_EVM_PKEY="your-evm-private-key"
npx ts-node evm-trading-test.tsSupported Networks
Base (8453) - Primary testnet
Ethereum (1)
BSC (56)
Arbitrum (42161)
Avalanche (43114)
Abstract
HyperEVM
Ink
Story
X Layer
Plasma
UniChain
Best Practices
Transaction Signing
Always check for approval transactions: Handle
approveif presentSign both transactions: Trade transaction and approval (if needed)
Order matters: Pass approval as
approveTxDataparameter
Gas Management
Use MEDIUM priority for most trades (good balance of speed/cost)
Use HIGH for time-sensitive trades during volatile markets
Monitor gas costs: Check
txCostUsdin quote stats before executing
Slippage Settings
2-5% (200-500 bps) for liquid tokens
5-10% (500-1000 bps) for less liquid tokens
Higher during volatility: Increase if trades keep failing
Security
Store private keys securely: Use environment variables, never hardcode
Validate quotes: Always check
successfield before executingTest with small amounts: Start with minimal values on testnet
Monitor transactions: Track TX hashes on block explorer
Error Recovery
Implement retries: With exponential backoff for network errors
Check wallet balance: Before attempting trades
Verify token liquidity: Use token-info endpoint first
Handle approval failures: Retry or skip if already approved
Chain Detection
Auto-detect chain from token address:
async function detectChain(tokenAddress: string): Promise<string> {
const response = await makeRequest<any>(
`/api/v1/token-info?tokenAddress=${tokenAddress}`
)
return response.chain || 'BASE'
}
const chain = await detectChain('0xFb31f85A8367210B2e4Ed2360D2dA9Dc2D2Ccc95')
console.log(`Detected chain: ${chain}`)MEV Protection
For large trades on Ethereum mainnet:
const result = await executeTransaction({
txData: signedTx,
network: 'ETH',
mev: true,
skipSimulation: false,
quoteId: quote.transaction.quoteId
})For complete playground with all scenarios, see: src/trading-suite/playground.ts
Last updated

