StableOps
SDK

錢包 SDK

瞭解如何使用 @stableops/wallet-sdk,讓使用者透過自託管的 EVM、TRON 或 Solana 錢包完成鏈上付款;文件覆蓋付款指令解析、網路切換、代幣轉帳、交易結果處理和安全邊界,並說明前端 SDK 與伺服器端訂單介面的配合方式。

@stableops/wallet-sdk僅瀏覽器使用的前端庫:把後端建立訂單時返回的 paymentInstructions 交給使用者的錢包,發起一筆鏈上轉帳到該訂單的指定收款地址。

冪等、地址分配、鏈上掃描、確認數、Webhook 全部仍由 StableOps 後端負責;錢包 SDK 只做一件事:讓使用者把錢轉到正確的地址

不要在瀏覽器暴露 STABLEOPS_API_KEY。訂單建立必須在後端完成,前端只接收訂單 id、amountpaymentInstructions

安裝

pnpm add @stableops/wallet-sdk

需要支援 fetch 和 EIP-1193 / TronLink / Solana 錢包介面卡的瀏覽器環境。 WalletConnect 為可選能力,依賴在用到時再裝(見下文)。

想看可執行的完整示例?

Playground 在瀏覽器裡串起「建單 → 錢包支付 → 確認 → finalized」全流程,並附帶可閱讀的原始碼。

快速開始(注入式錢包)

getInjectedWalletProviders() 收集頁面裡已注入的錢包(MetaMask、TronLink、Phantom 等), sendOrderWalletPayment() 自動從訂單候選裡挑一條「有可用錢包」的鏈併發起轉帳。

import { getInjectedWalletProviders, sendOrderWalletPayment } from '@stableops/wallet-sdk'

const sent = await sendOrderWalletPayment({
  order, // { amount, paymentInstructions },來自後端
  providers: getInjectedWalletProviders(),
})

console.log(sent.txHash)

可用 preferredChains 指定優先嚐試的鏈順序:

await sendOrderWalletPayment({
  order,
  providers: getInjectedWalletProviders(),
  preferredChains: ['base', 'arbitrum'],
})

手動選擇候選指令

需要自己控制「選哪條鏈」時,先用 selectWalletPaymentInstruction() 選中, 再呼叫底層的 sendWalletPayment()

import {
  getInjectedWalletProviders,
  selectWalletPaymentInstruction,
  sendWalletPayment,
} from '@stableops/wallet-sdk'

const { instruction, provider } = selectWalletPaymentInstruction(
  order.paymentInstructions,
  getInjectedWalletProviders(),
  ['base'], // 可選:優先鏈
)

const sent = await sendWalletPayment({
  provider,
  instruction,
  amount: order.amount,
})

console.log(sent.txHash)

WalletConnect(移動端 / 自定義 UI)

移動端瀏覽器或沒有注入 EVM provider 的頁面,可以接入可選的 WalletConnect 執行時。 SDK 不內建 UI、也不維護錢包列表:錢包選項由你傳入,介面透過訂閱 controller 的 state 自行渲染(錢包列表、二維碼、連線中 / 失敗狀態)。

pnpm add @walletconnect/universal-provider
import { createWalletConnectController, sendOrderWalletPayment } from '@stableops/wallet-sdk'

const wc = await createWalletConnectController({
  projectId: 'YOUR_REOWN_PROJECT_ID',
  metadata: {
    name: 'Your App',
    description: 'StableOps checkout',
    url: window.location.origin,
    icons: [`${window.location.origin}/icon.png`],
  },
  // 啟用的名稱空間(按需取捨)
  chains: ['base', 'arbitrum'], // EVM
  solanaChains: ['solana'], // Solana
  tronChains: ['tron'], // TRON
  wallets: [
    {
      id: 'metamask',
      name: 'MetaMask',
      links: { native: 'metamask://', universal: 'https://metamask.app.link' },
    },
  ],
})

const unsubscribe = wc.subscribe((state) => {
  // 按 state.status 渲染:'idle' | 'connecting' | 'uri_ready' | 'connected' | 'failed' | 'disconnected'
  // state.status === 'uri_ready' 時,用 state.uri 生成二維碼。
})

await wc.connect({ walletId: 'metamask' })

const sent = await sendOrderWalletPayment({
  order,
  providers: wc.providers, // 把 controller 的 providers 直接交給傳送函式
})

unsubscribe()
console.log(sent.txHash)

EVM、Solana、TRON 三類名稱空間都可經 WalletConnect 走通:

  • EVM:行為與注入式一致。
  • Solana:取決於錢包是否支援 solana_signTransaction / solana_signAndSendTransaction; 自定義 RPC / devnet 流程需要 solana_signTransaction
  • TRON:錢包只做 tron_signTransaction 簽名,交易構造與廣播由 SDK 用 tronweb 完成 (預設 trongrid 公共節點,可用 tronRpcUrl 覆蓋)。

返回值:SentWalletPayment

sendWalletPaymentsendOrderWalletPayment 都返回:

{
  txHash: string
  chain: ChainId
  asset: 'USDC' | 'USDT'
  fromAddress: string
  toAddress: string
  tokenContract: string
  amount: string // 人類可讀金額,如 '49.00'
  amountUnits: string // 最小單位整數字符串
  confirmation: Promise<void>
}

confirmationbest-effort 參考訊號不阻塞函式返回(交易廣播後在後台查詢):

  • resolve:交易已上鍊且合約執行成功(或超時 ~90s 後 best-effort 放行)。
  • rejectcode: 'wallet_tx_reverted'):鏈上 revert,沒有代幣轉出(如餘額不足)。 設計目的是儘早捕獲「立即 revert」,避免使用者久等才發現失敗。
sent.confirmation.catch((err) => {
  // err.code === 'wallet_tx_reverted'
})
伺服器端鏈上掃描才是權威狀態。 如果 scanner 已把訂單推進到 detected / confirmed,一律以伺服器端為準,忽略 confirmation 的 reject。

支援的鏈

走法
ethereum base arbitrum polygon optimism bsc(及各自測試網 *-sepolia / polygon-amoy / bsc-testnet呼叫 EIP-1193 錢包,必要時切鏈 / 新增網路,傳送 ERC-20 transfer。可用 chainConfigs 覆蓋 RPC / 瀏覽器地址。
tron tron-nile呼叫 TronLink / TronWeb(或 WalletConnect TRON),構造、簽名並廣播 TRC-20 transfer。測試網或自建節點傳 tronRpcUrl
solana solana-devnet呼叫 Solana 錢包介面卡,冪等建立收款方關聯 token account,傳送 SPL Token TransferChecked。devnet 傳 solanaRpcUrl: 'https://api.devnet.solana.com'(或等價節點)。

錯誤處理

所有失敗都會拋 StableOpsWalletError,帶 .code.message、可選 .details

import { StableOpsWalletError } from '@stableops/wallet-sdk'

try {
  await sendOrderWalletPayment({ order, providers: getInjectedWalletProviders() })
} catch (err) {
  if (err instanceof StableOpsWalletError && err.code === 'wallet_user_rejected') {
    // 使用者在錢包裡取消了
  }
  throw err
}

常見 code

code含義
payment_instruction_not_found訂單沒有可支付的鏈上指令
wallet_provider_not_found所有候選鏈都沒有可用錢包 provider
wallet_user_rejected使用者在錢包裡拒絕簽名
wallet_tx_reverted鏈上 revert(多由 confirmation reject 丟擲)
unsupported_chain該鏈不被錢包助手支援
chain_config_not_found缺少對應 EVM 鏈設定(傳 chainConfigs 補充)
invalid_amount / invalid_evm_address / invalid_tron_address / invalid_solana_address入參非法
tron_dependency_missing / solana_dependency_missing缺少 TRON / Solana 執行依賴

除錯

開啟模組級除錯日誌(字首 [wallet-sdk])便於排查:

import { setWalletSdkDebug } from '@stableops/wallet-sdk'

setWalletSdkDebug(true)

也可不改程式碼臨時開啟:瀏覽器控制台設 globalThis.STABLEOPS_WALLET_DEBUG = true, 或建置時注入環境變數 WALLET_SDK_DEBUG=1

這篇文件怎麼樣?

最後更新

本頁內容