@zoralabs/protocol-sdk 0.9.6 → 0.11.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.
Files changed (86) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/CHANGELOG.md +17 -0
  3. package/dist/anvil.d.ts +11 -1
  4. package/dist/anvil.d.ts.map +1 -1
  5. package/dist/apis/multicall3.d.ts +9 -0
  6. package/dist/apis/multicall3.d.ts.map +1 -0
  7. package/dist/apis/subgraph-getter.d.ts +9 -0
  8. package/dist/apis/subgraph-getter.d.ts.map +1 -0
  9. package/dist/create/1155-create-helper.test.d.ts +3 -0
  10. package/dist/create/1155-create-helper.test.d.ts.map +1 -0
  11. package/dist/create/contract-getter.d.ts +3 -6
  12. package/dist/create/contract-getter.d.ts.map +1 -1
  13. package/dist/fixtures/contract-setup.d.ts +16 -0
  14. package/dist/fixtures/contract-setup.d.ts.map +1 -0
  15. package/dist/fixtures/mint-query-results.d.ts +10 -0
  16. package/dist/fixtures/mint-query-results.d.ts.map +1 -0
  17. package/dist/fixtures/rewards-query-results.d.ts +6 -0
  18. package/dist/fixtures/rewards-query-results.d.ts.map +1 -0
  19. package/dist/index.cjs +989 -238
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.js +1013 -238
  22. package/dist/index.js.map +1 -1
  23. package/dist/mint/subgraph-mint-getter.d.ts +3 -5
  24. package/dist/mint/subgraph-mint-getter.d.ts.map +1 -1
  25. package/dist/rewards/rewards-client.d.ts +34 -0
  26. package/dist/rewards/rewards-client.d.ts.map +1 -0
  27. package/dist/rewards/rewards-queries.d.ts +34 -0
  28. package/dist/rewards/rewards-queries.d.ts.map +1 -0
  29. package/dist/rewards/subgraph-queries.d.ts +20 -0
  30. package/dist/rewards/subgraph-queries.d.ts.map +1 -0
  31. package/dist/rewards/subgraph-rewards-getter.d.ts +15 -0
  32. package/dist/rewards/subgraph-rewards-getter.d.ts.map +1 -0
  33. package/dist/sdk.d.ts +9 -0
  34. package/dist/sdk.d.ts.map +1 -1
  35. package/dist/secondary/conversions.d.ts +7 -0
  36. package/dist/secondary/conversions.d.ts.map +1 -0
  37. package/dist/secondary/secondary-client.d.ts +67 -0
  38. package/dist/secondary/secondary-client.d.ts.map +1 -0
  39. package/dist/secondary/slippage.d.ts +25 -0
  40. package/dist/secondary/slippage.d.ts.map +1 -0
  41. package/dist/secondary/types.d.ts +37 -0
  42. package/dist/secondary/types.d.ts.map +1 -0
  43. package/dist/secondary/uniswap/abis.d.ts +152 -0
  44. package/dist/secondary/uniswap/abis.d.ts.map +1 -0
  45. package/dist/secondary/uniswap/uniswapQuote.d.ts +13 -0
  46. package/dist/secondary/uniswap/uniswapQuote.d.ts.map +1 -0
  47. package/dist/secondary/uniswap/uniswapQuoteExact.d.ts +37 -0
  48. package/dist/secondary/uniswap/uniswapQuoteExact.d.ts.map +1 -0
  49. package/dist/secondary/uniswap/uniswapReserves.d.ts +3 -0
  50. package/dist/secondary/uniswap/uniswapReserves.d.ts.map +1 -0
  51. package/dist/secondary/utils.d.ts +10 -0
  52. package/dist/secondary/utils.d.ts.map +1 -0
  53. package/dist/sparks/sparks-contracts.d.ts.map +1 -1
  54. package/dist/types.d.ts +3 -2
  55. package/dist/types.d.ts.map +1 -1
  56. package/dist/utils.d.ts +2 -1
  57. package/dist/utils.d.ts.map +1 -1
  58. package/package.json +1 -1
  59. package/src/apis/multicall3.ts +19 -0
  60. package/src/apis/subgraph-getter.ts +33 -0
  61. package/src/create/1155-create-helper.test.ts +18 -18
  62. package/src/create/contract-getter.ts +7 -29
  63. package/src/fixtures/contract-setup.ts +57 -0
  64. package/src/fixtures/mint-query-results.ts +55 -0
  65. package/src/fixtures/rewards-query-results.ts +25 -0
  66. package/src/mint/mint-client.test.ts +18 -46
  67. package/src/mint/subgraph-mint-getter.ts +7 -27
  68. package/src/rewards/rewards-client.test.ts +310 -0
  69. package/src/rewards/rewards-client.ts +67 -0
  70. package/src/rewards/rewards-queries.ts +253 -0
  71. package/src/rewards/subgraph-queries.ts +49 -0
  72. package/src/rewards/subgraph-rewards-getter.ts +33 -0
  73. package/src/sdk.ts +29 -0
  74. package/src/secondary/conversions.ts +20 -0
  75. package/src/secondary/secondary-client.test.ts +276 -0
  76. package/src/secondary/secondary-client.ts +374 -0
  77. package/src/secondary/slippage.ts +42 -0
  78. package/src/secondary/types.ts +64 -0
  79. package/src/secondary/uniswap/abis.ts +20 -0
  80. package/src/secondary/uniswap/uniswapQuote.ts +134 -0
  81. package/src/secondary/uniswap/uniswapQuoteExact.ts +114 -0
  82. package/src/secondary/uniswap/uniswapReserves.ts +34 -0
  83. package/src/secondary/utils.ts +40 -0
  84. package/src/sparks/sparks-contracts.ts +1 -3
  85. package/src/types.ts +6 -7
  86. package/src/utils.ts +7 -1
package/src/sdk.ts CHANGED
@@ -12,6 +12,12 @@ import {
12
12
  IContractGetter,
13
13
  SubgraphContractGetter,
14
14
  } from "./create/contract-getter";
15
+ import { RewardsClient } from "./rewards/rewards-client";
16
+ import {
17
+ IRewardsGetter,
18
+ SubgraphRewardsGetter,
19
+ } from "./rewards/subgraph-rewards-getter";
20
+ import { SecondaryClient } from "./secondary/secondary-client";
15
21
 
16
22
  export type CreatorClient = {
17
23
  createPremint: PremintClient["createPremint"];
@@ -19,6 +25,8 @@ export type CreatorClient = {
19
25
  deletePremint: PremintClient["deletePremint"];
20
26
  create1155: Create1155Client["createNew1155"];
21
27
  create1155OnExistingContract: Create1155Client["createNew1155OnExistingContract"];
28
+ withdrawRewards: RewardsClient["withdrawRewards"];
29
+ getRewardsBalances: RewardsClient["getRewardsBalances"];
22
30
  };
23
31
 
24
32
  export type CollectorClient = {
@@ -28,12 +36,16 @@ export type CollectorClient = {
28
36
  getMintCosts: MintClient["getMintCosts"];
29
37
  getToken: MintClient["get"];
30
38
  getTokensOfContract: MintClient["getOfContract"];
39
+ buy1155OnSecondary: SecondaryClient["buy1155OnSecondary"];
40
+ sell1155OnSecondary: SecondaryClient["sell1155OnSecondary"];
41
+ getSecondaryInfo: SecondaryClient["getSecondaryInfo"];
31
42
  };
32
43
 
33
44
  export type CreatorClientConfig = ClientConfig & {
34
45
  /** API for submitting and getting premints. Defaults to the Zora Premint API */
35
46
  premintApi?: IPremintAPI;
36
47
  contractGetter?: IContractGetter;
48
+ rewardsGetter?: IRewardsGetter;
37
49
  };
38
50
 
39
51
  /**
@@ -60,6 +72,14 @@ export function createCreatorClient(
60
72
  new SubgraphContractGetter(clientConfig.chainId),
61
73
  });
62
74
 
75
+ const rewardsClient = new RewardsClient({
76
+ chainId: clientConfig.chainId,
77
+ publicClient: clientConfig.publicClient,
78
+ rewardsGetter:
79
+ clientConfig.rewardsGetter ||
80
+ new SubgraphRewardsGetter(clientConfig.chainId),
81
+ });
82
+
63
83
  return {
64
84
  createPremint: (p) => premintClient.createPremint(p),
65
85
  updatePremint: (p) => premintClient.updatePremint(p),
@@ -67,6 +87,8 @@ export function createCreatorClient(
67
87
  create1155: (p) => create1155CreatorClient.createNew1155(p),
68
88
  create1155OnExistingContract: (p) =>
69
89
  create1155CreatorClient.createNew1155OnExistingContract(p),
90
+ getRewardsBalances: (p) => rewardsClient.getRewardsBalances(p),
91
+ withdrawRewards: (p) => rewardsClient.withdrawRewards(p),
70
92
  };
71
93
  }
72
94
 
@@ -95,6 +117,10 @@ export function createCollectorClient(
95
117
  premintGetter: premintGetterToUse,
96
118
  mintGetter: mintGetterToUse,
97
119
  });
120
+ const secondaryClient = new SecondaryClient({
121
+ publicClient: params.publicClient,
122
+ chainId: params.chainId,
123
+ });
98
124
 
99
125
  return {
100
126
  getPremint: (p) =>
@@ -108,5 +134,8 @@ export function createCollectorClient(
108
134
  getTokensOfContract: (p) => mintClient.getOfContract(p),
109
135
  mint: (p) => mintClient.mint(p),
110
136
  getMintCosts: (p) => mintClient.getMintCosts(p),
137
+ buy1155OnSecondary: (p) => secondaryClient.buy1155OnSecondary(p),
138
+ sell1155OnSecondary: (p) => secondaryClient.sell1155OnSecondary(p),
139
+ getSecondaryInfo: (p) => secondaryClient.getSecondaryInfo(p),
111
140
  };
112
141
  }
@@ -0,0 +1,20 @@
1
+ import { formatEther } from "viem";
2
+
3
+ export const WEI_PER_SPARK = 1_000_000_000_000n;
4
+
5
+ export function convertWeiToSparks(wei: string | number | bigint) {
6
+ return BigInt(wei) / WEI_PER_SPARK;
7
+ }
8
+
9
+ // Returns the price in USDC given an amount in WEI
10
+ export function convertWeiToUSD({
11
+ amount,
12
+ ethPriceInUSD,
13
+ }: {
14
+ amount: bigint;
15
+ ethPriceInUSD: number;
16
+ }) {
17
+ const amountInEth = formatEther(amount);
18
+
19
+ return parseFloat(amountInEth) * ethPriceInUSD;
20
+ }
@@ -0,0 +1,276 @@
1
+ import { describe, expect, vi } from "vitest";
2
+ import {
3
+ Address,
4
+ parseEther,
5
+ PublicClient,
6
+ TestClient,
7
+ WalletClient,
8
+ Account,
9
+ } from "viem";
10
+ import { zoraSepolia } from "viem/chains";
11
+ import {
12
+ forkUrls,
13
+ makeAnvilTest,
14
+ simulateAndWriteContractWithRetries,
15
+ } from "src/anvil";
16
+ import { createCollectorClient } from "src/sdk";
17
+ import {
18
+ zoraCreator1155ImplABI,
19
+ zoraTimedSaleStrategyABI,
20
+ zoraTimedSaleStrategyAddress,
21
+ } from "@zoralabs/protocol-deployments";
22
+ import { makeContractParameters } from "src/utils";
23
+ import { setupContractAndToken } from "src/fixtures/contract-setup";
24
+ import { CollectorClient } from "src/sdk";
25
+ import { ERROR_SECONDARY_NOT_STARTED } from "./secondary-client";
26
+ import { ISubgraphQuerier } from "src/apis/subgraph-querier";
27
+ import { mockTimedSaleStrategyTokenQueryResult } from "src/fixtures/mint-query-results";
28
+ import { new1155ContractVersion } from "src/create/contract-setup";
29
+
30
+ export async function advanceToSaleAndAndLaunchMarket({
31
+ contractAddress,
32
+ tokenId,
33
+ testClient,
34
+ publicClient,
35
+ walletClient,
36
+ collectorClient,
37
+ chainId,
38
+ account,
39
+ }: {
40
+ contractAddress: Address;
41
+ tokenId: bigint;
42
+ testClient: TestClient;
43
+ publicClient: PublicClient;
44
+ walletClient: WalletClient;
45
+ collectorClient: CollectorClient;
46
+ chainId: number;
47
+ account: Address | Account;
48
+ }) {
49
+ const saleEnd = (await collectorClient.getSecondaryInfo({
50
+ contract: contractAddress,
51
+ tokenId,
52
+ }))!.saleEnd!;
53
+
54
+ // advance to end of sale
55
+ await testClient.setNextBlockTimestamp({
56
+ timestamp: saleEnd,
57
+ });
58
+
59
+ await testClient.mine({
60
+ blocks: 1,
61
+ });
62
+
63
+ // advance to end of sale
64
+ // launch the market
65
+ await simulateAndWriteContractWithRetries({
66
+ parameters: makeContractParameters({
67
+ abi: zoraTimedSaleStrategyABI,
68
+ functionName: "launchMarket",
69
+ args: [contractAddress, tokenId],
70
+ address:
71
+ zoraTimedSaleStrategyAddress[
72
+ chainId as keyof typeof zoraTimedSaleStrategyAddress
73
+ ],
74
+ account: account,
75
+ }),
76
+ publicClient,
77
+ walletClient,
78
+ });
79
+ }
80
+
81
+ describe("secondary", () => {
82
+ makeAnvilTest({
83
+ forkBlockNumber: 13914833,
84
+ forkUrl: forkUrls.zoraSepolia,
85
+ anvilChainId: zoraSepolia.id,
86
+ })(
87
+ "it returns an error when the market is not launched",
88
+ async ({
89
+ viemClients: { publicClient, chain, walletClient, testClient },
90
+ }) => {
91
+ const creatorAccount = (await walletClient.getAddresses()!)[0]!;
92
+ const collectorAccount = (await walletClient.getAddresses()!)[1]!;
93
+
94
+ const { contractAddress, newTokenId } = await setupContractAndToken({
95
+ chain,
96
+ publicClient,
97
+ creatorAccount,
98
+ walletClient,
99
+ });
100
+
101
+ await testClient.setBalance({
102
+ address: collectorAccount,
103
+ value: parseEther("100"),
104
+ });
105
+
106
+ const collectorClient = createCollectorClient({
107
+ chainId: chain.id,
108
+ publicClient,
109
+ });
110
+
111
+ const secondaryInfo = await collectorClient.getSecondaryInfo({
112
+ contract: contractAddress,
113
+ tokenId: newTokenId,
114
+ });
115
+
116
+ expect(secondaryInfo?.secondaryActivated).toBe(false);
117
+
118
+ const buyResult = await collectorClient.buy1155OnSecondary({
119
+ account: collectorAccount,
120
+ quantity: 100n,
121
+ contract: contractAddress,
122
+ tokenId: newTokenId,
123
+ });
124
+
125
+ expect(buyResult.error).toEqual(ERROR_SECONDARY_NOT_STARTED);
126
+ },
127
+ 20_000,
128
+ );
129
+
130
+ makeAnvilTest({
131
+ forkBlockNumber: 13914833,
132
+ forkUrl: forkUrls.zoraSepolia,
133
+ anvilChainId: zoraSepolia.id,
134
+ })(
135
+ "it can buy and sell on secondary when the market is launched",
136
+ async ({
137
+ viemClients: { publicClient, chain, walletClient, testClient },
138
+ }) => {
139
+ const creatorAccount = (await walletClient.getAddresses()!)[0]!;
140
+ const collectorAccount = (await walletClient.getAddresses()!)[1]!;
141
+
142
+ const { contractAddress, newTokenId, mintGetter } =
143
+ await setupContractAndToken({
144
+ chain,
145
+ publicClient,
146
+ creatorAccount,
147
+ walletClient,
148
+ });
149
+
150
+ await testClient.setBalance({
151
+ address: collectorAccount,
152
+ value: parseEther("100"),
153
+ });
154
+
155
+ const quantityToMint = 100_000n;
156
+
157
+ mintGetter.subgraphQuerier.query = vi
158
+ .fn<ISubgraphQuerier["query"]>()
159
+ .mockResolvedValue({
160
+ zoraCreateToken: mockTimedSaleStrategyTokenQueryResult({
161
+ chainId: chain.id,
162
+ tokenId: newTokenId,
163
+ contractAddress,
164
+ contractVersion:
165
+ new1155ContractVersion[
166
+ chain.id as keyof typeof new1155ContractVersion
167
+ ],
168
+ }),
169
+ });
170
+
171
+ const collectorClient = createCollectorClient({
172
+ chainId: chain.id,
173
+ publicClient,
174
+ mintGetter,
175
+ });
176
+
177
+ const { parameters: collectParameters } = await collectorClient.mint({
178
+ minterAccount: collectorAccount,
179
+ mintType: "1155",
180
+ quantityToMint,
181
+ tokenId: newTokenId,
182
+ tokenContract: contractAddress,
183
+ });
184
+
185
+ await simulateAndWriteContractWithRetries({
186
+ parameters: collectParameters,
187
+ walletClient,
188
+ publicClient,
189
+ });
190
+
191
+ await advanceToSaleAndAndLaunchMarket({
192
+ contractAddress,
193
+ tokenId: newTokenId,
194
+ testClient,
195
+ publicClient,
196
+ walletClient,
197
+ collectorClient,
198
+ chainId: chain.id,
199
+ account: collectorAccount,
200
+ });
201
+
202
+ // now get the price ot buy on secondary
203
+ const quantityToBuy = 1000n;
204
+
205
+ const buyResult = await collectorClient.buy1155OnSecondary({
206
+ account: collectorAccount,
207
+ quantity: quantityToBuy,
208
+ contract: contractAddress,
209
+ tokenId: newTokenId,
210
+ });
211
+
212
+ expect(buyResult.error).toBeUndefined();
213
+
214
+ expect(buyResult.price!.wei.perToken).toBeGreaterThan(
215
+ parseEther("0.000111"),
216
+ );
217
+
218
+ // expected amount with slippage is total price * 1.005 considering bigint:
219
+ const expectedTotalWithSlippage =
220
+ buyResult.price!.wei.total + (buyResult.price!.wei.total * 5n) / 1000n;
221
+
222
+ expect(buyResult.parameters!.value).toBe(expectedTotalWithSlippage);
223
+
224
+ // execute the buy
225
+ await simulateAndWriteContractWithRetries({
226
+ parameters: buyResult.parameters!,
227
+ walletClient,
228
+ publicClient,
229
+ });
230
+
231
+ // now get balance of erc1155, should be minted by quantity bought
232
+ let balance = await publicClient.readContract({
233
+ abi: zoraCreator1155ImplABI,
234
+ address: contractAddress,
235
+ functionName: "balanceOf",
236
+ args: [collectorAccount, newTokenId],
237
+ });
238
+
239
+ expect(balance).toBe(quantityToBuy + quantityToMint);
240
+
241
+ // now sell 10_000n tokens
242
+ const quantityToSell = 10_000n;
243
+
244
+ const sellResult = await collectorClient.sell1155OnSecondary({
245
+ account: collectorAccount,
246
+ quantity: quantityToSell,
247
+ contract: contractAddress,
248
+ tokenId: newTokenId,
249
+ });
250
+
251
+ expect(sellResult.error).toBeUndefined();
252
+
253
+ expect(sellResult.price!.wei.perToken).toBeLessThan(
254
+ parseEther("0.000111"),
255
+ );
256
+
257
+ // execute the sell
258
+ await simulateAndWriteContractWithRetries({
259
+ parameters: sellResult.parameters!,
260
+ walletClient,
261
+ publicClient,
262
+ });
263
+
264
+ // now get balance of erc1155, should be minted by quantity bought
265
+ balance = await publicClient.readContract({
266
+ abi: zoraCreator1155ImplABI,
267
+ address: contractAddress,
268
+ functionName: "balanceOf",
269
+ args: [collectorAccount, newTokenId],
270
+ });
271
+
272
+ expect(balance).toBe(quantityToMint + quantityToBuy - quantityToSell);
273
+ },
274
+ 30_000,
275
+ );
276
+ });