thirdweb 5.101.2 → 5.102.0
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/engine/create-server-wallet.js +46 -0
- package/dist/cjs/engine/create-server-wallet.js.map +1 -0
- package/dist/cjs/engine/get-status.js +0 -54
- package/dist/cjs/engine/get-status.js.map +1 -1
- package/dist/cjs/engine/index.js +9 -2
- package/dist/cjs/engine/index.js.map +1 -1
- package/dist/cjs/engine/list-server-wallets.js +40 -0
- package/dist/cjs/engine/list-server-wallets.js.map +1 -0
- package/dist/cjs/engine/search-transactions.js +115 -0
- package/dist/cjs/engine/search-transactions.js.map +1 -0
- package/dist/cjs/engine/server-wallet.js +97 -17
- package/dist/cjs/engine/server-wallet.js.map +1 -1
- package/dist/cjs/engine/wait-for-tx-hash.js +59 -0
- package/dist/cjs/engine/wait-for-tx-hash.js.map +1 -0
- package/dist/cjs/insight/get-nfts.js +6 -1
- package/dist/cjs/insight/get-nfts.js.map +1 -1
- package/dist/cjs/utils/fetch.js +1 -0
- package/dist/cjs/utils/fetch.js.map +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/engine/create-server-wallet.js +43 -0
- package/dist/esm/engine/create-server-wallet.js.map +1 -0
- package/dist/esm/engine/get-status.js +0 -53
- package/dist/esm/engine/get-status.js.map +1 -1
- package/dist/esm/engine/index.js +5 -1
- package/dist/esm/engine/index.js.map +1 -1
- package/dist/esm/engine/list-server-wallets.js +37 -0
- package/dist/esm/engine/list-server-wallets.js.map +1 -0
- package/dist/esm/engine/search-transactions.js +112 -0
- package/dist/esm/engine/search-transactions.js.map +1 -0
- package/dist/esm/engine/server-wallet.js +96 -16
- package/dist/esm/engine/server-wallet.js.map +1 -1
- package/dist/esm/engine/wait-for-tx-hash.js +56 -0
- package/dist/esm/engine/wait-for-tx-hash.js.map +1 -0
- package/dist/esm/insight/get-nfts.js +6 -1
- package/dist/esm/insight/get-nfts.js.map +1 -1
- package/dist/esm/utils/fetch.js +1 -0
- package/dist/esm/utils/fetch.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/types/engine/create-server-wallet.d.ts +29 -0
- package/dist/types/engine/create-server-wallet.d.ts.map +1 -0
- package/dist/types/engine/get-status.d.ts +0 -23
- package/dist/types/engine/get-status.d.ts.map +1 -1
- package/dist/types/engine/index.d.ts +5 -1
- package/dist/types/engine/index.d.ts.map +1 -1
- package/dist/types/engine/list-server-wallets.d.ts +25 -0
- package/dist/types/engine/list-server-wallets.d.ts.map +1 -0
- package/dist/types/engine/search-transactions.d.ts +127 -0
- package/dist/types/engine/search-transactions.d.ts.map +1 -0
- package/dist/types/engine/server-wallet.d.ts +36 -0
- package/dist/types/engine/server-wallet.d.ts.map +1 -1
- package/dist/types/engine/wait-for-tx-hash.d.ts +25 -0
- package/dist/types/engine/wait-for-tx-hash.d.ts.map +1 -0
- package/dist/types/utils/fetch.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +2 -2
- package/src/bridge/Chains.test.ts +1 -1
- package/src/engine/create-server-wallet.ts +57 -0
- package/src/engine/get-status.ts +0 -69
- package/src/engine/index.ts +13 -1
- package/src/engine/list-server-wallets.ts +46 -0
- package/src/engine/search-transactions.ts +132 -0
- package/src/engine/server-wallet.test.ts +54 -0
- package/src/engine/server-wallet.ts +104 -17
- package/src/engine/wait-for-tx-hash.ts +75 -0
- package/src/extensions/erc1155/read/getOwnedNFTs.test.ts +25 -0
- package/src/extensions/erc20/drop20.test.ts +91 -1
- package/src/insight/get-nfts.ts +6 -1
- package/src/utils/fetch.ts +1 -0
- package/src/version.ts +1 -1
@@ -0,0 +1,132 @@
|
|
1
|
+
import {
|
2
|
+
type TransactionsFilterNested,
|
3
|
+
type TransactionsFilterValue,
|
4
|
+
searchTransactions as engineSearchTransactions,
|
5
|
+
} from "@thirdweb-dev/engine";
|
6
|
+
import type { ThirdwebClient } from "../client/client.js";
|
7
|
+
import { getThirdwebBaseUrl } from "../utils/domains.js";
|
8
|
+
import { getClientFetch } from "../utils/fetch.js";
|
9
|
+
import { stringify } from "../utils/json.js";
|
10
|
+
|
11
|
+
export type SearchTransactionsArgs = {
|
12
|
+
client: ThirdwebClient;
|
13
|
+
filters?: (TransactionsFilterValue | TransactionsFilterNested)[];
|
14
|
+
pageSize?: number;
|
15
|
+
page?: number;
|
16
|
+
};
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Search for transactions by their ids.
|
20
|
+
* @param args - The arguments for the search.
|
21
|
+
* @param args.client - The thirdweb client to use.
|
22
|
+
* @param args.transactionIds - The ids of the transactions to search for.
|
23
|
+
* @engine
|
24
|
+
* @example
|
25
|
+
* ## Search for transactions by their ids
|
26
|
+
*
|
27
|
+
* ```ts
|
28
|
+
* import { Engine } from "thirdweb";
|
29
|
+
*
|
30
|
+
* const transactions = await Engine.searchTransactions({
|
31
|
+
* client,
|
32
|
+
* filters: [
|
33
|
+
* {
|
34
|
+
* field: "id",
|
35
|
+
* values: ["1", "2", "3"],
|
36
|
+
* },
|
37
|
+
* ],
|
38
|
+
* });
|
39
|
+
* console.log(transactions);
|
40
|
+
* ```
|
41
|
+
*
|
42
|
+
* ## Search for transactions by chain id
|
43
|
+
*
|
44
|
+
* ```ts
|
45
|
+
* import { Engine } from "thirdweb";
|
46
|
+
*
|
47
|
+
* const transactions = await Engine.searchTransactions({
|
48
|
+
* client,
|
49
|
+
* filters: [
|
50
|
+
* {
|
51
|
+
* field: "chainId",
|
52
|
+
* values: ["1", "137"],
|
53
|
+
* },
|
54
|
+
* ],
|
55
|
+
* });
|
56
|
+
* console.log(transactions);
|
57
|
+
* ```
|
58
|
+
*
|
59
|
+
* ## Search for transactions by sender wallet address
|
60
|
+
*
|
61
|
+
* ```ts
|
62
|
+
* import { Engine } from "thirdweb";
|
63
|
+
*
|
64
|
+
* const transactions = await Engine.searchTransactions({
|
65
|
+
* client,
|
66
|
+
* filters: [
|
67
|
+
* {
|
68
|
+
* field: "from",
|
69
|
+
* values: ["0x1234567890123456789012345678901234567890"],
|
70
|
+
* },
|
71
|
+
* ],
|
72
|
+
* });
|
73
|
+
* console.log(transactions);
|
74
|
+
* ```
|
75
|
+
*
|
76
|
+
* ## Combined search
|
77
|
+
*
|
78
|
+
* ```ts
|
79
|
+
* import { Engine } from "thirdweb";
|
80
|
+
*
|
81
|
+
* const transactions = await Engine.searchTransactions({
|
82
|
+
* client,
|
83
|
+
* filters: [
|
84
|
+
* {
|
85
|
+
* filters: [
|
86
|
+
* {
|
87
|
+
* field: "from",
|
88
|
+
* values: ["0x1234567890123456789012345678901234567890"],
|
89
|
+
* },
|
90
|
+
* {
|
91
|
+
* field: "chainId",
|
92
|
+
* values: ["8453"],
|
93
|
+
* },
|
94
|
+
* ],
|
95
|
+
* operation: "AND",
|
96
|
+
* },
|
97
|
+
* ],
|
98
|
+
* pageSize: 100,
|
99
|
+
* page: 0,
|
100
|
+
* });
|
101
|
+
* console.log(transactions);
|
102
|
+
* ```
|
103
|
+
*/
|
104
|
+
export async function searchTransactions(args: SearchTransactionsArgs) {
|
105
|
+
const { client, filters, pageSize = 100, page = 1 } = args;
|
106
|
+
const searchResult = await engineSearchTransactions({
|
107
|
+
baseUrl: getThirdwebBaseUrl("engineCloud"),
|
108
|
+
bodySerializer: stringify,
|
109
|
+
fetch: getClientFetch(client),
|
110
|
+
body: {
|
111
|
+
filters,
|
112
|
+
limit: pageSize,
|
113
|
+
page,
|
114
|
+
},
|
115
|
+
});
|
116
|
+
|
117
|
+
if (searchResult.error) {
|
118
|
+
throw new Error(
|
119
|
+
`Error searching for transaction with filters ${stringify(filters)}: ${stringify(
|
120
|
+
searchResult.error,
|
121
|
+
)}`,
|
122
|
+
);
|
123
|
+
}
|
124
|
+
|
125
|
+
const data = searchResult.data?.result;
|
126
|
+
|
127
|
+
if (!data) {
|
128
|
+
throw new Error(`No transactions found with filters ${stringify(filters)}`);
|
129
|
+
}
|
130
|
+
|
131
|
+
return data;
|
132
|
+
}
|
@@ -47,6 +47,23 @@ describe.runIf(
|
|
47
47
|
});
|
48
48
|
});
|
49
49
|
|
50
|
+
it("should create a server wallet", async () => {
|
51
|
+
const serverWallet = await Engine.createServerWallet({
|
52
|
+
client: TEST_CLIENT,
|
53
|
+
label: "My Server Wallet",
|
54
|
+
});
|
55
|
+
expect(serverWallet).toBeDefined();
|
56
|
+
|
57
|
+
const serverWallets = await Engine.getServerWallets({
|
58
|
+
client: TEST_CLIENT,
|
59
|
+
});
|
60
|
+
expect(serverWallets).toBeDefined();
|
61
|
+
expect(serverWallets.length).toBeGreaterThan(0);
|
62
|
+
expect(
|
63
|
+
serverWallets.find((s) => s.address === serverWallet.address),
|
64
|
+
).toBeDefined();
|
65
|
+
});
|
66
|
+
|
50
67
|
it("should sign a message", async () => {
|
51
68
|
const signature = await serverWallet.signMessage({
|
52
69
|
message: "hello",
|
@@ -95,6 +112,16 @@ describe.runIf(
|
|
95
112
|
transactionId: result.transactionId,
|
96
113
|
});
|
97
114
|
expect(txHash.transactionHash).toBeDefined();
|
115
|
+
|
116
|
+
const res = await Engine.searchTransactions({
|
117
|
+
client: TEST_CLIENT,
|
118
|
+
filters: [
|
119
|
+
{ field: "id", values: [result.transactionId], operation: "OR" },
|
120
|
+
],
|
121
|
+
});
|
122
|
+
expect(res).toBeDefined();
|
123
|
+
expect(res.transactions.length).toBe(1);
|
124
|
+
expect(res.transactions[0]?.id).toBe(result.transactionId);
|
98
125
|
});
|
99
126
|
|
100
127
|
it("should send a extension tx", async () => {
|
@@ -115,6 +142,33 @@ describe.runIf(
|
|
115
142
|
expect(tx).toBeDefined();
|
116
143
|
});
|
117
144
|
|
145
|
+
it("should enqueue a batch of txs", async () => {
|
146
|
+
const tokenContract = getContract({
|
147
|
+
client: TEST_CLIENT,
|
148
|
+
chain: baseSepolia,
|
149
|
+
address: "0x87C52295891f208459F334975a3beE198fE75244",
|
150
|
+
});
|
151
|
+
const claimTx1 = mintTo({
|
152
|
+
contract: tokenContract,
|
153
|
+
to: serverWallet.address,
|
154
|
+
amount: "0.001",
|
155
|
+
});
|
156
|
+
const claimTx2 = mintTo({
|
157
|
+
contract: tokenContract,
|
158
|
+
to: serverWallet.address,
|
159
|
+
amount: "0.002",
|
160
|
+
});
|
161
|
+
const tx = await serverWallet.enqueueBatchTransaction({
|
162
|
+
transactions: [claimTx1, claimTx2],
|
163
|
+
});
|
164
|
+
expect(tx.transactionId).toBeDefined();
|
165
|
+
const txHash = await Engine.waitForTransactionHash({
|
166
|
+
client: TEST_CLIENT,
|
167
|
+
transactionId: tx.transactionId,
|
168
|
+
});
|
169
|
+
expect(txHash.transactionHash).toBeDefined();
|
170
|
+
});
|
171
|
+
|
118
172
|
it("should get revert reason", async () => {
|
119
173
|
const nftContract = getContract({
|
120
174
|
client: TEST_CLIENT,
|
@@ -19,7 +19,7 @@ import type {
|
|
19
19
|
Account,
|
20
20
|
SendTransactionOption,
|
21
21
|
} from "../wallets/interfaces/wallet.js";
|
22
|
-
import { waitForTransactionHash } from "./
|
22
|
+
import { waitForTransactionHash } from "./wait-for-tx-hash.js";
|
23
23
|
|
24
24
|
/**
|
25
25
|
* Options for creating an server wallet.
|
@@ -54,6 +54,9 @@ export type ServerWallet = Account & {
|
|
54
54
|
transaction: PreparedTransaction;
|
55
55
|
simulate?: boolean;
|
56
56
|
}) => Promise<{ transactionId: string }>;
|
57
|
+
enqueueBatchTransaction: (args: {
|
58
|
+
transactions: PreparedTransaction[];
|
59
|
+
}) => Promise<{ transactionId: string }>;
|
57
60
|
};
|
58
61
|
|
59
62
|
/**
|
@@ -102,6 +105,37 @@ export type ServerWallet = Account & {
|
|
102
105
|
* console.log("Transaction sent:", transactionHash);
|
103
106
|
* ```
|
104
107
|
*
|
108
|
+
* ### Sending a batch of transactions
|
109
|
+
* ```ts
|
110
|
+
* // prepare the transactions
|
111
|
+
* const transaction1 = claimTo({
|
112
|
+
* contract,
|
113
|
+
* to: firstRecipient,
|
114
|
+
* quantity: 1n,
|
115
|
+
* });
|
116
|
+
* const transaction2 = claimTo({
|
117
|
+
* contract,
|
118
|
+
* to: secondRecipient,
|
119
|
+
* quantity: 1n,
|
120
|
+
* });
|
121
|
+
*
|
122
|
+
*
|
123
|
+
* // enqueue the transactions in a batch
|
124
|
+
* const { transactionId } = await myServerWallet.enqueueBatchTransaction({
|
125
|
+
* transactions: [transaction1, transaction2],
|
126
|
+
* });
|
127
|
+
* ```
|
128
|
+
*
|
129
|
+
* ### Polling for the batch of transactions to be submitted onchain
|
130
|
+
* ```ts
|
131
|
+
* // optionally poll for the transaction to be submitted onchain
|
132
|
+
* const { transactionHash } = await Engine.waitForTransactionHash({
|
133
|
+
* client,
|
134
|
+
* transactionId,
|
135
|
+
* });
|
136
|
+
* console.log("Transaction sent:", transactionHash);
|
137
|
+
* ```
|
138
|
+
*
|
105
139
|
* ### Getting the execution status of a transaction
|
106
140
|
* ```ts
|
107
141
|
* const executionResult = await Engine.getTransactionStatus({
|
@@ -130,16 +164,30 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet {
|
|
130
164
|
};
|
131
165
|
};
|
132
166
|
|
133
|
-
const enqueueTx = async (transaction: SendTransactionOption) => {
|
167
|
+
const enqueueTx = async (transaction: SendTransactionOption[]) => {
|
168
|
+
if (transaction.length === 0) {
|
169
|
+
throw new Error("No transactions to enqueue");
|
170
|
+
}
|
171
|
+
const firstTransaction = transaction[0];
|
172
|
+
if (!firstTransaction) {
|
173
|
+
throw new Error("No transactions to enqueue");
|
174
|
+
}
|
175
|
+
const chainId = firstTransaction.chainId;
|
176
|
+
// Validate all transactions are on the same chain
|
177
|
+
for (let i = 1; i < transaction.length; i++) {
|
178
|
+
if (transaction[i]?.chainId !== chainId) {
|
179
|
+
throw new Error(
|
180
|
+
`All transactions in batch must be on the same chain. Expected ${chainId}, got ${transaction[i]?.chainId} at index ${i}`,
|
181
|
+
);
|
182
|
+
}
|
183
|
+
}
|
134
184
|
const body = {
|
135
|
-
executionOptions: getExecutionOptions(
|
136
|
-
params:
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
},
|
142
|
-
],
|
185
|
+
executionOptions: getExecutionOptions(chainId),
|
186
|
+
params: transaction.map((t) => ({
|
187
|
+
to: t.to ?? undefined,
|
188
|
+
data: t.data,
|
189
|
+
value: t.value?.toString(),
|
190
|
+
})),
|
143
191
|
};
|
144
192
|
|
145
193
|
const result = await sendTransaction({
|
@@ -158,11 +206,7 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet {
|
|
158
206
|
if (!data) {
|
159
207
|
throw new Error("No data returned from engine");
|
160
208
|
}
|
161
|
-
|
162
|
-
if (!transactionId) {
|
163
|
-
throw new Error("No transactionId returned from engine");
|
164
|
-
}
|
165
|
-
return transactionId;
|
209
|
+
return data.transactions.map((t) => t.id);
|
166
210
|
};
|
167
211
|
|
168
212
|
return {
|
@@ -193,11 +237,54 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet {
|
|
193
237
|
value: value ?? undefined,
|
194
238
|
};
|
195
239
|
}
|
196
|
-
const
|
240
|
+
const transactionIds = await enqueueTx([serializedTransaction]);
|
241
|
+
const transactionId = transactionIds[0];
|
242
|
+
if (!transactionId) {
|
243
|
+
throw new Error("No transactionId returned from engine");
|
244
|
+
}
|
245
|
+
return { transactionId };
|
246
|
+
},
|
247
|
+
enqueueBatchTransaction: async (args: {
|
248
|
+
transactions: PreparedTransaction[];
|
249
|
+
}) => {
|
250
|
+
const serializedTransactions: SendTransactionOption[] = [];
|
251
|
+
for (const transaction of args.transactions) {
|
252
|
+
const [to, data, value] = await Promise.all([
|
253
|
+
transaction.to ? resolvePromisedValue(transaction.to) : null,
|
254
|
+
encode(transaction),
|
255
|
+
transaction.value ? resolvePromisedValue(transaction.value) : null,
|
256
|
+
]);
|
257
|
+
serializedTransactions.push({
|
258
|
+
chainId: transaction.chain.id,
|
259
|
+
data,
|
260
|
+
to: to ?? undefined,
|
261
|
+
value: value ?? undefined,
|
262
|
+
});
|
263
|
+
}
|
264
|
+
const transactionIds = await enqueueTx(serializedTransactions);
|
265
|
+
const transactionId = transactionIds[0];
|
266
|
+
if (!transactionId) {
|
267
|
+
throw new Error("No transactionId returned from engine");
|
268
|
+
}
|
197
269
|
return { transactionId };
|
198
270
|
},
|
199
271
|
sendTransaction: async (transaction: SendTransactionOption) => {
|
200
|
-
const
|
272
|
+
const transactionIds = await enqueueTx([transaction]);
|
273
|
+
const transactionId = transactionIds[0];
|
274
|
+
if (!transactionId) {
|
275
|
+
throw new Error("No transactionId returned from engine");
|
276
|
+
}
|
277
|
+
return waitForTransactionHash({
|
278
|
+
client,
|
279
|
+
transactionId,
|
280
|
+
});
|
281
|
+
},
|
282
|
+
sendBatchTransaction: async (transactions: SendTransactionOption[]) => {
|
283
|
+
const transactionIds = await enqueueTx(transactions);
|
284
|
+
const transactionId = transactionIds[0];
|
285
|
+
if (!transactionId) {
|
286
|
+
throw new Error("No transactionId returned from engine");
|
287
|
+
}
|
201
288
|
return waitForTransactionHash({
|
202
289
|
client,
|
203
290
|
transactionId,
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import { stringify } from "viem";
|
2
|
+
|
3
|
+
import type { Hex } from "../utils/encoding/hex.js";
|
4
|
+
|
5
|
+
import type { ThirdwebClient } from "../client/client.js";
|
6
|
+
import type { WaitForReceiptOptions } from "../transaction/actions/wait-for-tx-receipt.js";
|
7
|
+
import { getTransactionStatus } from "./get-status.js";
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Wait for a transaction to be submitted onchain and return the transaction hash.
|
11
|
+
* @param args - The arguments for the transaction.
|
12
|
+
* @param args.client - The thirdweb client to use.
|
13
|
+
* @param args.transactionId - The id of the transaction to wait for.
|
14
|
+
* @param args.timeoutInSeconds - The timeout in seconds.
|
15
|
+
* @engine
|
16
|
+
* @example
|
17
|
+
* ```ts
|
18
|
+
* import { Engine } from "thirdweb";
|
19
|
+
*
|
20
|
+
* const { transactionHash } = await Engine.waitForTransactionHash({
|
21
|
+
* client,
|
22
|
+
* transactionId, // the transaction id returned from enqueueTransaction
|
23
|
+
* });
|
24
|
+
* ```
|
25
|
+
*/
|
26
|
+
export async function waitForTransactionHash(args: {
|
27
|
+
client: ThirdwebClient;
|
28
|
+
transactionId: string;
|
29
|
+
timeoutInSeconds?: number;
|
30
|
+
}): Promise<WaitForReceiptOptions> {
|
31
|
+
const startTime = Date.now();
|
32
|
+
const TIMEOUT_IN_MS = args.timeoutInSeconds
|
33
|
+
? args.timeoutInSeconds * 1000
|
34
|
+
: 5 * 60 * 1000; // 5 minutes in milliseconds
|
35
|
+
|
36
|
+
while (Date.now() - startTime < TIMEOUT_IN_MS) {
|
37
|
+
const executionResult = await getTransactionStatus(args);
|
38
|
+
const status = executionResult.status;
|
39
|
+
|
40
|
+
switch (status) {
|
41
|
+
case "FAILED": {
|
42
|
+
throw new Error(
|
43
|
+
`Transaction failed: ${executionResult.error || "Unknown error"}`,
|
44
|
+
);
|
45
|
+
}
|
46
|
+
case "CONFIRMED": {
|
47
|
+
const onchainStatus =
|
48
|
+
executionResult && "onchainStatus" in executionResult
|
49
|
+
? executionResult.onchainStatus
|
50
|
+
: null;
|
51
|
+
if (onchainStatus === "REVERTED") {
|
52
|
+
const revertData =
|
53
|
+
"revertData" in executionResult
|
54
|
+
? executionResult.revertData
|
55
|
+
: undefined;
|
56
|
+
throw new Error(
|
57
|
+
`Transaction reverted: ${revertData?.errorName || "unknown error"} ${revertData?.errorArgs ? stringify(revertData.errorArgs) : ""} - ${executionResult.transactionHash ? executionResult.transactionHash : ""}`,
|
58
|
+
);
|
59
|
+
}
|
60
|
+
return {
|
61
|
+
transactionHash: executionResult.transactionHash as Hex,
|
62
|
+
client: args.client,
|
63
|
+
chain: executionResult.chain,
|
64
|
+
};
|
65
|
+
}
|
66
|
+
default: {
|
67
|
+
// wait for the transaction to be confirmed
|
68
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
throw new Error(
|
73
|
+
`Transaction timed out after ${TIMEOUT_IN_MS / 1000} seconds`,
|
74
|
+
);
|
75
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
2
|
+
|
3
|
+
import { DROP1155_CONTRACT } from "~test/test-contracts.js";
|
4
|
+
import { getOwnedNFTs } from "./getOwnedNFTs.js";
|
5
|
+
|
6
|
+
describe.runIf(process.env.TW_SECRET_KEY)("erc1155.getOwnedNFTs", () => {
|
7
|
+
it("with indexer", async () => {
|
8
|
+
const nfts = await getOwnedNFTs({
|
9
|
+
contract: DROP1155_CONTRACT,
|
10
|
+
address: "0x00d4da27dedce60f859471d8f595fdb4ae861557",
|
11
|
+
});
|
12
|
+
expect(nfts.length).toBe(3);
|
13
|
+
expect(nfts.find((nft) => nft.id === 4n)?.quantityOwned).toBe(411n);
|
14
|
+
});
|
15
|
+
|
16
|
+
it("without indexer", async () => {
|
17
|
+
const nfts = await getOwnedNFTs({
|
18
|
+
contract: DROP1155_CONTRACT,
|
19
|
+
address: "0x00d4da27dedce60f859471d8f595fdb4ae861557",
|
20
|
+
useIndexer: false,
|
21
|
+
});
|
22
|
+
expect(nfts.length).toBe(3);
|
23
|
+
expect(nfts.find((nft) => nft.id === 4n)?.quantityOwned).toBe(411n);
|
24
|
+
});
|
25
|
+
});
|
@@ -11,7 +11,7 @@ import {
|
|
11
11
|
import { type ThirdwebContract, getContract } from "../../contract/contract.js";
|
12
12
|
import { sendAndConfirmTransaction } from "../../transaction/actions/send-and-confirm-transaction.js";
|
13
13
|
import { resolvePromisedValue } from "../../utils/promise/resolve-promised-value.js";
|
14
|
-
import { toEther } from "../../utils/units.js";
|
14
|
+
import { toEther, toWei } from "../../utils/units.js";
|
15
15
|
import { name } from "../common/read/name.js";
|
16
16
|
import { deployERC20Contract } from "../prebuilts/deploy-erc20.js";
|
17
17
|
import { canClaim } from "./drops/read/canClaim.js";
|
@@ -20,6 +20,8 @@ import { claimTo } from "./drops/write/claimTo.js";
|
|
20
20
|
import { resetClaimEligibility } from "./drops/write/resetClaimEligibility.js";
|
21
21
|
import { setClaimConditions } from "./drops/write/setClaimConditions.js";
|
22
22
|
import { getBalance } from "./read/getBalance.js";
|
23
|
+
import { getApprovalForTransaction } from "./write/getApprovalForTransaction.js";
|
24
|
+
import { mintTo } from "./write/mintTo.js";
|
23
25
|
|
24
26
|
describe.runIf(process.env.TW_SECRET_KEY)(
|
25
27
|
"DropERC20",
|
@@ -135,6 +137,94 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
|
135
137
|
).toBe("2");
|
136
138
|
});
|
137
139
|
|
140
|
+
it("should allow to claim tokens with erc20 price", async () => {
|
141
|
+
expect(
|
142
|
+
(await getBalance({ contract, address: TEST_ACCOUNT_C.address }))
|
143
|
+
.displayValue,
|
144
|
+
).toBe("2");
|
145
|
+
const erc20ContractAddres = await deployERC20Contract({
|
146
|
+
account: TEST_ACCOUNT_A,
|
147
|
+
chain: ANVIL_CHAIN,
|
148
|
+
client: TEST_CLIENT,
|
149
|
+
type: "TokenERC20",
|
150
|
+
params: {
|
151
|
+
name: "Test DropERC20",
|
152
|
+
},
|
153
|
+
});
|
154
|
+
const erc20Contract = getContract({
|
155
|
+
address: erc20ContractAddres,
|
156
|
+
chain: ANVIL_CHAIN,
|
157
|
+
client: TEST_CLIENT,
|
158
|
+
});
|
159
|
+
const mintToTx = mintTo({
|
160
|
+
contract: erc20Contract,
|
161
|
+
to: TEST_ACCOUNT_C.address,
|
162
|
+
amount: "0.02",
|
163
|
+
});
|
164
|
+
await sendAndConfirmTransaction({
|
165
|
+
transaction: mintToTx,
|
166
|
+
account: TEST_ACCOUNT_A,
|
167
|
+
});
|
168
|
+
expect(
|
169
|
+
(
|
170
|
+
await getBalance({
|
171
|
+
contract: erc20Contract,
|
172
|
+
address: TEST_ACCOUNT_C.address,
|
173
|
+
})
|
174
|
+
).displayValue,
|
175
|
+
).toBe("0.02");
|
176
|
+
// set cc with price
|
177
|
+
await sendAndConfirmTransaction({
|
178
|
+
transaction: setClaimConditions({
|
179
|
+
contract,
|
180
|
+
phases: [
|
181
|
+
{
|
182
|
+
price: "0.01",
|
183
|
+
currencyAddress: erc20ContractAddres,
|
184
|
+
},
|
185
|
+
],
|
186
|
+
}),
|
187
|
+
account: TEST_ACCOUNT_A,
|
188
|
+
});
|
189
|
+
const claimTx = claimTo({
|
190
|
+
contract,
|
191
|
+
to: TEST_ACCOUNT_C.address,
|
192
|
+
quantity: "2",
|
193
|
+
});
|
194
|
+
// assert value is set correctly
|
195
|
+
const value = await resolvePromisedValue(claimTx.erc20Value);
|
196
|
+
expect(value).toBeDefined();
|
197
|
+
if (!value) throw new Error("value is undefined");
|
198
|
+
expect(value.amountWei).toBe(toWei("0.02"));
|
199
|
+
const approve = await getApprovalForTransaction({
|
200
|
+
transaction: claimTx,
|
201
|
+
account: TEST_ACCOUNT_C,
|
202
|
+
});
|
203
|
+
if (approve) {
|
204
|
+
await sendAndConfirmTransaction({
|
205
|
+
transaction: approve,
|
206
|
+
account: TEST_ACCOUNT_C,
|
207
|
+
});
|
208
|
+
}
|
209
|
+
// claim
|
210
|
+
await sendAndConfirmTransaction({
|
211
|
+
transaction: claimTx,
|
212
|
+
account: TEST_ACCOUNT_C,
|
213
|
+
});
|
214
|
+
expect(
|
215
|
+
(await getBalance({ contract, address: TEST_ACCOUNT_C.address }))
|
216
|
+
.displayValue,
|
217
|
+
).toBe("4");
|
218
|
+
expect(
|
219
|
+
(
|
220
|
+
await getBalance({
|
221
|
+
contract: erc20Contract,
|
222
|
+
address: TEST_ACCOUNT_C.address,
|
223
|
+
})
|
224
|
+
).displayValue,
|
225
|
+
).toBe("0");
|
226
|
+
});
|
227
|
+
|
138
228
|
describe("Allowlists", () => {
|
139
229
|
it("should allow to claim tokens with an allowlist", async () => {
|
140
230
|
await sendAndConfirmTransaction({
|
package/src/insight/get-nfts.ts
CHANGED
@@ -319,7 +319,12 @@ async function transformNFTModel(
|
|
319
319
|
});
|
320
320
|
}
|
321
321
|
|
322
|
-
return
|
322
|
+
return {
|
323
|
+
...parsedNft,
|
324
|
+
...(contract?.type === "erc1155"
|
325
|
+
? { quantityOwned: balance ? BigInt(balance) : undefined }
|
326
|
+
: {}),
|
327
|
+
};
|
323
328
|
}),
|
324
329
|
);
|
325
330
|
}
|
package/src/utils/fetch.ts
CHANGED
package/src/version.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export const version = "5.
|
1
|
+
export const version = "5.102.0";
|