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
package/README.md
ADDED
|
@@ -0,0 +1,735 @@
|
|
|
1
|
+
# Anchor SDK
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/%40keccak256-evg%2Fanchor-sdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](http://www.typescriptlang.org/)
|
|
6
|
+
|
|
7
|
+
Anchor SDK 是一个用于与 Anchor 生态系统交互的 TypeScript 开发工具包,支持徽章铸造、支付处理和 ERC1155 代币管理。
|
|
8
|
+
|
|
9
|
+
## ✨ 特性
|
|
10
|
+
|
|
11
|
+
- 🌐 **多网络支持** - 支持以太坊主网、Saigon、Ronin、Base Sepolia、Bera 等多个网络
|
|
12
|
+
- 🔐 **双模式支持** - 同时支持账户抽象(AA)和外部拥有账户(EOA)模式
|
|
13
|
+
- 🎯 **简单易用** - 提供直观的 API 接口进行徽章铸造和查询
|
|
14
|
+
- 💰 **多种支付方式** - 支持使用 ETH 或 ERC20 代币购买徽章
|
|
15
|
+
- ✍️ **自定义签名** - 支持使用自定义签名购买徽章
|
|
16
|
+
- 🆓 **免费铸造** - 支持铸造免费徽章
|
|
17
|
+
- 📝 **完全类型化** - 提供完整的 TypeScript 类型支持,确保良好的开发体验
|
|
18
|
+
- ⚡ **批量操作** - 支持批量铸造和 multicall 操作
|
|
19
|
+
- 🔄 **React 支持** - 提供 React Hook 和组件
|
|
20
|
+
|
|
21
|
+
## 📦 安装
|
|
22
|
+
|
|
23
|
+
### 使用 npm
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install anchor-sdk
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 使用 yarn
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
yarn add anchor-sdk
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 使用 pnpm
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pnpm add anchor-sdk
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 📋 依赖要求
|
|
42
|
+
|
|
43
|
+
Anchor SDK 需要以下依赖:
|
|
44
|
+
|
|
45
|
+
- **Node.js**: >= 16.0.0
|
|
46
|
+
- **TypeScript**: >= 4.5.0 (如果使用 TypeScript)
|
|
47
|
+
- **viem**: ^2.23.9
|
|
48
|
+
- **ethers**: ^6.15.0
|
|
49
|
+
|
|
50
|
+
### 可选依赖
|
|
51
|
+
|
|
52
|
+
- **React**: ^19.0.0 (如果使用 React 组件)
|
|
53
|
+
- **@types/react**: ^19.0.10 (如果使用 TypeScript 和 React)
|
|
54
|
+
|
|
55
|
+
## 🚀 快速开始
|
|
56
|
+
|
|
57
|
+
### 1. 初始化 SDK
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { createPublicClient, createWalletClient, http } from "viem";
|
|
61
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
62
|
+
import { mainnet } from "viem/chains";
|
|
63
|
+
import { AnchorSDK, NETWORKS, Environment } from "anchor-sdk";
|
|
64
|
+
|
|
65
|
+
// 创建客户端
|
|
66
|
+
const rpcUrl = "https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY";
|
|
67
|
+
const privateKey = "0xYOUR_PRIVATE_KEY";
|
|
68
|
+
|
|
69
|
+
const publicClient = createPublicClient({
|
|
70
|
+
chain: mainnet,
|
|
71
|
+
transport: http(rpcUrl),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const account = privateKeyToAccount(
|
|
75
|
+
`0x${
|
|
76
|
+
privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey
|
|
77
|
+
}` as `0x${string}`
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const walletClient = createWalletClient({
|
|
81
|
+
account,
|
|
82
|
+
chain: mainnet,
|
|
83
|
+
transport: http(rpcUrl),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// 创建 SDK 实例
|
|
87
|
+
const sdk = new AnchorSDK({
|
|
88
|
+
publicClient,
|
|
89
|
+
walletClient,
|
|
90
|
+
network: NETWORKS.mainnet,
|
|
91
|
+
// 可以指定环境,支持 DEV、BETA 和 PROD
|
|
92
|
+
env: Environment.DEV,
|
|
93
|
+
// 也可以直接指定 API URL,这将覆盖环境配置
|
|
94
|
+
// apiBaseUrl: "https://api.example.com",
|
|
95
|
+
authToken: "YOUR_JWT_TOKEN",
|
|
96
|
+
clientId: "YOUR_CLIENT_ID",
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 2. 使用 ETH 购买徽章(EOA 模式)
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// 直接发送交易
|
|
104
|
+
const txHash = await sdk.buyBadgeWithETH(
|
|
105
|
+
"0xRECIPIENT_ADDRESS", // 接收徽章的地址
|
|
106
|
+
"0xCONTRACT_ADDRESS", // 合约地址
|
|
107
|
+
1, // Badge ID
|
|
108
|
+
1, // 数量
|
|
109
|
+
"0xRECEIPT_ADDRESS", // 接收支付的地址
|
|
110
|
+
{
|
|
111
|
+
value: "0.1", // 支付金额(ETH)
|
|
112
|
+
gas: 300000n, // 可选:指定 gas 限制
|
|
113
|
+
sendTransaction: true, // 明确指定直接发送交易
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
console.log(`交易已发送: ${txHash}`);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 3. 使用 ETH 购买徽章(AA 模式)
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// 只返回交易数据,不发送交易
|
|
124
|
+
const txData = await sdk.buyBadgeWithETH(
|
|
125
|
+
"0xRECIPIENT_ADDRESS", // 接收徽章的地址
|
|
126
|
+
"0xCONTRACT_ADDRESS", // 合约地址
|
|
127
|
+
1, // Badge ID
|
|
128
|
+
1, // 数量
|
|
129
|
+
"0xRECEIPT_ADDRESS", // 接收支付的地址
|
|
130
|
+
{
|
|
131
|
+
value: "0.1", // 支付金额(ETH)
|
|
132
|
+
sendTransaction: false, // 指定不发送交易,只返回交易数据
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
console.log(`交易数据: ${txData}`);
|
|
137
|
+
// 使用你的 AA 钱包发送此交易数据
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 4. 铸造免费徽章
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import { createPublicClient, createWalletClient, http } from "viem";
|
|
144
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
145
|
+
import { saigon, baseSepolia } from "viem/chains";
|
|
146
|
+
import { AnchorSDK, NETWORKS, Environment } from "anchor-sdk";
|
|
147
|
+
|
|
148
|
+
// 创建客户端
|
|
149
|
+
const privateKey = "0xYOUR_PRIVATE_KEY";
|
|
150
|
+
|
|
151
|
+
// 这里使用 saigon 测试网,也可以使用 baseSepolia 或其他支持的网络
|
|
152
|
+
const publicClient = createPublicClient({
|
|
153
|
+
chain: saigon,
|
|
154
|
+
transport: http(),
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const account = privateKeyToAccount(
|
|
158
|
+
`0x${
|
|
159
|
+
privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey
|
|
160
|
+
}` as `0x${string}`
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const walletClient = createWalletClient({
|
|
164
|
+
account,
|
|
165
|
+
chain: saigon,
|
|
166
|
+
transport: http(),
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// 创建 SDK 实例
|
|
170
|
+
const sdk = new AnchorSDK({
|
|
171
|
+
publicClient,
|
|
172
|
+
walletClient,
|
|
173
|
+
env: Environment.DEV,
|
|
174
|
+
network: NETWORKS.saigon,
|
|
175
|
+
authToken: "YOUR_JWT_TOKEN",
|
|
176
|
+
clientId: "YOUR_CLIENT_ID",
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
// 使用封装的 mintFreeBadge 方法(推荐)
|
|
181
|
+
// 这个方法会自动从后端获取签名请求并执行铸造
|
|
182
|
+
const customerAddress = account.address;
|
|
183
|
+
const contractAddress =
|
|
184
|
+
"0x23Da7778F6152D7B91C20808bEF7163c5EC2C470" as `0x${string}`; // 替换为合约地址
|
|
185
|
+
const claimableIds = ["CLAIMABLE_ID"]; // 替换为实际的可领取 ID
|
|
186
|
+
|
|
187
|
+
const txHash = await sdk.mintFreeBadge(
|
|
188
|
+
customerAddress,
|
|
189
|
+
contractAddress,
|
|
190
|
+
claimableIds,
|
|
191
|
+
{ sendTransaction: true } // 明确指定直接发送交易
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
console.log(`免费徽章铸造交易已提交:${txHash}`);
|
|
195
|
+
|
|
196
|
+
// 检查铸造结果
|
|
197
|
+
const receipt = await publicClient.waitForTransactionReceipt({
|
|
198
|
+
hash: txHash,
|
|
199
|
+
});
|
|
200
|
+
console.log(`铸造成功: ${receipt.status === "success"}`);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error("铸造免费徽章失败:", error);
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 5. 使用纯支付功能
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { createPublicClient, createWalletClient, http } from "viem";
|
|
210
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
211
|
+
import { saigon } from "viem/chains";
|
|
212
|
+
import { AnchorSDK, Environment } from "anchor-sdk";
|
|
213
|
+
|
|
214
|
+
// 创建客户端
|
|
215
|
+
const privateKey = "0xYOUR_PRIVATE_KEY";
|
|
216
|
+
|
|
217
|
+
const publicClient = createPublicClient({
|
|
218
|
+
chain: saigon,
|
|
219
|
+
transport: http(),
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const account = privateKeyToAccount(
|
|
223
|
+
`0x${
|
|
224
|
+
privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey
|
|
225
|
+
}` as `0x${string}`
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const walletClient = createWalletClient({
|
|
229
|
+
account,
|
|
230
|
+
chain: saigon,
|
|
231
|
+
transport: http(),
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// 创建 SDK 实例
|
|
235
|
+
const sdk = new AnchorSDK({
|
|
236
|
+
publicClient,
|
|
237
|
+
walletClient,
|
|
238
|
+
env: Environment.DEV,
|
|
239
|
+
network: NETWORKS.saigon,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
try {
|
|
243
|
+
// EOA 模式 - 直接发送交易
|
|
244
|
+
const txHash = await sdk.pay(
|
|
245
|
+
"order-123", // 订单 ID
|
|
246
|
+
"0.01", // 支付金额(ETH)
|
|
247
|
+
"0xRECEIPT_ADDRESS", // 接收地址
|
|
248
|
+
{ sendTransaction: true } // 明确指定直接发送交易
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
console.log(`交易已提交:${txHash}`);
|
|
252
|
+
|
|
253
|
+
// AA 模式 - 只返回交易数据,不发送交易
|
|
254
|
+
const txData = await sdk.pay(
|
|
255
|
+
"order-456", // 订单 ID
|
|
256
|
+
"0.05", // 支付金额(ETH)
|
|
257
|
+
"0xRECEIPT_ADDRESS", // 接收地址
|
|
258
|
+
{ sendTransaction: false } // 指定不发送交易,只返回交易数据
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
console.log("交易数据:", txData);
|
|
262
|
+
// 使用你的 AA 钱包发送此交易数据
|
|
263
|
+
} catch (error) {
|
|
264
|
+
console.error("支付失败:", error);
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 6. 使用自定义签名购买徽章
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { createPublicClient, createWalletClient, http } from "viem";
|
|
272
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
273
|
+
import { mainnet, saigon } from "viem/chains";
|
|
274
|
+
import { AnchorSDK, NETWORKS, Environment } from "anchor-sdk";
|
|
275
|
+
import MugenApiClient from "./MugenApiClient";
|
|
276
|
+
|
|
277
|
+
// 创建客户端
|
|
278
|
+
const rpcUrl = "https://saigon-testnet.roninchain.com/rpc";
|
|
279
|
+
const privateKey = "0xYOUR_PRIVATE_KEY";
|
|
280
|
+
|
|
281
|
+
const publicClient = createPublicClient({
|
|
282
|
+
chain: saigon,
|
|
283
|
+
transport: http(rpcUrl),
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const account = privateKeyToAccount(
|
|
287
|
+
`0x${
|
|
288
|
+
privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey
|
|
289
|
+
}` as `0x${string}`
|
|
290
|
+
);
|
|
291
|
+
const userAddress = account.address;
|
|
292
|
+
|
|
293
|
+
const walletClient = createWalletClient({
|
|
294
|
+
account,
|
|
295
|
+
chain: saigon,
|
|
296
|
+
transport: http(rpcUrl),
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// 创建 SDK 实例
|
|
300
|
+
const sdk = new AnchorSDK({
|
|
301
|
+
publicClient,
|
|
302
|
+
walletClient,
|
|
303
|
+
network: NETWORKS.saigon,
|
|
304
|
+
env: Environment.BETA,
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// 从 Mugen API 获取签名数据
|
|
308
|
+
const mugenApiClient = new MugenApiClient(
|
|
309
|
+
"https://api.mugen.com/",
|
|
310
|
+
"YOUR_JWT_TOKEN"
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
// 创建订单
|
|
315
|
+
const orderResult = await mugenApiClient.orderCreate(
|
|
316
|
+
"PRODUCT_CODE",
|
|
317
|
+
"PRODUCT_ID",
|
|
318
|
+
userAddress
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
console.log("创建订单结果:", orderResult);
|
|
322
|
+
|
|
323
|
+
if (orderResult.success && orderResult.obj) {
|
|
324
|
+
// 使用 SDK 的自定义签名方法购买徽章
|
|
325
|
+
const signedRequest = {
|
|
326
|
+
request: {
|
|
327
|
+
to: userAddress,
|
|
328
|
+
tokenId: "TOKEN_ID",
|
|
329
|
+
amount: 1,
|
|
330
|
+
price: "0.01",
|
|
331
|
+
currency: "0x0000000000000000000000000000000000000000", // ETH的地址是零地址
|
|
332
|
+
deadline: Math.floor(Date.now() / 1000) + 3600, // 1小时后过期
|
|
333
|
+
quantity: 1,
|
|
334
|
+
},
|
|
335
|
+
signature: orderResult.obj.signature,
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
const txHash = await sdk.buyBadgeWithETHWithSignedRequest(
|
|
339
|
+
signedRequest,
|
|
340
|
+
userAddress, // 接收地址
|
|
341
|
+
{ value: "0.01", sendTransaction: true }
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
console.log("交易已发送:", txHash);
|
|
345
|
+
} else {
|
|
346
|
+
console.error("创建订单失败:", orderResult);
|
|
347
|
+
}
|
|
348
|
+
} catch (error) {
|
|
349
|
+
console.error("购买徽章失败:", error);
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## 🎯 DApp 函数调用场景
|
|
354
|
+
|
|
355
|
+
在 dApp 中,您可以在以下特定情况下调用这些函数来与 Anchor SDK 交互:
|
|
356
|
+
|
|
357
|
+
- **buyBadgeWithETH**: 当用户想要使用 ETH 购买徽章时调用此函数,在 EOA 模式下直接发送交易,或在 AA 模式下获取交易数据而不发送。
|
|
358
|
+
- **buyBadgeWithETHWithSignedRequest**: 用于使用预签名请求购买徽章,通常在集成外部 API 进行自定义签名时使用。
|
|
359
|
+
- **buyBadgeWithERC20**: 当用户使用 ERC20 代币购买徽章时调用此函数,处理代币批准和转账。
|
|
360
|
+
- **buyBadgeWithERC20WithCustomSignature**: 用于需要签名请求的 ERC20 购买,例如来自后端的验证订单场景。
|
|
361
|
+
- **pay**: 用于一般支付,如使用 ETH 处理订单或为 AA 钱包获取交易数据。
|
|
362
|
+
- **mintFreeBadge**: 为符合条件的用户铸造免费徽章时调用此函数,通常在从 API 获取可领取 ID 后使用。
|
|
363
|
+
- **其他函数**: 对于批量操作或高级交互,请参考 batchMintBadge 等方法在单个交易中进行多次铸造。
|
|
364
|
+
|
|
365
|
+
## 🌐 支持的网络
|
|
366
|
+
|
|
367
|
+
SDK 支持多种网络,包括:
|
|
368
|
+
|
|
369
|
+
| 网络 | 类型 | 链 ID | 说明 |
|
|
370
|
+
| ------------------ | ------ | ----- | ------------------- |
|
|
371
|
+
| `mainnet` | 主网 | 1 | 以太坊主网 |
|
|
372
|
+
| `saigon` | 测试网 | 2021 | Saigon 测试网 |
|
|
373
|
+
| `ronin` | 主网 | 2020 | Ronin 网络 |
|
|
374
|
+
| `baseSepolia` | 测试网 | 84532 | Base Sepolia 测试网 |
|
|
375
|
+
| `berachain` | 主网 | 80094 | Bera 主网 |
|
|
376
|
+
| `berachainBepolia` | 测试网 | 80085 | Bera 测试网 |
|
|
377
|
+
| `abstractTestnet` | 测试网 | 11124 | Abstract 测试网 |
|
|
378
|
+
| `base` | 主网 | 8453 | Base 主网 |
|
|
379
|
+
| `abstract` | 主网 | 11111 | Abstract 主网 |
|
|
380
|
+
|
|
381
|
+
## 🔐 API 认证
|
|
382
|
+
|
|
383
|
+
使用 Anchor API 功能时,需要提供以下认证参数:
|
|
384
|
+
|
|
385
|
+
- `authToken` - JWT 令牌,格式为 "your-jwt-token"
|
|
386
|
+
- `clientId` - 客户端标识
|
|
387
|
+
|
|
388
|
+
您可以在初始化 SDK 时提供这些参数,也可以在运行时更新:
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
// 初始化时设置
|
|
392
|
+
const sdk = new AnchorSDK({
|
|
393
|
+
// 其他配置...
|
|
394
|
+
apiBaseUrl: "https://api.example.com",
|
|
395
|
+
authToken: "YOUR_JWT_TOKEN",
|
|
396
|
+
clientId: "YOUR_CLIENT_ID",
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// 运行时更新
|
|
400
|
+
sdk.anchorApi.setAuthToken("NEW_JWT_TOKEN");
|
|
401
|
+
sdk.anchorApi.setClientId("NEW_CLIENT_ID");
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Token 过期处理
|
|
405
|
+
|
|
406
|
+
SDK 提供了 token 过期回调机制,当 API 调用遇到 token 过期错误时,会自动调用回调函数:
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
// 初始化时设置 token 过期回调
|
|
410
|
+
const sdk = new AnchorSDK({
|
|
411
|
+
// 其他配置...
|
|
412
|
+
apiBaseUrl: "https://api.example.com",
|
|
413
|
+
authToken: "YOUR_JWT_TOKEN",
|
|
414
|
+
clientId: "YOUR_CLIENT_ID",
|
|
415
|
+
onTokenExpired: (error: Error) => {
|
|
416
|
+
console.log("Token 已过期:", error.message);
|
|
417
|
+
|
|
418
|
+
// 处理 token 过期逻辑
|
|
419
|
+
// 例如:刷新 token、重新登录、通知用户等
|
|
420
|
+
refreshToken().then((newToken) => {
|
|
421
|
+
sdk.anchorApi?.setAuthToken(newToken);
|
|
422
|
+
console.log("Token 已刷新");
|
|
423
|
+
});
|
|
424
|
+
},
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
// 运行时设置 token 过期回调
|
|
428
|
+
sdk.setTokenExpiredCallback((error: Error) => {
|
|
429
|
+
console.log("Token 已过期:", error.message);
|
|
430
|
+
// 处理 token 过期逻辑
|
|
431
|
+
});
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
回调函数会在以下情况下触发:
|
|
435
|
+
|
|
436
|
+
- 响应体中的 `code` 字段为 `params.jwt.check.invalid`(即使 HTTP 状态码为 200)
|
|
437
|
+
|
|
438
|
+
### 错误码说明
|
|
439
|
+
|
|
440
|
+
当 API 返回 `code: "params.jwt.check.invalid"` 时,表示 JWT token 验证失败,可能的原因包括:
|
|
441
|
+
|
|
442
|
+
- Token 已过期
|
|
443
|
+
- Token 格式不正确
|
|
444
|
+
- Token 签名无效
|
|
445
|
+
- Token 被撤销
|
|
446
|
+
|
|
447
|
+
**注意**:即使 token 过期,API 也可能返回 HTTP 状态码 200,SDK 会检查响应体中的错误码来判断 token 是否有效。
|
|
448
|
+
|
|
449
|
+
SDK 会自动检测这种错误码并调用回调函数,让您可以执行相应的处理逻辑。
|
|
450
|
+
|
|
451
|
+
## 📚 API 文档
|
|
452
|
+
|
|
453
|
+
### 核心类
|
|
454
|
+
|
|
455
|
+
#### `AnchorSDK`
|
|
456
|
+
|
|
457
|
+
主要的 SDK 类,提供与 Anchor 生态系统交互的所有功能。
|
|
458
|
+
|
|
459
|
+
```typescript
|
|
460
|
+
class AnchorSDK {
|
|
461
|
+
constructor(config: AnchorSDKConfig);
|
|
462
|
+
|
|
463
|
+
// 徽章购买方法
|
|
464
|
+
buyBadgeWithETH(
|
|
465
|
+
customerAddress: string,
|
|
466
|
+
contractAddress: string,
|
|
467
|
+
tokenId: string | number | bigint,
|
|
468
|
+
quantity: string | number | bigint,
|
|
469
|
+
receiptAddress: string,
|
|
470
|
+
options?: PaymentOptions
|
|
471
|
+
): Promise<TransactionReceipt | { to: string; data: string; value: bigint }>;
|
|
472
|
+
|
|
473
|
+
buyBadgeWithETHWithSignedRequest(
|
|
474
|
+
signedRequest: SignedMintRequest,
|
|
475
|
+
receiptAddress: string,
|
|
476
|
+
options?: PaymentOptions
|
|
477
|
+
): Promise<TransactionReceipt | { to: string; data: string; value: bigint }>;
|
|
478
|
+
|
|
479
|
+
buyBadgeWithERC20(
|
|
480
|
+
customerAddress: string,
|
|
481
|
+
contractAddress: string,
|
|
482
|
+
tokenId: string | number | bigint,
|
|
483
|
+
quantity: string | number | bigint,
|
|
484
|
+
currency: string,
|
|
485
|
+
receiptAddress: string,
|
|
486
|
+
options?: PaymentOptions
|
|
487
|
+
): Promise<TransactionReceipt | { to: string; data: string; value: bigint }>;
|
|
488
|
+
|
|
489
|
+
// 免费铸造方法
|
|
490
|
+
mintFreeBadge(
|
|
491
|
+
customerAddress: string,
|
|
492
|
+
contractAddress: string,
|
|
493
|
+
tokenIds: string[],
|
|
494
|
+
options?: { sendTransaction?: boolean }
|
|
495
|
+
): Promise<
|
|
496
|
+
| TransactionReceipt
|
|
497
|
+
| { to: string; data: string; value: bigint }
|
|
498
|
+
| { to: string; data: string; value: bigint }[]
|
|
499
|
+
>;
|
|
500
|
+
|
|
501
|
+
// 批量操作
|
|
502
|
+
batchMintBadge(
|
|
503
|
+
customerAddress: string,
|
|
504
|
+
contractAddress: string,
|
|
505
|
+
tokenIds: string[],
|
|
506
|
+
options?: { sendTransaction?: boolean }
|
|
507
|
+
): Promise<
|
|
508
|
+
TransactionReceipt | { to: string; data: string; value: bigint }[]
|
|
509
|
+
>;
|
|
510
|
+
|
|
511
|
+
batchMintBadgeWithMulticall(
|
|
512
|
+
customerAddress: string,
|
|
513
|
+
contractAddress: string,
|
|
514
|
+
tokenIds: string[],
|
|
515
|
+
options?: { sendTransaction?: boolean }
|
|
516
|
+
): Promise<TransactionReceipt | { to: string; data: string; value: bigint }>;
|
|
517
|
+
|
|
518
|
+
// 支付方法
|
|
519
|
+
pay(
|
|
520
|
+
orderId: string,
|
|
521
|
+
amount: string | number | bigint,
|
|
522
|
+
receiptAddress: string,
|
|
523
|
+
options?: PaymentOptions
|
|
524
|
+
): Promise<TransactionReceipt | { to: string; data: string; value: bigint }>;
|
|
525
|
+
|
|
526
|
+
sendPaymentWithNativeToken(params: {
|
|
527
|
+
callData: `0x${string}`;
|
|
528
|
+
amount: string | number | bigint;
|
|
529
|
+
receiptAddress: string;
|
|
530
|
+
contractName?: string;
|
|
531
|
+
options?: PaymentOptions;
|
|
532
|
+
}): Promise<TransactionReceipt | { to: string; data: string; value: bigint }>;
|
|
533
|
+
|
|
534
|
+
sendPaymentWithERC20(params: {
|
|
535
|
+
callData: `0x${string}`;
|
|
536
|
+
amount: string | number | bigint;
|
|
537
|
+
receiptAddress: string;
|
|
538
|
+
tokenAddress: string;
|
|
539
|
+
contractName?: string;
|
|
540
|
+
options?: PaymentOptions;
|
|
541
|
+
}): Promise<TransactionReceipt | { to: string; data: string; value: bigint }>;
|
|
542
|
+
|
|
543
|
+
// 工具方法
|
|
544
|
+
setWalletClient(signerOrWalletClient: any): AnchorSDK;
|
|
545
|
+
setTokenExpiredCallback(callback: (error: Error) => void): void;
|
|
546
|
+
processTransactionHash(txHash: string): Promise<any>;
|
|
547
|
+
getERC20ApprovalData(
|
|
548
|
+
tokenAddress: Address,
|
|
549
|
+
amount: bigint,
|
|
550
|
+
spender?: Address
|
|
551
|
+
): { to: string; data: string; value: bigint };
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### 类型定义
|
|
556
|
+
|
|
557
|
+
#### `AnchorSDKConfig`
|
|
558
|
+
|
|
559
|
+
SDK 配置接口:
|
|
560
|
+
|
|
561
|
+
```typescript
|
|
562
|
+
interface AnchorSDKConfig {
|
|
563
|
+
provider?: string | any; // Provider URL 或 Web3 Provider
|
|
564
|
+
signer?: any; // 可选的签名者或钱包
|
|
565
|
+
network: {
|
|
566
|
+
// 网络信息
|
|
567
|
+
id: number;
|
|
568
|
+
name: string;
|
|
569
|
+
[key: string]: any;
|
|
570
|
+
};
|
|
571
|
+
env: Environment; // 环境枚举
|
|
572
|
+
apiBaseUrl?: string; // API 基础 URL
|
|
573
|
+
authToken?: string; // 认证令牌
|
|
574
|
+
projectId?: string; // 项目 ID
|
|
575
|
+
anchorPayAddress?: string; // AnchorPay 合约地址
|
|
576
|
+
anchorERC1155Address?: string; // AnchorERC1155 合约地址
|
|
577
|
+
publicClient?: PublicClient; // 公共客户端
|
|
578
|
+
walletClient?: WalletClient; // 钱包客户端
|
|
579
|
+
account?: Account; // 账户信息
|
|
580
|
+
onTokenExpired?: (error: Error) => void; // Token 过期回调
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
#### `PaymentOptions`
|
|
585
|
+
|
|
586
|
+
支付选项接口:
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
interface PaymentOptions {
|
|
590
|
+
autoApprove?: boolean; // 是否自动批准 ERC20 代币
|
|
591
|
+
gas?: bigint; // Gas 限制
|
|
592
|
+
maxFeePerGas?: bigint; // 最大 Gas 费用
|
|
593
|
+
maxPriorityFeePerGas?: bigint; // 最大优先费用
|
|
594
|
+
value?: bigint; // 交易值
|
|
595
|
+
nonce?: number; // 交易 nonce
|
|
596
|
+
sendTransaction?: boolean; // 是否直接发送交易
|
|
597
|
+
}
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
#### `SignedMintRequest`
|
|
601
|
+
|
|
602
|
+
签名铸造请求接口:
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
interface SignedMintRequest {
|
|
606
|
+
request: IMintRequest; // 铸造请求
|
|
607
|
+
signature: string; // 签名
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
interface IMintRequest {
|
|
611
|
+
to: Address; // 接收者地址
|
|
612
|
+
tokenId: number | bigint; // 代币 ID
|
|
613
|
+
quantity: number | bigint; // 数量
|
|
614
|
+
price: bigint; // 价格
|
|
615
|
+
currency: Address; // 货币地址
|
|
616
|
+
validityStartTimestamp?: number | bigint; // 有效期开始时间戳
|
|
617
|
+
validityEndTimestamp?: number | bigint; // 有效期结束时间戳
|
|
618
|
+
uid: Hex; // 唯一 ID
|
|
619
|
+
chainId: bigint; // 链 ID
|
|
620
|
+
contractAddress?: string; // 合约地址
|
|
621
|
+
projectHandle?: string; // 项目句柄
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
### 环境配置
|
|
626
|
+
|
|
627
|
+
#### `Environment`
|
|
628
|
+
|
|
629
|
+
环境枚举:
|
|
630
|
+
|
|
631
|
+
```typescript
|
|
632
|
+
enum Environment {
|
|
633
|
+
DEV = "dev", // 开发环境
|
|
634
|
+
BETA = "beta", // 测试环境
|
|
635
|
+
PROD = "prod", // 生产环境
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
### React 支持
|
|
640
|
+
|
|
641
|
+
SDK 还提供了 React Hook 和组件支持:
|
|
642
|
+
|
|
643
|
+
```typescript
|
|
644
|
+
import { useAnchorSDK, AnchorProvider } from "anchor-sdk/react";
|
|
645
|
+
|
|
646
|
+
// 使用 Hook
|
|
647
|
+
const { sdk, loading, error } = useAnchorSDK();
|
|
648
|
+
|
|
649
|
+
// 使用 Provider
|
|
650
|
+
<AnchorProvider config={sdkConfig}>
|
|
651
|
+
<YourApp />
|
|
652
|
+
</AnchorProvider>;
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
## 🛠️ 开发指南
|
|
656
|
+
|
|
657
|
+
### 本地开发
|
|
658
|
+
|
|
659
|
+
1. 克隆仓库:
|
|
660
|
+
|
|
661
|
+
```bash
|
|
662
|
+
git clone https://github.com/keccak256-evg/anchor-sdk.git
|
|
663
|
+
cd anchor-sdk
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
2. 安装依赖:
|
|
667
|
+
|
|
668
|
+
```bash
|
|
669
|
+
npm install
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
3. 构建项目:
|
|
673
|
+
|
|
674
|
+
```bash
|
|
675
|
+
npm run build
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
4. 运行测试:
|
|
679
|
+
|
|
680
|
+
```bash
|
|
681
|
+
npm test
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
### 项目结构
|
|
685
|
+
|
|
686
|
+
```
|
|
687
|
+
src/
|
|
688
|
+
├── index.ts # 主入口文件
|
|
689
|
+
├── AnchorSDK.ts # 核心 SDK 类
|
|
690
|
+
├── AnchorPayClient.ts # AnchorPay 客户端
|
|
691
|
+
├── AnchorERC1155Client.ts # AnchorERC1155 客户端
|
|
692
|
+
├── AnchorApiClientV2.ts # API 客户端
|
|
693
|
+
├── constants.ts # 常量定义
|
|
694
|
+
├── types.ts # 类型定义
|
|
695
|
+
├── abi/ # 合约 ABI
|
|
696
|
+
├── generated/ # 生成的 API 代码
|
|
697
|
+
├── react/ # React 组件和 Hook
|
|
698
|
+
└── utils/ # 工具函数
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
## 🤝 贡献
|
|
702
|
+
|
|
703
|
+
我们欢迎社区贡献!请遵循以下步骤:
|
|
704
|
+
|
|
705
|
+
1. Fork 这个仓库
|
|
706
|
+
2. 创建您的特性分支 (`git checkout -b feature/AmazingFeature`)
|
|
707
|
+
3. 提交您的更改 (`git commit -m 'Add some AmazingFeature'`)
|
|
708
|
+
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
|
709
|
+
5. 打开一个 Pull Request
|
|
710
|
+
|
|
711
|
+
### 贡献指南
|
|
712
|
+
|
|
713
|
+
- 请确保您的代码遵循项目的 TypeScript 配置
|
|
714
|
+
- 添加适当的测试覆盖
|
|
715
|
+
- 更新相关文档
|
|
716
|
+
- 遵循现有的代码风格
|
|
717
|
+
|
|
718
|
+
## 📄 许可证
|
|
719
|
+
|
|
720
|
+
本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。
|
|
721
|
+
|
|
722
|
+
## 🔗 相关链接
|
|
723
|
+
|
|
724
|
+
- [项目主页](https://github.com/keccak256-evg/anchor-sdk)
|
|
725
|
+
- [npm 包](https://www.npmjs.com/package/anchor-sdk)
|
|
726
|
+
- [文档](https://github.com/keccak256-evg/anchor-sdk/tree/main/docs)
|
|
727
|
+
- [示例代码](https://github.com/keccak256-evg/anchor-sdk/tree/main/examples)
|
|
728
|
+
|
|
729
|
+
## 📞 支持
|
|
730
|
+
|
|
731
|
+
如果您遇到任何问题或有疑问,请:
|
|
732
|
+
|
|
733
|
+
1. 查看 [文档](https://github.com/keccak256-evg/anchor-sdk/tree/main/docs)
|
|
734
|
+
2. 搜索 [Issues](https://github.com/keccak256-evg/anchor-sdk/issues)
|
|
735
|
+
3. 创建新的 [Issue](https://github.com/keccak256-evg/anchor-sdk/issues/new)
|