Approval Mechanics

Overview

The Naos Trade API automatically manages token approvals for EVM chains, ensuring seamless trading without manual approval steps. This document explains how approval transactions work for both BUY and SELL operations.

Key Concepts

What is Token Approval?

On EVM chains, before a smart contract (like the NAOS router) can spend your ERC20 tokens, you must first approve it. The API automatically:

  • Detects when approvals are needed

  • Generates approval transactions

  • Executes them in the correct order

Infinite Approval

The API uses infinite approval (type(uint256).max) to minimize gas costs. Once a token is approved, you never need to approve it again for future trades.

BUY Transaction Flow

When buying tokens with native currency (ETH, BNB, etc.):

1. Quote Generation

GET /api/v1/quote?side=BUY&...

Response includes:

  • serializedTx: The buy transaction (unsigned)

  • serializedApproveTx: Post-buy approval transaction (unsigned, if needed)

  • quoteId: Unique identifier

Nonce Assignment:

  • Buy transaction: nonce n

  • Approval transaction: nonce n+1

2. Sign Both Transactions

// Sign buy transaction
const buyTx = ethers.Transaction.from(quote.transaction.serializedTx)
const signedBuyTx = await wallet.signTransaction(buyTx)

// Sign approval transaction (if provided)
if (quote.transaction.serializedApproveTx) {
  const approveTx = ethers.Transaction.from(quote.transaction.serializedApproveTx)
  const signedApproveTx = await wallet.signTransaction(approveTx)
}

3. Execute

POST /api/v1/execute
{
  "txData": "0x...",           // Signed buy transaction
  "approveTxData": "0x...",    // Signed approval transaction
  "network": "BASE",
  "quoteId": "...",
  "mev": false,
  "skipSimulation": false
}

Execution Order:

  1. ✅ Buy transaction is broadcast and confirmed

  2. 📤 API returns success response to you

  3. ✅ Approval transaction is broadcast and confirmed (background)

  4. 🎉 Token is now approved for future sells

Why This Order?

  • You get your tokens immediately

  • Approval happens in the background

  • You can start planning your sell strategy while approval confirms

  • If approval fails, it's logged but doesn't affect your buy

SELL Transaction Flow

When selling tokens for native currency:

1. Quote Generation

GET /api/v1/quote?side=SELL&...

Response includes:

  • serializedApproveTx: Pre-sell approval transaction (unsigned, if needed)

  • serializedTx: The sell transaction (unsigned)

  • quoteId: Unique identifier

Nonce Assignment:

  • Approval transaction: nonce n

  • Sell transaction: nonce n+1

2. Sign Both Transactions

// Sign approval transaction first (if provided)
if (quote.transaction.serializedApproveTx) {
  const approveTx = ethers.Transaction.from(quote.transaction.serializedApproveTx)
  const signedApproveTx = await wallet.signTransaction(approveTx)
}

// Sign sell transaction
const sellTx = ethers.Transaction.from(quote.transaction.serializedTx)
const signedSellTx = await wallet.signTransaction(sellTx)

3. Execute

POST /api/v1/execute
{
  "approveTxData": "0x...",    // Signed approval transaction (if needed)
  "txData": "0x...",           // Signed sell transaction
  "network": "BASE",
  "quoteId": "...",
  "mev": false,
  "skipSimulation": false
}

Execution Order:

  1. ✅ Approval transaction is broadcast and confirmed (if provided)

  2. ❌ If approval fails, entire request fails

  3. ✅ Sell transaction is broadcast and confirmed

  4. 📤 API returns success response

  5. 🎉 You have your native currency

Why This Order?

  • Approval must happen before the sell

  • If approval fails, you don't waste gas on a failing sell

  • Both transactions must succeed for success response

Nonce Management Summary

Transaction Type
First TX (nonce n)
Second TX (nonce n+1)

BUY

Trade (buy tokens)

Approval (approve token)

SELL

Approval (approve token)

Trade (sell tokens)

Critical: The nonces in the quote response are pre-calculated. You must:

  • Sign transactions with the provided nonces

  • Send them in the correct order to the execute endpoint

  • Not modify or reorder the nonces

When Are Approvals Needed?

Approvals ARE Generated For:

  • ✅ First time buying a token (post-buy approval)

  • ✅ First time selling a token (pre-sell approval)

  • ✅ If approval was revoked manually

  • ✅ If current allowance < type(uint256).max

Approvals Are NOT Generated For:

  • ❌ Token already has infinite approval

  • ❌ Solana transactions (no approvals needed on Solana)

  • ❌ Buying with native currency (no approval needed for ETH/BNB/etc.)

Best Practices

1. Always Check for Approval Transactions

const quote = await getQuote(params)

if (quote.transaction.serializedApproveTx) {
  console.log('⚠️  Approval transaction required')
  // Sign and include in execute request
}

2. Don't Skip Approvals

Both transactions are signed client-side and must be included in the execute request:

await executeTransaction({
  txData: signedTradeTx,
  approveTxData: signedApproveTx,  // Don't forget this!
  // ...
})

3. Monitor Approval Status

For BUY transactions, the approval happens after you receive the success response:

// You get success for the buy
const buyResult = await execute(...)
console.log('Buy complete:', buyResult.txRes.txHash)

// Approval is happening in the background
// Check blockchain explorer for approval TX
// It will use nonce n+1

4. Handle Errors Appropriately

try {
  const result = await execute({...})
  
  if (result.success) {
    console.log('Trade executed:', result.txRes.txHash)
  } else {
    console.error('Trade failed:', result.error)
    // For SELL: Could be approval failure
    // For BUY: Could be trade failure (approval not attempted)
  }
} catch (error) {
  console.error('Request failed:', error)
}

Solana Differences

Solana works differently and doesn't require approvals:

  • ✅ No approval transactions ever generated

  • serializedApproveTx is always undefined

  • ✅ Single transaction for both BUY and SELL

  • ✅ Simpler flow, fewer steps

Example: Complete BUY Flow

// 1. Get quote
const quote = await fetch('https://api.naos.trade/api/v1/quote?' + new URLSearchParams({
  tokenAddress: '0xToken...',
  amount: '0.1',
  side: 'BUY',
  slippageBps: '500',
  trader: wallet.address,
  chain: 'BASE'
}))

const quoteData = await quote.json()

// 2. Sign trade transaction
const buyTx = ethers.Transaction.from(quoteData.transaction.serializedTx)
const signedBuyTx = await wallet.signTransaction(buyTx)

// 3. Sign approval transaction if present
let signedApproveTx
if (quoteData.transaction.serializedApproveTx) {
  const approveTx = ethers.Transaction.from(quoteData.transaction.serializedApproveTx)
  signedApproveTx = await wallet.signTransaction(approveTx)
}

// 4. Execute
const result = await fetch('https://api.naos.trade/api/v1/execute', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    txData: signedBuyTx,
    approveTxData: signedApproveTx,
    network: 'BASE',
    mev: false,
    skipSimulation: false,
    quoteId: quoteData.transaction.quoteId
  })
})

const executeData = await result.json()

if (executeData.success) {
  console.log('✅ Buy successful!')
  console.log('TX:', executeData.txRes.txHash)
  console.log('Tokens received:', executeData.txRes.received)
  console.log('(Approval transaction broadcasting in background)')
}

Troubleshooting

"Transaction simulation failed"

  • Usually means approval is needed but not provided

  • Check if serializedApproveTx was in the quote response

  • Ensure you signed and included the approval transaction

"Nonce too low" or "Nonce already used"

  • Don't modify the nonces from the quote response

  • Don't reuse signed transactions

  • Get a fresh quote if you need to retry

"Quote not found - invalid requestId"

  • Quote may have expired (get a new one)

  • Ensure you're using the correct quoteId

Approval transaction not found on explorer

  • For BUY: Check transactions with nonce n+1 from your address

  • It may take a few seconds to appear

  • Check API logs for approval execution status

Summary

The API handles all complexity:

  • Detects when approvals are needed

  • Generates correctly ordered transactions

  • Manages nonces automatically

  • Executes in the optimal order

🎯 You just need to:

  • Sign all provided transactions

  • Send them to the execute endpoint

  • Handle the response

🚀 Benefits:

  • Seamless trading experience

  • Optimized gas usage

  • No manual approval steps

  • Works across all supported chains

Last updated