anchor-sdk 0.1.36
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/LICENSE +21 -0
- package/README.md +735 -0
- package/dist/AnchorApiClient.d.ts +203 -0
- package/dist/AnchorApiClient.js +279 -0
- package/dist/AnchorApiClientV2.d.ts +270 -0
- package/dist/AnchorApiClientV2.js +424 -0
- package/dist/AnchorERC1155Client.d.ts +85 -0
- package/dist/AnchorERC1155Client.js +280 -0
- package/dist/AnchorPayClient.d.ts +79 -0
- package/dist/AnchorPayClient.js +217 -0
- package/dist/abi/AnchorERC1155.d.ts +1359 -0
- package/dist/abi/AnchorERC1155.js +1122 -0
- package/dist/abi/AnchorPay.json +452 -0
- package/dist/api/AnchorApiHttpClient.d.ts +210 -0
- package/dist/api/AnchorApiHttpClient.js +411 -0
- package/dist/api/types.d.ts +764 -0
- package/dist/api/types.js +2 -0
- package/dist/constants.d.ts +49 -0
- package/dist/constants.js +221 -0
- package/dist/generated/Api.d.ts +1083 -0
- package/dist/generated/Api.js +571 -0
- package/dist/index.d.ts +341 -0
- package/dist/index.js +1377 -0
- package/dist/react/AnchorReactSDK.d.ts +59 -0
- package/dist/react/AnchorReactSDK.js +181 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +8 -0
- package/dist/typechain/AnchorERC1155.d.ts +999 -0
- package/dist/typechain/AnchorERC1155.js +2 -0
- package/dist/typechain/AnchorPay.d.ts +242 -0
- package/dist/typechain/AnchorPay.js +2 -0
- package/dist/typechain/common.d.ts +50 -0
- package/dist/typechain/common.js +2 -0
- package/dist/typechain/factories/AnchorERC1155__factory.d.ts +1365 -0
- package/dist/typechain/factories/AnchorERC1155__factory.js +1766 -0
- package/dist/typechain/factories/AnchorPay__factory.d.ts +358 -0
- package/dist/typechain/factories/AnchorPay__factory.js +469 -0
- package/dist/typechain/factories/index.d.ts +2 -0
- package/dist/typechain/factories/index.js +10 -0
- package/dist/typechain/index.d.ts +5 -0
- package/dist/typechain/index.js +41 -0
- package/dist/types.d.ts +109 -0
- package/dist/types.js +2 -0
- package/package.json +87 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Account, Address, Chain, Hex, PublicClient, TransactionReceipt, WalletClient } from "viem";
|
|
2
|
+
import { SignedMintRequest } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* AnchorERC1155 客户端
|
|
5
|
+
* 用于与 AnchorERC1155 合约交互
|
|
6
|
+
*/
|
|
7
|
+
export declare class AnchorERC1155Client {
|
|
8
|
+
private publicClient;
|
|
9
|
+
private walletClient?;
|
|
10
|
+
private account?;
|
|
11
|
+
private network;
|
|
12
|
+
private contracts;
|
|
13
|
+
/**
|
|
14
|
+
* 创建 AnchorERC1155 客户端
|
|
15
|
+
* @param publicClient 公共客户端(只读操作)
|
|
16
|
+
* @param network 网络配置
|
|
17
|
+
* @param walletClient 钱包客户端(写入操作)
|
|
18
|
+
* @param account 账户(可选,如果不提供则使用只读模式)
|
|
19
|
+
*/
|
|
20
|
+
constructor(publicClient: PublicClient, network: Chain, walletClient?: WalletClient, account?: Account, contracts?: {
|
|
21
|
+
anchorPay?: string;
|
|
22
|
+
anchorERC1155?: string;
|
|
23
|
+
[key: string]: string | undefined;
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* 获取代币 URI
|
|
27
|
+
* @param tokenId 代币 ID
|
|
28
|
+
* @returns 代币 URI
|
|
29
|
+
*/
|
|
30
|
+
getTokenURI(tokenId: bigint): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* 获取代币名称
|
|
33
|
+
* @returns 代币名称
|
|
34
|
+
*/
|
|
35
|
+
getName(): Promise<string>;
|
|
36
|
+
/**
|
|
37
|
+
* 获取代币符号
|
|
38
|
+
* @returns 代币符号
|
|
39
|
+
*/
|
|
40
|
+
getSymbol(): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* 使用签名铸造代币(免费代币)
|
|
43
|
+
* @param signedRequest 签名铸造请求
|
|
44
|
+
* @param options 选项,可以控制是否直接发送交易
|
|
45
|
+
* @returns 如果直接发送交易,返回交易收据;否则返回交易数据
|
|
46
|
+
*/
|
|
47
|
+
mintWithSignature(signedRequest: SignedMintRequest, anchorERC1155Address?: Address, options?: {
|
|
48
|
+
sendTransaction?: boolean;
|
|
49
|
+
}): Promise<TransactionReceipt | {
|
|
50
|
+
to: string;
|
|
51
|
+
data: string;
|
|
52
|
+
value: bigint;
|
|
53
|
+
}>;
|
|
54
|
+
/**
|
|
55
|
+
* 编码签名铸造请求(用于通过 AnchorPay 支付)
|
|
56
|
+
* @param signedRequest 签名铸造请求
|
|
57
|
+
* @returns 编码后的数据
|
|
58
|
+
*/
|
|
59
|
+
encodeTokenReceivedData(signedRequest: SignedMintRequest): Hex;
|
|
60
|
+
/**
|
|
61
|
+
* 编码签名铸造请求(用于通过 AnchorPay 支付),使用空接口字符串
|
|
62
|
+
* @param signedRequest 签名铸造请求
|
|
63
|
+
* @returns 编码后的数据
|
|
64
|
+
*/
|
|
65
|
+
encodeTokenReceivedDataWithEmptyInterface(signedRequest: SignedMintRequest): Hex;
|
|
66
|
+
/**
|
|
67
|
+
* multicall 方法,用于批量执行交易
|
|
68
|
+
* @param data 编码后的交易数据数组
|
|
69
|
+
* @param options 选项,可以控制是否直接发送交易
|
|
70
|
+
* @returns 如果直接发送交易,返回交易收据;否则返回交易数据
|
|
71
|
+
*/
|
|
72
|
+
multicall(data: Hex[], options?: {
|
|
73
|
+
sendTransaction?: boolean;
|
|
74
|
+
}): Promise<TransactionReceipt | {
|
|
75
|
+
to: string;
|
|
76
|
+
data: string;
|
|
77
|
+
value: bigint;
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* 格式化铸造请求,将 bigint 转换为字符串
|
|
81
|
+
* @param request 铸造请求
|
|
82
|
+
* @returns 格式化后的铸造请求
|
|
83
|
+
*/
|
|
84
|
+
private formatMintRequest;
|
|
85
|
+
}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AnchorERC1155Client = void 0;
|
|
4
|
+
const viem_1 = require("viem");
|
|
5
|
+
const AnchorERC1155_1 = require("./abi/AnchorERC1155");
|
|
6
|
+
const typechain_1 = require("./typechain");
|
|
7
|
+
/**
|
|
8
|
+
* AnchorERC1155 客户端
|
|
9
|
+
* 用于与 AnchorERC1155 合约交互
|
|
10
|
+
*/
|
|
11
|
+
class AnchorERC1155Client {
|
|
12
|
+
/**
|
|
13
|
+
* 创建 AnchorERC1155 客户端
|
|
14
|
+
* @param publicClient 公共客户端(只读操作)
|
|
15
|
+
* @param network 网络配置
|
|
16
|
+
* @param walletClient 钱包客户端(写入操作)
|
|
17
|
+
* @param account 账户(可选,如果不提供则使用只读模式)
|
|
18
|
+
*/
|
|
19
|
+
constructor(publicClient, network, walletClient, account, contracts) {
|
|
20
|
+
this.publicClient = publicClient;
|
|
21
|
+
this.network = network;
|
|
22
|
+
this.walletClient = walletClient;
|
|
23
|
+
this.account = account;
|
|
24
|
+
this.contracts = contracts || {};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 获取代币 URI
|
|
28
|
+
* @param tokenId 代币 ID
|
|
29
|
+
* @returns 代币 URI
|
|
30
|
+
*/
|
|
31
|
+
async getTokenURI(tokenId) {
|
|
32
|
+
if (!this.contracts?.anchorERC1155) {
|
|
33
|
+
throw new Error("AnchorERC1155 contract address not set, please check network configuration");
|
|
34
|
+
}
|
|
35
|
+
return (await this.publicClient.readContract({
|
|
36
|
+
address: this.contracts.anchorERC1155,
|
|
37
|
+
abi: AnchorERC1155_1.AnchorERC1155ABI,
|
|
38
|
+
functionName: "uri",
|
|
39
|
+
args: [tokenId],
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 获取代币名称
|
|
44
|
+
* @returns 代币名称
|
|
45
|
+
*/
|
|
46
|
+
async getName() {
|
|
47
|
+
if (!this.contracts?.anchorERC1155) {
|
|
48
|
+
throw new Error("AnchorERC1155 contract address not set, please check network configuration");
|
|
49
|
+
}
|
|
50
|
+
return (await this.publicClient.readContract({
|
|
51
|
+
address: this.contracts.anchorERC1155,
|
|
52
|
+
abi: AnchorERC1155_1.AnchorERC1155ABI,
|
|
53
|
+
functionName: "name",
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 获取代币符号
|
|
58
|
+
* @returns 代币符号
|
|
59
|
+
*/
|
|
60
|
+
async getSymbol() {
|
|
61
|
+
if (!this.contracts?.anchorERC1155) {
|
|
62
|
+
throw new Error("AnchorERC1155 contract address not set, please check network configuration");
|
|
63
|
+
}
|
|
64
|
+
return (await this.publicClient.readContract({
|
|
65
|
+
address: this.contracts.anchorERC1155,
|
|
66
|
+
abi: AnchorERC1155_1.AnchorERC1155ABI,
|
|
67
|
+
functionName: "symbol",
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 使用签名铸造代币(免费代币)
|
|
72
|
+
* @param signedRequest 签名铸造请求
|
|
73
|
+
* @param options 选项,可以控制是否直接发送交易
|
|
74
|
+
* @returns 如果直接发送交易,返回交易收据;否则返回交易数据
|
|
75
|
+
*/
|
|
76
|
+
async mintWithSignature(signedRequest, anchorERC1155Address, options) {
|
|
77
|
+
if (BigInt(signedRequest.request.price) !== 0n) {
|
|
78
|
+
throw new Error("mintWithSignature method can only be used to mint free tokens");
|
|
79
|
+
}
|
|
80
|
+
const contractAddress = anchorERC1155Address || this.contracts?.anchorERC1155;
|
|
81
|
+
// 用 typechain encodeFunctionData,参数断言为 any 以兼容类型
|
|
82
|
+
const data = typechain_1.AnchorERC1155__factory.createInterface().encodeFunctionData("mintWithSignature", [
|
|
83
|
+
this.formatMintRequest(signedRequest.request),
|
|
84
|
+
signedRequest.signature,
|
|
85
|
+
]);
|
|
86
|
+
// const data = encodeFunctionData({
|
|
87
|
+
// abi: AnchorERC1155ABI,
|
|
88
|
+
// functionName: "mintWithSignature",
|
|
89
|
+
// args: [
|
|
90
|
+
// this.formatMintRequest(signedRequest.request),
|
|
91
|
+
// signedRequest.signature as `0x${string}`,
|
|
92
|
+
// ],
|
|
93
|
+
// });
|
|
94
|
+
console.log(data, "data");
|
|
95
|
+
if (options?.sendTransaction === false) {
|
|
96
|
+
return {
|
|
97
|
+
to: contractAddress,
|
|
98
|
+
data,
|
|
99
|
+
value: 0n,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (!this.walletClient || !this.account) {
|
|
103
|
+
throw new Error("Wallet client and account are required to send transactions");
|
|
104
|
+
}
|
|
105
|
+
const txHash = await this.walletClient.writeContract({
|
|
106
|
+
account: this.account,
|
|
107
|
+
address: contractAddress,
|
|
108
|
+
abi: typechain_1.AnchorERC1155__factory.abi,
|
|
109
|
+
functionName: "mintWithSignature",
|
|
110
|
+
args: [
|
|
111
|
+
this.formatMintRequest(signedRequest.request),
|
|
112
|
+
signedRequest.signature,
|
|
113
|
+
],
|
|
114
|
+
chain: null,
|
|
115
|
+
});
|
|
116
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
117
|
+
hash: txHash,
|
|
118
|
+
});
|
|
119
|
+
return receipt;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 编码签名铸造请求(用于通过 AnchorPay 支付)
|
|
123
|
+
* @param signedRequest 签名铸造请求
|
|
124
|
+
* @returns 编码后的数据
|
|
125
|
+
*/
|
|
126
|
+
encodeTokenReceivedData(signedRequest) {
|
|
127
|
+
// 计算接口哈希 - AnchorERC1155 接口标识
|
|
128
|
+
const interfaceHash = (0, viem_1.keccak256)((0, viem_1.stringToHex)("AnchorERC1155"));
|
|
129
|
+
// 准备签名数据
|
|
130
|
+
const signature = signedRequest.signature.startsWith("0x")
|
|
131
|
+
? signedRequest.signature
|
|
132
|
+
: `0x${signedRequest.signature}`;
|
|
133
|
+
// 格式化请求数据
|
|
134
|
+
const formattedRequest = this.formatMintRequest(signedRequest.request);
|
|
135
|
+
console.log("Formatted request data:", JSON.stringify(formattedRequest, (_, v) => typeof v === "bigint" ? v.toString() : v));
|
|
136
|
+
console.log("Signature:", signature);
|
|
137
|
+
// 编码tokenReceived函数调用
|
|
138
|
+
// tokenReceived(address token, address from, address to, uint256 amount, bytes calldata userData)
|
|
139
|
+
// 其中userData是通过abi.encode(MintRequest, signature)编码的
|
|
140
|
+
// 1. 首先编码userData - 这是合约中通过abi.decode解码的部分
|
|
141
|
+
const userData = (0, viem_1.encodeAbiParameters)([
|
|
142
|
+
{
|
|
143
|
+
components: [
|
|
144
|
+
{ name: "to", type: "address" },
|
|
145
|
+
{ name: "tokenId", type: "uint256" },
|
|
146
|
+
{ name: "quantity", type: "uint256" },
|
|
147
|
+
{ name: "price", type: "uint256" },
|
|
148
|
+
{ name: "currency", type: "address" },
|
|
149
|
+
{ name: "validityStartTimestamp", type: "uint128" },
|
|
150
|
+
{ name: "validityEndTimestamp", type: "uint128" },
|
|
151
|
+
{ name: "uid", type: "bytes32" },
|
|
152
|
+
{ name: "chainId", type: "uint256" },
|
|
153
|
+
{ name: "projectHandle", type: "bytes32" },
|
|
154
|
+
],
|
|
155
|
+
name: "req",
|
|
156
|
+
type: "tuple",
|
|
157
|
+
},
|
|
158
|
+
{ name: "signature", type: "bytes" },
|
|
159
|
+
], [formattedRequest, signature]);
|
|
160
|
+
console.log("Encoded userData:", userData);
|
|
161
|
+
// 返回完整的编码数据
|
|
162
|
+
return (0, viem_1.concat)([interfaceHash, userData]);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* 编码签名铸造请求(用于通过 AnchorPay 支付),使用空接口字符串
|
|
166
|
+
* @param signedRequest 签名铸造请求
|
|
167
|
+
* @returns 编码后的数据
|
|
168
|
+
*/
|
|
169
|
+
encodeTokenReceivedDataWithEmptyInterface(signedRequest) {
|
|
170
|
+
// 计算接口哈希 - 使用空字符串
|
|
171
|
+
const interfaceHash = (0, viem_1.keccak256)((0, viem_1.stringToHex)(""));
|
|
172
|
+
// 准备签名数据
|
|
173
|
+
const signature = signedRequest.signature.startsWith("0x")
|
|
174
|
+
? signedRequest.signature
|
|
175
|
+
: `0x${signedRequest.signature}`;
|
|
176
|
+
// 格式化请求数据
|
|
177
|
+
const formattedRequest = this.formatMintRequest(signedRequest.request);
|
|
178
|
+
console.log("Formatted request data (empty interface):", JSON.stringify(formattedRequest, (_, v) => typeof v === "bigint" ? v.toString() : v));
|
|
179
|
+
console.log("Signature:", signature);
|
|
180
|
+
// 编码userData - 与标准方法相同,只是接口哈希不同
|
|
181
|
+
const userData = (0, viem_1.encodeAbiParameters)([
|
|
182
|
+
{
|
|
183
|
+
components: [
|
|
184
|
+
{ name: "to", type: "address" },
|
|
185
|
+
{ name: "tokenId", type: "uint256" },
|
|
186
|
+
{ name: "quantity", type: "uint256" },
|
|
187
|
+
{ name: "price", type: "uint256" },
|
|
188
|
+
{ name: "currency", type: "address" },
|
|
189
|
+
{ name: "validityStartTimestamp", type: "uint128" },
|
|
190
|
+
{ name: "validityEndTimestamp", type: "uint128" },
|
|
191
|
+
{ name: "uid", type: "bytes32" },
|
|
192
|
+
{ name: "chainId", type: "uint256" },
|
|
193
|
+
{ name: "projectHandle", type: "bytes32" },
|
|
194
|
+
],
|
|
195
|
+
name: "req",
|
|
196
|
+
type: "tuple",
|
|
197
|
+
},
|
|
198
|
+
{ name: "signature", type: "bytes" },
|
|
199
|
+
], [formattedRequest, signature]);
|
|
200
|
+
console.log("Encoded userData (empty interface):", userData);
|
|
201
|
+
// 返回完整的编码数据
|
|
202
|
+
return (0, viem_1.concat)([interfaceHash, userData]);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* multicall 方法,用于批量执行交易
|
|
206
|
+
* @param data 编码后的交易数据数组
|
|
207
|
+
* @param options 选项,可以控制是否直接发送交易
|
|
208
|
+
* @returns 如果直接发送交易,返回交易收据;否则返回交易数据
|
|
209
|
+
*/
|
|
210
|
+
async multicall(data, options) {
|
|
211
|
+
if (!this.contracts?.anchorERC1155) {
|
|
212
|
+
throw new Error("AnchorERC1155 contract address not set, please check network configuration");
|
|
213
|
+
}
|
|
214
|
+
const contractAddress = this.contracts.anchorERC1155;
|
|
215
|
+
const calldata = (0, viem_1.encodeFunctionData)({
|
|
216
|
+
abi: AnchorERC1155_1.AnchorERC1155ABI,
|
|
217
|
+
functionName: "multicall",
|
|
218
|
+
args: [data],
|
|
219
|
+
});
|
|
220
|
+
if (options?.sendTransaction === false) {
|
|
221
|
+
return {
|
|
222
|
+
to: contractAddress,
|
|
223
|
+
data: calldata,
|
|
224
|
+
value: 0n,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
if (!this.walletClient || !this.account) {
|
|
228
|
+
throw new Error("Wallet client and account are required to send transactions");
|
|
229
|
+
}
|
|
230
|
+
const txHash = await this.walletClient.writeContract({
|
|
231
|
+
account: this.account,
|
|
232
|
+
address: contractAddress,
|
|
233
|
+
abi: AnchorERC1155_1.AnchorERC1155ABI,
|
|
234
|
+
functionName: "multicall",
|
|
235
|
+
args: [data],
|
|
236
|
+
chain: null,
|
|
237
|
+
});
|
|
238
|
+
return await this.publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* 格式化铸造请求,将 bigint 转换为字符串
|
|
242
|
+
* @param request 铸造请求
|
|
243
|
+
* @returns 格式化后的铸造请求
|
|
244
|
+
*/
|
|
245
|
+
formatMintRequest(request) {
|
|
246
|
+
let uid;
|
|
247
|
+
if (typeof request.uid === "string") {
|
|
248
|
+
if (request.uid.startsWith("0x")) {
|
|
249
|
+
uid = request.uid;
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
uid = (0, viem_1.keccak256)((0, viem_1.stringToHex)(request.uid));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
uid = request.uid;
|
|
257
|
+
}
|
|
258
|
+
// 计算当前时间戳(秒)
|
|
259
|
+
const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
|
|
260
|
+
return {
|
|
261
|
+
to: request.to,
|
|
262
|
+
tokenId: BigInt(request.tokenId),
|
|
263
|
+
quantity: BigInt(request.quantity),
|
|
264
|
+
price: BigInt(request.price),
|
|
265
|
+
currency: request.currency,
|
|
266
|
+
validityStartTimestamp: request.validityStartTimestamp
|
|
267
|
+
? BigInt(request.validityStartTimestamp)
|
|
268
|
+
: currentTimestamp,
|
|
269
|
+
validityEndTimestamp: request.validityEndTimestamp
|
|
270
|
+
? BigInt(request.validityEndTimestamp)
|
|
271
|
+
: request.validUntil
|
|
272
|
+
? BigInt(request.validUntil)
|
|
273
|
+
: currentTimestamp + 3600n, // 默认1小时后过期
|
|
274
|
+
uid: uid,
|
|
275
|
+
chainId: BigInt(request.chainId || this.network.id),
|
|
276
|
+
projectHandle: request.projectHandle,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
exports.AnchorERC1155Client = AnchorERC1155Client;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Address, Hex, PublicClient, WalletClient, Account, TransactionReceipt, Chain } from "viem";
|
|
2
|
+
import { PaymentOptions } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* AnchorPay 客户端
|
|
5
|
+
* 用于与 AnchorPay 合约交互
|
|
6
|
+
*/
|
|
7
|
+
export declare class AnchorPayClient {
|
|
8
|
+
private publicClient;
|
|
9
|
+
private walletClient?;
|
|
10
|
+
private account?;
|
|
11
|
+
private network;
|
|
12
|
+
private contracts;
|
|
13
|
+
/**
|
|
14
|
+
* 创建 AnchorPay 客户端
|
|
15
|
+
* @param publicClient 公共客户端(只读操作)
|
|
16
|
+
* @param network 网络配置
|
|
17
|
+
* @param walletClient 钱包客户端(写入操作)
|
|
18
|
+
* @param account 账户(可选,如果不提供则使用只读模式)
|
|
19
|
+
*/
|
|
20
|
+
constructor(publicClient: PublicClient, network: Chain, walletClient?: WalletClient, account?: Account, contracts?: {
|
|
21
|
+
anchorPay?: string;
|
|
22
|
+
anchorERC1155?: string;
|
|
23
|
+
[key: string]: string | undefined;
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* 发送 ETH
|
|
27
|
+
* @param recipient 接收者地址
|
|
28
|
+
* @param amount 金额(单位:wei)
|
|
29
|
+
* @param data 附加数据
|
|
30
|
+
* @param options 交易选项
|
|
31
|
+
* @returns 交易收据或交易数据
|
|
32
|
+
*/
|
|
33
|
+
sendETH(recipient: Address, amount: bigint, data?: Hex, options?: PaymentOptions): Promise<TransactionReceipt | {
|
|
34
|
+
to: string;
|
|
35
|
+
data: string;
|
|
36
|
+
value: bigint;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* 发送 ERC20 代币
|
|
40
|
+
* @param recipient 接收者地址
|
|
41
|
+
* @param tokenAddress ERC20 代币地址
|
|
42
|
+
* @param amount 金额
|
|
43
|
+
* @param data 附加数据
|
|
44
|
+
* @param options 交易选项
|
|
45
|
+
* @returns 交易收据或交易数据
|
|
46
|
+
*/
|
|
47
|
+
sendERC20(recipient: Address, tokenAddress: Address, amount: bigint, data?: Hex, options?: PaymentOptions): Promise<TransactionReceipt | {
|
|
48
|
+
to: string;
|
|
49
|
+
data: string;
|
|
50
|
+
value: bigint;
|
|
51
|
+
}>;
|
|
52
|
+
/**
|
|
53
|
+
* 获取接口实现者
|
|
54
|
+
* @param account 账户地址
|
|
55
|
+
* @param interfaceHash 接口哈希
|
|
56
|
+
* @returns 实现者地址
|
|
57
|
+
*/
|
|
58
|
+
getInterfaceImplementer(account: Address, interfaceHash: Hex): Promise<Address>;
|
|
59
|
+
/**
|
|
60
|
+
* 设置接口实现者(仅限管理员)
|
|
61
|
+
* @param account 账户地址
|
|
62
|
+
* @param interfaceHash 接口哈希
|
|
63
|
+
* @param implementer 实现者地址
|
|
64
|
+
* @returns 交易收据
|
|
65
|
+
*/
|
|
66
|
+
setInterfaceImplementer(account: Address, interfaceHash: Hex, implementer: Address): Promise<TransactionReceipt>;
|
|
67
|
+
/**
|
|
68
|
+
* 获取 ERC20 代币批准的交易数据(用于 AA 模式)
|
|
69
|
+
* @param tokenAddress ERC20 代币地址
|
|
70
|
+
* @param amount 批准金额
|
|
71
|
+
* @param spender 花费者地址(默认为 AnchorPay 合约地址)
|
|
72
|
+
* @returns 交易数据对象,包含 to、data 和 value 字段
|
|
73
|
+
*/
|
|
74
|
+
getERC20ApprovalData(tokenAddress: Address, amount: bigint, spender?: Address): {
|
|
75
|
+
to: string;
|
|
76
|
+
data: string;
|
|
77
|
+
value: bigint;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
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 AnchorPay_json_1 = __importDefault(require("./abi/AnchorPay.json"));
|
|
9
|
+
const constants_1 = require("./constants");
|
|
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 && (!this.walletClient || !this.account)) {
|
|
40
|
+
throw new Error("Wallet client and account are required to send transactions");
|
|
41
|
+
}
|
|
42
|
+
// 准备交易数据
|
|
43
|
+
const calldata = (0, viem_1.encodeFunctionData)({
|
|
44
|
+
abi: AnchorPay_json_1.default,
|
|
45
|
+
functionName: 'send',
|
|
46
|
+
args: [recipient, constants_1.NATIVE_TOKEN_ADDRESS, amount, data]
|
|
47
|
+
});
|
|
48
|
+
// 如果不需要发送交易,只返回交易数据(AA 模式)
|
|
49
|
+
if (options?.sendTransaction === false) {
|
|
50
|
+
return {
|
|
51
|
+
to: this.contracts?.anchorPay || "",
|
|
52
|
+
data: calldata,
|
|
53
|
+
value: amount
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// 发送交易(EOA 模式)
|
|
57
|
+
const txHash = await this.walletClient.sendTransaction({
|
|
58
|
+
account: this.account,
|
|
59
|
+
to: this.contracts?.anchorPay || "",
|
|
60
|
+
data: calldata,
|
|
61
|
+
value: amount,
|
|
62
|
+
maxFeePerGas: options?.maxFeePerGas,
|
|
63
|
+
maxPriorityFeePerGas: options?.maxPriorityFeePerGas,
|
|
64
|
+
gas: options?.gas,
|
|
65
|
+
chain: null
|
|
66
|
+
});
|
|
67
|
+
// 等待交易确认并返回收据
|
|
68
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
69
|
+
hash: txHash
|
|
70
|
+
});
|
|
71
|
+
return receipt;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 发送 ERC20 代币
|
|
75
|
+
* @param recipient 接收者地址
|
|
76
|
+
* @param tokenAddress ERC20 代币地址
|
|
77
|
+
* @param amount 金额
|
|
78
|
+
* @param data 附加数据
|
|
79
|
+
* @param options 交易选项
|
|
80
|
+
* @returns 交易收据或交易数据
|
|
81
|
+
*/
|
|
82
|
+
async sendERC20(recipient, tokenAddress, amount, data = '0x', options) {
|
|
83
|
+
// 如果需要发送交易,但没有钱包客户端或账户
|
|
84
|
+
if (options?.sendTransaction !== false && (!this.walletClient || !this.account)) {
|
|
85
|
+
throw new Error("Wallet client and account are required to send transactions");
|
|
86
|
+
}
|
|
87
|
+
// 如果需要自动批准,则先批准代币(默认开启自动批准)
|
|
88
|
+
if ((options?.autoApprove !== false) && this.walletClient && this.account) {
|
|
89
|
+
try {
|
|
90
|
+
console.log(`Checking ERC20 token approval status: ${tokenAddress}`);
|
|
91
|
+
// 检查授权
|
|
92
|
+
const allowance = await this.publicClient.readContract({
|
|
93
|
+
address: tokenAddress,
|
|
94
|
+
abi: constants_1.ERC20_ABI,
|
|
95
|
+
functionName: 'allowance',
|
|
96
|
+
args: [this.account.address, this.contracts?.anchorPay]
|
|
97
|
+
});
|
|
98
|
+
console.log(`Current allowance: ${allowance}, Required amount: ${amount}, AnchorPay contract address: ${this.contracts?.anchorPay}`);
|
|
99
|
+
if (allowance < amount) {
|
|
100
|
+
console.log(`Approving ${amount} tokens to AnchorPay contract...`);
|
|
101
|
+
// 批准代币 - 使用最大可能值进行授权,避免多次授权
|
|
102
|
+
const maxApproveAmount = 2n ** 256n - 1n;
|
|
103
|
+
const approveTxHash = await this.walletClient.writeContract({
|
|
104
|
+
account: this.account,
|
|
105
|
+
address: tokenAddress,
|
|
106
|
+
abi: constants_1.ERC20_ABI,
|
|
107
|
+
functionName: 'approve',
|
|
108
|
+
args: [this.contracts?.anchorPay, maxApproveAmount],
|
|
109
|
+
chain: null
|
|
110
|
+
});
|
|
111
|
+
console.log(`Approval transaction sent, hash: ${approveTxHash}`);
|
|
112
|
+
// 等待交易确认
|
|
113
|
+
await this.publicClient.waitForTransactionReceipt({ hash: approveTxHash });
|
|
114
|
+
console.log(`Approval transaction confirmed`);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.log(`Sufficient allowance already exists, no need for additional approval`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error(`Approval failed:`, error);
|
|
122
|
+
throw new Error(`ERC20 approval failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// 准备交易数据
|
|
126
|
+
const calldata = (0, viem_1.encodeFunctionData)({
|
|
127
|
+
abi: AnchorPay_json_1.default,
|
|
128
|
+
functionName: 'send',
|
|
129
|
+
args: [recipient, tokenAddress, amount, data]
|
|
130
|
+
});
|
|
131
|
+
// 如果不需要发送交易,只返回交易数据(AA 模式)
|
|
132
|
+
if (options?.sendTransaction === false) {
|
|
133
|
+
return {
|
|
134
|
+
to: this.contracts?.anchorPay || "",
|
|
135
|
+
data: calldata,
|
|
136
|
+
value: 0n
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// 发送交易(EOA 模式)
|
|
140
|
+
const txHash = await this.walletClient.sendTransaction({
|
|
141
|
+
account: this.account,
|
|
142
|
+
to: this.contracts?.anchorPay || "",
|
|
143
|
+
data: calldata,
|
|
144
|
+
// value: amount,
|
|
145
|
+
maxFeePerGas: options?.maxFeePerGas,
|
|
146
|
+
maxPriorityFeePerGas: options?.maxPriorityFeePerGas,
|
|
147
|
+
gas: options?.gas,
|
|
148
|
+
chain: null
|
|
149
|
+
});
|
|
150
|
+
// 等待交易确认并返回收据
|
|
151
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
152
|
+
hash: txHash
|
|
153
|
+
});
|
|
154
|
+
return receipt;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* 获取接口实现者
|
|
158
|
+
* @param account 账户地址
|
|
159
|
+
* @param interfaceHash 接口哈希
|
|
160
|
+
* @returns 实现者地址
|
|
161
|
+
*/
|
|
162
|
+
async getInterfaceImplementer(account, interfaceHash) {
|
|
163
|
+
return await this.publicClient.readContract({
|
|
164
|
+
address: this.contracts?.anchorPay || "",
|
|
165
|
+
abi: AnchorPay_json_1.default,
|
|
166
|
+
functionName: 'getInterfaceImplementer',
|
|
167
|
+
args: [account, interfaceHash]
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* 设置接口实现者(仅限管理员)
|
|
172
|
+
* @param account 账户地址
|
|
173
|
+
* @param interfaceHash 接口哈希
|
|
174
|
+
* @param implementer 实现者地址
|
|
175
|
+
* @returns 交易收据
|
|
176
|
+
*/
|
|
177
|
+
async setInterfaceImplementer(account, interfaceHash, implementer) {
|
|
178
|
+
if (!this.walletClient || !this.account) {
|
|
179
|
+
throw new Error("Wallet client and account are required to send transactions");
|
|
180
|
+
}
|
|
181
|
+
const txHash = await this.walletClient.writeContract({
|
|
182
|
+
account: this.account,
|
|
183
|
+
address: this.contracts?.anchorPay || "",
|
|
184
|
+
abi: AnchorPay_json_1.default,
|
|
185
|
+
functionName: 'setInterfaceImplementer',
|
|
186
|
+
args: [account, interfaceHash, implementer],
|
|
187
|
+
chain: null
|
|
188
|
+
});
|
|
189
|
+
// 等待交易确认并返回收据
|
|
190
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
191
|
+
hash: txHash
|
|
192
|
+
});
|
|
193
|
+
return receipt;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* 获取 ERC20 代币批准的交易数据(用于 AA 模式)
|
|
197
|
+
* @param tokenAddress ERC20 代币地址
|
|
198
|
+
* @param amount 批准金额
|
|
199
|
+
* @param spender 花费者地址(默认为 AnchorPay 合约地址)
|
|
200
|
+
* @returns 交易数据对象,包含 to、data 和 value 字段
|
|
201
|
+
*/
|
|
202
|
+
getERC20ApprovalData(tokenAddress, amount, spender) {
|
|
203
|
+
const approveSpender = spender || (this.contracts?.anchorPay || "");
|
|
204
|
+
// 编码 approve 函数调用
|
|
205
|
+
const data = (0, viem_1.encodeFunctionData)({
|
|
206
|
+
abi: constants_1.ERC20_ABI,
|
|
207
|
+
functionName: 'approve',
|
|
208
|
+
args: [approveSpender, amount]
|
|
209
|
+
});
|
|
210
|
+
return {
|
|
211
|
+
to: tokenAddress,
|
|
212
|
+
data,
|
|
213
|
+
value: 0n // ERC20 批准不需要发送 ETH
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
exports.AnchorPayClient = AnchorPayClient;
|