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
- Authentication — authorize an agent with an owner wallet
- Info API — query books, balances, fees, and risk
- Exchange API — cancel, modify, and manage leverage