接入Luffa钱包

This commit is contained in:
chen wei bo
2025-09-28 23:04:39 +08:00
parent 303003b550
commit 7489206537
5 changed files with 134 additions and 61 deletions
+2 -2
View File
@@ -154,12 +154,12 @@ export class SDKManager {
}
// 签名交易
public async signTransaction(rawData: any): Promise<{ signedData: string }> {
public async signTransaction(rawTx: any): Promise<{ signedData: string }> {
if (!this.walletSDK) return;
// 判断是否实现交易能力
if ("signTransaction" in this.walletSDK) {
const txCap = this.walletSDK as unknown as ITransactionCap;
return txCap.signTransaction(rawData);
return txCap.signTransaction(rawTx);
}
throw new Error("当前钱包 SDK 不支持 signTransaction 功能");
}
@@ -5,12 +5,12 @@
export interface ITransactionCap {
/**
* 签名交易(由 DApp 构造交易对象)
* 签名交易
*
* @param rawData 原始交易对象
* @param rawTx 原始交易参数
* @returns 已签名交易
*/
signTransaction(rawData: any): Promise<{ signedData: string }>;
signTransaction(rawTx: any): Promise<{ signedData: string }>;
/**
* 发送交易(广播到链上)
@@ -1,12 +1,19 @@
import { IWalletSDK } from "../core/IWalletSDK";
import { ISignCap } from "../core/ISignCap";
import { ITransactionCap } from "../core/ITransactionCap";
import { logger } from "db://assets/Scripts/Main/Common/Logger";
export class LuffaWalletSDK implements IWalletSDK, ISignCap, ITransactionCap {
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 钱包初始化");
@@ -22,11 +29,11 @@ export class LuffaWalletSDK implements IWalletSDK, ISignCap, ITransactionCap {
uuid: this.create16String(),
methodName: "connect",
initData: {
network: "endless", // endless 为主网, ends 为测试网
network: this.network, // endless 为主网, eds 为测试网
},
metadata: {
superBox: true,
url: "https://your-game-domain.com", // 建议填自己游戏的唯一标识
url: "https://xchat188.com/", // 建议填自己游戏的唯一标识
// icon: "https://your-game-domain.com/icon.png",
},
from: "",
@@ -56,54 +63,79 @@ export class LuffaWalletSDK implements IWalletSDK, ISignCap, ITransactionCap {
return this.address;
}
// 签名消息 (单签)
async signMessage(message: string, options?: any): Promise<{ signature: string; fullMessage?: string }> {
logger.log("调用 Luffa 单签签名");
// 签名交易
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) => {
const opts = {
api_name: "luffaWebRequest",
data: {
uuid: this.create16String(),
methodName: "signMessageV2",
initData: { network: "endless" },
from: this.address ?? "",
data: {
message,
nonce: options?.nonce ?? Date.now(), // 默认用时间戳
address: options?.address ?? false,
application: options?.application ?? false,
chainId: options?.chainId ?? false,
},
// 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 为测试网
},
success: (res) => {
logger.log("signMessageV2 success:", res);
resolve({
signature: res.data?.signature,
fullMessage: res.data?.fullMessage,
});
},
fail: (err) => {
logger.error("signMessageV2 fail:", err);
reject(err);
},
};
wx.invokeNativePlugin(opts);
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 signTransaction(rawData: any): Promise<{ signedData: string }> {
logger.log("签名交易", rawData);
// 签名交易,方法二
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 ?? "",
from: this.address ?? "", //自己的钱包地址
methodName: "packageTransactionV2",
initData: { network: "endless" },
initData: { network: this.network },
data: {
data: JSON.stringify(rawData),
data: JSON.stringify(allData),
},
},
success: (res) => {
@@ -117,11 +149,11 @@ export class LuffaWalletSDK implements IWalletSDK, ISignCap, ITransactionCap {
};
wx.invokeNativePlugin(opts);
});
}
}
// 发送交易(广播到链上)
async sendTransaction(signedData: string): Promise<{ hash: string }> {
logger.log("发送交易", signedData);
logger.log("发送交易(广播到链上)", signedData);
return new Promise((resolve, reject) => {
const opts = {
api_name: "luffaWebRequest",
@@ -129,7 +161,7 @@ export class LuffaWalletSDK implements IWalletSDK, ISignCap, ITransactionCap {
uuid: this.create16String(),
from: this.address ?? "",
methodName: "signAndSubmitTransaction",
initData: { network: "endless" },
initData: { network: this.network },
data: {
serializedTransaction: {
data: signedData,
+53 -12
View File
@@ -9,20 +9,61 @@ import { type OpenStrategy } from "./PaymentOpener";
import { DataManager, DataId } from "db://assets/Scripts/chat18x/data/DataManager";
import { OrderData } from "db://assets/Scripts/chat18x/data/OrderData";
import { logger } from "db://assets/Scripts/Main/Common/Logger";
import { SDKManager } from "db://assets/Scripts/Main/Channel/SDKManager";
export class LuffaPayFlow implements PaymentFlow {
constructor(private delayMs: number = 5000) {}
constructor(private delayMs: number = 10000) {}
async run(orderId: string, _payUrl: string, _open: OpenStrategy): Promise<proto.cs.ICSQueryOrderRes | null> {
// 延时
await this.delay(this.delayMs);
// 开始轮询
const data = await this.pollOrder(orderId);
// 刷新订单数据
const orderData = DataManager.I.getDataById<OrderData>(DataId.Order);
orderData.applyQueryOrder(orderId, data);
// 返回结果
return data;
try {
// 连接钱包(只需一次,如果已连过可以跳过)
const address = SDKManager.I.getWalletAddress();
if (!address) {
logger.log("钱包未连接,开始连接 Luffa 钱包...");
await new Promise<void>((resolve, reject) => {
SDKManager.I.connectWallet((addr) => {
if (addr) {
logger.log("已连接 Luffa 钱包:", addr);
resolve();
} else {
logger.error("Luffa 钱包连接失败");
reject(new Error("Luffa 钱包连接失败"));
}
});
});
}
// 构造交易参数
const rawTx = {
toAddress: "Hm3g4xXM4JHt5EwFUcvVZ8RthR4KWUnR51fKHCbnKkiZ", // TODO
amount: 1 // TODO
};
// 签名交易
const signed = await SDKManager.I.signTransaction(rawTx);
logger.log("Luffa 签名结果:", signed);
// 发送交易
const sent = await SDKManager.I.sendTransaction(signed.signedData);
logger.log("Luffa 交易已提交,hash:", sent.hash);
// 等待一会再开始轮询
await this.delay(this.delayMs);
// 开始轮询订单状态
const data = await this.pollOrder(orderId);
// 刷新订单数据
const orderData = DataManager.I.getDataById<OrderData>(DataId.Order);
orderData.applyQueryOrder(orderId, data);
// 返回结果
return data;
} catch (e) {
logger.error("Luffa Payment process exception:", e);
return null;
}
}
async resume(orderId: string, _payUrl: string): Promise<proto.cs.ICSQueryOrderRes | null> {
@@ -33,8 +74,8 @@ export class LuffaPayFlow implements PaymentFlow {
private async pollOrder(orderId: string) {
const poller = new PaymentPoller();
return poller.poll(orderId, {
maxDurationMs: 10 * 60 * 1000,
startIntervalMs: 5000,
maxDurationMs: 2 * 60 * 1000,
startIntervalMs: 3000,
maxIntervalMs: 10000,
jitter: true,
}, (d) => logger.log());
@@ -28,7 +28,7 @@ export class PaymentService {
this.flowMap = new Map<PaymentMethod, PaymentFlow>();
this.flowMap.set(PaymentMethod.CashPay, new CashInrFlow(this.waitAppResumeIfNeeded.bind(this)));
this.flowMap.set(PaymentMethod.Web3, new WebUsdFlow(5000));
this.flowMap.set(PaymentMethod.Luffa, new LuffaPayFlow(5000));
this.flowMap.set(PaymentMethod.Luffa, new LuffaPayFlow(10000));
}
/** 发起支付:创建订单→打开URL→回到App后开始轮询 */