Skip to main content

SDK Integration

Directly integrate the @navalabs/sdk package into your TypeScript/Node agent.

Install

npm install @navalabs/sdk

The base package has zero heavy dependencies and only needs fetch (Node 18+).

Subpath Exports

The SDK is split into three entry points so you only pull in what you need:

ImportWhat you getExtra deps
@navalabs/sdkNavaClient + typesNone
@navalabs/sdk/aiVercel AI SDK toolsai, zod
@navalabs/sdk/mcpMCP server + NavaBackend interface@modelcontextprotocol/sdk, zod

Install optional peer dependencies only for the entry points you use:

# For Vercel AI integration
npm install ai zod

# For MCP server
npm install @modelcontextprotocol/sdk zod

Configuration

const nava = new NavaClient({
apiKey: 'nava_live_...', // Required - your Nava API key
walletAddress: '0x...', // Required - your wallet address
baseUrl: '...', // Optional - defaults to https://internal.navalabs.dev/api
chainId: 11155111, // Optional - defaults to 11155111 (Sepolia)
});

Methods

requestVerification(params)

Submit a transaction for arbiter review.

const result = await nava.requestVerification({
userPrompt: 'Swap 1 ETH for USDC on Uniswap',
tx: {
to: '0x...', // Target contract address
value: '0', // Value in Wei
data: '0x...', // Encoded calldata
},
protocol: 'uniswap_v3', // Optional - skips arbiter protocol detection
decodedTx: { // Optional - skips arbiter TX normalization
functionName: 'swapExactTokensForTokens',
tokenIn: { address: '0x...', symbol: 'WETH', decimals: 18 },
tokenOut: { address: '0x...', symbol: 'USDC', decimals: 6 },
amountIn: '1000000000000000000',
amountOut: '3200000000',
},
contextLogs: { ... }, // Optional - additional context for the arbiter
agentSignature: '...', // Optional - agent signature
});

// result.requestHash → '0xabc...' (use this to poll status)
// result.id → transaction UUID
// result.status → 'PENDING' (initial status)
// Throws NavaFetchError on HTTP errors

checkVerificationStatus(requestHash)

Poll for the arbiter’s decision.

const status = await nava.checkVerificationStatus('0xabc...');

// status.status → 'APPROVED' | 'REJECTED' | 'UNDECIDED' | 'PENDING' | 'NONE'
// status.decision → 'APPROVED' | 'REJECTED' | 'UNDECIDED' (when an Orion decision exists)
// status.canExecute → true only when status is APPROVED
// status.confidence → arbiter confidence score (0-1)
// status.analysis → arbiter reasoning
// status.message → human-readable summary
// status.executionTrace → per-node arbiter pipeline results (on rejection)
// status.failedNodes → IDs of nodes that failed (on rejection)
// status.primaryFailure → main node responsible for rejection

Status meanings:

  • APPROVED: Transaction approved and executed (or will execute automatically)
  • REJECTED: Transaction rejected; read analysis and executionTrace for the arbiter’s feedback
  • UNDECIDED: Arbiter completed checks but could not make an approve/reject decision; treat as terminal
  • PENDING: Still under review; poll again in 2-3 seconds
  • NONE: No transaction found for this hash

requestAndAwaitVerification(params, options?)

Submit a transaction and block until the arbiter reaches a terminal status.

const status = await nava.requestAndAwaitVerification(
{
userPrompt: 'Swap 1 ETH for USDC',
tx: { to: '0x...', value: '0', data: '0x...' },
protocol: 'uniswap_v3',
},
{ intervalMs: 2000, maxAttempts: 30 },
);

Throws NavaTimeoutError if maxAttempts is exceeded without a terminal status.

waitForVerification(requestHash, options?)

Poll an already-submitted request until it leaves PENDING.

const status = await nava.waitForVerification('0xabc...', {
intervalMs: 2000, // Polling interval (default: 2000ms)
maxAttempts: 30, // Max polls before timeout (default: 30)
onPoll: (attempt, result) => console.log(`Poll${attempt}:${result.status}`),
});

getWalletAddress()

Returns the wallet address configured for this client instance.