· 大約9小時 ago
前端钱包签名,后端链上verify & settle。
// x402_payment_controller.js
import { Controller } from "@hotwired/stimulus"
import { wrapFetchWithPayment } from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm'
import { createWalletClient, custom } from "viem"
import { baseSepolia } from "viem/chains"
export default class extends Controller { static targets = ["status", "result", "button"] static values = { url: String }
async pay() { this.buttonTarget.disabled = true this.buttonTarget.textContent = "连接中..."
if (!window.ethereum) {
this.statusTarget.textContent = "错误:请安装 MetaMask"
this.resetButton()
return
}
try {
// 1. 请求账户权限
await window.ethereum.request({ method: "eth_requestAccounts" })
const address = window.ethereum.selectedAddress
// 2. 创建 viem wallet client(兼容 window.ethereum)
const walletClient = createWalletClient({
account: address,
chain: baseSepolia, // 换成 mainnet 也行
transport: custom(window.ethereum),
})
// 3. 包装 fetch 支持 x402 支付
const fetchWithPay = wrapFetchWithPayment(fetch, walletClient)
this.statusTarget.textContent = `已连接: ${address.slice(0, 6)}...${address.slice(-4)}`
// 4. 调用付费 API(替换为真实 x402 API)
const response = await fetchWithPay(this.urlValue, {
method: "GET",
headers: { "Accept": "application/json" }
})
if (!response.ok) throw new Error(`HTTP ${response.status}`)
const data = await response.json()
this.resultTarget.textContent = JSON.stringify(data, null, 2)
} catch (error) {
console.error(error)
this.statusTarget.textContent = `失败: ${error.message}`
this.resultTarget.textContent = ""
} finally {
this.resetButton()
}
}
resetButton() { this.buttonTarget.disabled = false this.buttonTarget.textContent = "连接钱包并获取数据" } }
作者 Robert
與您的關注者分享。
回覆