import { IWalletSDK } from "../core/IWalletSDK"; import { ITransactionCap } from "../core/ITransactionCap"; import { logger } from "db://assets/Scripts/Main/Common/Logger"; export class LuffaWalletSDK implements IWalletSDK, ITransactionCap { // 运行环境,endless 为主网, eds 为测试网 private network: string; // 自己的钱包地址 private address: string | null = null; // Luffa ID private luffaId: any = null; constructor() { this.network = "eds"; } // 初始化 init(cb?: Function): void { logger.log("Luffa 钱包初始化"); cb && cb(); } // 连接钱包 connectWallet(cb: (address: string, publicKey?: string) => void): void { logger.log("连接 Luffa 钱包"); const opts = { api_name: "luffaWebRequest", data: { uuid: this.create16String(), methodName: "connect", initData: { network: this.network, // endless 为主网, eds 为测试网 }, metadata: { superBox: true, url: "https://xchat188.com/", // 建议填自己游戏的唯一标识 // icon: "https://your-game-domain.com/icon.png", }, from: "", data: {}, }, success: (res) => { logger.log("Luffa connect success:", res); this.address = res.data?.address ?? null; this.luffaId = res.data?.uid ?? null; cb(this.address ?? "", res.data?.publicKey ?? ""); }, fail: (err) => { logger.error("Luffa connect fail:", err); cb("", ""); }, }; wx.invokeNativePlugin(opts); } // 断开钱包连接 disconnectWallet(): void { this.address = null; } // 获取当前钱包地址 getWalletAddress(): string | null { return this.address; } // 签名交易 async signTransaction(rawTx: any): Promise<{ signedData: string }> { logger.log("签名交易:", rawTx); if ("contract" in rawTx) { return this.signTransactionV2(rawTx); } else { return this.signTransactionV1(rawTx); } } // 签名交易,方法一 async signTransactionV1(rawTx: any): Promise<{ signedData: string }> { return new Promise((resolve, reject) => { // DATA const DATA = { module: "0x1", // 固定写死 moduleName: "endless_account", // 固定写死 functionName: "transfer", // 固定写死 data: JSON.stringify({ "1_address_address": rawTx.toAddress, // 对方钱包地址 "2_u128_amount": String(rawTx.amount * 100000000), // 金额 * 10^8 }), argsData: [], }; const opts = { api_name: "luffaWebRequest", data: { uuid: this.create16String(), // 生成随机16位字符串 from: this.address ?? "", // 自己的钱包地址 methodName: "packageTransaction", initData: { network: this.network, // endless 为主网, eds 为测试网 }, data: DATA, // 传入构造好的 DATA }, success: (res) => { logger.log("packageTransactionV1 success:", res); resolve({ signedData: res.data?.rawData }); }, fail: (err) => { logger.error("packageTransactionV1 fail:", err); reject(err); }, }; wx.invokeNativePlugin(opts); }); } // 签名交易,方法二 async signTransactionV2(rawTx: any): Promise<{ signedData: string }> { const payload = { function: rawTx.contract, // 合约地址::合约名::函数名 functionArguments: rawTx.args ?? [], typeArguments: rawTx.typeArgs ?? [], typeEnum: [] }; const allData = { payload, secondarySignerAddresses: rawTx.secondarySigners ?? [], //多签地址集合 非多签可以不用 feePayer: rawTx.feePayer ?? "" //手续费 }; return new Promise((resolve, reject) => { const opts = { api_name: "luffaWebRequest", data: { uuid: this.create16String(), from: this.address ?? "", //自己的钱包地址 methodName: "packageTransactionV2", initData: { network: this.network }, data: { data: JSON.stringify(allData), }, }, success: (res) => { logger.log("packageTransactionV2 success:", res); resolve({ signedData: res.data?.rawData }); }, fail: (err) => { logger.error("packageTransactionV2 fail:", err); reject(err); }, }; wx.invokeNativePlugin(opts); }); } // 发送交易(广播到链上) async sendTransaction(signedData: string): Promise<{ hash: string }> { logger.log("发送交易(广播到链上)", signedData); return new Promise((resolve, reject) => { const opts = { api_name: "luffaWebRequest", data: { uuid: this.create16String(), from: this.address ?? "", methodName: "signAndSubmitTransaction", initData: { network: this.network }, data: { serializedTransaction: { data: signedData, }, }, }, success: (res) => { logger.log("sendTransaction success:", res); resolve({ hash: res.data?.hash }); }, fail: (err) => { logger.error("sendTransaction fail:", err); reject(err); }, }; wx.invokeNativePlugin(opts); }); } // 工具:生成随机 16 长度字符串 private create16String(): string { const len = 16; const strVals = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"; let randomStr = ""; for (let i = 0; i < len; i++) { randomStr += strVals.charAt(Math.floor(Math.random() * strVals.length)); } return randomStr; } }