React Native 设置
ONE SDK 提供了 React Native 专用入口点:
import { ... } from "@one_deploy/sdk/react-native";
此入口点仅导出为移动端设计的组件和工具:
- AI 交易组件(链选择器、等级选择器、周期选择器、交易对选择器)
- 外汇组件(资金池卡片、资金分配、控制台视图、交易对选择器、交易历史)
createCachedEngineClient-- 持久化、支持离线的 engine 客户端createDeepLinkHandler-- 通用 / 深度链接路由BiometricConfig-- 指纹 / Face ID 验证
注意
仅限 Web 的组件,如 ConnectButton、PayWidget、OnrampWidget、OfframpWidget、SwapWidget、NftGallery 和 BalanceDisplay,不能从 react-native 入口点导入。请使用 hooks 和 OneEngineClient 为这些功能构建自定义移动端 UI。
1. 安装依赖
npm install @one_deploy/sdk@1.1.0 react-native @react-native-async-storage/async-storage
缓存 engine 客户端的 StorageAdapter 需要 @react-native-async-storage/async-storage。
如需生物识别支持,还需安装:
npm install react-native-biometrics
2. 创建缓存 Engine 客户端
在移动端,网络可能不稳定。createCachedEngineClient 使用 AsyncStorage(或任何实现了 StorageAdapter 接口的存储)支持的离线缓存来封装 OneEngineClient。
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 StorageAdapter {
getItem(key: string): Promise<string | null>;
setItem(key: string, value: string): Promise<void>;
removeItem(key: string): Promise<void>;
}
任何满足此接口的键值存储都可以使用 -- AsyncStorage、MMKV、expo-secure-store 等。
3. 使用 OneProvider 包裹应用
即使在 React Native 中,你仍然使用主 providers 路径中的 OneProvider。它共享 hooks 所依赖的相同上下文。
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>
);
}
4. 深度链接处理
createDeepLinkHandler 将传入的深度链接(例如 myapp://trading/order/123)映射到回调函数。这对于推送通知点击、WalletConnect 重定向和通用链接非常有用。
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);
},
});
将其接入你的根组件:
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. 生物识别配置
在敏感操作(创建订单、提款)前要求指纹或 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,
};
将其传入 SDK 初始化:
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 类型
interface BiometricConfig {
enabled: boolean;
promptMessage?: string;
cancelButtonText?: string;
protectedActions?: Array<
| "createOrder"
| "earlyWithdrawal"
| "signOut"
| "transferCrypto"
| "createForexPosition"
>;
allowDeviceCredentials?: boolean;
}
6. 使用 AI 交易组件
AI 交易组件从 React Native 入口点导入:
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. 使用外汇组件
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>
);
}