接入Luffa钱包
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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后开始轮询 */
|
||||
|
||||
Reference in New Issue
Block a user