mcpField
O
orderly-sdk-wallet-connection

orderly-sdk-wallet-connection

github.com/orderlynetwork开发247 次安装3 天前更新
代码仓库

关于 orderly-sdk-wallet-connection

orderly-sdk-wallet-connection 是面向 Orderly Network DEX 开发者的钱包接入指南,介绍 EVM 与 Solana 钱包的配置、连接及账户状态管理。指南也说明标准连接器与 Privy 社交登录方案的选择和配置。

主要功能

  1. 01配置 EVM 与 Solana 钱包
  2. 02标准连接器和 Privy 方案
  3. 03连接状态与账户状态管理
  4. 04切换和筛选支持的链
  5. 05钱包连接界面与访问保护

适用场景

  1. 01为新 DEX 配置钱包接入
  2. 02支持多种钱包与链切换
  3. 03按账户状态控制交易功能
  4. 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-walletsMetaMask、Rabby、Coinbase 等
@web3-onboard/walletconnectWalletConnect(移动端 / 多平台)
@binance/w3w-blocknative-connectorBinance Web3 Wallet
wagmiEVM 连接器(injected、walletConnect)
@solana/wallet-adapter-baseSolana 适配器基础包 + 网络枚举
@solana/wallet-adapter-walletsPhantom、Solflare、Ledger 适配器
@solana-mobile/wallet-adapter-mobileSolana 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钱包未连接,但交易已启用
NotConnected0未连接钱包
Connected1钱包已连接,但尚无 Orderly 账户
NotSignedIn2账户已创建,但尚未登录
SignedIn3已登录 Orderly
DisabledTrading4交易已禁用
EnableTrading5交易已启用

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
Arbitrum42161
Optimism10
Base8453
Ethereum1
EVM 测试网
链链 ID
Arbitrum Sepolia421614
Base Sepolia84532
Solana
网络内部 ID
Mainnet1399811149
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。登录方式默认为 email。

最佳实践

  1. 从配置中读取 WalletConnect 项目 ID,不要硬编码。
  2. 只派生一次 networkId(例如 getNetworkId()),并将其同时传给钱包连接器和 OrderlyAppProvider。
  3. 在 localStorage(orderly_network_id)中持久化网络选择,并在主网与测试网切换时重新加载。
  4. 如果支持 Solana Mobile 设备,请加入 SolanaMobileWalletAdapter。
  5. 在运行时选择 Privy 或标准连接器(根据是否配置了 Privy 应用 ID),而非在构建时选择。

相关技能

  • orderly-sdk-dex-architecture - 提供程序设置与配置
  • orderly-sdk-install-dependency - 安装钱包包
  • orderly-sdk-trading-workflows - 交易实现
  • orderly-sdk-debugging - 钱包问题排查
  • orderly-api-authentication - 了解身份验证流程

评论

支持 Markdown