Skip to main content

React Native Setup

The ONE SDK has a dedicated entry point for React Native:

import { ... } from "@one_deploy/sdk/react-native";

This entry point exports only the components and utilities designed for mobile:

  • AI Trading components (chain selector, tier selector, cycle selector, pair selector)
  • Forex components (pool card, capital split, console view, pair selector, trade history)
  • createCachedEngineClient -- persistent, offline-capable engine client
  • createDeepLinkHandler -- universal / deep link routing
  • BiometricConfig -- fingerprint / Face ID gating
warning

Web-only widgets such as ConnectButton, PayWidget, OnrampWidget, OfframpWidget, SwapWidget, NftGallery, and BalanceDisplay are not available from the react-native entry point. Use the hooks and OneEngineClient to build custom mobile UIs for those features.

1. Install Dependencies

npm install @one_deploy/sdk@1.1.0 react-native @react-native-async-storage/async-storage

@react-native-async-storage/async-storage is required for the cached engine client's StorageAdapter.

For biometric support, also install:

npm install react-native-biometrics

2. Create the Cached Engine Client

On mobile, network can be unreliable. createCachedEngineClient wraps OneEngineClient with an offline cache backed by AsyncStorage (or any storage that implements the StorageAdapter interface).

src/services/engine.ts
import AsyncStorage from "@react-native-async-storage/async-storage";
import {
createCachedEngineClient,
type StorageAdapter,
} from "@one_deploy/sdk/react-native";

const storage: StorageAdapter = {
getItem: (key: string) => AsyncStorage.getItem(key),
setItem: (key: string, value: string) => AsyncStorage.setItem(key, value),
removeItem: (key: string) => AsyncStorage.removeItem(key),
};

export const engine = createCachedEngineClient({
baseUrl: "https://engine.one23.io",
clientId: "your_client_id",
storage,
cacheTTL: 5 * 60 * 1000, // 5 minutes (default)
maxCacheSize: 50, // max cached responses (default: 100)
});

StorageAdapter Interface

interface StorageAdapter {
getItem(key: string): Promise<string | null>;
setItem(key: string, value: string): Promise<void>;
removeItem(key: string): Promise<void>;
}

Any key-value store that satisfies this interface works -- AsyncStorage, MMKV, expo-secure-store, etc.

3. Wrap Your App with OneProvider

Even in React Native you still use OneProvider from the main providers path. It shares the same context that hooks depend on.

App.tsx
import React from "react";
import { OneProvider } from "@one_deploy/sdk/providers";
import { initOneSDK } from "@one_deploy/sdk";
import { engine } from "./src/services/engine";
import HomeScreen from "./src/screens/HomeScreen";

const oneSDK = initOneSDK({
clientId: "your_client_id",
engineUrl: "https://engine.one23.io",
engineClient: engine, // inject the cached client
});

export default function App() {
return (
<OneProvider sdk={oneSDK}>
<HomeScreen />
</OneProvider>
);
}

createDeepLinkHandler maps incoming deep links (e.g. myapp://trading/order/123) to callback functions. This is useful for push-notification taps, wallet-connect redirects, and universal links.

src/services/deepLinks.ts
import { createDeepLinkHandler } from "@one_deploy/sdk/react-native";

export const deepLinkHandler = createDeepLinkHandler({
// Map URL path patterns to handlers
routes: {
"trading/order/:orderId": ({ orderId }) => {
// Navigate to order detail screen
console.log("Open order", orderId);
},
"forex/pool/:poolId": ({ poolId }) => {
console.log("Open forex pool", poolId);
},
"wallet/receive": () => {
console.log("Open receive screen");
},
},
// Called when no route matches
fallback: (url) => {
console.warn("Unhandled deep link:", url);
},
});

Wire it into your root component:

App.tsx
import { useEffect } from "react";
import { Linking } from "react-native";
import { deepLinkHandler } from "./src/services/deepLinks";

export default function App() {
useEffect(() => {
// Handle link that launched the app
Linking.getInitialURL().then((url) => {
if (url) deepLinkHandler.handle(url);
});

// Handle links while the app is running
const subscription = Linking.addEventListener("url", ({ url }) => {
deepLinkHandler.handle(url);
});

return () => subscription.remove();
}, []);

return (
<OneProvider sdk={oneSDK}>
{/* ... */}
</OneProvider>
);
}

5. Biometric Config

Gate sensitive actions (order creation, withdrawal) behind fingerprint or Face ID.

src/services/biometrics.ts
import { BiometricConfig } from "@one_deploy/sdk/react-native";

export const biometricConfig: BiometricConfig = {
enabled: true,
promptMessage: "Authenticate to confirm this action",
cancelButtonText: "Cancel",
// Which actions require biometric confirmation
protectedActions: [
"createOrder",
"earlyWithdrawal",
"signOut",
],
// Fallback to device passcode if biometrics unavailable
allowDeviceCredentials: true,
};

Pass it into your SDK initialization:

App.tsx
import { initOneSDK } from "@one_deploy/sdk";
import { biometricConfig } from "./src/services/biometrics";

const oneSDK = initOneSDK({
clientId: "your_client_id",
engineUrl: "https://engine.one23.io",
biometrics: biometricConfig,
});

BiometricConfig Type

interface BiometricConfig {
enabled: boolean;
promptMessage?: string;
cancelButtonText?: string;
protectedActions?: Array<
| "createOrder"
| "earlyWithdrawal"
| "signOut"
| "transferCrypto"
| "createForexPosition"
>;
allowDeviceCredentials?: boolean;
}

6. Using AI Trading Components

AI trading components are imported from the React Native entry point:

src/screens/TradingScreen.tsx
import {
ChainSelector,
TierSelector,
CycleSelector,
PairSelector,
} from "@one_deploy/sdk/react-native";
import { useAIStrategies, useAITrading } from "@one_deploy/sdk/hooks";

export default function TradingScreen() {
const { strategies, isLoading } = useAIStrategies();
const { createOrder } = useAITrading();

const [chainId, setChainId] = React.useState<number>(137);
const [tier, setTier] = React.useState<string>("conservative");
const [cycle, setCycle] = React.useState<number>(30);
const [pair, setPair] = React.useState<string>("ETH/USDC");

if (isLoading) return <ActivityIndicator />;

return (
<ScrollView>
<ChainSelector value={chainId} onChange={setChainId} />
<TierSelector value={tier} onChange={setTier} strategies={strategies} />
<CycleSelector value={cycle} onChange={setCycle} />
<PairSelector value={pair} onChange={setPair} chainId={chainId} />

<Button
title="Create Order"
onPress={() =>
createOrder({ chainId, tier, cycle, pair, amount: "100" })
}
/>
</ScrollView>
);
}

7. Using Forex Components

src/screens/ForexScreen.tsx
import {
ForexPoolCard,
ForexCapitalSplit,
ForexConsoleView,
ForexPairSelector,
ForexTradeHistory,
} from "@one_deploy/sdk/react-native";
import { useForexPools, useForexTrading } from "@one_deploy/sdk/hooks";

export default function ForexScreen() {
const { pools, isLoading } = useForexPools();
const { createPosition } = useForexTrading();
const [selectedPool, setSelectedPool] = React.useState<string | null>(null);

if (isLoading) return <ActivityIndicator />;

return (
<ScrollView>
{pools.map((pool) => (
<ForexPoolCard
key={pool.id}
pool={pool}
onPress={() => setSelectedPool(pool.id)}
/>
))}

{selectedPool && (
<>
<ForexCapitalSplit poolId={selectedPool} />
<ForexPairSelector
poolId={selectedPool}
onSelect={(pair) => console.log("Selected pair:", pair)}
/>
<ForexConsoleView poolId={selectedPool} />
<ForexTradeHistory poolId={selectedPool} />
</>
)}
</ScrollView>
);
}

Next Steps