@zoralabs/protocol-sdk 0.11.7 → 0.11.9

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.
Files changed (50) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/CHANGELOG.md +15 -0
  3. package/dist/anvil.d.ts +1 -0
  4. package/dist/anvil.d.ts.map +1 -1
  5. package/dist/create/mint-from-create.d.ts +2 -1
  6. package/dist/create/mint-from-create.d.ts.map +1 -1
  7. package/dist/fixtures/rewards-query-results.d.ts +4 -1
  8. package/dist/fixtures/rewards-query-results.d.ts.map +1 -1
  9. package/dist/index.cjs +219 -52
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.js +225 -54
  12. package/dist/index.js.map +1 -1
  13. package/dist/mint/mint-client.d.ts +3 -1
  14. package/dist/mint/mint-client.d.ts.map +1 -1
  15. package/dist/mint/mint-queries.d.ts +5 -3
  16. package/dist/mint/mint-queries.d.ts.map +1 -1
  17. package/dist/mint/mint-transactions.d.ts +4 -2
  18. package/dist/mint/mint-transactions.d.ts.map +1 -1
  19. package/dist/rewards/rewards-queries.d.ts.map +1 -1
  20. package/dist/rewards/subgraph-queries.d.ts +2 -1
  21. package/dist/rewards/subgraph-queries.d.ts.map +1 -1
  22. package/dist/rewards/subgraph-rewards-getter.d.ts +9 -3
  23. package/dist/rewards/subgraph-rewards-getter.d.ts.map +1 -1
  24. package/dist/sdk.d.ts.map +1 -1
  25. package/dist/secondary/secondary-client.d.ts +2 -1
  26. package/dist/secondary/secondary-client.d.ts.map +1 -1
  27. package/dist/secondary/types.d.ts +1 -0
  28. package/dist/secondary/types.d.ts.map +1 -1
  29. package/dist/test-utils.d.ts +5 -1
  30. package/dist/test-utils.d.ts.map +1 -1
  31. package/package.json +4 -4
  32. package/src/comments/comments.test.ts +338 -0
  33. package/src/create/1155-create-helper.test.ts +2 -12
  34. package/src/create/1155-create-helper.ts +2 -0
  35. package/src/create/mint-from-create.ts +3 -0
  36. package/src/fixtures/rewards-query-results.ts +9 -2
  37. package/src/mint/mint-client.test.ts +67 -30
  38. package/src/mint/mint-client.ts +10 -1
  39. package/src/mint/mint-queries.ts +16 -5
  40. package/src/mint/mint-transactions.ts +80 -16
  41. package/src/rewards/rewards-client.test.ts +41 -9
  42. package/src/rewards/rewards-queries.ts +15 -5
  43. package/src/rewards/subgraph-queries.ts +3 -1
  44. package/src/rewards/subgraph-rewards-getter.ts +24 -10
  45. package/src/sdk.ts +1 -0
  46. package/src/secondary/secondary-client.test.ts +248 -2
  47. package/src/secondary/secondary-client.ts +136 -6
  48. package/src/secondary/types.ts +2 -0
  49. package/src/sparks/sparks-sponsored-sparks-spender.test.ts +1 -0
  50. package/src/test-utils.ts +19 -0
@@ -75,6 +75,7 @@ export function makeOnchainPrepareMintFromCreate({
75
75
  minter,
76
76
  getContractMintFee,
77
77
  contractVersion,
78
+ chainId,
78
79
  }: {
79
80
  contractAddress: Address;
80
81
  tokenId: bigint;
@@ -82,6 +83,7 @@ export function makeOnchainPrepareMintFromCreate({
82
83
  minter: Address;
83
84
  getContractMintFee: () => Promise<bigint>;
84
85
  contractVersion: string;
86
+ chainId: number;
85
87
  }): AsyncPrepareMint {
86
88
  return async (params: MintParametersBase): Promise<PrepareMintReturn> => {
87
89
  const subgraphSalesConfig = await toSalesStrategyFromSubgraph({
@@ -98,6 +100,7 @@ export function makeOnchainPrepareMintFromCreate({
98
100
  ...params,
99
101
  tokenContract: contractAddress,
100
102
  tokenId,
103
+ chainId,
101
104
  }),
102
105
  costs: parseMintCosts({
103
106
  allowListEntry: params.allowListEntry,
@@ -4,10 +4,17 @@ import {
4
4
  CreatorERC20zQueryResult,
5
5
  } from "../rewards/subgraph-queries";
6
6
 
7
- const mockResult = (erz20z: Address): RewardsToken => ({
7
+ const mockResult = ({
8
+ erz20z,
9
+ secondaryActivated,
10
+ }: {
11
+ erz20z: Address;
12
+ secondaryActivated: boolean;
13
+ }): RewardsToken => ({
8
14
  salesStrategies: [
9
15
  {
10
16
  zoraTimedMinter: {
17
+ secondaryActivated,
11
18
  erc20Z: {
12
19
  id: erz20z,
13
20
  },
@@ -19,7 +26,7 @@ const mockResult = (erz20z: Address): RewardsToken => ({
19
26
  export const mockRewardsQueryResults = ({
20
27
  erc20z,
21
28
  }: {
22
- erc20z: Address[];
29
+ erc20z: { secondaryActivated: boolean; erz20z: Address }[];
23
30
  }): CreatorERC20zQueryResult => ({
24
31
  zoraCreateTokens: erc20z.map(mockResult),
25
32
  });
@@ -1,16 +1,28 @@
1
1
  import { describe, expect, vi } from "vitest";
2
- import { Address, erc20Abi, parseAbi, parseEther } from "viem";
2
+ import {
3
+ Address,
4
+ erc20Abi,
5
+ parseAbi,
6
+ parseEther,
7
+ TransactionReceipt,
8
+ parseEventLogs,
9
+ } from "viem";
3
10
  import { zora, zoraSepolia } from "viem/chains";
4
- import { zoraCreator1155ImplABI } from "@zoralabs/protocol-deployments";
11
+ import {
12
+ zoraCreator1155ImplABI,
13
+ CommentIdentifier,
14
+ commentsABI,
15
+ callerAndCommenterABI,
16
+ } from "@zoralabs/protocol-deployments";
5
17
  import { forkUrls, makeAnvilTest, writeContractWithRetries } from "src/anvil";
6
18
  import { createCollectorClient, createCreatorClient } from "src/sdk";
7
19
  import { getAllowListEntry } from "src/allow-list/allow-list-client";
20
+ import { SubgraphMintGetter } from "./subgraph-mint-getter";
21
+ import { new1155ContractVersion } from "src/create/contract-setup";
8
22
  import {
9
23
  demoContractMetadataURI,
10
24
  demoTokenMetadataURI,
11
- } from "src/create/1155-create-helper.test";
12
- import { SubgraphMintGetter } from "./subgraph-mint-getter";
13
- import { new1155ContractVersion } from "src/create/contract-setup";
25
+ } from "src/fixtures/contract-setup";
14
26
  import { ISubgraphQuerier } from "src/apis/subgraph-querier";
15
27
  import { mockTimedSaleStrategyTokenQueryResult } from "src/fixtures/mint-query-results";
16
28
 
@@ -18,52 +30,64 @@ const erc721ABI = parseAbi([
18
30
  "function balanceOf(address owner) public view returns (uint256)",
19
31
  ] as const);
20
32
 
33
+ const getCommentIdentifierFromReceipt = (
34
+ receipt: TransactionReceipt,
35
+ ): CommentIdentifier => {
36
+ const logs = parseEventLogs({
37
+ abi: commentsABI,
38
+ logs: receipt.logs,
39
+ eventName: "Commented",
40
+ });
41
+
42
+ if (logs.length === 0) {
43
+ throw new Error("No Commented event found in receipt");
44
+ }
45
+
46
+ return logs[0]!.args.commentIdentifier;
47
+ };
48
+
21
49
  describe("mint-helper", () => {
22
50
  makeAnvilTest({
23
- forkBlockNumber: 16028671,
24
- forkUrl: forkUrls.zoraMainnet,
25
- anvilChainId: zora.id,
51
+ forkBlockNumber: 16028124,
52
+ forkUrl: forkUrls.zoraSepolia,
53
+ anvilChainId: zoraSepolia.id,
26
54
  })(
27
- "mints a new 1155 token",
55
+ "mints a new 1155 token with a comment",
28
56
  async ({ viemClients }) => {
29
- const { testClient, walletClient, publicClient } = viemClients;
57
+ const { testClient, walletClient, publicClient, chain } = viemClients;
30
58
  const creatorAccount = (await walletClient.getAddresses())[0]!;
31
59
  await testClient.setBalance({
32
60
  address: creatorAccount,
33
61
  value: parseEther("2000"),
34
62
  });
35
63
  const targetContract: Address =
36
- "0xa2fea3537915dc6c7c7a97a82d1236041e6feb2e";
37
- const targetTokenId = 1n;
64
+ "0xD42557F24034b53e7340A40bb5813eF9Ba88F2b4";
65
+ const targetTokenId = 3n;
38
66
  const collectorClient = createCollectorClient({
39
- chainId: zora.id,
67
+ chainId: chain.id,
40
68
  publicClient,
41
69
  });
42
70
 
43
- const {
44
- token: mintable,
45
- prepareMint,
46
- primaryMintActive,
47
- } = await collectorClient.getToken({
48
- tokenContract: targetContract,
49
- mintType: "1155",
50
- tokenId: targetTokenId,
51
- });
52
-
53
- mintable.maxSupply;
54
- mintable.totalMinted;
55
- mintable.tokenURI;
56
- mintable;
71
+ const { prepareMint, primaryMintActive } = await collectorClient.getToken(
72
+ {
73
+ tokenContract: targetContract,
74
+ mintType: "1155",
75
+ tokenId: targetTokenId,
76
+ },
77
+ );
57
78
 
58
79
  expect(primaryMintActive).toBe(true);
59
80
  expect(prepareMint).toBeDefined();
60
81
 
82
+ const quantityToMint = 5n;
83
+
61
84
  const { parameters, costs } = prepareMint!({
62
85
  minterAccount: creatorAccount,
63
- quantityToMint: 1,
86
+ quantityToMint,
87
+ mintComment: "This is a fun comment :)",
64
88
  });
65
89
 
66
- expect(costs.totalCostEth).toBe(1n * parseEther("0.000777"));
90
+ expect(costs.totalCostEth).toBe(quantityToMint * parseEther("0.000111"));
67
91
 
68
92
  const oldBalance = await publicClient.readContract({
69
93
  abi: zoraCreator1155ImplABI,
@@ -84,7 +108,20 @@ describe("mint-helper", () => {
84
108
  });
85
109
  expect(receipt).to.not.be.null;
86
110
  expect(oldBalance).to.be.equal(0n);
87
- expect(newBalance).to.be.equal(1n);
111
+ expect(newBalance).to.be.equal(quantityToMint);
112
+
113
+ // search for the Commented event in the logs
114
+ const commentIdentifier = getCommentIdentifierFromReceipt(receipt);
115
+
116
+ expect(commentIdentifier).toBeDefined();
117
+
118
+ const logs = parseEventLogs({
119
+ abi: callerAndCommenterABI,
120
+ logs: receipt.logs,
121
+ eventName: "MintedAndCommented",
122
+ });
123
+
124
+ expect(logs.length).toBe(1);
88
125
  },
89
126
  12 * 1000,
90
127
  );
@@ -24,19 +24,22 @@ export class MintClient {
24
24
  private readonly publicClient: IPublicClient;
25
25
  private readonly mintGetter: IOnchainMintGetter;
26
26
  private readonly premintGetter: IPremintGetter;
27
-
27
+ private readonly chainId: number;
28
28
  constructor({
29
29
  publicClient,
30
30
  premintGetter,
31
31
  mintGetter,
32
+ chainId,
32
33
  }: {
33
34
  publicClient: IPublicClient;
34
35
  premintGetter: IPremintGetter;
35
36
  mintGetter: IOnchainMintGetter;
37
+ chainId: number;
36
38
  }) {
37
39
  this.publicClient = publicClient;
38
40
  this.mintGetter = mintGetter;
39
41
  this.premintGetter = premintGetter;
42
+ this.chainId = chainId;
40
43
  }
41
44
 
42
45
  /**
@@ -54,6 +57,7 @@ export class MintClient {
54
57
  publicClient: this.publicClient,
55
58
  mintGetter: this.mintGetter,
56
59
  premintGetter: this.premintGetter,
60
+ chainId: this.chainId,
57
61
  });
58
62
  }
59
63
 
@@ -69,6 +73,7 @@ export class MintClient {
69
73
  mintGetter: this.mintGetter,
70
74
  premintGetter: this.premintGetter,
71
75
  publicClient: this.publicClient,
76
+ chainId: this.chainId,
72
77
  });
73
78
  }
74
79
 
@@ -87,6 +92,7 @@ export class MintClient {
87
92
  mintGetter: this.mintGetter,
88
93
  premintGetter: this.premintGetter,
89
94
  publicClient: this.publicClient,
95
+ chainId: this.chainId,
90
96
  });
91
97
  }
92
98
 
@@ -110,17 +116,20 @@ async function mint({
110
116
  publicClient,
111
117
  mintGetter,
112
118
  premintGetter,
119
+ chainId,
113
120
  }: {
114
121
  parameters: MakeMintParametersArguments;
115
122
  publicClient: IPublicClient;
116
123
  mintGetter: IOnchainMintGetter;
117
124
  premintGetter: IPremintGetter;
125
+ chainId: number;
118
126
  }): Promise<PrepareMintReturn> {
119
127
  const { prepareMint, primaryMintActive } = await getMint({
120
128
  params: parameters,
121
129
  mintGetter,
122
130
  premintGetter,
123
131
  publicClient,
132
+ chainId,
124
133
  });
125
134
 
126
135
  if (!primaryMintActive) {
@@ -36,11 +36,13 @@ export async function getMint({
36
36
  mintGetter,
37
37
  premintGetter,
38
38
  publicClient,
39
+ chainId,
39
40
  }: {
40
41
  params: GetMintParameters;
41
42
  mintGetter: IOnchainMintGetter;
42
43
  premintGetter: IPremintGetter;
43
44
  publicClient: IPublicClient;
45
+ chainId: number;
44
46
  }): Promise<MintableReturn> {
45
47
  const { tokenContract } = params;
46
48
  if (isOnChainMint(params)) {
@@ -53,7 +55,7 @@ export async function getMint({
53
55
  blockTime: blockTime,
54
56
  });
55
57
 
56
- return toMintableReturn(result);
58
+ return toMintableReturn(result, chainId);
57
59
  }
58
60
 
59
61
  const premint = await premintGetter.get({
@@ -103,17 +105,19 @@ export async function getMintsOfContract({
103
105
  mintGetter,
104
106
  premintGetter,
105
107
  publicClient,
108
+ chainId,
106
109
  }: {
107
110
  params: GetMintsOfContractParameters;
108
111
  mintGetter: IOnchainMintGetter;
109
112
  premintGetter: IPremintGetter;
110
113
  publicClient: IPublicClient;
114
+ chainId: number;
111
115
  }): Promise<{ contract?: ContractInfo; tokens: MintableReturn[] }> {
112
116
  const onchainMints = (
113
117
  await mintGetter.getContractMintable({
114
118
  tokenAddress: params.tokenContract,
115
119
  })
116
- ).map(toMintableReturn);
120
+ ).map((result) => toMintableReturn(result, chainId));
117
121
 
118
122
  const offchainMints = await getPremintsOfContractMintable({
119
123
  mintGetter,
@@ -270,7 +274,7 @@ function parsePremint({
270
274
  }
271
275
 
272
276
  export const makeOnchainPrepareMint =
273
- (result: OnchainSalesConfigAndTokenInfo): PrepareMint =>
277
+ (result: OnchainSalesConfigAndTokenInfo, chainId: number): PrepareMint =>
274
278
  (params: MintParametersBase) => {
275
279
  if (!result.salesConfig) {
276
280
  throw new Error("No valid sales config found for token");
@@ -280,6 +284,7 @@ export const makeOnchainPrepareMint =
280
284
  parameters: makeOnchainMintCall({
281
285
  token: result as Concrete<OnchainSalesConfigAndTokenInfo>,
282
286
  mintParams: params,
287
+ chainId,
283
288
  }),
284
289
  erc20Approval: getRequiredErc20Approvals(params, result.salesConfig),
285
290
  costs: parseMintCosts({
@@ -290,7 +295,10 @@ export const makeOnchainPrepareMint =
290
295
  };
291
296
  };
292
297
 
293
- function toMintableReturn(result: GetMintableReturn): MintableReturn {
298
+ function toMintableReturn(
299
+ result: GetMintableReturn,
300
+ chainId: number,
301
+ ): MintableReturn {
294
302
  const primaryMintActive = result.primaryMintActive;
295
303
  if (!primaryMintActive) {
296
304
  return {
@@ -306,7 +314,10 @@ function toMintableReturn(result: GetMintableReturn): MintableReturn {
306
314
  primaryMintActive,
307
315
  primaryMintEnd: result.primaryMintEnd,
308
316
  secondaryMarketActive: result.secondaryMarketActive,
309
- prepareMint: makeOnchainPrepareMint(result.salesConfigAndTokenInfo),
317
+ prepareMint: makeOnchainPrepareMint(
318
+ result.salesConfigAndTokenInfo,
319
+ chainId,
320
+ ),
310
321
  };
311
322
  }
312
323
 
@@ -11,6 +11,8 @@ import {
11
11
  erc20MinterABI,
12
12
  zoraCreator1155ImplABI,
13
13
  zoraTimedSaleStrategyABI,
14
+ callerAndCommenterABI,
15
+ callerAndCommenterAddress,
14
16
  } from "@zoralabs/protocol-deployments";
15
17
  import { zora721Abi, zora1155LegacyAbi } from "src/constants";
16
18
  import {
@@ -32,9 +34,11 @@ import { AllowListEntry } from "src/allow-list/types";
32
34
  export function makeOnchainMintCall({
33
35
  token,
34
36
  mintParams,
37
+ chainId,
35
38
  }: {
36
39
  token: Concrete<OnchainSalesConfigAndTokenInfo>;
37
40
  mintParams: Omit<MakeMintParametersArgumentsBase, "tokenContract">;
41
+ chainId: number;
38
42
  }): SimulateContractParametersWithAccount {
39
43
  if (token.mintType === "721") {
40
44
  return makePrepareMint721TokenParams({
@@ -48,6 +52,7 @@ export function makeOnchainMintCall({
48
52
  salesConfigAndTokenInfo: token,
49
53
  tokenContract: token.contract.address,
50
54
  tokenId: token.tokenId!,
55
+ chainId,
51
56
  ...mintParams,
52
57
  });
53
58
  }
@@ -57,6 +62,69 @@ export type MintableParameters = Pick<
57
62
  "contractVersion" | "salesConfig"
58
63
  >;
59
64
 
65
+ function makeZoraTimedSaleStrategyMintCall({
66
+ minterAccount,
67
+ salesConfigAndTokenInfo,
68
+ mintQuantity,
69
+ mintTo,
70
+ tokenContract,
71
+ tokenId,
72
+ mintReferral,
73
+ mintComment,
74
+ chainId,
75
+ }: {
76
+ minterAccount: Address | Account;
77
+ salesConfigAndTokenInfo: Concrete<MintableParameters>;
78
+ mintQuantity: bigint;
79
+ mintTo: Address;
80
+ tokenContract: Address;
81
+ tokenId: GenericTokenIdTypes;
82
+ mintReferral?: Address;
83
+ mintComment?: string;
84
+ chainId: number;
85
+ }) {
86
+ // if there is a mint comment, use the caller and commenter
87
+ if (mintComment && mintComment !== "") {
88
+ return makeContractParameters({
89
+ abi: callerAndCommenterABI,
90
+ address:
91
+ callerAndCommenterAddress[
92
+ chainId as keyof typeof callerAndCommenterAddress
93
+ ],
94
+ functionName: "timedSaleMintAndComment",
95
+ account: minterAccount,
96
+ value:
97
+ salesConfigAndTokenInfo.salesConfig.mintFeePerQuantity * mintQuantity,
98
+ args: [
99
+ mintTo,
100
+ mintQuantity,
101
+ tokenContract,
102
+ tokenId,
103
+ mintReferral || zeroAddress,
104
+ mintComment,
105
+ ],
106
+ });
107
+ }
108
+
109
+ return makeContractParameters({
110
+ abi: zoraTimedSaleStrategyABI,
111
+ functionName: "mint",
112
+ account: minterAccount,
113
+ address: salesConfigAndTokenInfo.salesConfig.address,
114
+ value:
115
+ salesConfigAndTokenInfo.salesConfig.mintFeePerQuantity * mintQuantity,
116
+ /* args: mintTo, quantity, collection, tokenId, mintReferral, comment */
117
+ args: [
118
+ mintTo,
119
+ mintQuantity,
120
+ tokenContract,
121
+ BigInt(tokenId),
122
+ mintReferral || zeroAddress,
123
+ "",
124
+ ],
125
+ });
126
+ }
127
+
60
128
  export function makePrepareMint1155TokenParams({
61
129
  tokenContract: tokenContract,
62
130
  tokenId,
@@ -67,9 +135,11 @@ export function makePrepareMint1155TokenParams({
67
135
  mintRecipient,
68
136
  quantityToMint,
69
137
  allowListEntry,
138
+ chainId,
70
139
  }: {
71
140
  salesConfigAndTokenInfo: Concrete<MintableParameters>;
72
141
  tokenId: GenericTokenIdTypes;
142
+ chainId: number;
73
143
  } & Pick<
74
144
  MakeMintParametersArgumentsBase,
75
145
  | "minterAccount"
@@ -101,22 +171,16 @@ export function makePrepareMint1155TokenParams({
101
171
  }
102
172
 
103
173
  if (saleType === "timed") {
104
- return makeContractParameters({
105
- abi: zoraTimedSaleStrategyABI,
106
- functionName: "mint",
107
- account: minterAccount,
108
- address: salesConfigAndTokenInfo.salesConfig.address,
109
- value:
110
- salesConfigAndTokenInfo.salesConfig.mintFeePerQuantity * mintQuantity,
111
- /* args: mintTo, quantity, collection, tokenId, mintReferral, comment */
112
- args: [
113
- mintTo,
114
- mintQuantity,
115
- tokenContract,
116
- BigInt(tokenId),
117
- mintReferral || zeroAddress,
118
- mintComment || "",
119
- ],
174
+ return makeZoraTimedSaleStrategyMintCall({
175
+ minterAccount,
176
+ salesConfigAndTokenInfo,
177
+ mintQuantity,
178
+ mintTo,
179
+ tokenContract,
180
+ tokenId,
181
+ mintReferral,
182
+ mintComment,
183
+ chainId,
120
184
  });
121
185
  }
122
186
 
@@ -1,12 +1,12 @@
1
1
  import { describe, expect, vi } from "vitest";
2
2
  import { encodeAbiParameters, erc20Abi, parseEther } from "viem";
3
- import { zoraSepolia } from "viem/chains";
3
+ import { zoraSepolia, base } from "viem/chains";
4
4
  import {
5
5
  forkUrls,
6
6
  makeAnvilTest,
7
7
  simulateAndWriteContractWithRetries,
8
8
  } from "src/anvil";
9
- import { createCollectorClient } from "src/sdk";
9
+ import { createCollectorClient, createCreatorClient } from "src/sdk";
10
10
  import { new1155ContractVersion } from "src/create/contract-setup";
11
11
  import { ISubgraphQuerier } from "src/apis/subgraph-querier";
12
12
  import { mockTimedSaleStrategyTokenQueryResult } from "src/fixtures/mint-query-results";
@@ -16,11 +16,32 @@ import {
16
16
  zoraCreator1155ImplABI,
17
17
  } from "@zoralabs/protocol-deployments";
18
18
  import { makeContractParameters } from "src/utils";
19
- import { mockRewardsQueryResults } from "src/fixtures/rewards-query-results";
20
19
  import { setupContractAndToken } from "src/fixtures/contract-setup";
21
20
  import { advanceToSaleAndAndLaunchMarket } from "src/fixtures/secondary";
21
+ import { CreatorERC20zQueryResult } from "./subgraph-queries";
22
22
 
23
23
  describe("rewardsClient", () => {
24
+ makeAnvilTest({
25
+ forkBlockNumber: 22375202,
26
+ forkUrl: forkUrls.baseMainnet,
27
+ anvilChainId: base.id,
28
+ })(
29
+ "it can query rewards balances where there are multiple minters",
30
+ async ({ viemClients: { publicClient, chain } }) => {
31
+ const creatorClient = createCreatorClient({
32
+ chainId: chain.id,
33
+ publicClient,
34
+ });
35
+ const rewardsBalance = await creatorClient.getRewardsBalances({
36
+ account: "0x129F04B140Acc1AA350be2F9f048C178103c62f3",
37
+ });
38
+
39
+ const erc20zKeys = Object.keys(rewardsBalance.secondaryRoyalties.erc20);
40
+
41
+ expect(erc20zKeys.length).toBeGreaterThan(0);
42
+ },
43
+ 20_000,
44
+ );
24
45
  makeAnvilTest({
25
46
  forkBlockNumber: 14653556,
26
47
  forkUrl: forkUrls.zoraSepolia,
@@ -251,20 +272,31 @@ describe("rewardsClient", () => {
251
272
 
252
273
  // now we should be able to get rewards balances for these royalties
253
274
 
275
+ const mockResult: CreatorERC20zQueryResult = {
276
+ zoraCreateTokens: [
277
+ {
278
+ salesStrategies: [
279
+ {
280
+ zoraTimedMinter: {
281
+ secondaryActivated: true,
282
+ erc20Z: { id: erc20z },
283
+ },
284
+ },
285
+ ],
286
+ },
287
+ ],
288
+ };
289
+
254
290
  // we need to stub the subgraph return
255
291
  rewardsGetter.subgraphQuerier.query = vi
256
292
  .fn<ISubgraphQuerier["query"]>()
257
- .mockResolvedValue(
258
- mockRewardsQueryResults({
259
- erc20z: [erc20z],
260
- }),
261
- );
293
+ .mockResolvedValue(mockResult);
262
294
 
263
295
  const rewardsBalance = await creatorClient.getRewardsBalances({
264
296
  account: creatorAccount,
265
297
  });
266
298
 
267
- expect(rewardsBalance.secondaryRoyalties.eth).toBeGreaterThan(0);
299
+ expect(rewardsBalance.protocolRewards).toBeGreaterThan(0n);
268
300
  expect(rewardsBalance.secondaryRoyalties.erc20[erc20z]).toBeGreaterThan(
269
301
  0,
270
302
  );
@@ -77,7 +77,13 @@ export const getRewardsBalance = async ({
77
77
  rewardsGetter: IRewardsGetter;
78
78
  }): Promise<RewardsBalance> => {
79
79
  const address = typeof account === "string" ? account : account.address;
80
- const erc20Zs = await rewardsGetter.getErc20ZzForCreator({ address });
80
+ const erc20ZsAndSecondaryActivated = await rewardsGetter.getErc20ZzForCreator(
81
+ { address },
82
+ );
83
+
84
+ const validErc20Zs = erc20ZsAndSecondaryActivated
85
+ .filter(({ secondaryActivated }) => secondaryActivated)
86
+ .map(({ erc20z }) => erc20z);
81
87
 
82
88
  // Perform multicall to get protocol rewards balance and unclaimed fees
83
89
  const result = await (publicClient as PublicClientWithMulticall).multicall({
@@ -98,7 +104,7 @@ export const getRewardsBalance = async ({
98
104
  ],
99
105
  abi: erc20ZRoyaltiesABI,
100
106
  functionName: "getUnclaimedFeesBatch",
101
- args: [erc20Zs],
107
+ args: [validErc20Zs],
102
108
  },
103
109
  ],
104
110
  multicallAddress: multicall3Address,
@@ -147,9 +153,13 @@ const makeClaimSecondaryRoyaltiesCalls = async ({
147
153
  chainId: number;
148
154
  rewardsGetter: IRewardsGetter;
149
155
  }) => {
150
- const erc20z = await rewardsGetter.getErc20ZzForCreator({
151
- address: claimFor,
152
- });
156
+ const erc20ZsAndSecondaryActivated = await rewardsGetter.getErc20ZzForCreator(
157
+ { address: claimFor },
158
+ );
159
+
160
+ const erc20z = erc20ZsAndSecondaryActivated
161
+ .filter(({ secondaryActivated }) => secondaryActivated)
162
+ .map(({ erc20z }) => erc20z);
153
163
 
154
164
  const royaltiesAddress =
155
165
  erc20ZRoyaltiesAddress[chainId as keyof typeof erc20ZRoyaltiesAddress];
@@ -4,7 +4,8 @@ import { Address } from "viem";
4
4
  export type RewardsToken = {
5
5
  salesStrategies: [
6
6
  {
7
- zoraTimedMinter: {
7
+ zoraTimedMinter?: {
8
+ secondaryActivated: boolean;
8
9
  erc20Z: {
9
10
  id: Address;
10
11
  };
@@ -33,6 +34,7 @@ export function buildCreatorERC20zs({
33
34
  }
34
35
  salesStrategies {
35
36
  zoraTimedMinter {
37
+ secondaryActivated
36
38
  erc20Z {
37
39
  id
38
40
  }
@@ -4,7 +4,9 @@ import { Address } from "viem";
4
4
  import { buildCreatorERC20zs } from "./subgraph-queries";
5
5
 
6
6
  export interface IRewardsGetter {
7
- getErc20ZzForCreator: (params: { address: Address }) => Promise<Address[]>;
7
+ getErc20ZzForCreator: (params: {
8
+ address: Address;
9
+ }) => Promise<{ secondaryActivated: boolean; erc20z: Address }[]>;
8
10
  }
9
11
 
10
12
  export class SubgraphRewardsGetter
@@ -15,19 +17,31 @@ export class SubgraphRewardsGetter
15
17
  super(chainId, subgraphQuerier);
16
18
  }
17
19
 
18
- async getErc20ZzForCreator({
19
- address,
20
- }: {
21
- address: Address;
22
- }): Promise<Address[]> {
20
+ async getErc20ZzForCreator({ address }: { address: Address }) {
23
21
  const queryResults = await this.querySubgraphWithRetries(
24
22
  buildCreatorERC20zs({ address }),
25
23
  );
26
24
 
27
- return (
28
- queryResults?.map(
29
- (result) => result.salesStrategies[0].zoraTimedMinter.erc20Z.id,
30
- ) || []
25
+ const results = (
26
+ queryResults?.map((result) => {
27
+ const timedMinter = result.salesStrategies[0].zoraTimedMinter;
28
+
29
+ if (!timedMinter) {
30
+ return null;
31
+ }
32
+
33
+ return {
34
+ secondaryActivated: timedMinter.secondaryActivated,
35
+ erc20z: timedMinter.erc20Z.id,
36
+ };
37
+ }) || []
38
+ ).filter(
39
+ (
40
+ idAndActivated,
41
+ ): idAndActivated is { secondaryActivated: boolean; erc20z: Address } =>
42
+ !!idAndActivated,
31
43
  );
44
+
45
+ return results;
32
46
  }
33
47
  }
package/src/sdk.ts CHANGED
@@ -116,6 +116,7 @@ export function createCollectorClient(
116
116
  publicClient: params.publicClient,
117
117
  premintGetter: premintGetterToUse,
118
118
  mintGetter: mintGetterToUse,
119
+ chainId: params.chainId,
119
120
  });
120
121
  const secondaryClient = new SecondaryClient({
121
122
  publicClient: params.publicClient,