anchor-sdk 0.1.43-beta.1 → 0.1.43-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +1 -1
- package/dist/generated/Api.d.ts +199 -197
- package/dist/index.js +3 -1379
- package/dist/index.js.map +12 -11
- package/dist/react/index.js +3 -8
- package/dist/react/index.js.map +19 -0
- package/package.json +15 -15
- package/dist/AnchorApiClientV2.d.ts.map +0 -1
- package/dist/AnchorApiClientV2.js +0 -358
- package/dist/AnchorERC1155Client.d.ts.map +0 -1
- package/dist/AnchorERC1155Client.js +0 -301
- package/dist/AnchorPayClient.d.ts.map +0 -1
- package/dist/AnchorPayClient.js +0 -908
- package/dist/abi/AnchorERC1155.d.ts.map +0 -1
- package/dist/abi/AnchorERC1155.js +0 -1122
- package/dist/abi/AnchorPay.json +0 -578
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -367
- package/dist/generated/Api.d.ts.map +0 -1
- package/dist/generated/Api.js +0 -868
- package/dist/index.d.ts.map +0 -1
- package/dist/react/AnchorReactSDK.js +0 -192
- package/dist/typechain/AnchorERC1155.d.ts.map +0 -1
- package/dist/typechain/AnchorERC1155.js +0 -2
- package/dist/typechain/AnchorPay.d.ts.map +0 -1
- package/dist/typechain/AnchorPay.js +0 -2
- package/dist/typechain/common.d.ts.map +0 -1
- package/dist/typechain/common.js +0 -2
- package/dist/typechain/factories/AnchorERC1155__factory.d.ts.map +0 -1
- package/dist/typechain/factories/AnchorERC1155__factory.js +0 -1766
- package/dist/typechain/factories/AnchorPay__factory.d.ts.map +0 -1
- package/dist/typechain/factories/AnchorPay__factory.js +0 -469
- package/dist/typechain/factories/index.d.ts.map +0 -1
- package/dist/typechain/factories/index.js +0 -10
- package/dist/typechain/index.d.ts.map +0 -1
- package/dist/typechain/index.js +0 -41
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
package/dist/AnchorPayClient.js
DELETED
|
@@ -1,908 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.AnchorPayClient = void 0;
|
|
7
|
-
const viem_1 = require("viem");
|
|
8
|
-
const constants_1 = require("./constants");
|
|
9
|
-
const AnchorPay_json_1 = __importDefault(require("./abi/AnchorPay.json"));
|
|
10
|
-
/**
|
|
11
|
-
* AnchorPay 客户端
|
|
12
|
-
* 用于与 AnchorPay 合约交互
|
|
13
|
-
*/
|
|
14
|
-
class AnchorPayClient {
|
|
15
|
-
/**
|
|
16
|
-
* 创建 AnchorPay 客户端
|
|
17
|
-
* @param publicClient 公共客户端(只读操作)
|
|
18
|
-
* @param network 网络配置
|
|
19
|
-
* @param walletClient 钱包客户端(写入操作)
|
|
20
|
-
* @param account 账户(可选,如果不提供则使用只读模式)
|
|
21
|
-
*/
|
|
22
|
-
constructor(publicClient, network, walletClient, account, contracts) {
|
|
23
|
-
this.publicClient = publicClient;
|
|
24
|
-
this.network = network;
|
|
25
|
-
this.walletClient = walletClient;
|
|
26
|
-
this.account = account;
|
|
27
|
-
this.contracts = contracts || {};
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* 发送 ETH
|
|
31
|
-
* @param recipient 接收者地址
|
|
32
|
-
* @param amount 金额(单位:wei)
|
|
33
|
-
* @param data 附加数据
|
|
34
|
-
* @param options 交易选项
|
|
35
|
-
* @returns 交易收据或交易数据
|
|
36
|
-
*/
|
|
37
|
-
async sendETH(recipient, amount, data = "0x", options) {
|
|
38
|
-
// 如果需要发送交易,但没有钱包客户端或账户
|
|
39
|
-
if (options?.sendTransaction !== false &&
|
|
40
|
-
(!this.walletClient || !this.account)) {
|
|
41
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
42
|
-
}
|
|
43
|
-
// 准备交易数据
|
|
44
|
-
const calldata = (0, viem_1.encodeFunctionData)({
|
|
45
|
-
abi: AnchorPay_json_1.default,
|
|
46
|
-
functionName: "send",
|
|
47
|
-
args: [recipient, constants_1.NATIVE_TOKEN_ADDRESS, amount, data],
|
|
48
|
-
});
|
|
49
|
-
// 如果不需要发送交易,只返回交易数据(AA 模式)
|
|
50
|
-
if (options?.sendTransaction === false) {
|
|
51
|
-
return {
|
|
52
|
-
to: this.contracts?.anchorPay || "",
|
|
53
|
-
data: calldata,
|
|
54
|
-
value: amount,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
// 估算 gas 和费用
|
|
58
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas();
|
|
59
|
-
const gas = await this.publicClient.estimateGas({
|
|
60
|
-
to: this.contracts?.anchorPay || "",
|
|
61
|
-
data: calldata,
|
|
62
|
-
value: amount,
|
|
63
|
-
account: this.account,
|
|
64
|
-
});
|
|
65
|
-
// 发送交易(EOA 模式)
|
|
66
|
-
if (!this.walletClient || !this.account) {
|
|
67
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
68
|
-
}
|
|
69
|
-
const txHash = await this.walletClient.sendTransaction({
|
|
70
|
-
account: this.account,
|
|
71
|
-
to: this.contracts?.anchorPay || "",
|
|
72
|
-
data: calldata,
|
|
73
|
-
value: amount,
|
|
74
|
-
maxFeePerGas: options?.maxFeePerGas || maxFeePerGas,
|
|
75
|
-
maxPriorityFeePerGas: options?.maxPriorityFeePerGas || maxPriorityFeePerGas,
|
|
76
|
-
gas: options?.gas || gas,
|
|
77
|
-
chain: this.publicClient.chain,
|
|
78
|
-
});
|
|
79
|
-
// 等待交易确认并返回收据
|
|
80
|
-
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
81
|
-
hash: txHash,
|
|
82
|
-
});
|
|
83
|
-
return receipt;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* 发送 ERC20 代币
|
|
87
|
-
* @param recipient 接收者地址
|
|
88
|
-
* @param tokenAddress ERC20 代币地址
|
|
89
|
-
* @param amount 金额
|
|
90
|
-
* @param data 附加数据
|
|
91
|
-
* @param options 交易选项
|
|
92
|
-
* @returns 交易收据或交易数据
|
|
93
|
-
*/
|
|
94
|
-
async sendERC20(recipient, tokenAddress, amount, data = "0x", options) {
|
|
95
|
-
// 如果需要发送交易,但没有钱包客户端或账户
|
|
96
|
-
if (options?.sendTransaction !== false &&
|
|
97
|
-
(!this.walletClient || !this.account)) {
|
|
98
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
99
|
-
}
|
|
100
|
-
// 如果需要自动批准,则先批准代币(默认开启自动批准)
|
|
101
|
-
if (options?.autoApprove !== false && this.walletClient && this.account) {
|
|
102
|
-
try {
|
|
103
|
-
console.log(`Checking ERC20 token approval status: ${tokenAddress}`);
|
|
104
|
-
// 检查授权
|
|
105
|
-
const allowance = (await this.publicClient.readContract({
|
|
106
|
-
address: tokenAddress,
|
|
107
|
-
abi: constants_1.ERC20_ABI,
|
|
108
|
-
functionName: "allowance",
|
|
109
|
-
args: [this.account.address, this.contracts?.anchorPay],
|
|
110
|
-
}));
|
|
111
|
-
console.log(`Current allowance: ${allowance}, Required amount: ${amount}, AnchorPay contract address: ${this.contracts?.anchorPay}`);
|
|
112
|
-
if (allowance < amount) {
|
|
113
|
-
console.log(`Approving ${amount} tokens to AnchorPay contract...`);
|
|
114
|
-
// 批准代币 - 使用最大可能值进行授权,避免多次授权
|
|
115
|
-
const maxApproveAmount = 2n ** 256n - 1n;
|
|
116
|
-
// 估算 gas 和费用
|
|
117
|
-
const { maxFeePerGas: approveMaxFeePerGas, maxPriorityFeePerGas: approveMaxPriorityFeePerGas, } = await this.publicClient.estimateFeesPerGas();
|
|
118
|
-
const approveCalldata = (0, viem_1.encodeFunctionData)({
|
|
119
|
-
abi: constants_1.ERC20_ABI,
|
|
120
|
-
functionName: "approve",
|
|
121
|
-
args: [this.contracts?.anchorPay, maxApproveAmount],
|
|
122
|
-
});
|
|
123
|
-
const approveGas = await this.publicClient.estimateGas({
|
|
124
|
-
to: tokenAddress,
|
|
125
|
-
data: approveCalldata,
|
|
126
|
-
value: 0n,
|
|
127
|
-
account: this.account,
|
|
128
|
-
});
|
|
129
|
-
const approveTxHash = await this.walletClient.writeContract({
|
|
130
|
-
account: this.account,
|
|
131
|
-
address: tokenAddress,
|
|
132
|
-
abi: constants_1.ERC20_ABI,
|
|
133
|
-
functionName: "approve",
|
|
134
|
-
args: [this.contracts?.anchorPay, maxApproveAmount],
|
|
135
|
-
chain: this.publicClient.chain,
|
|
136
|
-
maxFeePerGas: approveMaxFeePerGas,
|
|
137
|
-
maxPriorityFeePerGas: approveMaxPriorityFeePerGas,
|
|
138
|
-
gas: approveGas,
|
|
139
|
-
});
|
|
140
|
-
console.log(`Approval transaction sent, hash: ${approveTxHash}`);
|
|
141
|
-
// 等待交易确认
|
|
142
|
-
await this.publicClient.waitForTransactionReceipt({
|
|
143
|
-
hash: approveTxHash,
|
|
144
|
-
});
|
|
145
|
-
console.log(`Approval transaction confirmed`);
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
console.log(`Sufficient allowance already exists, no need for additional approval`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
catch (error) {
|
|
152
|
-
console.error(`Approval failed:`, error);
|
|
153
|
-
throw new Error(`ERC20 approval failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
// 准备交易数据
|
|
157
|
-
const calldata = (0, viem_1.encodeFunctionData)({
|
|
158
|
-
abi: AnchorPay_json_1.default,
|
|
159
|
-
functionName: "send",
|
|
160
|
-
args: [recipient, tokenAddress, amount, data],
|
|
161
|
-
});
|
|
162
|
-
// 如果不需要发送交易,只返回交易数据(AA 模式)
|
|
163
|
-
if (options?.sendTransaction === false) {
|
|
164
|
-
return {
|
|
165
|
-
to: this.contracts?.anchorPay || "",
|
|
166
|
-
data: calldata,
|
|
167
|
-
value: 0n,
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
// 估算 gas 和费用
|
|
171
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas();
|
|
172
|
-
const gas = await this.publicClient.estimateGas({
|
|
173
|
-
to: this.contracts?.anchorPay || "",
|
|
174
|
-
data: calldata,
|
|
175
|
-
value: 0n,
|
|
176
|
-
account: this.account,
|
|
177
|
-
});
|
|
178
|
-
// 发送交易(EOA 模式)
|
|
179
|
-
if (!this.walletClient || !this.account) {
|
|
180
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
181
|
-
}
|
|
182
|
-
const txHash = await this.walletClient.sendTransaction({
|
|
183
|
-
account: this.account,
|
|
184
|
-
to: this.contracts?.anchorPay || "",
|
|
185
|
-
data: calldata,
|
|
186
|
-
// value: amount,
|
|
187
|
-
maxFeePerGas: options?.maxFeePerGas || maxFeePerGas,
|
|
188
|
-
maxPriorityFeePerGas: options?.maxPriorityFeePerGas || maxPriorityFeePerGas,
|
|
189
|
-
gas: options?.gas || gas,
|
|
190
|
-
chain: this.publicClient.chain,
|
|
191
|
-
});
|
|
192
|
-
// 等待交易确认并返回收据
|
|
193
|
-
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
194
|
-
hash: txHash,
|
|
195
|
-
});
|
|
196
|
-
return receipt;
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* 获取接口实现者
|
|
200
|
-
* @param account 账户地址
|
|
201
|
-
* @param interfaceHash 接口哈希
|
|
202
|
-
* @returns 实现者地址
|
|
203
|
-
*/
|
|
204
|
-
async getInterfaceImplementer(account, interfaceHash) {
|
|
205
|
-
return (await this.publicClient.readContract({
|
|
206
|
-
address: this.contracts?.anchorPay || "",
|
|
207
|
-
abi: AnchorPay_json_1.default,
|
|
208
|
-
functionName: "getInterfaceImplementer",
|
|
209
|
-
args: [account, interfaceHash],
|
|
210
|
-
}));
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* 设置接口实现者(仅限管理员)
|
|
214
|
-
* @param account 账户地址
|
|
215
|
-
* @param interfaceHash 接口哈希
|
|
216
|
-
* @param implementer 实现者地址
|
|
217
|
-
* @returns 交易收据
|
|
218
|
-
*/
|
|
219
|
-
async setInterfaceImplementer(account, interfaceHash, implementer) {
|
|
220
|
-
if (!this.walletClient || !this.account) {
|
|
221
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
222
|
-
}
|
|
223
|
-
// 估算 gas 和费用
|
|
224
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas();
|
|
225
|
-
const calldata = (0, viem_1.encodeFunctionData)({
|
|
226
|
-
abi: AnchorPay_json_1.default,
|
|
227
|
-
functionName: "setInterfaceImplementer",
|
|
228
|
-
args: [account, interfaceHash, implementer],
|
|
229
|
-
});
|
|
230
|
-
const gas = await this.publicClient.estimateGas({
|
|
231
|
-
to: this.contracts?.anchorPay || "",
|
|
232
|
-
data: calldata,
|
|
233
|
-
value: 0n,
|
|
234
|
-
account: this.account,
|
|
235
|
-
});
|
|
236
|
-
const txHash = await this.walletClient.writeContract({
|
|
237
|
-
account: this.account,
|
|
238
|
-
address: this.contracts?.anchorPay || "",
|
|
239
|
-
abi: AnchorPay_json_1.default,
|
|
240
|
-
functionName: "setInterfaceImplementer",
|
|
241
|
-
args: [account, interfaceHash, implementer],
|
|
242
|
-
chain: this.publicClient.chain,
|
|
243
|
-
maxFeePerGas,
|
|
244
|
-
maxPriorityFeePerGas,
|
|
245
|
-
gas,
|
|
246
|
-
});
|
|
247
|
-
// 等待交易确认并返回收据
|
|
248
|
-
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
249
|
-
hash: txHash,
|
|
250
|
-
});
|
|
251
|
-
return receipt;
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* 获取 ERC20 代币批准的交易数据(用于 AA 模式)
|
|
255
|
-
* @param tokenAddress ERC20 代币地址
|
|
256
|
-
* @param amount 批准金额
|
|
257
|
-
* @param spender 花费者地址(默认为 AnchorPay 合约地址)
|
|
258
|
-
* @returns 交易数据对象,包含 to、data 和 value 字段
|
|
259
|
-
*/
|
|
260
|
-
getERC20ApprovalData(tokenAddress, amount, spender) {
|
|
261
|
-
const approveSpender = spender || this.contracts?.anchorPay || "";
|
|
262
|
-
// 编码 approve 函数调用
|
|
263
|
-
const data = (0, viem_1.encodeFunctionData)({
|
|
264
|
-
abi: constants_1.ERC20_ABI,
|
|
265
|
-
functionName: "approve",
|
|
266
|
-
args: [approveSpender, amount],
|
|
267
|
-
});
|
|
268
|
-
return {
|
|
269
|
-
to: tokenAddress,
|
|
270
|
-
data,
|
|
271
|
-
value: 0n, // ERC20 批准不需要发送 ETH
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* 查询账户在 AnchorPay 合约中的代币余额
|
|
276
|
-
* @param account 账户地址
|
|
277
|
-
* @param token 代币地址(使用 NATIVE_TOKEN_ADDRESS 表示原生代币)
|
|
278
|
-
* @returns 余额
|
|
279
|
-
*/
|
|
280
|
-
async balanceOf(account, token) {
|
|
281
|
-
return (await this.publicClient.readContract({
|
|
282
|
-
address: this.contracts?.anchorPay || "",
|
|
283
|
-
abi: AnchorPay_json_1.default,
|
|
284
|
-
functionName: "balanceOf",
|
|
285
|
-
args: [account, token],
|
|
286
|
-
}));
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* 为指定地址存入 ETH 到 AnchorPay 合约
|
|
290
|
-
* @param recipient 接收者地址
|
|
291
|
-
* @param amount 金额(单位:wei)
|
|
292
|
-
* @param options 交易选项
|
|
293
|
-
* @returns 交易收据或交易数据
|
|
294
|
-
*/
|
|
295
|
-
async depositETH(recipient, amount, options) {
|
|
296
|
-
// 如果需要发送交易,但没有钱包客户端或账户
|
|
297
|
-
if (options?.sendTransaction !== false &&
|
|
298
|
-
(!this.walletClient || !this.account)) {
|
|
299
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
300
|
-
}
|
|
301
|
-
// 准备交易数据
|
|
302
|
-
const calldata = (0, viem_1.encodeFunctionData)({
|
|
303
|
-
abi: AnchorPay_json_1.default,
|
|
304
|
-
functionName: "depositFor",
|
|
305
|
-
args: [recipient, constants_1.NATIVE_TOKEN_ADDRESS, amount],
|
|
306
|
-
});
|
|
307
|
-
// 如果不需要发送交易,只返回交易数据(AA 模式)
|
|
308
|
-
if (options?.sendTransaction === false) {
|
|
309
|
-
return {
|
|
310
|
-
to: this.contracts?.anchorPay || "",
|
|
311
|
-
data: calldata,
|
|
312
|
-
value: amount,
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
// 估算 gas 和费用
|
|
316
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas();
|
|
317
|
-
const gas = await this.publicClient.estimateGas({
|
|
318
|
-
to: this.contracts?.anchorPay || "",
|
|
319
|
-
data: calldata,
|
|
320
|
-
value: amount,
|
|
321
|
-
account: this.account,
|
|
322
|
-
});
|
|
323
|
-
// 发送交易(EOA 模式)
|
|
324
|
-
if (!this.walletClient || !this.account) {
|
|
325
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
326
|
-
}
|
|
327
|
-
const txHash = await this.walletClient.sendTransaction({
|
|
328
|
-
account: this.account,
|
|
329
|
-
to: this.contracts?.anchorPay || "",
|
|
330
|
-
data: calldata,
|
|
331
|
-
value: amount,
|
|
332
|
-
maxFeePerGas: options?.maxFeePerGas || maxFeePerGas,
|
|
333
|
-
maxPriorityFeePerGas: options?.maxPriorityFeePerGas || maxPriorityFeePerGas,
|
|
334
|
-
gas: options?.gas || gas,
|
|
335
|
-
chain: this.publicClient.chain,
|
|
336
|
-
});
|
|
337
|
-
// 等待交易确认并返回收据
|
|
338
|
-
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
339
|
-
hash: txHash,
|
|
340
|
-
});
|
|
341
|
-
return receipt;
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* 为指定地址存入 ERC20 代币到 AnchorPay 合约
|
|
345
|
-
* @param recipient 接收者地址
|
|
346
|
-
* @param tokenAddress ERC20 代币地址
|
|
347
|
-
* @param amount 金额
|
|
348
|
-
* @param options 交易选项
|
|
349
|
-
* @returns 交易收据或交易数据
|
|
350
|
-
*/
|
|
351
|
-
async depositERC20(recipient, tokenAddress, amount, options) {
|
|
352
|
-
// 如果需要发送交易,但没有钱包客户端或账户
|
|
353
|
-
if (options?.sendTransaction !== false &&
|
|
354
|
-
(!this.walletClient || !this.account)) {
|
|
355
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
356
|
-
}
|
|
357
|
-
// 如果需要自动批准,则先批准代币(默认开启自动批准)
|
|
358
|
-
if (options?.autoApprove !== false && this.walletClient && this.account) {
|
|
359
|
-
try {
|
|
360
|
-
console.log(`Checking ERC20 token approval status: ${tokenAddress}`);
|
|
361
|
-
// 检查授权
|
|
362
|
-
const allowance = (await this.publicClient.readContract({
|
|
363
|
-
address: tokenAddress,
|
|
364
|
-
abi: constants_1.ERC20_ABI,
|
|
365
|
-
functionName: "allowance",
|
|
366
|
-
args: [this.account.address, this.contracts?.anchorPay],
|
|
367
|
-
}));
|
|
368
|
-
console.log(`Current allowance: ${allowance}, Required amount: ${amount}, AnchorPay contract address: ${this.contracts?.anchorPay}`);
|
|
369
|
-
if (allowance < amount) {
|
|
370
|
-
console.log(`Approving ${amount} tokens to AnchorPay contract...`);
|
|
371
|
-
// 批准代币 - 使用最大可能值进行授权,避免多次授权
|
|
372
|
-
const maxApproveAmount = 2n ** 256n - 1n;
|
|
373
|
-
// 估算 gas 和费用
|
|
374
|
-
const { maxFeePerGas: approveMaxFeePerGas, maxPriorityFeePerGas: approveMaxPriorityFeePerGas, } = await this.publicClient.estimateFeesPerGas();
|
|
375
|
-
const approveCalldata = (0, viem_1.encodeFunctionData)({
|
|
376
|
-
abi: constants_1.ERC20_ABI,
|
|
377
|
-
functionName: "approve",
|
|
378
|
-
args: [this.contracts?.anchorPay, maxApproveAmount],
|
|
379
|
-
});
|
|
380
|
-
const approveGas = await this.publicClient.estimateGas({
|
|
381
|
-
to: tokenAddress,
|
|
382
|
-
data: approveCalldata,
|
|
383
|
-
value: 0n,
|
|
384
|
-
account: this.account,
|
|
385
|
-
});
|
|
386
|
-
const approveTxHash = await this.walletClient.writeContract({
|
|
387
|
-
account: this.account,
|
|
388
|
-
address: tokenAddress,
|
|
389
|
-
abi: constants_1.ERC20_ABI,
|
|
390
|
-
functionName: "approve",
|
|
391
|
-
args: [this.contracts?.anchorPay, maxApproveAmount],
|
|
392
|
-
chain: this.publicClient.chain,
|
|
393
|
-
maxFeePerGas: approveMaxFeePerGas,
|
|
394
|
-
maxPriorityFeePerGas: approveMaxPriorityFeePerGas,
|
|
395
|
-
gas: approveGas,
|
|
396
|
-
});
|
|
397
|
-
console.log(`Approval transaction sent, hash: ${approveTxHash}`);
|
|
398
|
-
// 等待交易确认
|
|
399
|
-
await this.publicClient.waitForTransactionReceipt({
|
|
400
|
-
hash: approveTxHash,
|
|
401
|
-
});
|
|
402
|
-
console.log(`Approval transaction confirmed`);
|
|
403
|
-
}
|
|
404
|
-
else {
|
|
405
|
-
console.log(`Sufficient allowance already exists, no need for additional approval`);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
catch (error) {
|
|
409
|
-
console.error(`Approval failed:`, error);
|
|
410
|
-
throw new Error(`ERC20 approval failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
// 准备交易数据
|
|
414
|
-
const calldata = (0, viem_1.encodeFunctionData)({
|
|
415
|
-
abi: AnchorPay_json_1.default,
|
|
416
|
-
functionName: "depositFor",
|
|
417
|
-
args: [recipient, tokenAddress, amount],
|
|
418
|
-
});
|
|
419
|
-
// 如果不需要发送交易,只返回交易数据(AA 模式)
|
|
420
|
-
if (options?.sendTransaction === false) {
|
|
421
|
-
return {
|
|
422
|
-
to: this.contracts?.anchorPay || "",
|
|
423
|
-
data: calldata,
|
|
424
|
-
value: 0n,
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
// 估算 gas 和费用
|
|
428
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas();
|
|
429
|
-
const gas = await this.publicClient.estimateGas({
|
|
430
|
-
to: this.contracts?.anchorPay || "",
|
|
431
|
-
data: calldata,
|
|
432
|
-
value: 0n,
|
|
433
|
-
account: this.account,
|
|
434
|
-
});
|
|
435
|
-
// 发送交易(EOA 模式)
|
|
436
|
-
if (!this.walletClient || !this.account) {
|
|
437
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
438
|
-
}
|
|
439
|
-
const txHash = await this.walletClient.sendTransaction({
|
|
440
|
-
account: this.account,
|
|
441
|
-
to: this.contracts?.anchorPay || "",
|
|
442
|
-
data: calldata,
|
|
443
|
-
maxFeePerGas: options?.maxFeePerGas || maxFeePerGas,
|
|
444
|
-
maxPriorityFeePerGas: options?.maxPriorityFeePerGas || maxPriorityFeePerGas,
|
|
445
|
-
gas: options?.gas || gas,
|
|
446
|
-
chain: this.publicClient.chain,
|
|
447
|
-
});
|
|
448
|
-
// 等待交易确认并返回收据
|
|
449
|
-
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
450
|
-
hash: txHash,
|
|
451
|
-
});
|
|
452
|
-
return receipt;
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* 从 AnchorPay 合约提取代币
|
|
456
|
-
* @param tokenAddress 代币地址(使用 NATIVE_TOKEN_ADDRESS 表示原生代币)
|
|
457
|
-
* @param amount 金额
|
|
458
|
-
* @param options 交易选项
|
|
459
|
-
* @returns 交易收据
|
|
460
|
-
*/
|
|
461
|
-
async withdraw(tokenAddress, amount, options) {
|
|
462
|
-
if (!this.walletClient || !this.account) {
|
|
463
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
464
|
-
}
|
|
465
|
-
// 估算 gas 和费用
|
|
466
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas();
|
|
467
|
-
const calldata = (0, viem_1.encodeFunctionData)({
|
|
468
|
-
abi: AnchorPay_json_1.default,
|
|
469
|
-
functionName: "withdraw",
|
|
470
|
-
args: [tokenAddress, amount],
|
|
471
|
-
});
|
|
472
|
-
const gas = await this.publicClient.estimateGas({
|
|
473
|
-
to: this.contracts?.anchorPay || "",
|
|
474
|
-
data: calldata,
|
|
475
|
-
value: 0n,
|
|
476
|
-
account: this.account,
|
|
477
|
-
});
|
|
478
|
-
const txHash = await this.walletClient.sendTransaction({
|
|
479
|
-
account: this.account,
|
|
480
|
-
to: this.contracts?.anchorPay || "",
|
|
481
|
-
data: calldata,
|
|
482
|
-
maxFeePerGas: options?.maxFeePerGas || maxFeePerGas,
|
|
483
|
-
maxPriorityFeePerGas: options?.maxPriorityFeePerGas || maxPriorityFeePerGas,
|
|
484
|
-
gas: options?.gas || gas,
|
|
485
|
-
chain: this.publicClient.chain,
|
|
486
|
-
});
|
|
487
|
-
// 等待交易确认并返回收据
|
|
488
|
-
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
489
|
-
hash: txHash,
|
|
490
|
-
});
|
|
491
|
-
return receipt;
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* 批量存入 ETH(使用 Multicall3)
|
|
495
|
-
* @param deposits 批量存款参数数组,每项包含接收者地址和金额
|
|
496
|
-
* @param options 交易选项
|
|
497
|
-
* @returns 交易收据或交易数据
|
|
498
|
-
*/
|
|
499
|
-
async batchDepositETH(deposits, options) {
|
|
500
|
-
if (deposits.length === 0) {
|
|
501
|
-
throw new Error("No deposits provided");
|
|
502
|
-
}
|
|
503
|
-
// 如果需要发送交易,但没有钱包客户端或账户
|
|
504
|
-
if (options?.sendTransaction !== false &&
|
|
505
|
-
(!this.walletClient || !this.account)) {
|
|
506
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
507
|
-
}
|
|
508
|
-
// 准备批量调用数据
|
|
509
|
-
const calls = deposits.map((deposit) => {
|
|
510
|
-
const calldata = (0, viem_1.encodeFunctionData)({
|
|
511
|
-
abi: AnchorPay_json_1.default,
|
|
512
|
-
functionName: "depositFor",
|
|
513
|
-
args: [deposit.recipient, constants_1.NATIVE_TOKEN_ADDRESS, deposit.amount],
|
|
514
|
-
});
|
|
515
|
-
return {
|
|
516
|
-
target: this.contracts?.anchorPay || "",
|
|
517
|
-
allowFailure: false,
|
|
518
|
-
value: deposit.amount,
|
|
519
|
-
callData: calldata,
|
|
520
|
-
};
|
|
521
|
-
});
|
|
522
|
-
// 计算总金额
|
|
523
|
-
const totalValue = deposits.reduce((sum, deposit) => sum + deposit.amount, 0n);
|
|
524
|
-
// 编码 Multicall3 调用
|
|
525
|
-
const multicallData = (0, viem_1.encodeFunctionData)({
|
|
526
|
-
abi: constants_1.MULTICALL3_ABI,
|
|
527
|
-
functionName: "aggregate3Value",
|
|
528
|
-
args: [calls],
|
|
529
|
-
});
|
|
530
|
-
// 如果不需要发送交易,只返回交易数据(AA 模式)
|
|
531
|
-
if (options?.sendTransaction === false) {
|
|
532
|
-
return {
|
|
533
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
534
|
-
data: multicallData,
|
|
535
|
-
value: totalValue,
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
|
-
// 估算 gas 和费用
|
|
539
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas();
|
|
540
|
-
const gas = await this.publicClient.estimateGas({
|
|
541
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
542
|
-
data: multicallData,
|
|
543
|
-
value: totalValue,
|
|
544
|
-
account: this.account,
|
|
545
|
-
});
|
|
546
|
-
// 发送交易(EOA 模式)
|
|
547
|
-
if (!this.walletClient || !this.account) {
|
|
548
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
549
|
-
}
|
|
550
|
-
const txHash = await this.walletClient.sendTransaction({
|
|
551
|
-
account: this.account,
|
|
552
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
553
|
-
data: multicallData,
|
|
554
|
-
value: totalValue,
|
|
555
|
-
maxFeePerGas: options?.maxFeePerGas || maxFeePerGas,
|
|
556
|
-
maxPriorityFeePerGas: options?.maxPriorityFeePerGas || maxPriorityFeePerGas,
|
|
557
|
-
gas: options?.gas || gas,
|
|
558
|
-
chain: this.publicClient.chain,
|
|
559
|
-
});
|
|
560
|
-
// 等待交易确认并返回收据
|
|
561
|
-
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
562
|
-
hash: txHash,
|
|
563
|
-
});
|
|
564
|
-
return receipt;
|
|
565
|
-
}
|
|
566
|
-
/**
|
|
567
|
-
* 批量存入 ERC20 代币(使用 Multicall3)
|
|
568
|
-
* @param tokenAddress ERC20 代币地址
|
|
569
|
-
* @param deposits 批量存款参数数组
|
|
570
|
-
* @param options 交易选项
|
|
571
|
-
* @returns 交易收据或交易数据
|
|
572
|
-
*/
|
|
573
|
-
async batchDepositERC20(tokenAddress, deposits, options) {
|
|
574
|
-
if (deposits.length === 0) {
|
|
575
|
-
throw new Error("No deposits provided");
|
|
576
|
-
}
|
|
577
|
-
// 如果需要发送交易,但没有钱包客户端或账户
|
|
578
|
-
if (options?.sendTransaction !== false &&
|
|
579
|
-
(!this.walletClient || !this.account)) {
|
|
580
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
581
|
-
}
|
|
582
|
-
// 计算总金额(用于批准检查)
|
|
583
|
-
const totalAmount = deposits.reduce((sum, deposit) => sum + deposit.amount, 0n);
|
|
584
|
-
// 如果需要自动批准,则先批准代币(默认开启自动批准)
|
|
585
|
-
if (options?.autoApprove !== false && this.walletClient && this.account) {
|
|
586
|
-
try {
|
|
587
|
-
console.log(`Checking ERC20 token approval status: ${tokenAddress}`);
|
|
588
|
-
// 检查授权
|
|
589
|
-
const allowance = (await this.publicClient.readContract({
|
|
590
|
-
address: tokenAddress,
|
|
591
|
-
abi: constants_1.ERC20_ABI,
|
|
592
|
-
functionName: "allowance",
|
|
593
|
-
args: [this.account.address, this.contracts?.anchorPay],
|
|
594
|
-
}));
|
|
595
|
-
console.log(`Current allowance: ${allowance}, Required amount: ${totalAmount}, AnchorPay contract address: ${this.contracts?.anchorPay}`);
|
|
596
|
-
if (allowance < totalAmount) {
|
|
597
|
-
console.log(`Approving ${totalAmount} tokens to AnchorPay contract...`);
|
|
598
|
-
// 批准代币 - 使用最大可能值进行授权,避免多次授权
|
|
599
|
-
const maxApproveAmount = 2n ** 256n - 1n;
|
|
600
|
-
// 估算 gas 和费用
|
|
601
|
-
const { maxFeePerGas: approveMaxFeePerGas, maxPriorityFeePerGas: approveMaxPriorityFeePerGas, } = await this.publicClient.estimateFeesPerGas();
|
|
602
|
-
const approveCalldata = (0, viem_1.encodeFunctionData)({
|
|
603
|
-
abi: constants_1.ERC20_ABI,
|
|
604
|
-
functionName: "approve",
|
|
605
|
-
args: [this.contracts?.anchorPay, maxApproveAmount],
|
|
606
|
-
});
|
|
607
|
-
const approveGas = await this.publicClient.estimateGas({
|
|
608
|
-
to: tokenAddress,
|
|
609
|
-
data: approveCalldata,
|
|
610
|
-
value: 0n,
|
|
611
|
-
account: this.account,
|
|
612
|
-
});
|
|
613
|
-
const approveTxHash = await this.walletClient.writeContract({
|
|
614
|
-
account: this.account,
|
|
615
|
-
address: tokenAddress,
|
|
616
|
-
abi: constants_1.ERC20_ABI,
|
|
617
|
-
functionName: "approve",
|
|
618
|
-
args: [this.contracts?.anchorPay, maxApproveAmount],
|
|
619
|
-
chain: this.publicClient.chain,
|
|
620
|
-
maxFeePerGas: approveMaxFeePerGas,
|
|
621
|
-
maxPriorityFeePerGas: approveMaxPriorityFeePerGas,
|
|
622
|
-
gas: approveGas,
|
|
623
|
-
});
|
|
624
|
-
console.log(`Approval transaction sent, hash: ${approveTxHash}`);
|
|
625
|
-
// 等待交易确认
|
|
626
|
-
await this.publicClient.waitForTransactionReceipt({
|
|
627
|
-
hash: approveTxHash,
|
|
628
|
-
});
|
|
629
|
-
console.log(`Approval transaction confirmed`);
|
|
630
|
-
}
|
|
631
|
-
else {
|
|
632
|
-
console.log(`Sufficient allowance already exists, no need for additional approval`);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
catch (error) {
|
|
636
|
-
console.error(`Approval failed:`, error);
|
|
637
|
-
throw new Error(`ERC20 approval failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
// 准备批量调用数据
|
|
641
|
-
const calls = deposits.map((deposit) => {
|
|
642
|
-
const calldata = (0, viem_1.encodeFunctionData)({
|
|
643
|
-
abi: AnchorPay_json_1.default,
|
|
644
|
-
functionName: "depositFor",
|
|
645
|
-
args: [deposit.recipient, tokenAddress, deposit.amount],
|
|
646
|
-
});
|
|
647
|
-
return {
|
|
648
|
-
target: this.contracts?.anchorPay || "",
|
|
649
|
-
allowFailure: false,
|
|
650
|
-
value: 0n,
|
|
651
|
-
callData: calldata,
|
|
652
|
-
};
|
|
653
|
-
});
|
|
654
|
-
// 编码 Multicall3 调用
|
|
655
|
-
const multicallData = (0, viem_1.encodeFunctionData)({
|
|
656
|
-
abi: constants_1.MULTICALL3_ABI,
|
|
657
|
-
functionName: "aggregate3Value",
|
|
658
|
-
args: [calls],
|
|
659
|
-
});
|
|
660
|
-
// 如果不需要发送交易,只返回交易数据(AA 模式)
|
|
661
|
-
if (options?.sendTransaction === false) {
|
|
662
|
-
return {
|
|
663
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
664
|
-
data: multicallData,
|
|
665
|
-
value: 0n,
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
// 估算 gas 和费用
|
|
669
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas();
|
|
670
|
-
const gas = await this.publicClient.estimateGas({
|
|
671
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
672
|
-
data: multicallData,
|
|
673
|
-
value: 0n,
|
|
674
|
-
account: this.account,
|
|
675
|
-
});
|
|
676
|
-
// 发送交易(EOA 模式)
|
|
677
|
-
if (!this.walletClient || !this.account) {
|
|
678
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
679
|
-
}
|
|
680
|
-
const txHash = await this.walletClient.sendTransaction({
|
|
681
|
-
account: this.account,
|
|
682
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
683
|
-
data: multicallData,
|
|
684
|
-
maxFeePerGas: options?.maxFeePerGas || maxFeePerGas,
|
|
685
|
-
maxPriorityFeePerGas: options?.maxPriorityFeePerGas || maxPriorityFeePerGas,
|
|
686
|
-
gas: options?.gas || gas,
|
|
687
|
-
chain: this.publicClient.chain,
|
|
688
|
-
});
|
|
689
|
-
// 等待交易确认并返回收据
|
|
690
|
-
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
691
|
-
hash: txHash,
|
|
692
|
-
});
|
|
693
|
-
return receipt;
|
|
694
|
-
}
|
|
695
|
-
/**
|
|
696
|
-
* 批量发送 ETH(使用 Multicall3)
|
|
697
|
-
* @param transfers 批量转账参数数组
|
|
698
|
-
* @param options 交易选项
|
|
699
|
-
* @returns 交易收据或交易数据
|
|
700
|
-
*/
|
|
701
|
-
async batchSendETH(transfers, options) {
|
|
702
|
-
if (transfers.length === 0) {
|
|
703
|
-
throw new Error("No transfers provided");
|
|
704
|
-
}
|
|
705
|
-
// 如果需要发送交易,但没有钱包客户端或账户
|
|
706
|
-
if (options?.sendTransaction !== false &&
|
|
707
|
-
(!this.walletClient || !this.account)) {
|
|
708
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
709
|
-
}
|
|
710
|
-
// 准备批量调用数据
|
|
711
|
-
const calls = transfers.map((transfer) => {
|
|
712
|
-
const calldata = (0, viem_1.encodeFunctionData)({
|
|
713
|
-
abi: AnchorPay_json_1.default,
|
|
714
|
-
functionName: "send",
|
|
715
|
-
args: [
|
|
716
|
-
transfer.recipient,
|
|
717
|
-
constants_1.NATIVE_TOKEN_ADDRESS,
|
|
718
|
-
transfer.amount,
|
|
719
|
-
transfer.data || "0x",
|
|
720
|
-
],
|
|
721
|
-
});
|
|
722
|
-
return {
|
|
723
|
-
target: this.contracts?.anchorPay || "",
|
|
724
|
-
allowFailure: false,
|
|
725
|
-
value: transfer.amount,
|
|
726
|
-
callData: calldata,
|
|
727
|
-
};
|
|
728
|
-
});
|
|
729
|
-
// 计算总金额
|
|
730
|
-
const totalValue = transfers.reduce((sum, transfer) => sum + transfer.amount, 0n);
|
|
731
|
-
// 编码 Multicall3 调用
|
|
732
|
-
const multicallData = (0, viem_1.encodeFunctionData)({
|
|
733
|
-
abi: constants_1.MULTICALL3_ABI,
|
|
734
|
-
functionName: "aggregate3Value",
|
|
735
|
-
args: [calls],
|
|
736
|
-
});
|
|
737
|
-
// 如果不需要发送交易,只返回交易数据(AA 模式)
|
|
738
|
-
if (options?.sendTransaction === false) {
|
|
739
|
-
return {
|
|
740
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
741
|
-
data: multicallData,
|
|
742
|
-
value: totalValue,
|
|
743
|
-
};
|
|
744
|
-
}
|
|
745
|
-
// 估算 gas 和费用
|
|
746
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas();
|
|
747
|
-
const gas = await this.publicClient.estimateGas({
|
|
748
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
749
|
-
data: multicallData,
|
|
750
|
-
value: totalValue,
|
|
751
|
-
account: this.account,
|
|
752
|
-
});
|
|
753
|
-
// 发送交易(EOA 模式)
|
|
754
|
-
if (!this.walletClient || !this.account) {
|
|
755
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
756
|
-
}
|
|
757
|
-
const txHash = await this.walletClient.sendTransaction({
|
|
758
|
-
account: this.account,
|
|
759
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
760
|
-
data: multicallData,
|
|
761
|
-
value: totalValue,
|
|
762
|
-
maxFeePerGas: options?.maxFeePerGas || maxFeePerGas,
|
|
763
|
-
maxPriorityFeePerGas: options?.maxPriorityFeePerGas || maxPriorityFeePerGas,
|
|
764
|
-
gas: options?.gas || gas,
|
|
765
|
-
chain: this.publicClient.chain,
|
|
766
|
-
});
|
|
767
|
-
// 等待交易确认并返回收据
|
|
768
|
-
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
769
|
-
hash: txHash,
|
|
770
|
-
});
|
|
771
|
-
return receipt;
|
|
772
|
-
}
|
|
773
|
-
/**
|
|
774
|
-
* 批量发送 ERC20 代币(使用 Multicall3)
|
|
775
|
-
* @param tokenAddress ERC20 代币地址
|
|
776
|
-
* @param transfers 批量转账参数数组
|
|
777
|
-
* @param options 交易选项
|
|
778
|
-
* @returns 交易收据或交易数据
|
|
779
|
-
*/
|
|
780
|
-
async batchSendERC20(tokenAddress, transfers, options) {
|
|
781
|
-
if (transfers.length === 0) {
|
|
782
|
-
throw new Error("No transfers provided");
|
|
783
|
-
}
|
|
784
|
-
// 如果需要发送交易,但没有钱包客户端或账户
|
|
785
|
-
if (options?.sendTransaction !== false &&
|
|
786
|
-
(!this.walletClient || !this.account)) {
|
|
787
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
788
|
-
}
|
|
789
|
-
// 计算总金额(用于批准检查)
|
|
790
|
-
const totalAmount = transfers.reduce((sum, transfer) => sum + transfer.amount, 0n);
|
|
791
|
-
// 如果需要自动批准,则先批准代币(默认开启自动批准)
|
|
792
|
-
if (options?.autoApprove !== false && this.walletClient && this.account) {
|
|
793
|
-
try {
|
|
794
|
-
console.log(`Checking ERC20 token approval status: ${tokenAddress}`);
|
|
795
|
-
// 检查授权
|
|
796
|
-
const allowance = (await this.publicClient.readContract({
|
|
797
|
-
address: tokenAddress,
|
|
798
|
-
abi: constants_1.ERC20_ABI,
|
|
799
|
-
functionName: "allowance",
|
|
800
|
-
args: [this.account.address, this.contracts?.anchorPay],
|
|
801
|
-
}));
|
|
802
|
-
console.log(`Current allowance: ${allowance}, Required amount: ${totalAmount}, AnchorPay contract address: ${this.contracts?.anchorPay}`);
|
|
803
|
-
if (allowance < totalAmount) {
|
|
804
|
-
console.log(`Approving ${totalAmount} tokens to AnchorPay contract...`);
|
|
805
|
-
// 批准代币 - 使用最大可能值进行授权,避免多次授权
|
|
806
|
-
const maxApproveAmount = 2n ** 256n - 1n;
|
|
807
|
-
// 估算 gas 和费用
|
|
808
|
-
const { maxFeePerGas: approveMaxFeePerGas, maxPriorityFeePerGas: approveMaxPriorityFeePerGas, } = await this.publicClient.estimateFeesPerGas();
|
|
809
|
-
const approveCalldata = (0, viem_1.encodeFunctionData)({
|
|
810
|
-
abi: constants_1.ERC20_ABI,
|
|
811
|
-
functionName: "approve",
|
|
812
|
-
args: [this.contracts?.anchorPay, maxApproveAmount],
|
|
813
|
-
});
|
|
814
|
-
const approveGas = await this.publicClient.estimateGas({
|
|
815
|
-
to: tokenAddress,
|
|
816
|
-
data: approveCalldata,
|
|
817
|
-
value: 0n,
|
|
818
|
-
account: this.account,
|
|
819
|
-
});
|
|
820
|
-
const approveTxHash = await this.walletClient.writeContract({
|
|
821
|
-
account: this.account,
|
|
822
|
-
address: tokenAddress,
|
|
823
|
-
abi: constants_1.ERC20_ABI,
|
|
824
|
-
functionName: "approve",
|
|
825
|
-
args: [this.contracts?.anchorPay, maxApproveAmount],
|
|
826
|
-
chain: this.publicClient.chain,
|
|
827
|
-
maxFeePerGas: approveMaxFeePerGas,
|
|
828
|
-
maxPriorityFeePerGas: approveMaxPriorityFeePerGas,
|
|
829
|
-
gas: approveGas,
|
|
830
|
-
});
|
|
831
|
-
console.log(`Approval transaction sent, hash: ${approveTxHash}`);
|
|
832
|
-
// 等待交易确认
|
|
833
|
-
await this.publicClient.waitForTransactionReceipt({
|
|
834
|
-
hash: approveTxHash,
|
|
835
|
-
});
|
|
836
|
-
console.log(`Approval transaction confirmed`);
|
|
837
|
-
}
|
|
838
|
-
else {
|
|
839
|
-
console.log(`Sufficient allowance already exists, no need for additional approval`);
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
catch (error) {
|
|
843
|
-
console.error(`Approval failed:`, error);
|
|
844
|
-
throw new Error(`ERC20 approval failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
// 准备批量调用数据
|
|
848
|
-
const calls = transfers.map((transfer) => {
|
|
849
|
-
const calldata = (0, viem_1.encodeFunctionData)({
|
|
850
|
-
abi: AnchorPay_json_1.default,
|
|
851
|
-
functionName: "send",
|
|
852
|
-
args: [
|
|
853
|
-
transfer.recipient,
|
|
854
|
-
tokenAddress,
|
|
855
|
-
transfer.amount,
|
|
856
|
-
transfer.data || "0x",
|
|
857
|
-
],
|
|
858
|
-
});
|
|
859
|
-
return {
|
|
860
|
-
target: this.contracts?.anchorPay || "",
|
|
861
|
-
allowFailure: false,
|
|
862
|
-
value: 0n,
|
|
863
|
-
callData: calldata,
|
|
864
|
-
};
|
|
865
|
-
});
|
|
866
|
-
// 编码 Multicall3 调用
|
|
867
|
-
const multicallData = (0, viem_1.encodeFunctionData)({
|
|
868
|
-
abi: constants_1.MULTICALL3_ABI,
|
|
869
|
-
functionName: "aggregate3Value",
|
|
870
|
-
args: [calls],
|
|
871
|
-
});
|
|
872
|
-
// 如果不需要发送交易,只返回交易数据(AA 模式)
|
|
873
|
-
if (options?.sendTransaction === false) {
|
|
874
|
-
return {
|
|
875
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
876
|
-
data: multicallData,
|
|
877
|
-
value: 0n,
|
|
878
|
-
};
|
|
879
|
-
}
|
|
880
|
-
// 估算 gas 和费用
|
|
881
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas();
|
|
882
|
-
const gas = await this.publicClient.estimateGas({
|
|
883
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
884
|
-
data: multicallData,
|
|
885
|
-
value: 0n,
|
|
886
|
-
account: this.account,
|
|
887
|
-
});
|
|
888
|
-
// 发送交易(EOA 模式)
|
|
889
|
-
if (!this.walletClient || !this.account) {
|
|
890
|
-
throw new Error("Wallet client and account are required to send transactions");
|
|
891
|
-
}
|
|
892
|
-
const txHash = await this.walletClient.sendTransaction({
|
|
893
|
-
account: this.account,
|
|
894
|
-
to: constants_1.MULTICALL3_ADDRESS,
|
|
895
|
-
data: multicallData,
|
|
896
|
-
maxFeePerGas: options?.maxFeePerGas || maxFeePerGas,
|
|
897
|
-
maxPriorityFeePerGas: options?.maxPriorityFeePerGas || maxPriorityFeePerGas,
|
|
898
|
-
gas: options?.gas || gas,
|
|
899
|
-
chain: this.publicClient.chain,
|
|
900
|
-
});
|
|
901
|
-
// 等待交易确认并返回收据
|
|
902
|
-
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
903
|
-
hash: txHash,
|
|
904
|
-
});
|
|
905
|
-
return receipt;
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
exports.AnchorPayClient = AnchorPayClient;
|