Skip to main content

OnePairSelector

The OnePairSelector component renders a selectable list of trading pairs, filtered by strategy and chain. Each pair is displayed with its icon (via PAIR_ICONS), symbol, and order size constraints.

React Native Only

OnePairSelector is exported from the React Native entry point of @one_deploy/sdk. It is not available on web.

Quick Start

import { useState } from 'react';
import { OnePairSelector } from '@one_deploy/sdk';
import type { TradingPair } from '@one_deploy/sdk';

function PairStep() {
const [selectedPair, setSelectedPair] = useState<TradingPair | null>(null);

return (
<OnePairSelector
strategyId="strat_abc123"
chainId={8453}
onSelect={(pair) => {
setSelectedPair(pair);
console.log('Selected:', pair.symbol);
}}
/>
);
}

OnePairSelectorProps

interface OnePairSelectorProps {
/** Strategy ID to filter pairs by the strategy's supported pairs. */
strategyId: string;

/** Chain ID to filter pairs available on this network. */
chainId: number;

/** Currently selected pair symbol. */
selectedPair?: string;

/** Callback fired when the user selects a pair. */
onSelect: (pair: TradingPair) => void;

/** Whether to show pair icons from PAIR_ICONS. Defaults to true. */
showIcons?: boolean;

/** Whether to show inactive pairs (greyed out, not selectable). Defaults to false. */
showInactive?: boolean;

/** Additional style applied to the container. */
style?: ViewStyle;

/** Style applied to each pair item. */
itemStyle?: ViewStyle;

/** Test ID for testing frameworks. */
testID?: string;
}

Props Table

PropTypeRequiredDefaultDescription
strategyIdstringYes--Strategy ID to filter supported pairs
chainIdnumberYes--Chain ID to filter chain-specific pairs
selectedPairstringNo--Currently selected pair symbol
onSelect(pair: TradingPair) => voidYes--Selection callback
showIconsbooleanNotrueShow icons from PAIR_ICONS
showInactivebooleanNofalseShow inactive (greyed) pairs
styleViewStyleNo--Container style
itemStyleViewStyleNo--Individual item style
testIDstringNo--Test ID

PAIR_ICONS Constant

The PAIR_ICONS constant maps asset symbols to their icon URIs.

import { PAIR_ICONS } from '@one_deploy/sdk';

// PAIR_ICONS: Record<string, string>
console.log(PAIR_ICONS['BTC']);
// 'https://assets.one23.io/icons/btc.png'

console.log(PAIR_ICONS['ETH']);
// 'https://assets.one23.io/icons/eth.png'

console.log(PAIR_ICONS['USDT']);
// 'https://assets.one23.io/icons/usdt.png'

console.log(PAIR_ICONS['SOL']);
// 'https://assets.one23.io/icons/sol.png'

Available icons:

AssetKeyDescription
BitcoinBTCBitcoin icon
EthereumETHEthereum icon
TetherUSDTTether USD icon
USD CoinUSDCUSDC icon
SolanaSOLSolana icon
BNBBNBBNB icon
AvalancheAVAXAvalanche icon
PolygonMATICPolygon icon
ChainlinkLINKChainlink icon
UniswapUNIUniswap icon

TradingPair Type

interface TradingPair {
/** Unique pair identifier, e.g. "BTC_USDT". */
symbol: string;

/** Base asset symbol, e.g. "BTC". */
baseAsset: string;

/** Quote asset symbol, e.g. "USDT". */
quoteAsset: string;

/** Chain ID where this pair is traded. */
chainId: number;

/** Whether the pair is currently available for new orders. */
isActive: boolean;

/** Minimum order size in quote currency. */
minOrderSize: number;

/** Maximum order size in quote currency, or null for unlimited. */
maxOrderSize: number | null;

/** Price precision (decimal places). */
pricePrecision: number;

/** Quantity precision (decimal places). */
quantityPrecision: number;
}

Usage Examples

With Strategy and Chain Filtering

import { useState } from 'react';
import { View, Text } from 'react-native';
import { OnePairSelector } from '@one_deploy/sdk';
import type { TradingPair } from '@one_deploy/sdk';

function PairSelection({
strategyId,
chainId,
}: {
strategyId: string;
chainId: number;
}) {
const [selectedPair, setSelectedPair] = useState<TradingPair | null>(null);

return (
<View>
<Text style={styles.heading}>Select Trading Pair</Text>

<OnePairSelector
strategyId={strategyId}
chainId={chainId}
selectedPair={selectedPair?.symbol}
showIcons={true}
onSelect={(pair) => setSelectedPair(pair)}
/>

{selectedPair && (
<View style={styles.info}>
<Text>Pair: {selectedPair.baseAsset}/{selectedPair.quoteAsset}</Text>
<Text>
Order range: {selectedPair.minOrderSize}
{selectedPair.maxOrderSize ? ` - ${selectedPair.maxOrderSize}` : '+'}
{' '}{selectedPair.quoteAsset}
</Text>
</View>
)}
</View>
);
}

Custom Styling

import { OnePairSelector } from '@one_deploy/sdk';

function StyledPairSelector() {
return (
<OnePairSelector
strategyId="strat_abc123"
chainId={8453}
showIcons={true}
showInactive={false}
style={{
backgroundColor: '#0f0f1a',
borderRadius: 16,
padding: 12,
}}
itemStyle={{
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 14,
paddingHorizontal: 16,
borderRadius: 10,
marginBottom: 6,
backgroundColor: '#1a1a2e',
}}
onSelect={(pair) => console.log('Selected:', pair.symbol)}
/>
);
}

Including Inactive Pairs

import { OnePairSelector } from '@one_deploy/sdk';

function PairSelectorWithInactive() {
return (
<OnePairSelector
strategyId="strat_abc123"
chainId={8453}
showInactive={true}
onSelect={(pair) => {
// Only active pairs fire onSelect
console.log('Selected active pair:', pair.symbol);
}}
/>
);
}

Building a Custom Pair Selector with PAIR_ICONS

If you need complete control over the pair list rendering, use the API directly with PAIR_ICONS.

import { useState, useEffect } from 'react';
import { View, Text, Image, Pressable, FlatList } from 'react-native';
import { OneEngineClient, PAIR_ICONS } from '@one_deploy/sdk';
import type { TradingPair } from '@one_deploy/sdk';

function CustomPairSelector({
engine,
onSelect,
}: {
engine: OneEngineClient;
onSelect: (pair: TradingPair) => void;
}) {
const [pairs, setPairs] = useState<TradingPair[]>([]);
const [selected, setSelected] = useState<string | null>(null);

useEffect(() => {
engine.getTradingPairs().then((allPairs) => {
setPairs(allPairs.filter((p) => p.isActive));
});
}, []);

return (
<FlatList
data={pairs}
keyExtractor={(item) => item.symbol}
renderItem={({ item }) => (
<Pressable
onPress={() => {
setSelected(item.symbol);
onSelect(item);
}}
style={[
styles.pairRow,
selected === item.symbol && styles.selectedRow,
]}
>
<View style={styles.iconContainer}>
<Image
source={{ uri: PAIR_ICONS[item.baseAsset] }}
style={styles.icon}
/>
<Image
source={{ uri: PAIR_ICONS[item.quoteAsset] }}
style={[styles.icon, styles.quoteIcon]}
/>
</View>
<View style={styles.pairInfo}>
<Text style={styles.pairSymbol}>
{item.baseAsset}/{item.quoteAsset}
</Text>
<Text style={styles.pairDetail}>
Min: {item.minOrderSize} {item.quoteAsset}
</Text>
</View>
</Pressable>
)}
/>
);
}

const styles = {
pairRow: {
flexDirection: 'row' as const,
alignItems: 'center' as const,
padding: 12,
borderBottomWidth: 1,
borderBottomColor: '#222',
},
selectedRow: {
backgroundColor: '#1a1a3e',
},
iconContainer: {
flexDirection: 'row' as const,
width: 48,
},
icon: {
width: 28,
height: 28,
borderRadius: 14,
},
quoteIcon: {
marginLeft: -10,
},
pairInfo: {
marginLeft: 12,
},
pairSymbol: {
color: '#fff',
fontWeight: '600' as const,
fontSize: 15,
},
pairDetail: {
color: '#888',
fontSize: 12,
marginTop: 2,
},
};

Controlled State with Navigation

import { useState } from 'react';
import { View, Text, Pressable } from 'react-native';
import { OnePairSelector } from '@one_deploy/sdk';
import type { TradingPair } from '@one_deploy/sdk';

function PairStepWithNav({
strategyId,
chainId,
onBack,
onNext,
}: {
strategyId: string;
chainId: number;
onBack: () => void;
onNext: (pair: TradingPair) => void;
}) {
const [selectedPair, setSelectedPair] = useState<TradingPair | null>(null);

return (
<View style={styles.container}>
<Text style={styles.heading}>Select Trading Pair</Text>
<Text style={styles.subtext}>
Choose the asset pair the AI agent will trade.
</Text>

<OnePairSelector
strategyId={strategyId}
chainId={chainId}
selectedPair={selectedPair?.symbol}
showIcons={true}
onSelect={setSelectedPair}
/>

<View style={styles.navRow}>
<Pressable onPress={onBack}>
<Text>Back</Text>
</Pressable>

<Pressable
onPress={() => selectedPair && onNext(selectedPair)}
disabled={!selectedPair}
>
<Text style={selectedPair ? styles.nextActive : styles.nextDisabled}>
Next
</Text>
</Pressable>
</View>
</View>
);
}

Next Steps