@zoralabs/protocol-sdk 0.7.2-ALLOWLIST.0 → 0.7.2
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/.turbo/turbo-build.log +15 -0
- package/CHANGELOG.md +2 -2
- package/dist/apis/http-api-base.d.ts.map +1 -1
- package/dist/constants.d.ts +27 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/create/1155-create-helper.d.ts +0 -1
- package/dist/create/1155-create-helper.d.ts.map +1 -1
- package/dist/create/token-setup.d.ts +4 -3
- package/dist/create/token-setup.d.ts.map +1 -1
- package/dist/create/types.d.ts +4 -24
- package/dist/create/types.d.ts.map +1 -1
- package/dist/index.cjs +127 -237
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +128 -238
- package/dist/index.js.map +1 -1
- package/dist/mint/mint-queries.d.ts +1 -3
- package/dist/mint/mint-queries.d.ts.map +1 -1
- package/dist/mint/mint-transactions.d.ts +3 -5
- package/dist/mint/mint-transactions.d.ts.map +1 -1
- package/dist/mint/subgraph-mint-getter.d.ts +2 -1
- package/dist/mint/subgraph-mint-getter.d.ts.map +1 -1
- package/dist/mint/subgraph-queries.d.ts +14 -27
- package/dist/mint/subgraph-queries.d.ts.map +1 -1
- package/dist/mint/types.d.ts +11 -22
- package/dist/mint/types.d.ts.map +1 -1
- package/dist/mints/mints-contracts.d.ts +16 -0
- package/dist/mints/mints-contracts.d.ts.map +1 -1
- package/dist/premint/premint-client.d.ts +8 -0
- package/dist/premint/premint-client.d.ts.map +1 -1
- package/package.json +1 -2
- package/src/apis/http-api-base.ts +0 -12
- package/src/constants.ts +36 -0
- package/src/create/1155-create-helper.test.ts +325 -0
- package/src/create/1155-create-helper.ts +0 -17
- package/src/create/token-setup.ts +19 -116
- package/src/create/types.ts +4 -32
- package/src/index.ts +0 -4
- package/src/mint/mint-client.test.ts +263 -0
- package/src/mint/mint-queries.ts +0 -6
- package/src/mint/mint-transactions.ts +8 -74
- package/src/mint/subgraph-mint-getter.ts +41 -17
- package/src/mint/subgraph-queries.ts +36 -39
- package/src/mint/types.ts +12 -38
- package/src/mints/mints-contracts.test.ts +529 -0
- package/src/mints/mints-eth-unwrapper-and-caller.test.ts +467 -0
- package/src/mints/mints-queries.test.ts +105 -0
- package/src/premint/premint-client.test.ts +290 -0
- package/src/premint/preminter.test.ts +866 -0
- package/test-integration/setup-test-contracts.ts +96 -0
- package/tsconfig.build.json +10 -0
- package/tsup.config.ts +12 -0
- package/dist/allow-list/allow-list-client.d.ts +0 -25
- package/dist/allow-list/allow-list-client.d.ts.map +0 -1
- package/dist/allow-list/types.d.ts +0 -14
- package/dist/allow-list/types.d.ts.map +0 -1
- package/dist/apis/generated/allow-list-api-types.d.ts +0 -288
- package/dist/apis/generated/allow-list-api-types.d.ts.map +0 -1
- package/src/allow-list/allow-list-client.ts +0 -102
- package/src/allow-list/types.ts +0 -15
- package/src/apis/generated/allow-list-api-types.ts +0 -288
- package/yarn-error.log +0 -8602
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
import { describe, expect } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { forkUrls, makeAnvilTest } from "src/anvil";
|
|
4
|
+
import {
|
|
5
|
+
mintsEthUnwrapperAndCallerABI,
|
|
6
|
+
mintsEthUnwrapperAndCallerAddress,
|
|
7
|
+
mintsEthUnwrapperAndCallerConfig,
|
|
8
|
+
zoraCreator1155ImplABI,
|
|
9
|
+
zoraMints1155ABI,
|
|
10
|
+
zoraMints1155Address,
|
|
11
|
+
zoraMintsManagerImplAddress,
|
|
12
|
+
} from "@zoralabs/protocol-deployments";
|
|
13
|
+
import {
|
|
14
|
+
Address,
|
|
15
|
+
Hex,
|
|
16
|
+
PublicClient,
|
|
17
|
+
encodeFunctionData,
|
|
18
|
+
parseEther,
|
|
19
|
+
} from "viem";
|
|
20
|
+
import { mintsBalanceOfAccountParams } from "./mints-contracts";
|
|
21
|
+
import { base, zora, zoraSepolia } from "viem/chains";
|
|
22
|
+
import {
|
|
23
|
+
getRelayCall,
|
|
24
|
+
makeAndSignSponsoredRelayCall,
|
|
25
|
+
validateAndExecuteSponsoredRelayCall,
|
|
26
|
+
} from "./mints-relay-example";
|
|
27
|
+
import { collectMINTsWithEth } from "./mints-contracts.test";
|
|
28
|
+
import {
|
|
29
|
+
fixedPriceMinterMinterArguments,
|
|
30
|
+
getFixedPricedMinter,
|
|
31
|
+
waitForSuccess,
|
|
32
|
+
} from "src/test-utils";
|
|
33
|
+
import { unwrapAndForwardEthPermitAndTypedDataDefinition } from "./mints-eth-unwrapper-and-caller";
|
|
34
|
+
|
|
35
|
+
const randomNonce = (): bigint => BigInt(Math.round(Math.random() * 1_000_000));
|
|
36
|
+
|
|
37
|
+
const anvilTest = makeAnvilTest({
|
|
38
|
+
forkUrl: forkUrls.zoraMainnet,
|
|
39
|
+
forkBlockNumber: 12990454,
|
|
40
|
+
anvilChainId: zora.id,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const makeLegacy1155MintCall = async ({
|
|
44
|
+
publicClient,
|
|
45
|
+
chainId,
|
|
46
|
+
mintRecipient,
|
|
47
|
+
tokenId,
|
|
48
|
+
quantityToMint,
|
|
49
|
+
}: {
|
|
50
|
+
publicClient: PublicClient;
|
|
51
|
+
chainId: keyof typeof zoraMints1155Address;
|
|
52
|
+
mintRecipient: Address;
|
|
53
|
+
tokenId: bigint;
|
|
54
|
+
quantityToMint: bigint;
|
|
55
|
+
}) => {
|
|
56
|
+
const fixedPriceMinter = await getFixedPricedMinter({
|
|
57
|
+
publicClient,
|
|
58
|
+
chainId,
|
|
59
|
+
});
|
|
60
|
+
const minterArguments = fixedPriceMinterMinterArguments({
|
|
61
|
+
mintRecipient,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// this is the external contract function that will be called
|
|
65
|
+
// by relay on the other chain
|
|
66
|
+
const mintCall = encodeFunctionData({
|
|
67
|
+
abi: zoraCreator1155ImplABI,
|
|
68
|
+
functionName: "mint",
|
|
69
|
+
args: [fixedPriceMinter, tokenId, quantityToMint, [], minterArguments],
|
|
70
|
+
});
|
|
71
|
+
// amount of eth required to mint the quantity of tokens on the other chain.
|
|
72
|
+
// this value will be bridged by relay and passed through to the target
|
|
73
|
+
// contract on the destination chain.
|
|
74
|
+
const mintFee = parseEther("0.000777") * quantityToMint;
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
mintCall,
|
|
78
|
+
mintFee,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
describe("MintsEthUnwrapperAndCaller", () => {
|
|
83
|
+
makeAnvilTest({
|
|
84
|
+
forkUrl: forkUrls.zoraSepolia,
|
|
85
|
+
forkBlockNumber: 7297306,
|
|
86
|
+
anvilChainId: zoraSepolia.id,
|
|
87
|
+
})(
|
|
88
|
+
"can be used to gaslessly unwrap MINTs values and collect older versions of 1155 contracts",
|
|
89
|
+
async ({ viemClients: { walletClient, publicClient, chain } }) => {
|
|
90
|
+
const [collectorAccount, permitExecutorAccount] =
|
|
91
|
+
await walletClient.getAddresses();
|
|
92
|
+
|
|
93
|
+
const chainId = chain.id as keyof typeof zoraMintsManagerImplAddress;
|
|
94
|
+
|
|
95
|
+
// 1. Collect some MINTs
|
|
96
|
+
const initialMintsQuantityToMint = 20n;
|
|
97
|
+
|
|
98
|
+
const mintsTokenId = await collectMINTsWithEth({
|
|
99
|
+
publicClient,
|
|
100
|
+
walletClient,
|
|
101
|
+
chainId,
|
|
102
|
+
collectorAccount: collectorAccount!,
|
|
103
|
+
quantityToMint: initialMintsQuantityToMint,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const initialMintsBalance = await publicClient.readContract(
|
|
107
|
+
mintsBalanceOfAccountParams({
|
|
108
|
+
account: collectorAccount!,
|
|
109
|
+
chainId: chainId,
|
|
110
|
+
}),
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const quantityToMintOn1155 = 3n;
|
|
114
|
+
|
|
115
|
+
const tokenId = 1n;
|
|
116
|
+
|
|
117
|
+
// this is the external contract that will be called
|
|
118
|
+
const legacy1155Address = "0x2988C3b4F3A823488e4E2d70F23bD66366639b81";
|
|
119
|
+
|
|
120
|
+
const { mintCall: contractCall, mintFee } = await makeLegacy1155MintCall({
|
|
121
|
+
chainId,
|
|
122
|
+
mintRecipient: collectorAccount!,
|
|
123
|
+
tokenId,
|
|
124
|
+
quantityToMint: quantityToMintOn1155,
|
|
125
|
+
publicClient,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// get typed data to sign, as well as permit to collect with
|
|
129
|
+
const { typedData: batchTransferTypeData, permit: batchTransferPermit } =
|
|
130
|
+
unwrapAndForwardEthPermitAndTypedDataDefinition({
|
|
131
|
+
from: collectorAccount!,
|
|
132
|
+
chainId: chainId,
|
|
133
|
+
nonce: randomNonce(),
|
|
134
|
+
deadline: (await publicClient.getBlock()).timestamp + 10n,
|
|
135
|
+
// token ids to unwrap and burn - must be eth based token ids
|
|
136
|
+
tokenIds: [mintsTokenId],
|
|
137
|
+
// quantities to unwrap and burn
|
|
138
|
+
quantities: [quantityToMintOn1155],
|
|
139
|
+
callWithEth: {
|
|
140
|
+
// external address to call
|
|
141
|
+
address: legacy1155Address,
|
|
142
|
+
// external contract call
|
|
143
|
+
call: contractCall,
|
|
144
|
+
// value to send to external contract, extra value from mints
|
|
145
|
+
// will be refunded
|
|
146
|
+
value: mintFee,
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const permitBatchSignature = await walletClient.signTypedData(
|
|
151
|
+
batchTransferTypeData,
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
// now simulate and execute the transaction
|
|
155
|
+
const permitBatchSimulated = await publicClient.simulateContract({
|
|
156
|
+
abi: zoraMints1155ABI,
|
|
157
|
+
address: zoraMints1155Address[chainId],
|
|
158
|
+
functionName: "permitSafeTransferBatch",
|
|
159
|
+
args: [batchTransferPermit, permitBatchSignature],
|
|
160
|
+
account: permitExecutorAccount,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
await waitForSuccess(
|
|
164
|
+
await walletClient.writeContract(permitBatchSimulated.request),
|
|
165
|
+
publicClient,
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
expect(
|
|
169
|
+
await publicClient.readContract(
|
|
170
|
+
mintsBalanceOfAccountParams({
|
|
171
|
+
account: collectorAccount!,
|
|
172
|
+
chainId: chainId,
|
|
173
|
+
}),
|
|
174
|
+
),
|
|
175
|
+
).toBe(initialMintsBalance - quantityToMintOn1155);
|
|
176
|
+
|
|
177
|
+
expect(
|
|
178
|
+
await publicClient.readContract(
|
|
179
|
+
mintsBalanceOfAccountParams({
|
|
180
|
+
account: mintsEthUnwrapperAndCallerConfig.address[chainId],
|
|
181
|
+
chainId: chainId,
|
|
182
|
+
}),
|
|
183
|
+
),
|
|
184
|
+
).toBe(0n);
|
|
185
|
+
|
|
186
|
+
const tokenBalance = await publicClient.readContract({
|
|
187
|
+
abi: zoraCreator1155ImplABI,
|
|
188
|
+
address: legacy1155Address,
|
|
189
|
+
functionName: "balanceOf",
|
|
190
|
+
args: [collectorAccount!, tokenId],
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
expect(tokenBalance).toBe(quantityToMintOn1155);
|
|
194
|
+
},
|
|
195
|
+
20_000,
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
anvilTest(
|
|
199
|
+
"can be used gaslessly to unwrap MINTs values and collect on other chains using Relay",
|
|
200
|
+
async ({ viemClients: { walletClient, publicClient, chain } }) => {
|
|
201
|
+
// this test shows how an account can unwrap eth value of MINTs
|
|
202
|
+
// and use relay to mint a zora creator 1155 token on another chain.
|
|
203
|
+
|
|
204
|
+
// it does this by:
|
|
205
|
+
// 1. getting the relay call to make on the other chain
|
|
206
|
+
// 2. signing a permit to transfer the MINTs to the eth unwrapper and caller,
|
|
207
|
+
// and using that unwrapped value to call relay with the unwrapped value.
|
|
208
|
+
// 3. Executing a transaction on the mintsEthUnwrapperAndCaller by passing
|
|
209
|
+
// in the permit, signature, and relay fee as the payable value,
|
|
210
|
+
// which unwraps the transferred MINTs eth, adds the relay fee, and calls
|
|
211
|
+
// relay with that value.
|
|
212
|
+
const [collectorAccount, permitExecutorAccount] =
|
|
213
|
+
await walletClient.getAddresses();
|
|
214
|
+
|
|
215
|
+
const chainId = chain.id as keyof typeof zoraMintsManagerImplAddress;
|
|
216
|
+
|
|
217
|
+
const initialMintsQuantityToMint = 20n;
|
|
218
|
+
|
|
219
|
+
const mintsTokenId = await collectMINTsWithEth({
|
|
220
|
+
publicClient,
|
|
221
|
+
walletClient,
|
|
222
|
+
chainId,
|
|
223
|
+
collectorAccount: collectorAccount!,
|
|
224
|
+
quantityToMint: initialMintsQuantityToMint,
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const tokenId = 6n;
|
|
228
|
+
|
|
229
|
+
const quantityToMint = 3n;
|
|
230
|
+
|
|
231
|
+
const destinationChainId = base.id;
|
|
232
|
+
|
|
233
|
+
// address of the 1155 contract on the other chain that will be called
|
|
234
|
+
const destinationContractAddress =
|
|
235
|
+
"0x5f69da5da41e5472afb88fc291e7a92b7f15fbc5" as Address;
|
|
236
|
+
|
|
237
|
+
const { mintCall, mintFee: mintFeeOnOtherChain } =
|
|
238
|
+
await makeLegacy1155MintCall({
|
|
239
|
+
publicClient,
|
|
240
|
+
chainId,
|
|
241
|
+
mintRecipient: collectorAccount!,
|
|
242
|
+
tokenId,
|
|
243
|
+
quantityToMint,
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// build the cross chain relay call by requesting it from their api.
|
|
247
|
+
// this will give: address to call, data to send in call, and value to send
|
|
248
|
+
// returns the call to relay, and how much of the value being sent to them is the fee
|
|
249
|
+
const { relayCall: relayCall, relayFee: relayFee } = await getRelayCall({
|
|
250
|
+
// the mints eth unwrapper and caller contract is the account
|
|
251
|
+
// that is doing to be depositing the eth value into relay
|
|
252
|
+
depositingAccount: mintsEthUnwrapperAndCallerAddress[chainId],
|
|
253
|
+
// the chain to call from (current chain)
|
|
254
|
+
originChainId: chain.id,
|
|
255
|
+
// the chain that the call will be executed on
|
|
256
|
+
toChainId: destinationChainId,
|
|
257
|
+
// the tx to call on the other chain:
|
|
258
|
+
tx: {
|
|
259
|
+
to: destinationContractAddress,
|
|
260
|
+
value: mintFeeOnOtherChain,
|
|
261
|
+
data: mintCall,
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// build permit to transfer mints to the mintsEthUnwrapperAndCaller,
|
|
266
|
+
// and call the relay with the unwrapped value.
|
|
267
|
+
// get data to be signed
|
|
268
|
+
const { typedData: transferTypeData, permit: transferPermit } =
|
|
269
|
+
unwrapAndForwardEthPermitAndTypedDataDefinition({
|
|
270
|
+
// mints will be transferred from this account
|
|
271
|
+
from: collectorAccount!,
|
|
272
|
+
chainId: chainId,
|
|
273
|
+
// random nonce
|
|
274
|
+
nonce: randomNonce(),
|
|
275
|
+
// deadling for signature
|
|
276
|
+
deadline: (await publicClient.getBlock()).timestamp + 100n,
|
|
277
|
+
// token ids to unwrap and burn - must be eth based token ids
|
|
278
|
+
tokenIds: [mintsTokenId],
|
|
279
|
+
// quantities to unwrap and burn
|
|
280
|
+
quantities: [quantityToMint],
|
|
281
|
+
callWithEth: {
|
|
282
|
+
// external address to call
|
|
283
|
+
address: relayCall.to,
|
|
284
|
+
// external contract call
|
|
285
|
+
call: relayCall.data as Hex,
|
|
286
|
+
// value to send to external contract, extra value from mints
|
|
287
|
+
// will be refunded
|
|
288
|
+
value: BigInt(relayCall.value),
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// sign the permit
|
|
293
|
+
const permitSignature =
|
|
294
|
+
await walletClient.signTypedData(transferTypeData);
|
|
295
|
+
|
|
296
|
+
const collectorBalanceBefore = await publicClient.getBalance({
|
|
297
|
+
address: collectorAccount!,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const collectorMintsBalanceBefore = await publicClient.readContract(
|
|
301
|
+
mintsBalanceOfAccountParams({
|
|
302
|
+
account: collectorAccount!,
|
|
303
|
+
chainId: chainId,
|
|
304
|
+
}),
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
// now we call a payable function on the mints eth unwrapper and caller contract,
|
|
308
|
+
// with the permit and corresponding signature to transfer the mints to the unwrapper,
|
|
309
|
+
// and call relay with the unwrapped value + relay fee.
|
|
310
|
+
// the payable value on this call is the relay fee, which is added to the unwrapped
|
|
311
|
+
// value of the mints and sent to the other chain.
|
|
312
|
+
// any remaining value from the unwrapped MINTs is refunded to the original caller.
|
|
313
|
+
const simulated = await publicClient.simulateContract({
|
|
314
|
+
abi: mintsEthUnwrapperAndCallerABI,
|
|
315
|
+
address: mintsEthUnwrapperAndCallerAddress[chainId],
|
|
316
|
+
functionName: "permitWithAdditionalValue",
|
|
317
|
+
args: [transferPermit, permitSignature],
|
|
318
|
+
account: permitExecutorAccount!,
|
|
319
|
+
// we must call this functio
|
|
320
|
+
value: relayFee,
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// wait for the transaction to succeed.
|
|
324
|
+
await waitForSuccess(
|
|
325
|
+
await walletClient.writeContract(simulated.request),
|
|
326
|
+
publicClient,
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
const ethUnwrapperBalance = await publicClient.getBalance({
|
|
330
|
+
address: mintsEthUnwrapperAndCallerAddress[chainId],
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// check that no remaining eth is left in the unwrapper
|
|
334
|
+
expect(ethUnwrapperBalance).toBe(0n);
|
|
335
|
+
|
|
336
|
+
// collector balance should not have changed
|
|
337
|
+
expect(
|
|
338
|
+
await publicClient.getBalance({
|
|
339
|
+
address: collectorAccount!,
|
|
340
|
+
}),
|
|
341
|
+
).toBe(collectorBalanceBefore);
|
|
342
|
+
|
|
343
|
+
expect(
|
|
344
|
+
await publicClient.readContract(
|
|
345
|
+
mintsBalanceOfAccountParams({
|
|
346
|
+
account: collectorAccount!,
|
|
347
|
+
chainId: chainId,
|
|
348
|
+
}),
|
|
349
|
+
),
|
|
350
|
+
).toBe(collectorMintsBalanceBefore - quantityToMint);
|
|
351
|
+
},
|
|
352
|
+
10_000,
|
|
353
|
+
);
|
|
354
|
+
anvilTest(
|
|
355
|
+
"can be used gaslessly to unwrap MINTs values and collect on other chains using Relay with a signature by the executor",
|
|
356
|
+
async ({ viemClients: { walletClient, publicClient, chain } }) => {
|
|
357
|
+
// this is similar to the above test, but it shows how the executor
|
|
358
|
+
// can sign a message indicating its willing to do the said relay call and pay the extra relay fee,
|
|
359
|
+
// with a deadline.
|
|
360
|
+
// this is a flow starts with a relay call being done on a server, and an executing account
|
|
361
|
+
// signing a message indicating its willing to execute that call and pay the relay fee.
|
|
362
|
+
// It the returns this call to the client, and the client signs the permit to transfer the mints
|
|
363
|
+
// with that call.
|
|
364
|
+
// That signature, premit, and original signature with deadline are then passed to the server,
|
|
365
|
+
// the server validates the original signature, checks the deadlined hasn't passed, and then executes the relay call,
|
|
366
|
+
// paying the relay fee.
|
|
367
|
+
const [collectorAccount, permitExecutorAccount] =
|
|
368
|
+
await walletClient.getAddresses();
|
|
369
|
+
|
|
370
|
+
const chainId = chain.id as keyof typeof zoraMintsManagerImplAddress;
|
|
371
|
+
|
|
372
|
+
const initialMintsQuantityToMint = 20n;
|
|
373
|
+
|
|
374
|
+
const mintsTokenId = await collectMINTsWithEth({
|
|
375
|
+
publicClient,
|
|
376
|
+
walletClient,
|
|
377
|
+
chainId,
|
|
378
|
+
collectorAccount: collectorAccount!,
|
|
379
|
+
quantityToMint: initialMintsQuantityToMint,
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
const tokenId = 6n;
|
|
383
|
+
|
|
384
|
+
const quantityToMint = 3n;
|
|
385
|
+
|
|
386
|
+
const destinationChainId = base.id;
|
|
387
|
+
|
|
388
|
+
// address of the 1155 contract on the other chain that will be called
|
|
389
|
+
const destinationContractAddress =
|
|
390
|
+
"0x5f69da5da41e5472afb88fc291e7a92b7f15fbc5" as Address;
|
|
391
|
+
|
|
392
|
+
const { mintCall, mintFee: mintFeeOnOtherChain } =
|
|
393
|
+
await makeLegacy1155MintCall({
|
|
394
|
+
publicClient,
|
|
395
|
+
chainId,
|
|
396
|
+
mintRecipient: collectorAccount!,
|
|
397
|
+
tokenId,
|
|
398
|
+
quantityToMint,
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// this call would happen on the server, which would call relay, and generate
|
|
402
|
+
// data to sign for the permit. It would also sign a message indicating it would be willing
|
|
403
|
+
// to pay the relay fee. This signature is used later.
|
|
404
|
+
const {
|
|
405
|
+
safeTransferData,
|
|
406
|
+
signature: sponsoredRelayCallSignature,
|
|
407
|
+
deadline,
|
|
408
|
+
additionalValueToSend,
|
|
409
|
+
} = await makeAndSignSponsoredRelayCall({
|
|
410
|
+
// this is the account that is to later execute the transaction and pay the additional relay fee.
|
|
411
|
+
// it will be the account that signs the message.
|
|
412
|
+
executingAccount: permitExecutorAccount!,
|
|
413
|
+
// the chain to call from (current chain)
|
|
414
|
+
originChainId: chainId,
|
|
415
|
+
// the chain that the call will be executed on
|
|
416
|
+
toChainId: destinationChainId,
|
|
417
|
+
// the tx to call on the other chain
|
|
418
|
+
tx: {
|
|
419
|
+
to: destinationContractAddress,
|
|
420
|
+
value: mintFeeOnOtherChain,
|
|
421
|
+
data: mintCall,
|
|
422
|
+
},
|
|
423
|
+
walletClient,
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// build permit to transfer mints to the mintsEthUnwrapperAndCaller,
|
|
427
|
+
// and call the relay with the unwrapped value, and gets the data
|
|
428
|
+
// to be signed. This would be built on the client-side
|
|
429
|
+
const { typedData: transferTypeData, permit: transferPermit } =
|
|
430
|
+
unwrapAndForwardEthPermitAndTypedDataDefinition({
|
|
431
|
+
// mints will be transferred from this account
|
|
432
|
+
from: collectorAccount!,
|
|
433
|
+
chainId: chainId,
|
|
434
|
+
// random nonce
|
|
435
|
+
nonce: randomNonce(),
|
|
436
|
+
// deadling for signature
|
|
437
|
+
deadline: (await publicClient.getBlock()).timestamp + 100n,
|
|
438
|
+
// token ids to unwrap and burn - must be eth based token ids
|
|
439
|
+
tokenIds: [mintsTokenId],
|
|
440
|
+
// quantities to unwrap and burn
|
|
441
|
+
quantities: [quantityToMint],
|
|
442
|
+
// we already have the data to call the external contract
|
|
443
|
+
safeTransferData,
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// have the collector sign the permit
|
|
447
|
+
const permitSignature =
|
|
448
|
+
await walletClient.signTypedData(transferTypeData);
|
|
449
|
+
|
|
450
|
+
// this call would happen on the server after the collector signs a message.
|
|
451
|
+
// the server would be passed the permit, permit signature, and
|
|
452
|
+
// sponsored call signature created above, then validate the sponsored call signature.
|
|
453
|
+
await validateAndExecuteSponsoredRelayCall({
|
|
454
|
+
permit: transferPermit,
|
|
455
|
+
permitSignature,
|
|
456
|
+
sponsoredCallSignature: sponsoredRelayCallSignature,
|
|
457
|
+
additionalValueToSend,
|
|
458
|
+
deadline,
|
|
459
|
+
chainId,
|
|
460
|
+
executingAccount: permitExecutorAccount!,
|
|
461
|
+
walletClient,
|
|
462
|
+
publicClient,
|
|
463
|
+
});
|
|
464
|
+
},
|
|
465
|
+
10_000,
|
|
466
|
+
);
|
|
467
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
MintAccountBalance,
|
|
4
|
+
selectMintsToCollectWithFromQueryResult,
|
|
5
|
+
sumBalances,
|
|
6
|
+
} from "./mints-queries";
|
|
7
|
+
|
|
8
|
+
describe("MINTs queries", () => {
|
|
9
|
+
describe("selectMintsToCollectWithFromQueryResult", () => {
|
|
10
|
+
it("should return the optimum tokenIds and quantities to collect", async () => {
|
|
11
|
+
// account has 3 of token 1, 4 of token 2, 10 of token 3
|
|
12
|
+
// token 1 price is 2, token 2 price is 1, token 3 price is 3
|
|
13
|
+
// we want to collect 10 tokens
|
|
14
|
+
// we should return token 2 with 4 tokens, token 1 with 3 tokens, and token 3 with 3 tokens
|
|
15
|
+
const mintTokenBalances: MintAccountBalance[] = [
|
|
16
|
+
{
|
|
17
|
+
mintToken: {
|
|
18
|
+
id: "1",
|
|
19
|
+
pricePerToken: "2",
|
|
20
|
+
},
|
|
21
|
+
balance: "3",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
mintToken: {
|
|
25
|
+
id: "2",
|
|
26
|
+
pricePerToken: "1",
|
|
27
|
+
},
|
|
28
|
+
balance: "4",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
mintToken: {
|
|
32
|
+
id: "3",
|
|
33
|
+
pricePerToken: "3",
|
|
34
|
+
},
|
|
35
|
+
balance: "10",
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const result = selectMintsToCollectWithFromQueryResult(
|
|
40
|
+
mintTokenBalances,
|
|
41
|
+
10n,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const expectedResult = {
|
|
45
|
+
tokenIds: [2n, 1n, 3n],
|
|
46
|
+
quantities: [4n, 3n, 3n],
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
expect(result).toEqual(expectedResult);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should throw an error if not enough tokens to collect with", () => {
|
|
53
|
+
const mintTokenBalances: MintAccountBalance[] = [
|
|
54
|
+
{
|
|
55
|
+
mintToken: {
|
|
56
|
+
id: "1",
|
|
57
|
+
pricePerToken: "2",
|
|
58
|
+
},
|
|
59
|
+
balance: "3",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
mintToken: {
|
|
63
|
+
id: "2",
|
|
64
|
+
pricePerToken: "1",
|
|
65
|
+
},
|
|
66
|
+
balance: "4",
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
const quantityToCollect = 8n;
|
|
70
|
+
|
|
71
|
+
expect(() => {
|
|
72
|
+
selectMintsToCollectWithFromQueryResult(
|
|
73
|
+
mintTokenBalances,
|
|
74
|
+
quantityToCollect,
|
|
75
|
+
);
|
|
76
|
+
}).toThrowError("Not enough MINTs to collect with");
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe("sumBalances", () => {
|
|
81
|
+
it("should return the sum of the balances", async () => {
|
|
82
|
+
// account has 3 of token 1, 4 of token 2, 10 of token 3
|
|
83
|
+
// token 1 price is 2, token 2 price is 1, token 3 price is 3
|
|
84
|
+
// we want to collect 10 tokens
|
|
85
|
+
// we should return token 2 with 4 tokens, token 1 with 3 tokens, and token 3 with 3 tokens
|
|
86
|
+
const mintTokenBalances: Pick<MintAccountBalance, "balance">[] = [
|
|
87
|
+
{
|
|
88
|
+
balance: "3",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
balance: "4",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
balance: "10",
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
const result = sumBalances(mintTokenBalances);
|
|
99
|
+
|
|
100
|
+
const expectedResult = 3n + 4n + 10n;
|
|
101
|
+
|
|
102
|
+
expect(result).toEqual(expectedResult);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|