thirdweb 5.121.2 → 5.121.3
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/cjs/react/core/hooks/x402/useFetchWithPaymentCore.js +1 -0
- package/dist/cjs/react/core/hooks/x402/useFetchWithPaymentCore.js.map +1 -1
- package/dist/cjs/react/native/hooks/x402/useFetchWithPayment.js +1 -1
- package/dist/cjs/react/web/hooks/x402/useFetchWithPayment.js +2 -2
- package/dist/cjs/react/web/hooks/x402/useFetchWithPayment.js.map +1 -1
- package/dist/cjs/react/web/ui/x402/PaymentErrorModal.js +4 -4
- package/dist/cjs/react/web/ui/x402/PaymentErrorModal.js.map +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/x402/encode.js +41 -2
- package/dist/cjs/x402/encode.js.map +1 -1
- package/dist/cjs/x402/fetchWithPayment.js +56 -33
- package/dist/cjs/x402/fetchWithPayment.js.map +1 -1
- package/dist/cjs/x402/schemas.js +134 -2
- package/dist/cjs/x402/schemas.js.map +1 -1
- package/dist/cjs/x402/sign.js +56 -15
- package/dist/cjs/x402/sign.js.map +1 -1
- package/dist/esm/react/core/hooks/x402/useFetchWithPaymentCore.js +2 -1
- package/dist/esm/react/core/hooks/x402/useFetchWithPaymentCore.js.map +1 -1
- package/dist/esm/react/native/hooks/x402/useFetchWithPayment.js +1 -1
- package/dist/esm/react/web/hooks/x402/useFetchWithPayment.js +2 -2
- package/dist/esm/react/web/hooks/x402/useFetchWithPayment.js.map +1 -1
- package/dist/esm/react/web/ui/x402/PaymentErrorModal.js +5 -5
- package/dist/esm/react/web/ui/x402/PaymentErrorModal.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/x402/encode.js +40 -2
- package/dist/esm/x402/encode.js.map +1 -1
- package/dist/esm/x402/fetchWithPayment.js +57 -35
- package/dist/esm/x402/fetchWithPayment.js.map +1 -1
- package/dist/esm/x402/schemas.js +129 -1
- package/dist/esm/x402/schemas.js.map +1 -1
- package/dist/esm/x402/sign.js +57 -16
- package/dist/esm/x402/sign.js.map +1 -1
- package/dist/scripts/bridge-widget.js +2 -2
- package/dist/types/react/core/hooks/x402/useFetchWithPaymentCore.d.ts +1 -0
- package/dist/types/react/core/hooks/x402/useFetchWithPaymentCore.d.ts.map +1 -1
- package/dist/types/react/native/hooks/x402/useFetchWithPayment.d.ts +1 -1
- package/dist/types/react/web/hooks/x402/useFetchWithPayment.d.ts +1 -1
- package/dist/types/react/web/hooks/x402/useFetchWithPayment.d.ts.map +1 -1
- package/dist/types/react/web/ui/x402/PaymentErrorModal.d.ts +1 -0
- package/dist/types/react/web/ui/x402/PaymentErrorModal.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/x402/encode.d.ts +7 -0
- package/dist/types/x402/encode.d.ts.map +1 -1
- package/dist/types/x402/fetchWithPayment.d.ts +10 -1
- package/dist/types/x402/fetchWithPayment.d.ts.map +1 -1
- package/dist/types/x402/schemas.d.ts +60 -2
- package/dist/types/x402/schemas.d.ts.map +1 -1
- package/dist/types/x402/sign.d.ts +13 -1
- package/dist/types/x402/sign.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/contract/actions/resolve-abi.test.ts +3 -5
- package/src/extensions/airdrop/write/airdropERC721WithSignature.test.ts +4 -5
- package/src/extensions/erc1155/drop1155.test.ts +1 -1
- package/src/extensions/erc1155/write/sigMint1155.test.ts +189 -187
- package/src/extensions/erc20/drop20.test.ts +1 -1
- package/src/extensions/erc721/write/sigMint721.test.ts +4 -6
- package/src/extensions/modules/ClaimableERC1155/claimableERC1155.test.ts +180 -178
- package/src/extensions/modules/ClaimableERC20/claimableERC20.test.ts +1 -1
- package/src/extensions/modules/ClaimableERC721/claimableERC721.test.ts +1 -1
- package/src/extensions/prebuilts/process-ref-deployments.test.ts +1 -1
- package/src/react/core/hooks/x402/useFetchWithPaymentCore.ts +6 -1
- package/src/react/native/hooks/x402/useFetchWithPayment.ts +1 -1
- package/src/react/web/hooks/x402/useFetchWithPayment.tsx +3 -1
- package/src/react/web/ui/x402/PaymentErrorModal.tsx +9 -4
- package/src/version.ts +1 -1
- package/src/x402/encode.ts +46 -2
- package/src/x402/fetchWithPayment.test.ts +1173 -104
- package/src/x402/fetchWithPayment.ts +72 -54
- package/src/x402/schemas.test.ts +123 -0
- package/src/x402/schemas.ts +199 -6
- package/src/x402/sign.ts +86 -10
|
@@ -20,234 +20,236 @@ import { getInstalledModules } from "../__generated__/IModularCore/read/getInsta
|
|
|
20
20
|
import * as BatchMetadataERC1155 from "../BatchMetadataERC1155/index.js";
|
|
21
21
|
import * as ClaimableERC1155 from "./index.js";
|
|
22
22
|
|
|
23
|
-
describe
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
describe
|
|
24
|
+
.runIf(process.env.TW_SECRET_KEY)
|
|
25
|
+
.skip("ModularClaimableERC1155", () => {
|
|
26
|
+
let contract: ThirdwebContract;
|
|
27
|
+
beforeAll(async () => {
|
|
28
|
+
const address = await deployModularContract({
|
|
29
|
+
account: TEST_ACCOUNT_A,
|
|
30
|
+
chain: ANVIL_CHAIN,
|
|
31
|
+
client: TEST_CLIENT,
|
|
32
|
+
core: "ERC1155",
|
|
33
|
+
modules: [
|
|
34
|
+
ClaimableERC1155.module({
|
|
35
|
+
primarySaleRecipient: TEST_ACCOUNT_A.address,
|
|
36
|
+
}),
|
|
37
|
+
BatchMetadataERC1155.module(),
|
|
38
|
+
],
|
|
39
|
+
params: {
|
|
40
|
+
contractURI: TEST_CONTRACT_URI,
|
|
41
|
+
name: "TestDropERC1155",
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
contract = getContract({
|
|
45
|
+
address,
|
|
46
|
+
chain: ANVIL_CHAIN,
|
|
47
|
+
client: TEST_CLIENT,
|
|
48
|
+
});
|
|
49
|
+
}, 120000);
|
|
50
|
+
|
|
51
|
+
it("should have erc1155 module", async () => {
|
|
52
|
+
const modules = await getInstalledModules({ contract });
|
|
53
|
+
expect(modules.length).toBe(2);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should upload metadata", async () => {
|
|
57
|
+
const transaction = BatchMetadataERC1155.uploadMetadata({
|
|
58
|
+
contract,
|
|
59
|
+
metadatas: Array.from(
|
|
60
|
+
{ length: 10 },
|
|
61
|
+
(_, index) =>
|
|
62
|
+
`ipfs://QmP4JFzBhTGvb27GnJ9eL9vZGYpNBGjHnPudWndruiNERm/${index}`,
|
|
63
|
+
),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await sendAndConfirmTransaction({
|
|
67
|
+
account: TEST_ACCOUNT_A,
|
|
68
|
+
transaction,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("should not claim without claim conditions", async () => {
|
|
73
|
+
// should throw
|
|
74
|
+
await expect(
|
|
75
|
+
sendAndConfirmTransaction({
|
|
76
|
+
account: TEST_ACCOUNT_A,
|
|
77
|
+
transaction: ClaimableERC1155.mint({
|
|
78
|
+
contract,
|
|
79
|
+
quantity: 1,
|
|
80
|
+
to: TEST_ACCOUNT_A.address,
|
|
81
|
+
tokenId: 123123123213n,
|
|
82
|
+
}),
|
|
34
83
|
}),
|
|
35
|
-
|
|
36
|
-
],
|
|
37
|
-
params: {
|
|
38
|
-
contractURI: TEST_CONTRACT_URI,
|
|
39
|
-
name: "TestDropERC1155",
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
contract = getContract({
|
|
43
|
-
address,
|
|
44
|
-
chain: ANVIL_CHAIN,
|
|
45
|
-
client: TEST_CLIENT,
|
|
46
|
-
});
|
|
47
|
-
}, 120000);
|
|
48
|
-
|
|
49
|
-
it("should have erc1155 module", async () => {
|
|
50
|
-
const modules = await getInstalledModules({ contract });
|
|
51
|
-
expect(modules.length).toBe(2);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("should upload metadata", async () => {
|
|
55
|
-
const transaction = BatchMetadataERC1155.uploadMetadata({
|
|
56
|
-
contract,
|
|
57
|
-
metadatas: Array.from(
|
|
58
|
-
{ length: 10 },
|
|
59
|
-
(_, index) =>
|
|
60
|
-
`ipfs://QmP4JFzBhTGvb27GnJ9eL9vZGYpNBGjHnPudWndruiNERm/${index}`,
|
|
61
|
-
),
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
await sendAndConfirmTransaction({
|
|
65
|
-
account: TEST_ACCOUNT_A,
|
|
66
|
-
transaction,
|
|
84
|
+
).rejects.toThrowError(/ClaimableOutOfTimeWindow/);
|
|
67
85
|
});
|
|
68
|
-
});
|
|
69
86
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
await expect(
|
|
73
|
-
sendAndConfirmTransaction({
|
|
87
|
+
it("should claim tokens with claim conditions", async () => {
|
|
88
|
+
await sendAndConfirmTransaction({
|
|
74
89
|
account: TEST_ACCOUNT_A,
|
|
75
|
-
transaction: ClaimableERC1155.
|
|
90
|
+
transaction: ClaimableERC1155.setClaimCondition({
|
|
76
91
|
contract,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
tokenId:
|
|
92
|
+
maxClaimableSupply: "1",
|
|
93
|
+
pricePerToken: "0.1",
|
|
94
|
+
tokenId: 0n,
|
|
80
95
|
}),
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// should throw if claiming more than supply
|
|
99
|
+
await expect(
|
|
100
|
+
sendAndConfirmTransaction({
|
|
101
|
+
account: TEST_ACCOUNT_A,
|
|
102
|
+
transaction: ClaimableERC1155.mint({
|
|
103
|
+
contract,
|
|
104
|
+
quantity: 1000,
|
|
105
|
+
to: TEST_ACCOUNT_A.address,
|
|
106
|
+
tokenId: 0n,
|
|
107
|
+
}),
|
|
108
|
+
}),
|
|
109
|
+
).rejects.toThrowError(/ClaimableOutOfSupply/);
|
|
84
110
|
|
|
85
|
-
|
|
86
|
-
await sendAndConfirmTransaction({
|
|
87
|
-
account: TEST_ACCOUNT_A,
|
|
88
|
-
transaction: ClaimableERC1155.setClaimCondition({
|
|
111
|
+
let balance = await balanceOf({
|
|
89
112
|
contract,
|
|
90
|
-
|
|
91
|
-
pricePerToken: "0.1",
|
|
113
|
+
owner: TEST_ACCOUNT_A.address,
|
|
92
114
|
tokenId: 0n,
|
|
93
|
-
})
|
|
94
|
-
});
|
|
115
|
+
});
|
|
95
116
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
sendAndConfirmTransaction({
|
|
117
|
+
expect(balance).toBe(0n);
|
|
118
|
+
|
|
119
|
+
await sendAndConfirmTransaction({
|
|
99
120
|
account: TEST_ACCOUNT_A,
|
|
100
121
|
transaction: ClaimableERC1155.mint({
|
|
101
122
|
contract,
|
|
102
|
-
quantity:
|
|
123
|
+
quantity: 1,
|
|
103
124
|
to: TEST_ACCOUNT_A.address,
|
|
104
125
|
tokenId: 0n,
|
|
105
126
|
}),
|
|
106
|
-
})
|
|
107
|
-
).rejects.toThrowError(/ClaimableOutOfSupply/);
|
|
127
|
+
});
|
|
108
128
|
|
|
109
|
-
|
|
110
|
-
contract,
|
|
111
|
-
owner: TEST_ACCOUNT_A.address,
|
|
112
|
-
tokenId: 0n,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
expect(balance).toBe(0n);
|
|
116
|
-
|
|
117
|
-
await sendAndConfirmTransaction({
|
|
118
|
-
account: TEST_ACCOUNT_A,
|
|
119
|
-
transaction: ClaimableERC1155.mint({
|
|
129
|
+
balance = await balanceOf({
|
|
120
130
|
contract,
|
|
121
|
-
|
|
122
|
-
to: TEST_ACCOUNT_A.address,
|
|
131
|
+
owner: TEST_ACCOUNT_A.address,
|
|
123
132
|
tokenId: 0n,
|
|
124
|
-
})
|
|
125
|
-
|
|
133
|
+
});
|
|
134
|
+
expect(balance).toBe(1n);
|
|
126
135
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
});
|
|
132
|
-
expect(balance).toBe(1n);
|
|
133
|
-
|
|
134
|
-
const all = await getNFTs({
|
|
135
|
-
contract,
|
|
136
|
-
});
|
|
137
|
-
expect(all.length).toBe(10);
|
|
138
|
-
|
|
139
|
-
const owned = await getOwnedNFTs({
|
|
140
|
-
address: TEST_ACCOUNT_A.address,
|
|
141
|
-
contract,
|
|
142
|
-
});
|
|
143
|
-
expect(owned.length).toBe(1);
|
|
144
|
-
expect(owned?.[0]?.metadata.name).toBe("Test 0");
|
|
145
|
-
expect(owned?.[0]?.quantityOwned).toBe(1n);
|
|
146
|
-
});
|
|
136
|
+
const all = await getNFTs({
|
|
137
|
+
contract,
|
|
138
|
+
});
|
|
139
|
+
expect(all.length).toBe(10);
|
|
147
140
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
account: TEST_ACCOUNT_A,
|
|
151
|
-
transaction: ClaimableERC1155.setClaimCondition({
|
|
152
|
-
allowList: [TEST_ACCOUNT_A.address, TEST_ACCOUNT_B.address],
|
|
141
|
+
const owned = await getOwnedNFTs({
|
|
142
|
+
address: TEST_ACCOUNT_A.address,
|
|
153
143
|
contract,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
144
|
+
});
|
|
145
|
+
expect(owned.length).toBe(1);
|
|
146
|
+
expect(owned?.[0]?.metadata.name).toBe("Test 0");
|
|
147
|
+
expect(owned?.[0]?.quantityOwned).toBe(1n);
|
|
158
148
|
});
|
|
159
149
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
150
|
+
it("should claim tokens with allowlist", async () => {
|
|
151
|
+
await sendAndConfirmTransaction({
|
|
152
|
+
account: TEST_ACCOUNT_A,
|
|
153
|
+
transaction: ClaimableERC1155.setClaimCondition({
|
|
154
|
+
allowList: [TEST_ACCOUNT_A.address, TEST_ACCOUNT_B.address],
|
|
165
155
|
contract,
|
|
166
|
-
|
|
167
|
-
|
|
156
|
+
maxClaimableSupply: "2",
|
|
157
|
+
pricePerToken: "0.1",
|
|
168
158
|
tokenId: 0n,
|
|
169
159
|
}),
|
|
170
|
-
})
|
|
171
|
-
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// should throw if not in allowlist
|
|
163
|
+
await expect(
|
|
164
|
+
sendAndConfirmTransaction({
|
|
165
|
+
account: TEST_ACCOUNT_C,
|
|
166
|
+
transaction: ClaimableERC1155.mint({
|
|
167
|
+
contract,
|
|
168
|
+
quantity: 1,
|
|
169
|
+
to: TEST_ACCOUNT_C.address,
|
|
170
|
+
tokenId: 0n,
|
|
171
|
+
}),
|
|
172
|
+
}),
|
|
173
|
+
).rejects.toThrowError(/ClaimableNotInAllowlist/);
|
|
174
|
+
|
|
175
|
+
// should throw if in allowlist but over supply
|
|
176
|
+
await expect(
|
|
177
|
+
sendAndConfirmTransaction({
|
|
178
|
+
account: TEST_ACCOUNT_C,
|
|
179
|
+
transaction: ClaimableERC1155.mint({
|
|
180
|
+
contract,
|
|
181
|
+
quantity: 3,
|
|
182
|
+
to: TEST_ACCOUNT_C.address,
|
|
183
|
+
tokenId: 0n,
|
|
184
|
+
}),
|
|
185
|
+
}),
|
|
186
|
+
).rejects.toThrowError(/ClaimableOutOfSupply/);
|
|
172
187
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
sendAndConfirmTransaction({
|
|
188
|
+
// can claim to address in allowlist (regardless of sender)
|
|
189
|
+
await sendAndConfirmTransaction({
|
|
176
190
|
account: TEST_ACCOUNT_C,
|
|
177
191
|
transaction: ClaimableERC1155.mint({
|
|
178
192
|
contract,
|
|
179
|
-
quantity:
|
|
180
|
-
to:
|
|
193
|
+
quantity: 2,
|
|
194
|
+
to: TEST_ACCOUNT_B.address,
|
|
181
195
|
tokenId: 0n,
|
|
182
196
|
}),
|
|
183
|
-
})
|
|
184
|
-
).rejects.toThrowError(/ClaimableOutOfSupply/);
|
|
197
|
+
});
|
|
185
198
|
|
|
186
|
-
|
|
187
|
-
await sendAndConfirmTransaction({
|
|
188
|
-
account: TEST_ACCOUNT_C,
|
|
189
|
-
transaction: ClaimableERC1155.mint({
|
|
199
|
+
const balance = await balanceOf({
|
|
190
200
|
contract,
|
|
191
|
-
|
|
192
|
-
to: TEST_ACCOUNT_B.address,
|
|
201
|
+
owner: TEST_ACCOUNT_B.address,
|
|
193
202
|
tokenId: 0n,
|
|
194
|
-
})
|
|
203
|
+
});
|
|
204
|
+
expect(balance).toBe(2n);
|
|
195
205
|
});
|
|
196
206
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
207
|
+
it("should claim tokens with max per wallet", async () => {
|
|
208
|
+
await sendAndConfirmTransaction({
|
|
209
|
+
account: TEST_ACCOUNT_A,
|
|
210
|
+
transaction: ClaimableERC1155.setClaimCondition({
|
|
211
|
+
contract,
|
|
212
|
+
maxClaimablePerWallet: 1,
|
|
213
|
+
maxClaimableSupply: 10,
|
|
214
|
+
tokenId: 0n,
|
|
215
|
+
}),
|
|
216
|
+
});
|
|
204
217
|
|
|
205
|
-
|
|
206
|
-
await sendAndConfirmTransaction({
|
|
207
|
-
account: TEST_ACCOUNT_A,
|
|
208
|
-
transaction: ClaimableERC1155.setClaimCondition({
|
|
218
|
+
let balance = await balanceOf({
|
|
209
219
|
contract,
|
|
210
|
-
|
|
211
|
-
maxClaimableSupply: 10,
|
|
220
|
+
owner: TEST_ACCOUNT_C.address,
|
|
212
221
|
tokenId: 0n,
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
+
});
|
|
223
|
+
expect(balance).toBe(0n);
|
|
224
|
+
|
|
225
|
+
// should throw if max per wallet is reached
|
|
226
|
+
await expect(
|
|
227
|
+
sendAndConfirmTransaction({
|
|
228
|
+
account: TEST_ACCOUNT_C,
|
|
229
|
+
transaction: ClaimableERC1155.mint({
|
|
230
|
+
contract,
|
|
231
|
+
quantity: 4,
|
|
232
|
+
to: TEST_ACCOUNT_C.address,
|
|
233
|
+
tokenId: 0n,
|
|
234
|
+
}),
|
|
235
|
+
}),
|
|
236
|
+
).rejects.toThrowError(/ClaimableMaxMintPerWalletExceeded/);
|
|
222
237
|
|
|
223
|
-
|
|
224
|
-
await expect(
|
|
225
|
-
sendAndConfirmTransaction({
|
|
238
|
+
await sendAndConfirmTransaction({
|
|
226
239
|
account: TEST_ACCOUNT_C,
|
|
227
240
|
transaction: ClaimableERC1155.mint({
|
|
228
241
|
contract,
|
|
229
|
-
quantity:
|
|
242
|
+
quantity: 1,
|
|
230
243
|
to: TEST_ACCOUNT_C.address,
|
|
231
244
|
tokenId: 0n,
|
|
232
245
|
}),
|
|
233
|
-
})
|
|
234
|
-
).rejects.toThrowError(/ClaimableMaxMintPerWalletExceeded/);
|
|
246
|
+
});
|
|
235
247
|
|
|
236
|
-
|
|
237
|
-
account: TEST_ACCOUNT_C,
|
|
238
|
-
transaction: ClaimableERC1155.mint({
|
|
248
|
+
balance = await balanceOf({
|
|
239
249
|
contract,
|
|
240
|
-
|
|
241
|
-
to: TEST_ACCOUNT_C.address,
|
|
250
|
+
owner: TEST_ACCOUNT_C.address,
|
|
242
251
|
tokenId: 0n,
|
|
243
|
-
})
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
balance = await balanceOf({
|
|
247
|
-
contract,
|
|
248
|
-
owner: TEST_ACCOUNT_C.address,
|
|
249
|
-
tokenId: 0n,
|
|
252
|
+
});
|
|
253
|
+
expect(balance).toBe(1n);
|
|
250
254
|
});
|
|
251
|
-
expect(balance).toBe(1n);
|
|
252
255
|
});
|
|
253
|
-
});
|
|
@@ -17,7 +17,7 @@ import { deployModularContract } from "../../prebuilts/deploy-modular.js";
|
|
|
17
17
|
import { getInstalledModules } from "../__generated__/IModularCore/read/getInstalledModules.js";
|
|
18
18
|
import * as ClaimableERC20 from "./index.js";
|
|
19
19
|
|
|
20
|
-
describe.runIf(process.env.TW_SECRET_KEY)("ModularDropERC20", () => {
|
|
20
|
+
describe.runIf(process.env.TW_SECRET_KEY).skip("ModularDropERC20", () => {
|
|
21
21
|
let contract: ThirdwebContract;
|
|
22
22
|
beforeAll(async () => {
|
|
23
23
|
const address = await deployModularContract({
|
|
@@ -18,7 +18,7 @@ import { getInstalledModules } from "../__generated__/IModularCore/read/getInsta
|
|
|
18
18
|
import * as BatchMetadataERC721 from "../BatchMetadataERC721/index.js";
|
|
19
19
|
import * as ClaimableERC721 from "./index.js";
|
|
20
20
|
|
|
21
|
-
describe.runIf(process.env.TW_SECRET_KEY)("ModularClaimableERC721", () => {
|
|
21
|
+
describe.runIf(process.env.TW_SECRET_KEY).skip("ModularClaimableERC721", () => {
|
|
22
22
|
let contract: ThirdwebContract;
|
|
23
23
|
beforeAll(async () => {
|
|
24
24
|
const address = await deployModularContract({
|
|
@@ -8,7 +8,7 @@ import { readContract } from "../../transaction/read-contract.js";
|
|
|
8
8
|
import { getInstalledModules } from "../modules/__generated__/IModularCore/read/getInstalledModules.js";
|
|
9
9
|
import { deployPublishedContract } from "./deploy-published.js";
|
|
10
10
|
|
|
11
|
-
describe.runIf(process.env.TW_SECRET_KEY)(
|
|
11
|
+
describe.runIf(process.env.TW_SECRET_KEY).skip(
|
|
12
12
|
"deployref",
|
|
13
13
|
{
|
|
14
14
|
timeout: 120000,
|
|
@@ -4,7 +4,10 @@ import { useMutation } from "@tanstack/react-query";
|
|
|
4
4
|
import type { ThirdwebClient } from "../../../../client/client.js";
|
|
5
5
|
import type { AsyncStorage } from "../../../../utils/storage/AsyncStorage.js";
|
|
6
6
|
import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
getRequestUrl,
|
|
9
|
+
wrapFetchWithPayment,
|
|
10
|
+
} from "../../../../x402/fetchWithPayment.js";
|
|
8
11
|
import type { RequestedPaymentRequirements } from "../../../../x402/schemas.js";
|
|
9
12
|
import type { PaymentRequiredResult } from "../../../../x402/types.js";
|
|
10
13
|
import { useActiveWallet } from "../wallets/useActiveWallet.js";
|
|
@@ -24,6 +27,7 @@ export type UseFetchWithPaymentOptions = {
|
|
|
24
27
|
|
|
25
28
|
type ShowErrorModalCallback = (data: {
|
|
26
29
|
errorData: PaymentRequiredResult["responseBody"];
|
|
30
|
+
requestUrl?: string;
|
|
27
31
|
onRetry: () => void;
|
|
28
32
|
onCancel: () => void;
|
|
29
33
|
}) => void;
|
|
@@ -107,6 +111,7 @@ export function useFetchWithPaymentCore(
|
|
|
107
111
|
return new Promise<unknown>((resolve, reject) => {
|
|
108
112
|
showErrorModal({
|
|
109
113
|
errorData: errorBody,
|
|
114
|
+
requestUrl: getRequestUrl(input),
|
|
110
115
|
onRetry: async () => {
|
|
111
116
|
// Retry the entire fetch+error handling logic recursively
|
|
112
117
|
// Pass currentWallet to avoid re-showing connect modal with stale wallet state
|
|
@@ -27,7 +27,7 @@ export type { UseFetchWithPaymentOptions };
|
|
|
27
27
|
*
|
|
28
28
|
* @param client - The thirdweb client used to access RPC infrastructure
|
|
29
29
|
* @param options - Optional configuration for payment handling
|
|
30
|
-
* @param options.maxValue - The maximum allowed payment amount in base units
|
|
30
|
+
* @param options.maxValue - The maximum allowed payment amount in base units. `0n` only allows zero-amount payments
|
|
31
31
|
* @param options.paymentRequirementsSelector - Custom function to select payment requirements from available options
|
|
32
32
|
* @param options.parseAs - How to parse the response: "json" (default), "text", or "raw"
|
|
33
33
|
* @param options.storage - Storage for caching permit signatures (for "upto" scheme). Provide your own AsyncStorage implementation for React Native.
|
|
@@ -78,7 +78,7 @@ type UseFetchWithPaymentConfig = UseFetchWithPaymentOptions & {
|
|
|
78
78
|
*
|
|
79
79
|
* @param client - The thirdweb client used to access RPC infrastructure
|
|
80
80
|
* @param options - Optional configuration for payment handling
|
|
81
|
-
* @param options.maxValue - The maximum allowed payment amount in base units
|
|
81
|
+
* @param options.maxValue - The maximum allowed payment amount in base units. `0n` only allows zero-amount payments
|
|
82
82
|
* @param options.paymentRequirementsSelector - Custom function to select payment requirements from available options
|
|
83
83
|
* @param options.parseAs - How to parse the response: "json" (default), "text", or "raw"
|
|
84
84
|
* @param options.uiEnabled - Whether to show the UI for connection, funding or payment retries (defaults to true). Set to false to handle errors yourself
|
|
@@ -196,6 +196,7 @@ export function useFetchWithPayment(
|
|
|
196
196
|
const showErrorModal = showModal
|
|
197
197
|
? (data: {
|
|
198
198
|
errorData: Parameters<typeof PaymentErrorModal>[0]["errorData"];
|
|
199
|
+
requestUrl?: string;
|
|
199
200
|
onRetry: () => void;
|
|
200
201
|
onCancel: () => void;
|
|
201
202
|
}) => {
|
|
@@ -203,6 +204,7 @@ export function useFetchWithPayment(
|
|
|
203
204
|
<PaymentErrorModal
|
|
204
205
|
client={client}
|
|
205
206
|
errorData={data.errorData}
|
|
207
|
+
requestUrl={data.requestUrl}
|
|
206
208
|
onCancel={() => {
|
|
207
209
|
setRootEl(null);
|
|
208
210
|
data.onCancel();
|
|
@@ -5,6 +5,7 @@ import type { ThirdwebClient } from "../../../../client/client.js";
|
|
|
5
5
|
import {
|
|
6
6
|
extractEvmChainId,
|
|
7
7
|
networkToCaip2ChainId,
|
|
8
|
+
parsePaymentRequirementsForDisplay,
|
|
8
9
|
type RequestedPaymentRequirements,
|
|
9
10
|
} from "../../../../x402/schemas.js";
|
|
10
11
|
import type { PaymentRequiredResult } from "../../../../x402/types.js";
|
|
@@ -25,6 +26,7 @@ import { Text } from "../components/text.js";
|
|
|
25
26
|
type PaymentErrorModalProps = {
|
|
26
27
|
client: ThirdwebClient;
|
|
27
28
|
errorData: PaymentRequiredResult["responseBody"];
|
|
29
|
+
requestUrl?: string;
|
|
28
30
|
onRetry: () => void;
|
|
29
31
|
onCancel: () => void;
|
|
30
32
|
theme: Theme | "light" | "dark";
|
|
@@ -54,6 +56,7 @@ export function PaymentErrorModal(props: PaymentErrorModalProps) {
|
|
|
54
56
|
const {
|
|
55
57
|
client,
|
|
56
58
|
errorData,
|
|
59
|
+
requestUrl,
|
|
57
60
|
onRetry,
|
|
58
61
|
onCancel,
|
|
59
62
|
theme,
|
|
@@ -66,13 +69,15 @@ export function PaymentErrorModal(props: PaymentErrorModalProps) {
|
|
|
66
69
|
|
|
67
70
|
// Extract chain and token info from errorData for BuyWidget
|
|
68
71
|
const getBuyWidgetConfig = () => {
|
|
69
|
-
|
|
72
|
+
// Get payment requirements from errorData
|
|
73
|
+
const parsedPaymentRequirements = parsePaymentRequirementsForDisplay(
|
|
74
|
+
errorData,
|
|
75
|
+
requestUrl,
|
|
76
|
+
);
|
|
77
|
+
if (parsedPaymentRequirements.length === 0) {
|
|
70
78
|
return null;
|
|
71
79
|
}
|
|
72
80
|
|
|
73
|
-
// Get payment requirements from errorData
|
|
74
|
-
const parsedPaymentRequirements = errorData.accepts;
|
|
75
|
-
|
|
76
81
|
// Get the current chain from wallet
|
|
77
82
|
const currentChain = wallet?.getChain();
|
|
78
83
|
const currentChainId = currentChain?.id;
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "5.121.
|
|
1
|
+
export const version = "5.121.3";
|
package/src/x402/encode.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { ExactEvmPayload } from "x402/types";
|
|
2
|
+
import { cachedTextDecoder } from "../utils/text-decoder.js";
|
|
3
|
+
import { cachedTextEncoder } from "../utils/text-encoder.js";
|
|
2
4
|
import type {
|
|
3
5
|
RequestedPaymentPayload,
|
|
4
6
|
RequestedPaymentRequirements,
|
|
@@ -27,7 +29,7 @@ export function encodePayment(payment: RequestedPaymentPayload): string {
|
|
|
27
29
|
) as ExactEvmPayload["authorization"],
|
|
28
30
|
},
|
|
29
31
|
};
|
|
30
|
-
return
|
|
32
|
+
return base64EncodeUtf8(JSON.stringify(safe));
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
/**
|
|
@@ -37,7 +39,7 @@ export function encodePayment(payment: RequestedPaymentPayload): string {
|
|
|
37
39
|
* @returns The decoded and validated PaymentPayload object
|
|
38
40
|
*/
|
|
39
41
|
export function decodePayment(payment: string): RequestedPaymentPayload {
|
|
40
|
-
const decoded =
|
|
42
|
+
const decoded = base64DecodeUtf8(payment);
|
|
41
43
|
const parsed = JSON.parse(decoded);
|
|
42
44
|
|
|
43
45
|
const obj: RequestedPaymentPayload = {
|
|
@@ -93,3 +95,45 @@ export function safeBase64Decode(data: string): string {
|
|
|
93
95
|
}
|
|
94
96
|
return Buffer.from(data, "base64").toString("utf-8");
|
|
95
97
|
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Encodes a string as UTF-8 and then to base64
|
|
101
|
+
*
|
|
102
|
+
* @param data - The string to encode
|
|
103
|
+
* @returns The base64 encoded UTF-8 bytes
|
|
104
|
+
*/
|
|
105
|
+
function base64EncodeUtf8(data: string): string {
|
|
106
|
+
if (
|
|
107
|
+
typeof globalThis !== "undefined" &&
|
|
108
|
+
typeof globalThis.btoa === "function"
|
|
109
|
+
) {
|
|
110
|
+
const bytes = cachedTextEncoder().encode(data);
|
|
111
|
+
let binary = "";
|
|
112
|
+
for (const byte of bytes) {
|
|
113
|
+
binary += String.fromCharCode(byte);
|
|
114
|
+
}
|
|
115
|
+
return globalThis.btoa(binary);
|
|
116
|
+
}
|
|
117
|
+
return Buffer.from(data, "utf-8").toString("base64");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Decodes a base64 string and interprets the bytes as UTF-8
|
|
122
|
+
*
|
|
123
|
+
* @param data - The base64 encoded string
|
|
124
|
+
* @returns The decoded string
|
|
125
|
+
*/
|
|
126
|
+
export function base64DecodeUtf8(data: string): string {
|
|
127
|
+
if (
|
|
128
|
+
typeof globalThis !== "undefined" &&
|
|
129
|
+
typeof globalThis.atob === "function"
|
|
130
|
+
) {
|
|
131
|
+
const binary = globalThis.atob(data);
|
|
132
|
+
const bytes = new Uint8Array(binary.length);
|
|
133
|
+
for (let i = 0; i < binary.length; i++) {
|
|
134
|
+
bytes[i] = binary.charCodeAt(i);
|
|
135
|
+
}
|
|
136
|
+
return cachedTextDecoder().decode(bytes);
|
|
137
|
+
}
|
|
138
|
+
return Buffer.from(data, "base64").toString("utf-8");
|
|
139
|
+
}
|