Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Quickstart

This guide uses an already authorized agent key to discover a perpetual market, place a limit order on testnet, and confirm it through the Info API.

Prerequisites

  • Node.js 18 or later
  • The TypeScript SDK installed
  • A funded testnet account
  • An agent key authorized by the account owner

If you have not authorized an agent yet, follow Authentication. You can also use Try Testnet to understand the complete owner → agent → order flow.

1. Create the client

import { TxFlow } from 'txflow-typescript-sdk'
 
const sdk = new TxFlow('testnet')

The same instance exposes both sdk.info and sdk.exchange.

2. Discover the asset index

Exchange actions use a numeric asset index. Resolve it from perpMeta instead of hard-coding it:

const meta = await sdk.info.perpMeta()
const market = meta.universe.find(({ name }) => name === 'BTC-USDC')
 
if (!market) {
  throw new Error('BTC-USDC is not available')
}
 
console.log(market.index, market.priceTick, market.szDecimals)

Info methods generally accept an instrument id as a string; exchange methods accept the same index as a number.

3. Configure the agent signer

const agentPrivateKey = process.env.TXFLOW_AGENT_PRIVATE_KEY
 
if (!agentPrivateKey?.startsWith('0x')) {
  throw new Error('TXFLOW_AGENT_PRIVATE_KEY is missing')
}
 
sdk.exchange.setPrivateKey(agentPrivateKey as `0x${string}`)

Calling an exchange method before setting a signer throws AuthenticationError.

4. Place a limit order

Prices and sizes are decimal strings so JavaScript never rounds trading values:

const result = await sdk.exchange.placeLimitOrder({
  asset: market.index,
  side: 'buy',
  px: '60000',
  sz: '0.001',
  tif: 'gtc',
})
 
if (result.status !== 'ok') {
  const message =
    typeof result.response === 'string'
      ? result.response
      : 'Order was rejected'
 
  throw new Error(message)
}

Every exchange method signs and sends the request in one step. The SDK creates the nonce, signature, and request envelope automatically.

5. Confirm the order

The order response reports one status per submitted order but does not include the exchange-assigned order id. Query the owner's open orders to resolve it:

const ownerAddress = process.env.TXFLOW_OWNER_ADDRESS
 
if (!ownerAddress) {
  throw new Error('TXFLOW_OWNER_ADDRESS is missing')
}
 
const openOrders = await sdk.info.frontendOpenOrders({
  user: ownerAddress,
})
 
console.log(openOrders)

Complete example

import { TxFlow } from 'txflow-typescript-sdk'
 
const agentPrivateKey = process.env.TXFLOW_AGENT_PRIVATE_KEY
const ownerAddress = process.env.TXFLOW_OWNER_ADDRESS
 
if (!agentPrivateKey?.startsWith('0x') || !ownerAddress) {
  throw new Error('Missing testnet credentials')
}
 
const sdk = new TxFlow('testnet')
const meta = await sdk.info.perpMeta()
const market = meta.universe.find(({ name }) => name === 'BTC-USDC')
 
if (!market) {
  throw new Error('BTC-USDC is not available')
}
 
sdk.exchange.setPrivateKey(agentPrivateKey as `0x${string}`)
 
const result = await sdk.exchange.placeLimitOrder({
  asset: market.index,
  side: 'buy',
  px: '60000',
  sz: '0.001',
  tif: 'gtc',
})
 
if (result.status !== 'ok') {
  throw new Error(
    typeof result.response === 'string'
      ? result.response
      : 'Order was rejected',
  )
}
 
const openOrders = await sdk.info.frontendOpenOrders({
  user: ownerAddress,
})
 
console.log(openOrders)

Next steps