关于 orderly-sdk-wallet-connection
orderly-sdk-wallet-connection 是面向 Orderly Network DEX 开发者的钱包接入指南,介绍 EVM 与 Solana 钱包的配置、连接及账户状态管理。指南也说明标准连接器与 Privy 社交登录方案的选择和配置。
主要功能
- 01配置 EVM 与 Solana 钱包
- 02标准连接器和 Privy 方案
- 03连接状态与账户状态管理
- 04切换和筛选支持的链
- 05钱包连接界面与访问保护
适用场景
- 01为新 DEX 配置钱包接入
- 02支持多种钱包与链切换
- 03按账户状态控制交易功能
- 04为应用添加社交登录
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ orderlynetwork/ skills --skill orderly-sdk-wallet-connection安装后在 Claude Code 中输入/orderly-sdk-wallet-connection确认已加载。
详细介绍
Orderly Network:SDK 钱包连接
在 Orderly Network DEX 应用中集成钱包连接的全面指南,支持 EVM(Ethereum、Arbitrum、Optimism、Base 等)和 Solana 钱包,并提供可选的 Privy(社交登录)路径。
适用场景
- 为新的 DEX 设置钱包连接
- 支持多种钱包类型(MetaMask、Phantom 等)
- 实现链切换
- 在标准连接器和 Privy 之间进行选择
前提条件
- 已安装 Orderly SDK 软件包(请参阅
orderly-sdk-install-dependency) - 已配置 Provider(请参阅
orderly-sdk-dex-architecture) - 已安装钱包软件包
概述
Orderly Network 支持全链交易——用户可以连接来自多个生态系统的钱包:
- EVM 链:Arbitrum、Optimism、Base、Ethereum、BSC 等
- Solana:Mainnet 和 Devnet
SDK 提供两种连接器软件包,请选择其中一种:
| 软件包 | 适用场景 |
|---|---|
@orderly.network/wallet-connector | 默认选项——Web3-Onboard(EVM)+ Solana 钱包适配器 |
@orderly.network/wallet-connector-privy | 需要社交登录(Google、X、电子邮件、通行密钥)/嵌入式钱包时使用 |
Provider 在运行时选择:如果配置了 Privy 应用 ID,则使用 Privy 连接器;否则使用标准连接器。
evmInitial和solanaInitial都是已配置的属性——它们携带钱包网络和钱包列表。实际的 DEX 不会省略它们。参考模板始终会传入这两个属性(通过配置标志分别禁用其中一方)。
必需依赖项
# Connector package
npm install @orderly.network/wallet-connector
# EVM wallets
npm install @web3-onboard/injected-wallets @web3-onboard/walletconnect \
@binance/w3w-blocknative-connector wagmi
# Solana wallets
npm install @solana/wallet-adapter-base @solana/wallet-adapter-wallets \
@solana-mobile/wallet-adapter-mobile
| 软件包 | 用途 |
|---|---|
@web3-onboard/injected-wallets | MetaMask、Rabby、Coinbase 等 |
@web3-onboard/walletconnect | WalletConnect(移动端 / 多平台) |
@binance/w3w-blocknative-connector | Binance Web3 Wallet |
wagmi | EVM 连接器(injected、walletConnect) |
@solana/wallet-adapter-base | Solana 适配器基础包 + 网络枚举 |
@solana/wallet-adapter-wallets | Phantom、Solflare、Ledger 适配器 |
@solana-mobile/wallet-adapter-mobile | Solana Mobile Wallet Adapter |
标准连接器
1. 钱包连接器 Provider
使用 WalletConnectorProvider 包装 OrderlyAppProvider,并传入两种初始配置:
// app/components/orderlyProvider/walletConnector.tsx
import { ReactNode } from 'react';
import { WalletConnectorProvider } from '@orderly.network/wallet-connector';
import { WalletAdapterNetwork } from '@solana/wallet-adapter-base';
import type { NetworkId } from '@orderly.network/types';
import { getEvmInitialConfig, getSolanaWallets } from '@/utils/walletConfig';
const WalletConnector = ({
children,
networkId,
disableEvm,
disableSolana,
projectId,
appName,
}: {
children: ReactNode;
networkId: NetworkId;
disableEvm?: boolean; // from your config
disableSolana?: boolean; // from your config
projectId?: string; // WalletConnect project id (see below)
appName?: string;
}) => (
<WalletConnectorProvider
evmInitial={disableEvm ? undefined : getEvmInitialConfig(projectId, appName)}
solanaInitial={
disableSolana
? undefined
: {
network:
networkId === 'mainnet' ? WalletAdapterNetwork.Mainnet : WalletAdapterNetwork.Devnet,
wallets: getSolanaWallets(networkId),
}
}
>
{children}
</WalletConnectorProvider>
);
export default WalletConnector;
WalletConnectorProvider(Solana 网络)和OrderlyAppProvider中的networkId必须保持一致。参考 Provider 会通过同一个getNetworkId()获取这两个值。
2. EVM 钱包配置
模板分两个层级构建 EVM 连接器:getEvmConnectors()(wagmi CreateConnectorFn[],用于 Privy 路径)和 getOnboardEvmWallets()(Web3-Onboard 模块,由 getEvmInitialConfig() 用于标准连接器)。
// app/utils/walletConfig.ts (excerpt)
import { CreateConnectorFn } from 'wagmi';
import { injected, walletConnect } from 'wagmi/connectors';
import injectedOnboard from '@web3-onboard/injected-wallets';
import walletConnectOnboard from '@web3-onboard/walletconnect';
import binanceWallet from '@binance/w3w-blocknative-connector';
// wagmi connectors (Privy path)
export const getEvmConnectors = (
projectId?: string,
appName = 'Orderly App'
): CreateConnectorFn[] => {
const connectors: CreateConnectorFn[] = [injected()];
if (projectId && typeof window !== 'undefined') {
connectors.push(
walletConnect({
projectId,
showQrModal: true,
metadata: {
name: appName,
description: appName,
url: window.location.origin,
icons: [`${window.location.origin}/favicon.webp`],
},
})
);
}
return connectors;
};
// Web3-Onboard modules (standard connector path)
export const getOnboardEvmWallets = (projectId?: string) => {
if (!projectId || typeof window === 'undefined') return [];
return [
injectedOnboard(),
binanceWallet({ options: { lng: 'en' } }),
walletConnectOnboard({
projectId,
qrModalOptions: { themeMode: 'dark' },
dappUrl: window.location.origin,
}),
];
};
// evmInitial shape: { options: { wallets, appMetadata } } — undefined if no projectId
export const getEvmInitialConfig = (projectId?: string, appName = 'Orderly App') => {
const wallets = getOnboardEvmWallets(projectId);
return wallets.length > 0
? { options: { wallets, appMetadata: { name: appName, description: appName } } }
: undefined;
};
请按照你偏好的方式获取 WalletConnect 项目 ID(参考模板从
.env中读取import.meta.env.VITE_WALLETCONNECT_PROJECT_ID)。请访问 https://cloud.walletconnect.com 获取项目 ID。没有该 ID 时,只能使用浏览器注入的钱包。
3. Solana 钱包配置
// app/utils/walletConfig.ts (excerpt)
import {
WalletAdapterNetwork,
WalletError,
WalletNotReadyError,
Adapter,
} from '@solana/wallet-adapter-base';
import {
LedgerWalletAdapter,
PhantomWalletAdapter,
SolflareWalletAdapter,
} from '@solana/wallet-adapter-wallets';
import {
createDefaultAddressSelector,
createDefaultAuthorizationResultCache,
SolanaMobileWalletAdapter,
} from '@solana-mobile/wallet-adapter-mobile';
import type { NetworkId } from '@orderly.network/types';
export const getSolanaWallets = (networkId: NetworkId) => {
if (typeof window === 'undefined') return [];
return [
new PhantomWalletAdapter(),
new SolflareWalletAdapter(),
new LedgerWalletAdapter(),
new SolanaMobileWalletAdapter({
addressSelector: createDefaultAddressSelector(),
appIdentity: { uri: `${location.protocol}//${location.host}` },
authorizationResultCache: createDefaultAuthorizationResultCache(),
chain: networkId === 'mainnet' ? WalletAdapterNetwork.Mainnet : WalletAdapterNetwork.Devnet,
onWalletNotFound: () => Promise.reject(new WalletNotReadyError('wallet not ready')),
}),
];
};
export const getSolanaConfig = (networkId: NetworkId) => ({
wallets: getSolanaWallets(networkId),
onError: (error: WalletError, adapter?: Adapter) => {
console.log(error, adapter);
},
});
Solana Mobile / Saga 设备支持需要使用
SolanaMobileWalletAdapter(来自@solana-mobile/wallet-adapter-mobile)。省略它意味着 Solana 移动端用户无法连接。
访问钱包状态
使用 useWalletConnector() Hook。其返回值是扁平结构(connect、disconnect、setChain 等都位于顶层),而不是嵌套在 wallet 下。
import { useWalletConnector } from '@orderly.network/hooks';
function WalletStatus() {
const {
connect, // (options?) => Promise<WalletState[]>
disconnect, // (options) => Promise<any[]>
connecting, // boolean — connection in progress
wallet, // WalletState | null
connectedChain, // ConnectedChain | null
setChain, // ({ chainId }) => Promise<any>
chains, // available chains
settingChain, // boolean
namespace, // "evm" | "solana" | null
} = useWalletConnector();
return (
<div>
{wallet ? (
<>
<p>Connected: {wallet.accounts[0].address}</p>
<p>Chain: {connectedChain?.id}</p>
<button onClick={() => disconnect({})}>Disconnect</button>
</>
) : (
<button disabled={connecting} onClick={() => connect({ chainId: 42161 })}>
{connecting ? 'Connecting…' : 'Connect Wallet'}
</button>
)}
</div>
);
}
切换链
const { setChain } = useWalletConnector();
await setChain({ chainId: 10 }); // Optimism
await setChain({ chainId: 8453 }); // Base
账户状态机
钱包连接后,用户必须完成 Orderly 账户设置(创建账户密钥、启用交易)。使用 useAccount() 跟踪状态,其 state.status 是一个 AccountStatusEnum。
NotConnected(0) → Connected(1) → NotSignedIn(2) → SignedIn(3) → EnableTrading(5)
│
└→ DisabledTrading(4)
EnableTradingWithoutConnected(-1) — trading enabled without an explicit wallet
状态(AccountStatusEnum) | 值 | 含义 |
|---|---|---|
EnableTradingWithoutConnected | -1 | 钱包未连接,但交易已启用 |
NotConnected | 0 | 未连接钱包 |
Connected | 1 | 钱包已连接,但尚无 Orderly 账户 |
NotSignedIn | 2 | 账户已创建,但尚未登录 |
SignedIn | 3 | 已登录 Orderly |
DisabledTrading | 4 | 交易已禁用 |
EnableTrading | 5 | 交易已启用 |
AccountStatusEnum从@orderly.network/types导出,而非@orderly.network/hooks。
import { useAccount } from '@orderly.network/hooks';
import { AccountStatusEnum } from '@orderly.network/types';
function AccountStatus() {
const { account, state, createOrderlyKey, createAccount } = useAccount();
switch (state.status) {
case AccountStatusEnum.NotConnected:
return <ConnectWalletButton />;
case AccountStatusEnum.Connected:
return <button onClick={() => createAccount()}>Create Orderly Account</button>;
case AccountStatusEnum.NotSignedIn:
return <button onClick={() => createOrderlyKey()}>Enable Trading</button>;
case AccountStatusEnum.SignedIn:
case AccountStatusEnum.EnableTrading:
return <TradingInterface />;
}
}
钱包连接 UI 组件
连接按钮 / 弹窗
SDK 通过通知 / 弹窗系统提供连接弹窗:
import { modal } from '@orderly.network/ui';
import { WalletConnectorModalId } from '@orderly.network/ui-connector';
function ConnectButton() {
return <button onClick={() => modal.show(WalletConnectorModalId)}>Connect Wallet</button>;
}
@orderly.network/ui-connector 还提供了预设样式按钮 ConnectWalletButton。
AuthGuard
使用 AuthGuard 包裹需要已认证且已启用交易的账户才能访问的内容:
import { AuthGuard } from '@orderly.network/ui-connector';
function ProtectedArea() {
return (
<AuthGuard fallback={<ConnectPrompt />}>
<TradingUI />
</AuthGuard>
);
}
支持的链
EVM 主网
| 链 | 链 ID |
|---|---|
| Arbitrum | 42161 |
| Optimism | 10 |
| Base | 8453 |
| Ethereum | 1 |
EVM 测试网
| 链 | 链 ID |
|---|---|
| Arbitrum Sepolia | 421614 |
| Base Sepolia | 84532 |
Solana
| 网络 | 内部 ID |
|---|---|
| Mainnet | 1399811149 |
| Devnet | (devnet) |
链筛选
限制用户可切换的链。chainFilter 以网络为键,每个值是一个 { id } 数组:
<OrderlyAppProvider
brokerId="your_broker_id"
networkId="mainnet"
chainFilter={{
mainnet: [{ id: 42161 }, { id: 10 }],
testnet: [{ id: 421614 }],
}}
defaultChain={{ mainnet: { id: 42161 } }}
>
在参考模板中,此配置由 VITE_ORDERLY_MAINNET_CHAINS / VITE_ORDERLY_TESTNET_CHAINS / VITE_DEFAULT_CHAIN 构建(参见 orderly-sdk-dex-architecture)。
处理链切换
用户在主网链和测试网链之间切换时,必须切换 networkId 并重新加载,以便 SDK 重新绑定到正确的环境:
<OrderlyAppProvider
brokerId="your_broker_id"
networkId={networkId}
onChainChanged={(_chainId, { isTestnet }) => {
const current = getNetworkId();
if ((isTestnet && current === 'mainnet') ||
(!isTestnet && current === 'testnet')) {
localStorage.setItem('orderly_network_id', isTestnet ? 'testnet' : 'mainnet');
setTimeout(() => window.location.reload(), 100);
}
}}
>
Privy 集成(社交登录)
安装 Privy 连接器和 Privy SDK(使用 @privy-io/cross-app-connect,不要使用旧版 @privy-io/react-auth):
npm install @orderly.network/wallet-connector-privy @privy-io/cross-app-connect
Privy 提供程序是 WalletConnectorPrivyProvider(不是 WalletConnectorPrivy)。它接受 network、termsOfUse、wagmiConfig、solanaConfig、privyConfig,以及可选的 abstractConfig。
// app/components/orderlyProvider/privyConnector.tsx
import { ReactNode } from 'react';
import { WalletConnectorPrivyProvider, Network } from '@orderly.network/wallet-connector-privy';
import { QueryClient } from '@tanstack/query-core';
import type { NetworkId } from '@orderly.network/types';
import { getEvmConnectors, getSolanaConfig } from '@/utils/walletConfig';
type LoginMethod = 'email' | 'passkey' | 'twitter' | 'google';
type PrivyConnectorProps = {
children: ReactNode;
networkId: NetworkId;
appId: string; // your Privy app id (required)
loginMethods?: LoginMethod[]; // default ['email']
termsOfUse?: string;
disableEvm?: boolean;
disableSolana?: boolean;
enableAbstract?: boolean;
// plus projectId / appName if you enable EVM (see getEvmConnectors)
};
const PrivyConnector = ({
children, networkId, appId,
loginMethods = ['email'], termsOfUse,
disableEvm, disableSolana, enableAbstract,
}: PrivyConnectorProps) => (
<WalletConnectorPrivyProvider
network={networkId === 'mainnet' ? Network.mainnet : Network.testnet}
termsOfUse={termsOfUse}
wagmiConfig={disableEvm ? undefined : { connectors: getEvmConnectors(/* projectId */, /* appName */) }}
solanaConfig={disableSolana ? undefined : getSolanaConfig(networkId)}
privyConfig={{
config: { appearance: { showWalletLoginFirst: false }, loginMethods },
appid: appId,
}}
abstractConfig={enableAbstract ? { queryClient: new QueryClient() } : undefined}
>
{children}
</WalletConnectorPrivyProvider>
);
export default PrivyConnector;
提供程序属性(
appId、loginMethods等)来自你的配置——参考模板从.env中读取这些属性(VITE_PRIVY_APP_ID、VITE_PRIVY_LOGIN_METHODS等)。如果未配置 Privy 应用 ID,请改用标准WalletConnector。登录方式默认为
最佳实践
- 从配置中读取 WalletConnect 项目 ID,不要硬编码。
- 只派生一次
networkId(例如getNetworkId()),并将其同时传给钱包连接器和OrderlyAppProvider。 - 在
localStorage(orderly_network_id)中持久化网络选择,并在主网与测试网切换时重新加载。 - 如果支持 Solana Mobile 设备,请加入
SolanaMobileWalletAdapter。 - 在运行时选择 Privy 或标准连接器(根据是否配置了 Privy 应用 ID),而非在构建时选择。
相关技能
- orderly-sdk-dex-architecture - 提供程序设置与配置
- orderly-sdk-install-dependency - 安装钱包包
- orderly-sdk-trading-workflows - 交易实现
- orderly-sdk-debugging - 钱包问题排查
- orderly-api-authentication - 了解身份验证流程