@zoralabs/protocol-sdk 0.8.0 → 0.9.1
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 +7 -7
- package/CHANGELOG.md +17 -0
- package/dist/allow-list/allow-list-client.d.ts +26 -0
- package/dist/allow-list/allow-list-client.d.ts.map +1 -0
- package/dist/allow-list/types.d.ts +14 -0
- package/dist/allow-list/types.d.ts.map +1 -0
- package/dist/apis/generated/allow-list-api-types.d.ts +288 -0
- package/dist/apis/generated/allow-list-api-types.d.ts.map +1 -0
- package/dist/apis/http-api-base.d.ts.map +1 -1
- package/dist/apis/subgraph-querier.d.ts +18 -0
- package/dist/apis/subgraph-querier.d.ts.map +1 -0
- package/dist/create/1155-create-helper.d.ts.map +1 -1
- package/dist/create/contract-setup.d.ts +1 -0
- package/dist/create/contract-setup.d.ts.map +1 -1
- package/dist/create/mint-from-create.d.ts +12 -0
- package/dist/create/mint-from-create.d.ts.map +1 -0
- package/dist/create/minter-defaults.d.ts +5 -0
- package/dist/create/minter-defaults.d.ts.map +1 -0
- package/dist/create/minter-setup.d.ts +14 -0
- package/dist/create/minter-setup.d.ts.map +1 -0
- package/dist/create/token-setup.d.ts +4 -19
- package/dist/create/token-setup.d.ts.map +1 -1
- package/dist/create/types.d.ts +34 -7
- package/dist/create/types.d.ts.map +1 -1
- package/dist/create/update.d.ts +15 -0
- package/dist/create/update.d.ts.map +1 -0
- package/dist/index.cjs +2359 -1932
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2379 -1947
- package/dist/index.js.map +1 -1
- package/dist/ipfs/token-metadata.d.ts +1 -0
- package/dist/ipfs/token-metadata.d.ts.map +1 -1
- package/dist/mint/mint-client.d.ts +2 -6
- package/dist/mint/mint-client.d.ts.map +1 -1
- package/dist/mint/mint-queries.d.ts +6 -2
- package/dist/mint/mint-queries.d.ts.map +1 -1
- package/dist/mint/mint-transactions.d.ts +9 -7
- package/dist/mint/mint-transactions.d.ts.map +1 -1
- package/dist/mint/subgraph-mint-getter.d.ts +5 -4
- package/dist/mint/subgraph-mint-getter.d.ts.map +1 -1
- package/dist/mint/subgraph-queries.d.ts +42 -15
- package/dist/mint/subgraph-queries.d.ts.map +1 -1
- package/dist/mint/types.d.ts +33 -13
- package/dist/mint/types.d.ts.map +1 -1
- package/dist/sparks/sparks-contracts.d.ts +96 -96
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +1 -8
- package/dist/utils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/allow-list/allow-list-client.ts +105 -0
- package/src/allow-list/types.ts +15 -0
- package/src/apis/generated/allow-list-api-types.ts +288 -0
- package/src/apis/http-api-base.ts +12 -0
- package/src/apis/subgraph-querier.ts +38 -0
- package/src/create/1155-create-helper.test.ts +217 -89
- package/src/create/1155-create-helper.ts +25 -4
- package/src/create/contract-setup.ts +8 -0
- package/src/create/mint-from-create.ts +119 -0
- package/src/create/minter-defaults.test.ts +21 -0
- package/src/create/minter-defaults.ts +134 -0
- package/src/create/minter-setup.ts +293 -0
- package/src/create/token-setup.ts +14 -190
- package/src/create/types.ts +58 -9
- package/src/create/update.ts +93 -0
- package/src/index.ts +4 -0
- package/src/ipfs/token-metadata.ts +18 -0
- package/src/mint/mint-client.test.ts +219 -15
- package/src/mint/mint-client.ts +2 -34
- package/src/mint/mint-queries.ts +40 -19
- package/src/mint/mint-transactions.ts +104 -17
- package/src/mint/subgraph-mint-getter.ts +107 -50
- package/src/mint/subgraph-queries.ts +67 -37
- package/src/mint/types.ts +58 -16
- package/src/premint/premint-client.test.ts +6 -5
- package/src/types.ts +1 -1
- package/src/utils.ts +1 -25
package/src/create/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AsyncPrepareMint } from "src/mint/types";
|
|
1
2
|
import { Concrete } from "src/utils";
|
|
2
3
|
import { Account, Address, Hex, SimulateContractParameters } from "viem";
|
|
3
4
|
|
|
@@ -7,19 +8,54 @@ export type NewContractParams = {
|
|
|
7
8
|
defaultAdmin?: Address;
|
|
8
9
|
};
|
|
9
10
|
|
|
10
|
-
export type
|
|
11
|
-
// defaults to 0
|
|
12
|
-
pricePerToken?: bigint;
|
|
11
|
+
export type SaleStartAndEnd = {
|
|
13
12
|
// defaults to 0, in seconds
|
|
14
13
|
saleStart?: bigint;
|
|
15
14
|
// defaults to forever, in seconds
|
|
16
15
|
saleEnd?: bigint;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type MaxTokensPerAddress = {
|
|
17
19
|
// max tokens that can be minted per address
|
|
18
20
|
maxTokensPerAddress?: bigint;
|
|
19
|
-
// if an erc20 mint, the erc20 address. Leave null for eth mints
|
|
20
|
-
currency?: Address;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
export type FixedPriceParamsType = SaleStartAndEnd &
|
|
24
|
+
MaxTokensPerAddress & {
|
|
25
|
+
type?: "fixedPrice";
|
|
26
|
+
// the price per token, if it is a priced mint
|
|
27
|
+
pricePerToken: bigint;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type TimedSaleParamsType = SaleStartAndEnd & {
|
|
31
|
+
type?: "timed";
|
|
32
|
+
// Name of the erc20z token to create for the secondary sale. If not provided, fetches the metadata from the tokenMetadataURI and uses the name from it.
|
|
33
|
+
erc20Name?: string;
|
|
34
|
+
// Symbol of the erc20z token to create for the secondary sale. If not provided, extracts it from the name.
|
|
35
|
+
erc20Symbol?: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type Erc20ParamsType = SaleStartAndEnd &
|
|
39
|
+
MaxTokensPerAddress & {
|
|
40
|
+
type: "erc20Mint";
|
|
41
|
+
// if the erc20 address of the token to mint against
|
|
42
|
+
currency: Address;
|
|
43
|
+
// price in currency per token
|
|
44
|
+
pricePerToken: bigint;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type AllowListParamType = SaleStartAndEnd & {
|
|
48
|
+
type: "allowlistMint";
|
|
49
|
+
// the merkle root of the allowlist
|
|
50
|
+
presaleMerkleRoot: `0x${string}`;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type SalesConfigParamsType =
|
|
54
|
+
| AllowListParamType
|
|
55
|
+
| Erc20ParamsType
|
|
56
|
+
| FixedPriceParamsType
|
|
57
|
+
| TimedSaleParamsType;
|
|
58
|
+
|
|
23
59
|
export type CreateNew1155ParamsBase = {
|
|
24
60
|
account: Address;
|
|
25
61
|
getAdditionalSetupActions?: (args: { tokenId: bigint }) => Hex[];
|
|
@@ -34,28 +70,40 @@ export type CreateNew1155TokenParams = CreateNew1155ParamsBase & {
|
|
|
34
70
|
contractAddress: Address;
|
|
35
71
|
};
|
|
36
72
|
|
|
37
|
-
export
|
|
73
|
+
export type AllowlistData = {
|
|
74
|
+
saleStart?: bigint;
|
|
75
|
+
saleEnd?: bigint;
|
|
76
|
+
presaleMerkleRoot: `0x${string}`;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type CreateNew1155TokenProps = {
|
|
38
80
|
maxSupply?: bigint | number;
|
|
39
81
|
tokenMetadataURI: string;
|
|
40
82
|
royaltyBPS?: number;
|
|
41
|
-
salesConfig?: SalesConfigParamsType;
|
|
42
83
|
createReferral?: Address;
|
|
43
84
|
mintToCreatorCount?: number;
|
|
44
85
|
payoutRecipient?: Address;
|
|
45
|
-
|
|
86
|
+
salesConfig?: SalesConfigParamsType;
|
|
87
|
+
};
|
|
46
88
|
|
|
47
89
|
export interface ContractProps {
|
|
48
90
|
nextTokenId: bigint;
|
|
49
91
|
contractVersion: string;
|
|
50
92
|
}
|
|
51
93
|
|
|
94
|
+
export type ConcreteSalesConfig =
|
|
95
|
+
| Concrete<FixedPriceParamsType>
|
|
96
|
+
| Concrete<Erc20ParamsType>
|
|
97
|
+
| Concrete<AllowListParamType>
|
|
98
|
+
| Concrete<TimedSaleParamsType>;
|
|
99
|
+
|
|
52
100
|
export type New1155Token = {
|
|
53
101
|
payoutRecipient: Address;
|
|
54
102
|
createReferral: Address;
|
|
55
103
|
maxSupply: bigint;
|
|
56
104
|
royaltyBPS: number;
|
|
57
|
-
salesConfig: Concrete<SalesConfigParamsType>;
|
|
58
105
|
tokenMetadataURI: string;
|
|
106
|
+
salesConfig: ConcreteSalesConfig;
|
|
59
107
|
};
|
|
60
108
|
|
|
61
109
|
export type CreateNew1155TokenReturn = {
|
|
@@ -72,6 +120,7 @@ export type CreateNew1155TokenReturn = {
|
|
|
72
120
|
newToken: New1155Token;
|
|
73
121
|
minter: Address;
|
|
74
122
|
contractVersion: string;
|
|
123
|
+
prepareMint: AsyncPrepareMint;
|
|
75
124
|
};
|
|
76
125
|
|
|
77
126
|
export type CreateNew1155ContractAndTokenReturn = {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {
|
|
2
|
+
zoraCreator1155ImplABI,
|
|
3
|
+
zoraCreatorMerkleMinterStrategyABI,
|
|
4
|
+
zoraCreatorMerkleMinterStrategyAddress,
|
|
5
|
+
} from "@zoralabs/protocol-deployments";
|
|
6
|
+
import { Address, PublicClient, WalletClient, encodeFunctionData } from "viem";
|
|
7
|
+
|
|
8
|
+
function constructCallData({
|
|
9
|
+
tokenId,
|
|
10
|
+
saleEnd,
|
|
11
|
+
saleStart,
|
|
12
|
+
merkleRoot,
|
|
13
|
+
fundsRecipient,
|
|
14
|
+
}: {
|
|
15
|
+
mintLimit?: string;
|
|
16
|
+
tokenId: bigint;
|
|
17
|
+
saleEnd: bigint;
|
|
18
|
+
saleStart: bigint;
|
|
19
|
+
merkleRoot: `0x${string}`;
|
|
20
|
+
fundsRecipient: Address;
|
|
21
|
+
}) {
|
|
22
|
+
const saleData = encodeFunctionData({
|
|
23
|
+
abi: zoraCreatorMerkleMinterStrategyABI,
|
|
24
|
+
functionName: "setSale",
|
|
25
|
+
args: [
|
|
26
|
+
tokenId,
|
|
27
|
+
{
|
|
28
|
+
presaleStart: saleStart,
|
|
29
|
+
presaleEnd: saleEnd,
|
|
30
|
+
fundsRecipient,
|
|
31
|
+
merkleRoot,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return saleData;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function updateAllowListOnContract({
|
|
40
|
+
contractAddress: collectionAddress,
|
|
41
|
+
tokenId,
|
|
42
|
+
chainId,
|
|
43
|
+
saleStart,
|
|
44
|
+
saleEnd,
|
|
45
|
+
merkleRoot,
|
|
46
|
+
fundsRecipient,
|
|
47
|
+
tokenAdmin,
|
|
48
|
+
publicClient,
|
|
49
|
+
walletClient,
|
|
50
|
+
}: {
|
|
51
|
+
contractAddress: Address;
|
|
52
|
+
tokenId: bigint;
|
|
53
|
+
chainId: number;
|
|
54
|
+
address: Address;
|
|
55
|
+
saleStart: bigint;
|
|
56
|
+
saleEnd: bigint;
|
|
57
|
+
merkleRoot: `0x${string}`;
|
|
58
|
+
fundsRecipient: Address;
|
|
59
|
+
tokenAdmin: Address;
|
|
60
|
+
publicClient: PublicClient;
|
|
61
|
+
walletClient: WalletClient;
|
|
62
|
+
}) {
|
|
63
|
+
const saleData = constructCallData({
|
|
64
|
+
fundsRecipient,
|
|
65
|
+
merkleRoot,
|
|
66
|
+
saleEnd,
|
|
67
|
+
saleStart,
|
|
68
|
+
tokenId,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const merkleSaleStrategyAddress =
|
|
72
|
+
zoraCreatorMerkleMinterStrategyAddress[
|
|
73
|
+
chainId as keyof typeof zoraCreatorMerkleMinterStrategyAddress
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
const { request } = await publicClient.simulateContract({
|
|
77
|
+
abi: zoraCreator1155ImplABI,
|
|
78
|
+
address: collectionAddress,
|
|
79
|
+
functionName: "callSale",
|
|
80
|
+
args: [tokenId, merkleSaleStrategyAddress, saleData],
|
|
81
|
+
account: tokenAdmin,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const hash = await walletClient.writeContract(request);
|
|
85
|
+
|
|
86
|
+
const receipt = await publicClient.waitForTransactionReceipt({
|
|
87
|
+
hash,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (receipt.status !== "success") {
|
|
91
|
+
throw new Error("Transaction failed");
|
|
92
|
+
}
|
|
93
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -97,3 +97,21 @@ export const makeMediaTokenMetadata = async ({
|
|
|
97
97
|
attributes,
|
|
98
98
|
};
|
|
99
99
|
};
|
|
100
|
+
|
|
101
|
+
export async function fetchTokenMetadata(tokenMetadataURI: string) {
|
|
102
|
+
const fetchableUrl = getFetchableUrl(tokenMetadataURI);
|
|
103
|
+
|
|
104
|
+
if (!fetchableUrl) {
|
|
105
|
+
throw new Error(`Invalid token metadata URI: ${tokenMetadataURI}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const json = (await (await fetch(fetchableUrl)).json()) as
|
|
109
|
+
| TokenMetadataJson
|
|
110
|
+
| undefined;
|
|
111
|
+
|
|
112
|
+
if (!json) {
|
|
113
|
+
throw new Error(`Failed to fetch metadata from ${fetchableUrl}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return json;
|
|
117
|
+
}
|
|
@@ -1,9 +1,22 @@
|
|
|
1
|
-
import { describe, expect } from "vitest";
|
|
2
|
-
import { Address, erc20Abi, parseAbi, parseEther } from "viem";
|
|
1
|
+
import { describe, expect, vi } from "vitest";
|
|
2
|
+
import { Address, erc20Abi, parseAbi, parseEther, zeroAddress } from "viem";
|
|
3
3
|
import { zora, zoraSepolia } from "viem/chains";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
zoraCreator1155ImplABI,
|
|
6
|
+
zoraTimedSaleStrategyAddress,
|
|
7
|
+
} from "@zoralabs/protocol-deployments";
|
|
5
8
|
import { forkUrls, makeAnvilTest } from "src/anvil";
|
|
6
|
-
import { createCollectorClient } from "src/sdk";
|
|
9
|
+
import { createCollectorClient, createCreatorClient } from "src/sdk";
|
|
10
|
+
import { getAllowListEntry } from "src/allow-list/allow-list-client";
|
|
11
|
+
import {
|
|
12
|
+
demoContractMetadataURI,
|
|
13
|
+
demoTokenMetadataURI,
|
|
14
|
+
} from "src/create/1155-create-helper.test";
|
|
15
|
+
import { SubgraphMintGetter } from "./subgraph-mint-getter";
|
|
16
|
+
import { new1155ContractVersion } from "src/create/contract-setup";
|
|
17
|
+
import { SALE_END_FOREVER } from "src/create/minter-defaults";
|
|
18
|
+
import { ISubgraphQuerier } from "src/apis/subgraph-querier";
|
|
19
|
+
import { TokenQueryResult } from "./subgraph-queries";
|
|
7
20
|
|
|
8
21
|
const erc721ABI = parseAbi([
|
|
9
22
|
"function balanceOf(address owner) public view returns (uint256)",
|
|
@@ -239,25 +252,216 @@ describe("mint-helper", () => {
|
|
|
239
252
|
|
|
240
253
|
makeAnvilTest({
|
|
241
254
|
forkUrl: forkUrls.zoraSepolia,
|
|
242
|
-
forkBlockNumber:
|
|
255
|
+
forkBlockNumber: 10970943,
|
|
243
256
|
anvilChainId: zoraSepolia.id,
|
|
257
|
+
})("can mint allowlist tokens", async ({ viemClients }) => {
|
|
258
|
+
const { publicClient, chain, testClient, walletClient } = viemClients;
|
|
259
|
+
|
|
260
|
+
const collectorClient = createCollectorClient({
|
|
261
|
+
chainId: chain.id,
|
|
262
|
+
publicClient,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const targetContract = "0x440cF6a9f12b2f05Ec4Cee8eE0F317B0eC0c2eCD";
|
|
266
|
+
|
|
267
|
+
const tokenId = 1n;
|
|
268
|
+
|
|
269
|
+
const allowListUser = "0xf69fEc6d858c77e969509843852178bd24CAd2B6";
|
|
270
|
+
const merkleRoot =
|
|
271
|
+
"4d08ab87f97dda8811b4bb32a16a175db65e4c140797c993679a3d58aaadc791";
|
|
272
|
+
|
|
273
|
+
const allowListEntryResult = await getAllowListEntry({
|
|
274
|
+
address: allowListUser,
|
|
275
|
+
merkleRoot,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
const { prepareMint } = await collectorClient.getToken({
|
|
279
|
+
mintType: "1155",
|
|
280
|
+
tokenContract: targetContract,
|
|
281
|
+
tokenId,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const minter = (await walletClient.getAddresses())[0]!;
|
|
285
|
+
|
|
286
|
+
await testClient.setBalance({
|
|
287
|
+
address: minter,
|
|
288
|
+
value: parseEther("10"),
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const quantityToMint = allowListEntryResult.allowListEntry!.maxCanMint;
|
|
292
|
+
|
|
293
|
+
const { parameters } = prepareMint({
|
|
294
|
+
minterAccount: minter,
|
|
295
|
+
quantityToMint,
|
|
296
|
+
mintRecipient: allowListUser,
|
|
297
|
+
allowListEntry: allowListEntryResult.allowListEntry,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const { request } = await publicClient.simulateContract(parameters);
|
|
301
|
+
const hash = await walletClient.writeContract(request);
|
|
302
|
+
|
|
303
|
+
await publicClient.waitForTransactionReceipt({ hash });
|
|
304
|
+
|
|
305
|
+
const balance = await publicClient.readContract({
|
|
306
|
+
abi: zoraCreator1155ImplABI,
|
|
307
|
+
functionName: "balanceOf",
|
|
308
|
+
address: targetContract,
|
|
309
|
+
args: [allowListUser, tokenId],
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
expect(balance).toBe(BigInt(quantityToMint));
|
|
313
|
+
}),
|
|
314
|
+
makeAnvilTest({
|
|
315
|
+
forkUrl: forkUrls.zoraSepolia,
|
|
316
|
+
forkBlockNumber: 10294670,
|
|
317
|
+
anvilChainId: zoraSepolia.id,
|
|
318
|
+
})(
|
|
319
|
+
"gets onchain and premint mintables",
|
|
320
|
+
async ({ viemClients }) => {
|
|
321
|
+
const { publicClient, chain } = viemClients;
|
|
322
|
+
|
|
323
|
+
const targetContract: Address =
|
|
324
|
+
"0xa33e4228843092bb0f2fcbb2eb237bcefc1046b3";
|
|
325
|
+
|
|
326
|
+
const minter = createCollectorClient({
|
|
327
|
+
chainId: chain.id,
|
|
328
|
+
publicClient,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
const { tokens: mintables, contract } =
|
|
332
|
+
await minter.getTokensOfContract({
|
|
333
|
+
tokenContract: targetContract,
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
expect(mintables.length).toBe(4);
|
|
337
|
+
expect(contract).toBeDefined();
|
|
338
|
+
},
|
|
339
|
+
12 * 1000,
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
makeAnvilTest({
|
|
343
|
+
forkUrl: forkUrls.zoraMainnet,
|
|
344
|
+
forkBlockNumber: 18145203,
|
|
345
|
+
anvilChainId: zora.id,
|
|
244
346
|
})(
|
|
245
|
-
"
|
|
347
|
+
"can mint a zora timed sale strategy mint",
|
|
246
348
|
async ({ viemClients }) => {
|
|
247
|
-
const { publicClient, chain } = viemClients;
|
|
349
|
+
const { publicClient, chain, walletClient } = viemClients;
|
|
248
350
|
|
|
249
|
-
const
|
|
250
|
-
"0xa33e4228843092bb0f2fcbb2eb237bcefc1046b3";
|
|
351
|
+
const creator = (await walletClient.getAddresses())[0]!;
|
|
251
352
|
|
|
252
|
-
const
|
|
353
|
+
const creatorClient = createCreatorClient({
|
|
354
|
+
chainId: chain.id,
|
|
355
|
+
publicClient,
|
|
356
|
+
});
|
|
253
357
|
|
|
254
|
-
const {
|
|
255
|
-
|
|
358
|
+
const { parameters, contractAddress, newTokenId } =
|
|
359
|
+
await creatorClient.create1155({
|
|
360
|
+
account: creator,
|
|
361
|
+
contract: {
|
|
362
|
+
name: "Test Timed Sale",
|
|
363
|
+
uri: demoContractMetadataURI,
|
|
364
|
+
defaultAdmin: creator,
|
|
365
|
+
},
|
|
366
|
+
token: {
|
|
367
|
+
tokenMetadataURI: demoTokenMetadataURI,
|
|
368
|
+
},
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
const { request: createRequest } =
|
|
372
|
+
await publicClient.simulateContract(parameters);
|
|
373
|
+
const createHash = await walletClient.writeContract(createRequest);
|
|
374
|
+
const createReceipt = await publicClient.waitForTransactionReceipt({
|
|
375
|
+
hash: createHash,
|
|
376
|
+
});
|
|
377
|
+
expect(createReceipt.status).toBe("success");
|
|
378
|
+
|
|
379
|
+
const zoraCreateToken: TokenQueryResult = {
|
|
380
|
+
contract: {
|
|
381
|
+
address: contractAddress,
|
|
382
|
+
contractVersion: new1155ContractVersion(chain.id),
|
|
383
|
+
// not used:
|
|
384
|
+
mintFeePerQuantity: "0",
|
|
385
|
+
name: "",
|
|
386
|
+
contractURI: "",
|
|
387
|
+
salesStrategies: [],
|
|
388
|
+
},
|
|
389
|
+
creator: creator,
|
|
390
|
+
maxSupply: "1000",
|
|
391
|
+
tokenStandard: "ERC1155",
|
|
392
|
+
totalMinted: "0",
|
|
393
|
+
uri: "",
|
|
394
|
+
tokenId: newTokenId.toString(),
|
|
395
|
+
salesStrategies: [
|
|
396
|
+
{
|
|
397
|
+
type: "ZORA_TIMED",
|
|
398
|
+
zoraTimedMinter: {
|
|
399
|
+
address:
|
|
400
|
+
zoraTimedSaleStrategyAddress[
|
|
401
|
+
chain.id as keyof typeof zoraTimedSaleStrategyAddress
|
|
402
|
+
],
|
|
403
|
+
mintFee: "111000000000000",
|
|
404
|
+
saleEnd: SALE_END_FOREVER.toString(),
|
|
405
|
+
saleStart: "0",
|
|
406
|
+
erc20Z: {
|
|
407
|
+
// not needed
|
|
408
|
+
id: zeroAddress,
|
|
409
|
+
// note needed
|
|
410
|
+
pool: zeroAddress,
|
|
411
|
+
},
|
|
412
|
+
secondaryActivated: false,
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
const mockQuery = vi.fn<ISubgraphQuerier["query"]>().mockResolvedValue({
|
|
419
|
+
zoraCreateToken,
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
const mintGetter = new SubgraphMintGetter(chain.id);
|
|
423
|
+
mintGetter.subgraphQuerier.query = mockQuery;
|
|
424
|
+
|
|
425
|
+
const collectorClient = createCollectorClient({
|
|
426
|
+
chainId: chain.id,
|
|
427
|
+
publicClient,
|
|
428
|
+
mintGetter,
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
const collector = (await walletClient.getAddresses())[1]!;
|
|
432
|
+
|
|
433
|
+
const { prepareMint } = await collectorClient.getToken({
|
|
434
|
+
mintType: "1155",
|
|
435
|
+
tokenContract: contractAddress,
|
|
436
|
+
tokenId: newTokenId,
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
const quantityToMint = 10n;
|
|
440
|
+
|
|
441
|
+
const { parameters: mintParameters, costs } = prepareMint({
|
|
442
|
+
minterAccount: collector,
|
|
443
|
+
quantityToMint,
|
|
256
444
|
});
|
|
257
445
|
|
|
258
|
-
expect(
|
|
259
|
-
|
|
446
|
+
expect(costs.totalCostEth).toBe(quantityToMint * parseEther("0.000111"));
|
|
447
|
+
|
|
448
|
+
const { request: mintRequest } =
|
|
449
|
+
await publicClient.simulateContract(mintParameters);
|
|
450
|
+
const mintHash = await walletClient.writeContract(mintRequest);
|
|
451
|
+
const mintReceipt = await publicClient.waitForTransactionReceipt({
|
|
452
|
+
hash: mintHash,
|
|
453
|
+
});
|
|
454
|
+
expect(mintReceipt.status).toBe("success");
|
|
455
|
+
|
|
456
|
+
const balance = await publicClient.readContract({
|
|
457
|
+
abi: zoraCreator1155ImplABI,
|
|
458
|
+
address: contractAddress,
|
|
459
|
+
functionName: "balanceOf",
|
|
460
|
+
args: [collector, newTokenId],
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
expect(balance).toBe(quantityToMint);
|
|
260
464
|
},
|
|
261
|
-
|
|
465
|
+
20_000,
|
|
262
466
|
);
|
|
263
467
|
});
|
package/src/mint/mint-client.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Address
|
|
1
|
+
import { Address } from "viem";
|
|
2
2
|
import { IPublicClient } from "src/types";
|
|
3
3
|
import {
|
|
4
4
|
GetMintParameters,
|
|
@@ -7,16 +7,9 @@ import {
|
|
|
7
7
|
PrepareMintReturn,
|
|
8
8
|
SaleType,
|
|
9
9
|
} from "./types";
|
|
10
|
-
import {
|
|
11
|
-
MakeMintParametersArguments,
|
|
12
|
-
Make1155MintArguments,
|
|
13
|
-
Make721MintArguments,
|
|
14
|
-
GetMintCostsParameters,
|
|
15
|
-
is1155Mint,
|
|
16
|
-
} from "./types";
|
|
10
|
+
import { MakeMintParametersArguments, GetMintCostsParameters } from "./types";
|
|
17
11
|
import { IPremintGetter } from "src/premint/premint-api-client";
|
|
18
12
|
|
|
19
|
-
import { makeOnchainMintCall } from "./mint-transactions";
|
|
20
13
|
import { getMint, getMintCosts, getMintsOfContract } from "./mint-queries";
|
|
21
14
|
|
|
22
15
|
class MintError extends Error {}
|
|
@@ -139,28 +132,3 @@ async function mint({
|
|
|
139
132
|
mintReferral: parameters.mintReferral,
|
|
140
133
|
});
|
|
141
134
|
}
|
|
142
|
-
|
|
143
|
-
export async function collectOnchain({
|
|
144
|
-
chainId,
|
|
145
|
-
mintGetter,
|
|
146
|
-
...parameters
|
|
147
|
-
}: (Make1155MintArguments | Make721MintArguments) & {
|
|
148
|
-
mintGetter: IOnchainMintGetter;
|
|
149
|
-
chainId: number;
|
|
150
|
-
}): Promise<
|
|
151
|
-
SimulateContractParameters<any, any, any, any, any, Account | Address>
|
|
152
|
-
> {
|
|
153
|
-
const { tokenContract: tokenContract, preferredSaleType: saleType } =
|
|
154
|
-
parameters;
|
|
155
|
-
const tokenId = is1155Mint(parameters) ? parameters.tokenId : undefined;
|
|
156
|
-
const salesConfigAndTokenInfo = await mintGetter.getMintable({
|
|
157
|
-
tokenId,
|
|
158
|
-
tokenAddress: tokenContract,
|
|
159
|
-
preferredSaleType: saleType,
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
return makeOnchainMintCall({
|
|
163
|
-
mintParams: parameters,
|
|
164
|
-
token: salesConfigAndTokenInfo,
|
|
165
|
-
});
|
|
166
|
-
}
|
package/src/mint/mint-queries.ts
CHANGED
|
@@ -27,6 +27,8 @@ import {
|
|
|
27
27
|
import { makeOnchainMintCall, parseMintCosts } from "./mint-transactions";
|
|
28
28
|
import { buildPremintMintCall } from "src/premint/premint-client";
|
|
29
29
|
import { IPublicClient } from "src/types";
|
|
30
|
+
import { AllowListEntry } from "src/allow-list/types";
|
|
31
|
+
import { Concrete } from "src/utils";
|
|
30
32
|
|
|
31
33
|
export async function getMint({
|
|
32
34
|
params,
|
|
@@ -42,10 +44,12 @@ export async function getMint({
|
|
|
42
44
|
const { tokenContract } = params;
|
|
43
45
|
if (isOnChainMint(params)) {
|
|
44
46
|
const tokenId = is1155Mint(params) ? params.tokenId : undefined;
|
|
47
|
+
const blockTime = (await publicClient.getBlock()).timestamp;
|
|
45
48
|
const result = await mintGetter.getMintable({
|
|
46
49
|
tokenId,
|
|
47
50
|
tokenAddress: tokenContract,
|
|
48
51
|
preferredSaleType: params.preferredSaleType,
|
|
52
|
+
blockTime: blockTime,
|
|
49
53
|
});
|
|
50
54
|
|
|
51
55
|
return toMintableReturn(result);
|
|
@@ -129,11 +133,13 @@ export async function getMintsOfContract({
|
|
|
129
133
|
|
|
130
134
|
export async function getMintCosts({
|
|
131
135
|
params,
|
|
136
|
+
allowListEntry,
|
|
132
137
|
mintGetter,
|
|
133
138
|
premintGetter,
|
|
134
139
|
publicClient,
|
|
135
140
|
}: {
|
|
136
141
|
params: GetMintCostsParameters;
|
|
142
|
+
allowListEntry?: Pick<AllowListEntry, "price">;
|
|
137
143
|
mintGetter: IOnchainMintGetter;
|
|
138
144
|
premintGetter: IPremintGetter;
|
|
139
145
|
publicClient: IPublicClient;
|
|
@@ -141,15 +147,21 @@ export async function getMintCosts({
|
|
|
141
147
|
const { quantityMinted: quantityToMint, collection } = params;
|
|
142
148
|
if (isOnChainMint(params)) {
|
|
143
149
|
const tokenId = is1155Mint(params) ? params.tokenId : undefined;
|
|
150
|
+
const blockTime = (await publicClient.getBlock()).timestamp;
|
|
144
151
|
const salesConfigAndTokenInfo = await mintGetter.getMintable({
|
|
145
152
|
tokenId,
|
|
146
153
|
tokenAddress: collection,
|
|
154
|
+
blockTime,
|
|
147
155
|
});
|
|
148
156
|
|
|
157
|
+
if (!salesConfigAndTokenInfo.salesConfig) {
|
|
158
|
+
throw new Error("No valid sales config found for token");
|
|
159
|
+
}
|
|
160
|
+
|
|
149
161
|
return parseMintCosts({
|
|
150
|
-
mintFeePerQuantity: salesConfigAndTokenInfo.mintFeePerQuantity,
|
|
151
162
|
salesConfig: salesConfigAndTokenInfo.salesConfig,
|
|
152
163
|
quantityToMint: BigInt(quantityToMint),
|
|
164
|
+
allowListEntry,
|
|
153
165
|
});
|
|
154
166
|
}
|
|
155
167
|
|
|
@@ -226,7 +238,6 @@ function parsePremint({
|
|
|
226
238
|
return {
|
|
227
239
|
creator: premint.signer,
|
|
228
240
|
maxSupply: premint.premint.premintConfig.tokenConfig.maxSupply,
|
|
229
|
-
mintFeePerQuantity: mintFee,
|
|
230
241
|
mintType: "premint",
|
|
231
242
|
uid: premint.premint.premintConfig.uid,
|
|
232
243
|
contract: {
|
|
@@ -242,6 +253,7 @@ function parsePremint({
|
|
|
242
253
|
premint.premint.premintConfig.tokenConfig.maxTokensPerAddress,
|
|
243
254
|
pricePerToken: premint.premint.premintConfig.tokenConfig.pricePerToken,
|
|
244
255
|
saleType: "premint",
|
|
256
|
+
mintFeePerQuantity: mintFee,
|
|
245
257
|
},
|
|
246
258
|
};
|
|
247
259
|
}
|
|
@@ -249,17 +261,26 @@ function parsePremint({
|
|
|
249
261
|
throw new Error("Invalid premint config version");
|
|
250
262
|
}
|
|
251
263
|
|
|
252
|
-
const makeOnchainPrepareMint =
|
|
264
|
+
export const makeOnchainPrepareMint =
|
|
253
265
|
(result: OnchainSalesConfigAndTokenInfo): PrepareMint =>
|
|
254
|
-
(params: MintParametersBase) =>
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
266
|
+
(params: MintParametersBase) => {
|
|
267
|
+
if (!result.salesConfig) {
|
|
268
|
+
throw new Error("No valid sales config found for token");
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return {
|
|
272
|
+
parameters: makeOnchainMintCall({
|
|
273
|
+
token: result as Concrete<OnchainSalesConfigAndTokenInfo>,
|
|
274
|
+
mintParams: params,
|
|
275
|
+
}),
|
|
276
|
+
erc20Approval: getRequiredErc20Approvals(params, result.salesConfig),
|
|
277
|
+
costs: parseMintCosts({
|
|
278
|
+
salesConfig: result.salesConfig,
|
|
279
|
+
quantityToMint: BigInt(params.quantityToMint),
|
|
280
|
+
allowListEntry: params.allowListEntry,
|
|
281
|
+
}),
|
|
282
|
+
};
|
|
283
|
+
};
|
|
263
284
|
|
|
264
285
|
function toMintableReturn(
|
|
265
286
|
result: OnchainSalesConfigAndTokenInfo,
|
|
@@ -283,9 +304,9 @@ const makePremintPrepareMint =
|
|
|
283
304
|
premint,
|
|
284
305
|
}),
|
|
285
306
|
costs: parseMintCosts({
|
|
286
|
-
mintFeePerQuantity: mintFee,
|
|
287
307
|
quantityToMint: BigInt(params.quantityToMint),
|
|
288
308
|
salesConfig: mintable.salesConfig,
|
|
309
|
+
allowListEntry: params.allowListEntry,
|
|
289
310
|
}),
|
|
290
311
|
});
|
|
291
312
|
|
|
@@ -306,15 +327,15 @@ function toPremintMintReturn({
|
|
|
306
327
|
prepareMint: makePremintPrepareMint(mintable, mintFee, premint),
|
|
307
328
|
};
|
|
308
329
|
}
|
|
309
|
-
function getRequiredErc20Approvals(
|
|
330
|
+
export function getRequiredErc20Approvals(
|
|
310
331
|
params: MintParametersBase,
|
|
311
|
-
|
|
332
|
+
salesConfig: OnchainSalesConfigAndTokenInfo["salesConfig"],
|
|
312
333
|
): Erc20Approval | undefined {
|
|
313
|
-
if (
|
|
334
|
+
if (salesConfig?.saleType !== "erc20") return undefined;
|
|
314
335
|
|
|
315
336
|
return {
|
|
316
|
-
quantity:
|
|
317
|
-
approveTo:
|
|
318
|
-
erc20:
|
|
337
|
+
quantity: salesConfig.pricePerToken * BigInt(params.quantityToMint),
|
|
338
|
+
approveTo: salesConfig.address,
|
|
339
|
+
erc20: salesConfig.currency,
|
|
319
340
|
};
|
|
320
341
|
}
|