將 Gale Bridge 跨鏈操作介面嵌入合作夥伴網站。宿主應用程式提供頁面容器與使用者的錢包 Provider;Widget 負責資產選擇、報價、授權提示、交易提交與訂單追蹤。npm 和 CDN 使用相同的 SDK API,選擇其中一種載入方式即可。
| 資源 | 網址 |
|---|---|
| npm 套件 | @galebridge/widget |
| CDN SDK | https://galebridge.net/widget/v1/widget.js |
| 託管 Widget 頁面 | https://galebridge.net/widget |
| 可用網路與代幣 | Integration Networks API |
整合前準備#
- 正式頁面使用 HTTPS;本機開發使用
http://localhost或http://127.0.0.1,不要以file://直接開啟 HTML。 - 掛載前先建立 DOM 容器。建議寬度為
100%、最大寬度約500px;SDK 會依內容調整 iframe 高度。 - 使用支援 BigInt、
crypto.randomUUID()的現代瀏覽器。React / Next.js 應在用戶端元件掛載後建立 Widget。 - 嵌入式交易使用宿主提供的錢包適配器。EVM 使用 EIP-1193 Provider;TRON 使用 TronLink 或相容 Provider。建立 Widget 本身不會要求連接錢包或簽章。
- 將
your-project-web換成穩定的專案識別碼。同一宿主來源下的獨立 Widget 應使用不同識別碼,以區分待處理交易的復原記錄。clientId為公開標記,不代表身分驗證或佣金歸屬。
未提供錢包適配器時,Widget 仍可載入,並提供開啟獨立頁面的連結;在 iframe 內交易需要對應生態的適配器。以下範例使用英文介面;文件語言與 Widget 介面語言各自獨立。
方式一 npm 整合#
安裝固定版本:
npm install @galebridge/[email protected]在頁面加入容器與狀態提示:
<div id="bridge" style="width:100%;max-width:500px;margin:auto"></div>
<p id="bridge-status" role="status" aria-live="polite"></p>將以下程式碼加入 Vite、Webpack 等建置工具的用戶端入口:
import { createWidget, createEvmAdapter, type EVMProvider } from '@galebridge/widget'
const provider = (window as Window & { ethereum?: EVMProvider }).ethereum
const showStatus = (text: string) => {
const element = document.querySelector('#bridge-status')
if (element) element.textContent = text
}
const widget = createWidget({
container: '#bridge',
clientId: 'your-project-web',
theme: 'light',
lang: 'en',
wallets: provider ? { evm: createEvmAdapter(provider) } : {},
})
widget.on('error', ({ code, message }) => {
showStatus(message)
console.error('[Gale Widget]', code, message)
})
widget.on('transactionSent', ({ txHash }) => {
showStatus('Source transaction submitted; waiting for completion: ' + txHash)
})
widget.on('completed', ({ txHash, order }) => {
showStatus('Bridge order completed: ' + txHash)
console.log('Order details', order)
})
void widget.ready.catch((error: Error) => showStatus(error.message))
// Call when the SPA page or component unmounts:
// widget.destroy()範例使用瀏覽器注入的 EVM 錢包。若應用程式已有錢包連接器,請將其選定的 EIP-1193 Provider 傳入 createEvmAdapter(provider),讓宿主與 Widget 使用同一個錢包。此 TypeScript 必須經建置工具編譯,不應直接當作一般瀏覽器腳本載入。
React 與 Next.js 範例
provider 由宿主的錢包連接模組提供,請維持穩定的參照。未提供時,使用者可開啟獨立頁面。使用 Next.js App Router 時,保留檔案開頭的 'use client'。
'use client'
import { useEffect, useRef, useState } from 'react'
import { createWidget, createEvmAdapter, type EVMProvider } from '@galebridge/widget'
export function GaleBridge({ provider }: { provider?: EVMProvider }) {
const container = useRef<HTMLDivElement>(null)
const [status, setStatus] = useState('')
useEffect(() => {
if (!container.current) return
setStatus('')
const widget = createWidget({
container: container.current,
clientId: 'your-project-web',
lang: 'en',
theme: 'light',
wallets: provider ? { evm: createEvmAdapter(provider) } : {},
})
widget.on('error', ({ message }) => setStatus(message))
widget.on('transactionSent', ({ txHash }) => setStatus('Transaction submitted: ' + txHash))
widget.on('completed', ({ txHash }) => setStatus('Bridge order completed: ' + txHash))
void widget.ready.catch((error: Error) => setStatus(error.message))
return () => widget.destroy()
}, [provider])
return (
<section>
<div ref={container} style={{ width: '100%', maxWidth: 500 }} />
<p role="status" aria-live="polite">{status}</p>
</section>
)
}上述元件會在 provider 改變時重新建立 Widget。簽章或追蹤訂單期間,應避免主動更換 Provider 或卸載元件;卸載不會取消已提交的鏈上交易。
方式二 CDN 整合#
不需安裝 npm 套件。將以下內容儲存為 cdn.html,並透過 HTTP(S) 存取。SDK 以全域變數 GaleBridge 提供 API,請先載入腳本,再呼叫 createWidget。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Gale Bridge integration example</title>
</head>
<body>
<main style="max-width:500px;margin:24px auto;padding:0 12px">
<div id="bridge"></div>
<p id="bridge-status" role="status" aria-live="polite"></p>
</main>
<script src="https://galebridge.net/widget/v1/widget.js"></script>
<script>
const status = document.getElementById('bridge-status')
if (!window.GaleBridge) {
status.textContent = 'SDK failed to load. Check the network and CSP settings.'
} else {
const provider = window.ethereum
const widget = GaleBridge.createWidget({
container: '#bridge',
clientId: 'your-project-web',
lang: 'en',
theme: 'light',
wallets: provider ? { evm: GaleBridge.createEvmAdapter(provider) } : {},
})
widget.on('error', ({ code, message }) => {
status.textContent = message
console.error('[Gale Widget]', code, message)
})
widget.on('transactionSent', ({ txHash }) => {
status.textContent = 'Source transaction submitted; waiting for completion: ' + txHash
})
widget.on('completed', ({ txHash, order }) => {
status.textContent = 'Bridge order completed: ' + txHash
console.log('Order details', order)
})
widget.ready.catch((error) => { status.textContent = error.message })
// Call widget.destroy() when leaving this SPA page.
}
</script>
</body>
</html>/widget/v1/widget.js 為持續維護的正式網址,不是固定 npm 版本的不可變網址。如需固定 SDK 版本,請使用 npm 並鎖定 0.1.0。固定 SDK 版本不會固定託管頁面、可用資產或後端路由。
設定 Widget 語言
託管 Widget 預設為英文。如需繁體中文,可在建立時使用既有的 zh 值,或於閒置時更新:
widget.update({ lang: 'zh' }) // Traditional Chinese
// widget.update({ lang: 'en' }) // English使用者也可在 Widget 頂部切換語言,追蹤待處理交易時亦可使用。此操作僅改變顯示,不會發送或取消交易。
錢包整合#
EVM 錢包
import { createEvmAdapter } from '@galebridge/widget'
// provider is the EIP-1193 Provider selected by the host app.
widget.setWallet('evm', createEvmAdapter(provider))透過 setWallet 更換適配器後,使用者需按 Widget 的連接按鈕重新連接。EVM 適配器可切換至錢包已設定的網路,不會自動新增未知網路;提交前會再次檢查帳戶與網路。授權使用本次轉帳的準確額度。若代幣要求先將既有授權額度歸零,合作夥伴應提供符合其要求的自訂適配器。
TRON 錢包
在宿主注入 TronLink 或相容 TRON Provider 後,保留 getter,讓適配器可於連接後讀取更新的 tronWeb:
// npm: import createTronAdapter from @galebridge/widget.
// CDN: use const { createTronAdapter } = GaleBridge.
const provider = window.tronLink ?? window.tron ?? window.okxwallet?.tronLink
if (provider?.request) {
widget.setWallet('tron', createTronAdapter({
request: provider.request.bind(provider),
get tronWeb() { return provider.tronWeb ?? window.tronWeb },
}))
}內建 TRON 適配器要求主網。若舊版 Provider 不支援網路查詢,僅接受節點來源為 https://api.trongrid.io;其他舊版自訂 RPC 需使用能驗證網路的自訂適配器。授權與橋呼叫的 fee limit 分別為 100 TRX 與 150 TRX,這是上限,實際費用請以錢包確認頁為準。
CDN 錢包函式與 npm API 相同,包括 GaleBridge.createEvmAdapter 和 GaleBridge.createTronAdapter。0.1.0 版未內建 WalletConnect 或行動錢包深層連結。請在合作夥伴環境驗證預計支援的錢包版本及行動錢包瀏覽器。
設定參數#
除 container 外,所有參數皆為選填。鏈 ID、金額與地址使用字串;代幣地址使用 Networks API 回傳的 address,不要填入資料庫內部 ID。
| 參數 | 說明 |
|---|---|
container | 必填,CSS 選擇器或 HTMLElement;掛載前容器必須已存在 |
widgetUrl | 預設 https://galebridge.net/widget,應指定受信任的託管網址 |
clientId | 穩定的專案/Widget 識別碼;省略時共用預設復原分組 |
wallets | { evm, tron } 適配器,可透過 setWallet 後續設定 |
theme | light 或 dark,預設為淺色 |
lang | en(英文)或 zh(繁體中文),預設英文;Widget 也提供語言選單,文件語言另外選擇 |
accentColor | 六位十六進位色碼,例如 #245fef |
fromChainId、toChainId | 來源鏈與目標鏈的十進位 ID,例如 "1"、"137" |
fromTokenAddress、toTokenAddress | 對應網路的代幣地址;原生幣使用 API 回傳的佔位地址 |
amount | 預填來源金額,以人類可讀的代幣單位表示,例如 "10.5";不要傳入空字串或浮點運算後的近似值 |
receiver | 預填目標地址;可由使用者輸入。欄位空白且與錢包同生態時,連接後可自動填入目前錢包地址 |
lockDestination | 預設為 false。設為 true 時需同時提供目標鏈與代幣;已提供的 receiver 也會鎖定 |
allowedChains | 兩側可選的鏈 ID 清單,例如 ["1", "137"] |
allowedTokens | 兩側可選的 { chainId, address } 清單 |
slippage | 小數字串:"0.05" 表示 5%,亦為預設值;範圍大於 0 且不超過 0.5。設定後介面不可修改;不構成最低到帳保證 |
protocol | all、v1 或 v2,預設 all;實際報價決定可用路由 |
TRON Base58 地址須保留大小寫。網路、資產及路由可能變動,請以即時 API 與報價為準。預填不等於鎖定:不可用的預填資產可能改選其他可用資產;鎖定目標不可用時會阻止提交。allowedChains 與 allowedTokens 僅限制選擇,不會啟用後端未支援的資產。
範例 鎖定目標資產
以下設定將目標鎖定為 Ethereum DAI,使用者仍可選擇來源資產並輸入收款地址。若提供真實的 receiver,該地址也會鎖定。上線前請透過 Networks API 確認資產仍可用。
const destinationConfig = {
toChainId: '1',
toTokenAddress: '0x6b175474e89094c44da98b954eedeac495271d0f',
lockDestination: true,
}
// On creation: createWidget({ container: '#bridge', ...destinationConfig, wallets })
// Or update while no transaction is in progress:
widget.update(destinationConfig)事件與生命週期#
請立即註冊事件監聽,再等待 widget.ready。就緒表示宿主與 iframe 已完成握手,不表示資產已載入、錢包已連接或已有可執行報價。
| 事件 | 資料與意義 |
|---|---|
ready | { version: 1 },1 為通訊協定版本 |
needConnect | { ecosystem },正在要求連接對應錢包 |
connected | { address, chainId, ecosystem },錢包連接成功 |
transactionSent | { txHash, chainId },來源交易已提交,不代表目標結算完成 |
statusChanged | { txHash, status, order? },訂單狀態變更,也可能回報 source_failed |
completed | { txHash, order },已完成訂單與本次交易相符;txHash 仍為來源交易雜湊 |
error | { code, message },初始化、設定或交易錯誤 |
const off = widget.on('statusChanged', ({ txHash, status }) => {
console.log(txHash, status)
})
off() // Remove this listener
widget.update({ theme: 'dark', lang: 'en', accentColor: '#245fef' })
// Recreate the widget to change container or widgetUrl.
// Invalid configuration can throw; a locked update emits an error event.
widget.destroy() // Remove the iframe, listeners and SDK timers; safe to call againWidget 語言選單僅改變顯示,不會清除表單、錢包連接或待處理交易。閒置時僅更新 SDK 的 lang、theme 或 accentColor 也會保留表單。更改轉帳設定會重設表單選擇、錢包連接狀態與報價;未明確設定的欄位(包括金額)可能恢復預設值。簽章與訂單追蹤期間,Widget 會以 CONFIG_LOCKED 拒絕 update。destroy() 不會取消鏈上交易;重新建立後,可從儲存的待處理記錄恢復追蹤。復原功能使用 localStorage,第三方儲存被封鎖時可能阻止簽章,並提示開啟獨立頁面。
completed 為介面通知,重新整理或掛載後可能再次觸發。用於入帳、交付等業務時,合作夥伴應在伺服器端獨立驗證訂單及實際結算,並依交易或訂單處理重複通知,不應僅憑瀏覽器事件入帳。
CSP 與部署#
若宿主使用 CSP,請擴充既有原則,允許:
frame-src包含https://galebridge.net。- CDN 載入方式的
script-src包含https://galebridge.net。內嵌範例腳本需使用核准的 nonce/hash,或移至外部腳本。
Widget 呼叫託管來源的 API;宿主不需為 iframe 請求額外提供 API 網址或憑證。請使用 SDK 嵌入,並保留其 sandbox 設定,以維持握手與獨立頁面連結正常運作。
常見問題#
| 現象 | 處理方式 |
|---|---|
Widget container not found | 檢查選擇器,並在容器建立後掛載 |
INIT_TIMEOUT 或空白畫面 | 使用 HTTP(S),檢查 SDK/Widget 連線,以及宿主的腳本與 iframe CSP |
| iframe 內無法連接錢包 | 提供對應生態適配器,確認 Provider 是使用者實際選擇的錢包 |
| EVM 無法切換網路 | 先在錢包新增網路,再重新連接並取得新報價 |
INVALID_CONFIG/CONFIG_LOCKED | 檢查格式與鎖定目標的必要欄位;等待目前交易結束後再更新 |
| 暫時找不到訂單 | 來源索引可能尚未完成,請繼續追蹤,不要因索引延遲再次發送 |
| 錢包逾時或交易結果不確定 | 先檢查錢包歷史與鏈上記錄,再以既有雜湊恢復追蹤;不要自動重送 |
| 第三方儲存不可用 | 使用 Widget 的獨立頁面入口繼續操作或復原 |
功能範圍與驗收#
0.1.0 版提供 npm/CDN 載入、EVM/TRON 適配器、主題與語言、資產篩選、目標鎖定、訂單追蹤及復原。目標金額為估算值,slippage 不提供可強制執行的最低到帳保證;顯示費用不含錢包/網路 Gas。此版本未提供合作夥伴分潤、認證歸因或強制網域白名單。
上線前請驗證窄螢幕、錢包連接與切換網路、報價及授權、來源交易提交、最終結算、重新整理復原與元件卸載。請先約定測試方案;真實授權與交易應由具權限的錢包持有人確認。
範例檔案#
examples/widget/npm.ts:供頁面容器與建置工具使用的 npm 用戶端入口。examples/widget/cdn.html:透過 HTTP(S) 提供的完整 CDN 頁面。examples/widget/react.tsx:React/Next.js 用戶端元件。
範例連接正式 Widget,錢包操作須由使用者確認。