@zoralabs/coins-sdk 0.0.2-sdkalpha.2 → 0.0.2-sdkalpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,9 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
1
7
  // src/actions/createCoin.ts
2
8
  import { zoraFactoryImplABI } from "@zoralabs/coins";
3
9
  import {
@@ -72,6 +78,9 @@ async function createCoin(call, walletClient, publicClient) {
72
78
  ...createCoinCall(call),
73
79
  account: walletClient.account
74
80
  });
81
+ if (request.gas) {
82
+ request.gas = request.gas * 6n / 5n;
83
+ }
75
84
  const hash = await walletClient.writeContract(request);
76
85
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
77
86
  const deployment = getCoinCreateFromLogs(receipt);
@@ -142,43 +151,57 @@ async function tradeCoin(params, walletClient, publicClient) {
142
151
  };
143
152
  }
144
153
 
145
- // src/actions/getCoinDetails.ts
154
+ // src/actions/getOnchainCoinDetails.ts
146
155
  import { coinABI as coinABI2, iUniswapV3PoolABI } from "@zoralabs/coins";
147
- import { erc20Abi, formatEther, isAddressEqual, zeroAddress as zeroAddress2 } from "viem";
148
- async function getCoinDetails({
156
+ import {
157
+ erc20Abi,
158
+ formatEther,
159
+ isAddressEqual,
160
+ zeroAddress as zeroAddress2
161
+ } from "viem";
162
+ async function getOnchainCoinDetails({
149
163
  coin,
150
164
  user = zeroAddress2,
151
165
  publicClient
152
166
  }) {
153
167
  validateClientNetwork(publicClient);
154
- const [balance, pool, owners, payoutRecipient] = await publicClient.multicall({
155
- contracts: [
156
- {
157
- address: coin,
158
- abi: coinABI2,
159
- functionName: "balanceOf",
160
- args: [user]
161
- },
162
- {
163
- address: coin,
164
- abi: coinABI2,
165
- functionName: "poolAddress"
166
- },
167
- {
168
- address: coin,
169
- abi: coinABI2,
170
- functionName: "owners"
171
- },
172
- {
173
- address: coin,
174
- abi: coinABI2,
175
- functionName: "payoutRecipient"
176
- }
177
- ],
178
- allowFailure: false
179
- });
168
+ const [balance, pool, owners, payoutRecipient] = await publicClient.multicall(
169
+ {
170
+ contracts: [
171
+ {
172
+ address: coin,
173
+ abi: coinABI2,
174
+ functionName: "balanceOf",
175
+ args: [user]
176
+ },
177
+ {
178
+ address: coin,
179
+ abi: coinABI2,
180
+ functionName: "poolAddress"
181
+ },
182
+ {
183
+ address: coin,
184
+ abi: coinABI2,
185
+ functionName: "owners"
186
+ },
187
+ {
188
+ address: coin,
189
+ abi: coinABI2,
190
+ functionName: "payoutRecipient"
191
+ }
192
+ ],
193
+ allowFailure: false
194
+ }
195
+ );
180
196
  const USDC_WETH_POOL = USDC_WETH_POOLS_BY_CHAIN[publicClient.chain?.id || 0];
181
- const [coinWethPoolSlot0, coinWethPoolToken0, coinReservesRaw, coinTotalSupply, wethReservesRaw, usdcWethSlot0] = await publicClient.multicall({
197
+ const [
198
+ coinWethPoolSlot0,
199
+ coinWethPoolToken0,
200
+ coinReservesRaw,
201
+ coinTotalSupply,
202
+ wethReservesRaw,
203
+ usdcWethSlot0
204
+ ] = await publicClient.multicall({
182
205
  contracts: [
183
206
  {
184
207
  address: pool,
@@ -238,12 +261,20 @@ async function getCoinDetails({
238
261
  owners,
239
262
  payoutRecipient,
240
263
  marketCap: convertEthOutput(marketCap, wethPriceInUsdc),
241
- liquidity: convertEthOutput(wethLiquidity + tokenLiquidity, wethPriceInUsdc),
264
+ liquidity: convertEthOutput(
265
+ wethLiquidity + tokenLiquidity,
266
+ wethPriceInUsdc
267
+ ),
242
268
  poolState: coinWethPoolSlot0
243
269
  };
244
270
  }
245
271
  function convertEthOutput(amountETH, wethToUsdc) {
246
- return { eth: amountETH, ethDecimal: parseFloat(formatEther(amountETH)), usdc: wethToUsdc ? amountETH * wethToUsdc : null, usdcDecimal: wethToUsdc ? parseFloat(formatEther(amountETH * wethToUsdc / 10n ** 18n)) : null };
272
+ return {
273
+ eth: amountETH,
274
+ ethDecimal: parseFloat(formatEther(amountETH)),
275
+ usdc: wethToUsdc ? amountETH * wethToUsdc : null,
276
+ usdcDecimal: wethToUsdc ? parseFloat(formatEther(amountETH * wethToUsdc / 10n ** 18n)) : null
277
+ };
247
278
  }
248
279
  function uniswapV3SqrtPriceToBigIntScaled(sqrtPriceX96, token0Decimals, token1Decimals, isToken0Coin, scaleDecimals = 18) {
249
280
  const numerator = sqrtPriceX96 * sqrtPriceX96;
@@ -299,11 +330,76 @@ async function updateCoinURI(args, walletClient, publicClient) {
299
330
  );
300
331
  return { hash, receipt, uriUpdated };
301
332
  }
333
+
334
+ // src/client/client.gen.ts
335
+ import { createClient, createConfig } from "@hey-api/client-fetch";
336
+ var client = createClient(createConfig({
337
+ baseUrl: "https://api-sdk.zora.engineering/"
338
+ }));
339
+
340
+ // src/client/sdk.gen.ts
341
+ var getCoinDetails = (options) => {
342
+ return (options.client ?? client).get({
343
+ url: "/coinDetails",
344
+ ...options
345
+ });
346
+ };
347
+ var getCoinComments = (options) => {
348
+ return (options.client ?? client).get({
349
+ url: "/coinComments",
350
+ ...options
351
+ });
352
+ };
353
+ var getExplore = (options) => {
354
+ return (options.client ?? client).get({
355
+ url: "/explore",
356
+ ...options
357
+ });
358
+ };
359
+
360
+ // src/client/explore.ts
361
+ var explore_exports = {};
362
+ __export(explore_exports, {
363
+ getLastTraded: () => getLastTraded,
364
+ getLastTradedUnique: () => getLastTradedUnique,
365
+ getMostValuable: () => getMostValuable,
366
+ getNew: () => getNew,
367
+ getTopGainers: () => getTopGainers,
368
+ getTopVolume24h: () => getTopVolume24h
369
+ });
370
+ var getTopGainers = (options) => getExplore({
371
+ ...options,
372
+ query: { ...options?.query, listType: "TOP_GAINERS" }
373
+ });
374
+ var getTopVolume24h = (options) => getExplore({
375
+ ...options,
376
+ query: { ...options?.query, listType: "TOP_VOLUME_24H" }
377
+ });
378
+ var getMostValuable = (options) => getExplore({
379
+ ...options,
380
+ query: { ...options?.query, listType: "MOST_VALUABLE" }
381
+ });
382
+ var getNew = (options) => getExplore({
383
+ ...options,
384
+ query: { ...options?.query, listType: "NEW" }
385
+ });
386
+ var getLastTraded = (options) => getExplore({
387
+ ...options,
388
+ query: { ...options?.query, listType: "LAST_TRADED" }
389
+ });
390
+ var getLastTradedUnique = (options) => getExplore({
391
+ ...options,
392
+ query: { ...options?.query, listType: "LAST_TRADED_UNIQUE" }
393
+ });
302
394
  export {
303
395
  createCoin,
304
396
  createCoinCall,
397
+ explore_exports as explore,
398
+ getCoinComments,
305
399
  getCoinCreateFromLogs,
306
400
  getCoinDetails,
401
+ getExplore,
402
+ getOnchainCoinDetails,
307
403
  getTradeFromLogs,
308
404
  tradeCoin,
309
405
  tradeCoinCall,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/actions/createCoin.ts","../src/constants.ts","../src/utils/validateClientNetwork.ts","../src/actions/tradeCoin.ts","../src/actions/getCoinDetails.ts","../src/actions/updateCoinURI.ts"],"sourcesContent":["import { zoraFactoryImplABI } from \"@zoralabs/coins\";\nimport {\n Address,\n PublicClient,\n TransactionReceipt,\n WalletClient,\n SimulateContractParameters,\n ContractEventArgsFromTopics,\n parseEventLogs,\n} from \"viem\";\nimport { COIN_FACTORY_ADDRESS } from \"../constants\";\nimport { validateClientNetwork } from \"src/utils/validateClientNetwork\";\n\nexport type CoinDeploymentLogArgs = ContractEventArgsFromTopics<\n typeof zoraFactoryImplABI,\n \"CoinCreated\"\n>;\n\ntype CreateCoinArgs = {\n name: string;\n symbol: string;\n uri: string;\n owners?: Address[];\n tickLower?: number;\n payoutRecipient: Address;\n platformReferrer?: Address;\n initialPurchaseWei?: bigint;\n};\n\nexport function createCoinCall({\n name,\n symbol,\n uri,\n owners,\n payoutRecipient,\n initialPurchaseWei = 0n,\n tickLower = -199200,\n platformReferrer = \"0x0000000000000000000000000000000000000000\",\n}: CreateCoinArgs): SimulateContractParameters<\n typeof zoraFactoryImplABI,\n \"deploy\"\n> {\n if (!owners) {\n owners = [payoutRecipient];\n }\n\n const currency = \"0x4200000000000000000000000000000000000006\";\n return {\n abi: zoraFactoryImplABI,\n functionName: \"deploy\",\n address: COIN_FACTORY_ADDRESS,\n args: [\n payoutRecipient,\n owners,\n uri,\n name,\n symbol,\n platformReferrer,\n currency,\n tickLower,\n initialPurchaseWei,\n ],\n value: initialPurchaseWei,\n } as const;\n}\n\n/**\n * Gets the deployed coin address from transaction receipt logs\n * @param receipt Transaction receipt containing the CoinCreated event\n * @returns The deployment information if found\n */\nexport function getCoinCreateFromLogs(\n receipt: TransactionReceipt,\n): CoinDeploymentLogArgs | undefined {\n const eventLogs = parseEventLogs({\n abi: zoraFactoryImplABI,\n logs: receipt.logs,\n });\n return eventLogs.find((log) => log.eventName === \"CoinCreated\")?.args;\n}\n\n// Update createCoin to return both receipt and coin address\nexport async function createCoin(\n call: CreateCoinArgs,\n walletClient: WalletClient,\n publicClient: PublicClient,\n) {\n validateClientNetwork(publicClient);\n const { request } = await publicClient.simulateContract({\n ...createCoinCall(call),\n account: walletClient.account,\n });\n const hash = await walletClient.writeContract(request);\n const receipt = await publicClient.waitForTransactionReceipt({ hash });\n const deployment = getCoinCreateFromLogs(receipt);\n\n return {\n hash,\n receipt,\n address: deployment?.coin,\n deployment,\n };\n}\n","import { zoraFactoryImplAddress } from \"@zoralabs/coins\";\nimport { Address } from \"viem\";\nimport { base } from \"viem/chains\";\n\n// this is the same across all chains due to deterministic deploys.\nexport const COIN_FACTORY_ADDRESS = zoraFactoryImplAddress[\"8453\"] as Address;\n\nexport const SUPERCHAIN_WETH_ADDRESS = '0x4200000000000000000000000000000000000006';\n\nexport const USDC_WETH_POOLS_BY_CHAIN: Record<number, Address> = {\n [base.id]: '0xd0b53D9277642d899DF5C87A3966A349A798F224',\n}\n","import { PublicClient } from \"viem\"\nimport { base, baseSepolia } from \"viem/chains\"\n\nexport const validateClientNetwork = (publicClient: PublicClient) => {\n const clientChainId = publicClient?.chain?.id;\n if (clientChainId === base.id) {\n return;\n }\n if (clientChainId === baseSepolia.id) {\n return;\n }\n\n throw new Error('Client network needs to be base or baseSepolia for current coin deployments.');\n}","import { coinABI } from \"@zoralabs/coins\";\nimport { validateClientNetwork } from \"src/utils/validateClientNetwork\";\nimport {\n Address,\n PublicClient,\n TransactionReceipt,\n WalletClient,\n SimulateContractParameters,\n parseEther,\n zeroAddress,\n ContractEventArgsFromTopics,\n parseEventLogs,\n} from \"viem\";\nimport { baseSepolia } from \"viem/chains\";\n\n// Define trade event args type\n\nexport type SellEventArgs = ContractEventArgsFromTopics<\n typeof coinABI,\n \"CoinSell\"\n>;\nexport type BuyEventArgs = ContractEventArgsFromTopics<\n typeof coinABI,\n \"CoinBuy\"\n>;\n\nexport type TradeEventArgs = SellEventArgs | BuyEventArgs;\n\n/**\n * Simulates a buy order to get the expected output amount\n * @param {Object} params - The simulation parameters\n * @param {Address} params.target - The target coin contract address\n * @param {bigint} params.requestedOrderSize - The desired input amount for the buy\n * @param {PublicClient} params.publicClient - The viem public client instance\n * @returns {Promise<{orderSize: bigint, amountOut: bigint}>} The simulated order size and output amount\n */\nexport async function simulateBuy({\n target,\n requestedOrderSize,\n publicClient,\n}: {\n target: Address;\n requestedOrderSize: bigint;\n publicClient: PublicClient;\n}): Promise<{ orderSize: bigint; amountOut: bigint }> {\n const numberResult = await publicClient.simulateContract({\n address: target,\n abi: coinABI,\n functionName: \"buy\",\n args: [\n zeroAddress,\n requestedOrderSize,\n 0n, // minAmountOut\n 0n, // sqrtPriceLimitX96\n zeroAddress, // tradeReferrer\n ],\n stateOverride: [\n {\n address: baseSepolia.contracts.multicall3.address,\n balance: parseEther(\"100000\"),\n },\n ],\n });\n const orderSize = numberResult.result[0];\n const amountOut = numberResult.result[1];\n return { orderSize, amountOut };\n}\n\n/**\n * Parameters for creating a trade call\n * @typedef {Object} TradeParams\n * @property {'sell' | 'buy'} direction - The trade direction\n * @property {Address} target - The target coin contract address\n * @property {Object} args - The trade arguments\n * @property {Address} args.recipient - The recipient of the trade output\n * @property {bigint} args.orderSize - The size of the order\n * @property {bigint} [args.minAmountOut] - The minimum amount to receive\n * @property {bigint} [args.sqrtPriceLimitX96] - The price limit for the trade\n * @property {Address} [args.tradeReferrer] - The referrer address for the trade\n */\ntype TradeParams = {\n direction: \"sell\" | \"buy\";\n target: Address;\n args: {\n recipient: Address;\n orderSize: bigint;\n minAmountOut?: bigint;\n sqrtPriceLimitX96?: bigint;\n tradeReferrer?: Address;\n };\n};\n\n/**\n * Creates a trade call parameters object for buy or sell\n * @param {TradeParams} params - The trade parameters\n * @returns {SimulateContractParameters} The contract call parameters\n */\nexport function tradeCoinCall({\n target,\n direction,\n args: {\n recipient,\n orderSize,\n minAmountOut = 0n,\n sqrtPriceLimitX96 = 0n,\n tradeReferrer = zeroAddress,\n },\n}: TradeParams): SimulateContractParameters {\n return {\n abi: coinABI,\n functionName: direction,\n address: target,\n args: [\n recipient,\n orderSize,\n minAmountOut,\n sqrtPriceLimitX96,\n tradeReferrer,\n ],\n value: direction === \"buy\" ? orderSize : 0n,\n } as const;\n}\n\n/**\n * Gets the trade event from transaction receipt logs\n * @param {TransactionReceipt} receipt - The transaction receipt containing the logs\n * @param {'buy' | 'sell'} direction - The direction of the trade\n * @returns {TradeEventArgs | undefined} The decoded trade event args if found\n */\nexport function getTradeFromLogs(\n receipt: TransactionReceipt,\n direction: \"buy\" | \"sell\",\n): TradeEventArgs | undefined {\n const eventLogs = parseEventLogs({\n abi: coinABI,\n logs: receipt.logs,\n });\n\n if (direction === \"buy\") {\n return eventLogs.find((log) => log.eventName === \"CoinBuy\")?.args;\n }\n return eventLogs.find((log) => log.eventName === \"CoinSell\")?.args;\n}\n\n/**\n * Executes a trade transaction\n * @param {TradeParams} params - The trade parameters\n * @param {PublicClient} publicClient - The viem public client instance\n * @param {WalletClient} walletClient - The viem wallet client instance\n * @returns {Promise<{\n * hash: `0x${string}`,\n * receipt: TransactionReceipt,\n * trade: TradeEventArgs | undefined\n * }>} The transaction result with trade details\n */\nexport async function tradeCoin(\n params: TradeParams,\n walletClient: WalletClient,\n publicClient: PublicClient,\n) {\n validateClientNetwork(publicClient);\n const { request } = await publicClient.simulateContract({\n ...tradeCoinCall(params),\n account: walletClient.account,\n });\n const hash = await walletClient.writeContract(request);\n const receipt = await publicClient.waitForTransactionReceipt({ hash });\n const trade = getTradeFromLogs(receipt, params.direction);\n\n return {\n hash,\n receipt,\n trade,\n };\n}\n","import { coinABI, iUniswapV3PoolABI } from \"@zoralabs/coins\";\nimport { SUPERCHAIN_WETH_ADDRESS, USDC_WETH_POOLS_BY_CHAIN } from \"src/constants\";\nimport { validateClientNetwork } from \"src/utils/validateClientNetwork\";\nimport { Address, erc20Abi, formatEther, isAddressEqual, PublicClient, zeroAddress } from \"viem\";\n\n\ntype Slot0Result = {\n sqrtPriceX96: bigint;\n tick: number;\n observationIndex: number;\n observationCardinality: number;\n observationCardinalityNext: number;\n feeProtocol: number;\n unlocked: boolean;\n};\n\ntype PricingResult = {\n eth: bigint,\n usdc: bigint | null,\n usdcDecimal: number | null,\n ethDecimal: number,\n}\n\n/**\n * Represents the current state of a coin\n * @typedef {Object} CoinDetails\n * @property {bigint} balance - The user's balance of the coin\n * @property {PricingResult} marketCap - The market cap of the coin\n * @property {PricingResult} liquidity - The liquidity of the coin\n * @property {Address} pool - Pool address\n * @property {Slot0Result} poolState - Current state of the UniswapV3 pool\n * @property {Address[]} owners - List of owners for the coin\n * @property {Address} payoutRecipient - The payout recipient address\n */\nexport type CoinDetails = {\n balance: bigint;\n marketCap: PricingResult;\n liquidity: PricingResult;\n pool: Address;\n poolState: Slot0Result;\n owners: readonly Address[],\n payoutRecipient: Address,\n};\n\n/**\n * Gets the current state of a coin for a user\n * @param {Object} params - The query parameters\n * @param {Address} params.coin - The coin contract address\n * @param {Address} params.user - The user address to check balance for\n * @param {PublicClient} params.publicClient - The viem public client instance\n * @returns {Promise<CoinDetails>} The coin's current state\n */\nexport async function getCoinDetails({\n coin,\n user = zeroAddress,\n publicClient,\n}: {\n coin: Address;\n user?: Address;\n publicClient: PublicClient;\n}): Promise<CoinDetails> {\n validateClientNetwork(publicClient);\n const [balance, pool, owners, payoutRecipient] = await publicClient.multicall({\n contracts: [\n {\n address: coin,\n abi: coinABI,\n functionName: \"balanceOf\",\n args: [user],\n },\n {\n address: coin,\n abi: coinABI,\n functionName: \"poolAddress\",\n },\n {\n address: coin,\n abi: coinABI,\n functionName: 'owners',\n },\n {\n address: coin,\n abi: coinABI,\n functionName: 'payoutRecipient',\n }\n ],\n allowFailure: false,\n });\n\n const USDC_WETH_POOL = USDC_WETH_POOLS_BY_CHAIN[publicClient.chain?.id || 0];\n\n const [coinWethPoolSlot0, coinWethPoolToken0, coinReservesRaw, coinTotalSupply, wethReservesRaw, usdcWethSlot0] = await publicClient.multicall({\n contracts: [{\n address: pool,\n abi: iUniswapV3PoolABI,\n functionName: \"slot0\",\n },\n {\n address: pool,\n abi: iUniswapV3PoolABI,\n functionName: 'token0'\n }, {\n address: coin,\n abi: erc20Abi,\n functionName: 'balanceOf',\n args: [pool],\n },\n {\n address: coin,\n abi: coinABI,\n functionName: 'totalSupply',\n }, {\n address: SUPERCHAIN_WETH_ADDRESS,\n abi: erc20Abi,\n functionName: 'balanceOf',\n args: [pool],\n }, {\n address: USDC_WETH_POOL ?? coin,\n abi: iUniswapV3PoolABI,\n functionName: 'slot0',\n }], allowFailure: false\n });\n\n const wethPriceInUsdc = USDC_WETH_POOL ? uniswapV3SqrtPriceToBigIntScaled(\n usdcWethSlot0.sqrtPriceX96,\n 18,\n 6,\n true,\n 18\n ) : null;\n\n const coinPriceInWeth = uniswapV3SqrtPriceToBigIntScaled(\n coinWethPoolSlot0.sqrtPriceX96,\n 18,\n 18,\n isAddressEqual(coinWethPoolToken0, coin),\n 18\n );\n\n // Divide by 10^18 to remove percision from `coinPriceInWeth` after math since bigint is decimal.\n const marketCap = coinPriceInWeth * coinTotalSupply / 10n ** 18n;\n\n const wethLiquidity = wethReservesRaw;\n // Divide by 10^18 to remove percision from `coinPriceInWeth` after math since bigint is decimal.\n const tokenLiquidity = coinReservesRaw * coinPriceInWeth / 10n ** 18n;\n\n return {\n balance,\n pool,\n owners,\n payoutRecipient,\n marketCap: convertEthOutput(marketCap, wethPriceInUsdc),\n liquidity: convertEthOutput(wethLiquidity + tokenLiquidity, wethPriceInUsdc),\n poolState: coinWethPoolSlot0,\n };\n}\n\n\nfunction convertEthOutput(amountETH: bigint, wethToUsdc: bigint | null) {\n return { eth: amountETH, ethDecimal: parseFloat(formatEther(amountETH)), usdc: wethToUsdc ? amountETH * wethToUsdc : null, usdcDecimal: wethToUsdc ? parseFloat(formatEther(amountETH * wethToUsdc / 10n ** 18n)) : null }\n}\n\nfunction uniswapV3SqrtPriceToBigIntScaled(\n sqrtPriceX96: bigint,\n token0Decimals: number,\n token1Decimals: number,\n isToken0Coin: boolean,\n scaleDecimals: number = 18\n): bigint {\n // (sqrtPrice^2 / 2^192) => ratio\n // We'll do: ratioScaled = (sqrtPrice^2 * 10^scaleDecimals) / 2^192\n const numerator = sqrtPriceX96 * sqrtPriceX96;\n const denominator = 2n ** 192n;\n const scaleFactor = 10n ** BigInt(scaleDecimals);\n\n // raw ratioScaled\n let ratioScaled = (numerator * scaleFactor) / denominator; // BigInt\n\n // Adjust for difference in decimals:\n // ratioScaled *= 10^(dec0 - dec1)\n const decimalsDiff = BigInt(token0Decimals - token1Decimals);\n if (decimalsDiff > 0n) {\n ratioScaled *= 10n ** decimalsDiff;\n } else if (decimalsDiff < 0n) {\n ratioScaled /= 10n ** (-decimalsDiff);\n }\n\n if (!isToken0Coin) {\n // We want the reciprocal: coin is token1 => coinPriceInToken0 = 1 / ratio\n // But we also want it scaled by 10^scaleDecimals\n // reciprocalScaled = (10^scaleDecimals * 10^(decimalsDiff)) / ratioScaled\n // (assuming ratioScaled != 0)\n if (ratioScaled === 0n) {\n return 0n; // or some huge number representing infinity\n }\n ratioScaled = (scaleFactor * scaleFactor) / ratioScaled;\n // or if we already included decimalsDiff above, handle carefully.\n }\n\n return ratioScaled;\n}\n","import { coinABI } from \"@zoralabs/coins\";\nimport { validateClientNetwork } from \"src/utils/validateClientNetwork\";\nimport {\n Address,\n parseEventLogs,\n PublicClient,\n SimulateContractParameters,\n WalletClient,\n} from \"viem\";\n\ntype UpdateCoinURIArgs = {\n coin: Address;\n newURI: string;\n};\n\nexport function updateCoinURICall({\n newURI,\n coin,\n}: UpdateCoinURIArgs): SimulateContractParameters {\n if (!newURI.startsWith(\"ipfs://\")) {\n throw new Error(\"URI needs to be an ipfs:// prefix uri\");\n }\n\n return {\n abi: coinABI,\n address: coin,\n functionName: \"setContractURI\",\n args: [newURI],\n };\n}\n\nexport async function updateCoinURI(\n args: UpdateCoinURIArgs,\n walletClient: WalletClient,\n publicClient: PublicClient,\n) {\n validateClientNetwork(publicClient);\n const call = updateCoinURICall(args);\n const { request } = await publicClient.simulateContract({\n ...call,\n account: walletClient.account!,\n });\n const hash = await walletClient.writeContract(request);\n const receipt = await publicClient.waitForTransactionReceipt({ hash });\n const eventLogs = parseEventLogs({ abi: coinABI, logs: receipt.logs });\n const uriUpdated = eventLogs.find(\n (log) => log.eventName === \"ContractURIUpdated\",\n );\n\n return { hash, receipt, uriUpdated };\n}\n"],"mappings":"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","names":["base","parseEventLogs","baseSepolia","parseEventLogs","coinABI","zeroAddress","coinABI","coinABI","parseEventLogs","coinABI"]}
1
+ {"version":3,"sources":["../src/actions/createCoin.ts","../src/constants.ts","../src/utils/validateClientNetwork.ts","../src/actions/tradeCoin.ts","../src/actions/getOnchainCoinDetails.ts","../src/actions/updateCoinURI.ts","../src/client/client.gen.ts","../src/client/sdk.gen.ts","../src/client/explore.ts"],"sourcesContent":["import { zoraFactoryImplABI } from \"@zoralabs/coins\";\nimport {\n Address,\n PublicClient,\n TransactionReceipt,\n WalletClient,\n SimulateContractParameters,\n ContractEventArgsFromTopics,\n parseEventLogs,\n} from \"viem\";\nimport { COIN_FACTORY_ADDRESS } from \"../constants\";\nimport { validateClientNetwork } from \"src/utils/validateClientNetwork\";\n\nexport type CoinDeploymentLogArgs = ContractEventArgsFromTopics<\n typeof zoraFactoryImplABI,\n \"CoinCreated\"\n>;\n\ntype CreateCoinArgs = {\n name: string;\n symbol: string;\n uri: string;\n owners?: Address[];\n tickLower?: number;\n payoutRecipient: Address;\n platformReferrer?: Address;\n initialPurchaseWei?: bigint;\n};\n\nexport function createCoinCall({\n name,\n symbol,\n uri,\n owners,\n payoutRecipient,\n initialPurchaseWei = 0n,\n tickLower = -199200,\n platformReferrer = \"0x0000000000000000000000000000000000000000\",\n}: CreateCoinArgs): SimulateContractParameters<\n typeof zoraFactoryImplABI,\n \"deploy\"\n> {\n if (!owners) {\n owners = [payoutRecipient];\n }\n\n const currency = \"0x4200000000000000000000000000000000000006\";\n return {\n abi: zoraFactoryImplABI,\n functionName: \"deploy\",\n address: COIN_FACTORY_ADDRESS,\n args: [\n payoutRecipient,\n owners,\n uri,\n name,\n symbol,\n platformReferrer,\n currency,\n tickLower,\n initialPurchaseWei,\n ],\n value: initialPurchaseWei,\n } as const;\n}\n\n/**\n * Gets the deployed coin address from transaction receipt logs\n * @param receipt Transaction receipt containing the CoinCreated event\n * @returns The deployment information if found\n */\nexport function getCoinCreateFromLogs(\n receipt: TransactionReceipt,\n): CoinDeploymentLogArgs | undefined {\n const eventLogs = parseEventLogs({\n abi: zoraFactoryImplABI,\n logs: receipt.logs,\n });\n return eventLogs.find((log) => log.eventName === \"CoinCreated\")?.args;\n}\n\n// Update createCoin to return both receipt and coin address\nexport async function createCoin(\n call: CreateCoinArgs,\n walletClient: WalletClient,\n publicClient: PublicClient,\n) {\n validateClientNetwork(publicClient);\n const { request } = await publicClient.simulateContract({\n ...createCoinCall(call),\n account: walletClient.account,\n });\n\n // Add a 1/5th buffer on gas.\n if (request.gas) {\n request.gas = request.gas * 6n / 5n;\n }\n const hash = await walletClient.writeContract(request);\n const receipt = await publicClient.waitForTransactionReceipt({ hash });\n const deployment = getCoinCreateFromLogs(receipt);\n\n return {\n hash,\n receipt,\n address: deployment?.coin,\n deployment,\n };\n}\n","import { zoraFactoryImplAddress } from \"@zoralabs/coins\";\nimport { Address } from \"viem\";\nimport { base } from \"viem/chains\";\n\n// this is the same across all chains due to deterministic deploys.\nexport const COIN_FACTORY_ADDRESS = zoraFactoryImplAddress[\"8453\"] as Address;\n\nexport const SUPERCHAIN_WETH_ADDRESS = '0x4200000000000000000000000000000000000006';\n\nexport const USDC_WETH_POOLS_BY_CHAIN: Record<number, Address> = {\n [base.id]: '0xd0b53D9277642d899DF5C87A3966A349A798F224',\n}\n","import { PublicClient } from \"viem\"\nimport { base, baseSepolia } from \"viem/chains\"\n\nexport const validateClientNetwork = (publicClient: PublicClient) => {\n const clientChainId = publicClient?.chain?.id;\n if (clientChainId === base.id) {\n return;\n }\n if (clientChainId === baseSepolia.id) {\n return;\n }\n\n throw new Error('Client network needs to be base or baseSepolia for current coin deployments.');\n}","import { coinABI } from \"@zoralabs/coins\";\nimport { validateClientNetwork } from \"src/utils/validateClientNetwork\";\nimport {\n Address,\n PublicClient,\n TransactionReceipt,\n WalletClient,\n SimulateContractParameters,\n parseEther,\n zeroAddress,\n ContractEventArgsFromTopics,\n parseEventLogs,\n} from \"viem\";\nimport { baseSepolia } from \"viem/chains\";\n\n// Define trade event args type\n\nexport type SellEventArgs = ContractEventArgsFromTopics<\n typeof coinABI,\n \"CoinSell\"\n>;\nexport type BuyEventArgs = ContractEventArgsFromTopics<\n typeof coinABI,\n \"CoinBuy\"\n>;\n\nexport type TradeEventArgs = SellEventArgs | BuyEventArgs;\n\n/**\n * Simulates a buy order to get the expected output amount\n * @param {Object} params - The simulation parameters\n * @param {Address} params.target - The target coin contract address\n * @param {bigint} params.requestedOrderSize - The desired input amount for the buy\n * @param {PublicClient} params.publicClient - The viem public client instance\n * @returns {Promise<{orderSize: bigint, amountOut: bigint}>} The simulated order size and output amount\n */\nexport async function simulateBuy({\n target,\n requestedOrderSize,\n publicClient,\n}: {\n target: Address;\n requestedOrderSize: bigint;\n publicClient: PublicClient;\n}): Promise<{ orderSize: bigint; amountOut: bigint }> {\n const numberResult = await publicClient.simulateContract({\n address: target,\n abi: coinABI,\n functionName: \"buy\",\n args: [\n zeroAddress,\n requestedOrderSize,\n 0n, // minAmountOut\n 0n, // sqrtPriceLimitX96\n zeroAddress, // tradeReferrer\n ],\n stateOverride: [\n {\n address: baseSepolia.contracts.multicall3.address,\n balance: parseEther(\"100000\"),\n },\n ],\n });\n const orderSize = numberResult.result[0];\n const amountOut = numberResult.result[1];\n return { orderSize, amountOut };\n}\n\n/**\n * Parameters for creating a trade call\n * @typedef {Object} TradeParams\n * @property {'sell' | 'buy'} direction - The trade direction\n * @property {Address} target - The target coin contract address\n * @property {Object} args - The trade arguments\n * @property {Address} args.recipient - The recipient of the trade output\n * @property {bigint} args.orderSize - The size of the order\n * @property {bigint} [args.minAmountOut] - The minimum amount to receive\n * @property {bigint} [args.sqrtPriceLimitX96] - The price limit for the trade\n * @property {Address} [args.tradeReferrer] - The referrer address for the trade\n */\ntype TradeParams = {\n direction: \"sell\" | \"buy\";\n target: Address;\n args: {\n recipient: Address;\n orderSize: bigint;\n minAmountOut?: bigint;\n sqrtPriceLimitX96?: bigint;\n tradeReferrer?: Address;\n };\n};\n\n/**\n * Creates a trade call parameters object for buy or sell\n * @param {TradeParams} params - The trade parameters\n * @returns {SimulateContractParameters} The contract call parameters\n */\nexport function tradeCoinCall({\n target,\n direction,\n args: {\n recipient,\n orderSize,\n minAmountOut = 0n,\n sqrtPriceLimitX96 = 0n,\n tradeReferrer = zeroAddress,\n },\n}: TradeParams): SimulateContractParameters {\n return {\n abi: coinABI,\n functionName: direction,\n address: target,\n args: [\n recipient,\n orderSize,\n minAmountOut,\n sqrtPriceLimitX96,\n tradeReferrer,\n ],\n value: direction === \"buy\" ? orderSize : 0n,\n } as const;\n}\n\n/**\n * Gets the trade event from transaction receipt logs\n * @param {TransactionReceipt} receipt - The transaction receipt containing the logs\n * @param {'buy' | 'sell'} direction - The direction of the trade\n * @returns {TradeEventArgs | undefined} The decoded trade event args if found\n */\nexport function getTradeFromLogs(\n receipt: TransactionReceipt,\n direction: \"buy\" | \"sell\",\n): TradeEventArgs | undefined {\n const eventLogs = parseEventLogs({\n abi: coinABI,\n logs: receipt.logs,\n });\n\n if (direction === \"buy\") {\n return eventLogs.find((log) => log.eventName === \"CoinBuy\")?.args;\n }\n return eventLogs.find((log) => log.eventName === \"CoinSell\")?.args;\n}\n\n/**\n * Executes a trade transaction\n * @param {TradeParams} params - The trade parameters\n * @param {PublicClient} publicClient - The viem public client instance\n * @param {WalletClient} walletClient - The viem wallet client instance\n * @returns {Promise<{\n * hash: `0x${string}`,\n * receipt: TransactionReceipt,\n * trade: TradeEventArgs | undefined\n * }>} The transaction result with trade details\n */\nexport async function tradeCoin(\n params: TradeParams,\n walletClient: WalletClient,\n publicClient: PublicClient,\n) {\n validateClientNetwork(publicClient);\n const { request } = await publicClient.simulateContract({\n ...tradeCoinCall(params),\n account: walletClient.account,\n });\n const hash = await walletClient.writeContract(request);\n const receipt = await publicClient.waitForTransactionReceipt({ hash });\n const trade = getTradeFromLogs(receipt, params.direction);\n\n return {\n hash,\n receipt,\n trade,\n };\n}\n","import { coinABI, iUniswapV3PoolABI } from \"@zoralabs/coins\";\nimport {\n SUPERCHAIN_WETH_ADDRESS,\n USDC_WETH_POOLS_BY_CHAIN,\n} from \"src/constants\";\nimport { validateClientNetwork } from \"src/utils/validateClientNetwork\";\nimport {\n Address,\n erc20Abi,\n formatEther,\n isAddressEqual,\n PublicClient,\n zeroAddress,\n} from \"viem\";\n\ntype Slot0Result = {\n sqrtPriceX96: bigint;\n tick: number;\n observationIndex: number;\n observationCardinality: number;\n observationCardinalityNext: number;\n feeProtocol: number;\n unlocked: boolean;\n};\n\ntype PricingResult = {\n eth: bigint;\n usdc: bigint | null;\n usdcDecimal: number | null;\n ethDecimal: number;\n};\n\n/**\n * Represents the current state of a coin\n * @typedef {Object} OnchainCoinDetails\n * @property {bigint} balance - The user's balance of the coin\n * @property {PricingResult} marketCap - The market cap of the coin\n * @property {PricingResult} liquidity - The liquidity of the coin\n * @property {Address} pool - Pool address\n * @property {Slot0Result} poolState - Current state of the UniswapV3 pool\n * @property {Address[]} owners - List of owners for the coin\n * @property {Address} payoutRecipient - The payout recipient address\n */\nexport type OnchainCoinDetails = {\n balance: bigint;\n marketCap: PricingResult;\n liquidity: PricingResult;\n pool: Address;\n poolState: Slot0Result;\n owners: readonly Address[];\n payoutRecipient: Address;\n};\n\n/**\n * Gets the current state of a coin for a user\n * @param {Object} params - The query parameters\n * @param {Address} params.coin - The coin contract address\n * @param {Address} params.user - The user address to check balance for\n * @param {PublicClient} params.publicClient - The viem public client instance\n * @returns {Promise<OnchainCoinDetails>} The coin's current state\n */\nexport async function getOnchainCoinDetails({\n coin,\n user = zeroAddress,\n publicClient,\n}: {\n coin: Address;\n user?: Address;\n publicClient: PublicClient;\n}): Promise<OnchainCoinDetails> {\n validateClientNetwork(publicClient);\n const [balance, pool, owners, payoutRecipient] = await publicClient.multicall(\n {\n contracts: [\n {\n address: coin,\n abi: coinABI,\n functionName: \"balanceOf\",\n args: [user],\n },\n {\n address: coin,\n abi: coinABI,\n functionName: \"poolAddress\",\n },\n {\n address: coin,\n abi: coinABI,\n functionName: \"owners\",\n },\n {\n address: coin,\n abi: coinABI,\n functionName: \"payoutRecipient\",\n },\n ],\n allowFailure: false,\n },\n );\n\n const USDC_WETH_POOL = USDC_WETH_POOLS_BY_CHAIN[publicClient.chain?.id || 0];\n\n const [\n coinWethPoolSlot0,\n coinWethPoolToken0,\n coinReservesRaw,\n coinTotalSupply,\n wethReservesRaw,\n usdcWethSlot0,\n ] = await publicClient.multicall({\n contracts: [\n {\n address: pool,\n abi: iUniswapV3PoolABI,\n functionName: \"slot0\",\n },\n {\n address: pool,\n abi: iUniswapV3PoolABI,\n functionName: \"token0\",\n },\n {\n address: coin,\n abi: erc20Abi,\n functionName: \"balanceOf\",\n args: [pool],\n },\n {\n address: coin,\n abi: coinABI,\n functionName: \"totalSupply\",\n },\n {\n address: SUPERCHAIN_WETH_ADDRESS,\n abi: erc20Abi,\n functionName: \"balanceOf\",\n args: [pool],\n },\n {\n address: USDC_WETH_POOL ?? coin,\n abi: iUniswapV3PoolABI,\n functionName: \"slot0\",\n },\n ],\n allowFailure: false,\n });\n\n const wethPriceInUsdc = USDC_WETH_POOL\n ? uniswapV3SqrtPriceToBigIntScaled(\n usdcWethSlot0.sqrtPriceX96,\n 18,\n 6,\n true,\n 18,\n )\n : null;\n\n const coinPriceInWeth = uniswapV3SqrtPriceToBigIntScaled(\n coinWethPoolSlot0.sqrtPriceX96,\n 18,\n 18,\n isAddressEqual(coinWethPoolToken0, coin),\n 18,\n );\n\n // Divide by 10^18 to remove percision from `coinPriceInWeth` after math since bigint is decimal.\n const marketCap = (coinPriceInWeth * coinTotalSupply) / 10n ** 18n;\n\n const wethLiquidity = wethReservesRaw;\n // Divide by 10^18 to remove percision from `coinPriceInWeth` after math since bigint is decimal.\n const tokenLiquidity = (coinReservesRaw * coinPriceInWeth) / 10n ** 18n;\n\n return {\n balance,\n pool,\n owners,\n payoutRecipient,\n marketCap: convertEthOutput(marketCap, wethPriceInUsdc),\n liquidity: convertEthOutput(\n wethLiquidity + tokenLiquidity,\n wethPriceInUsdc,\n ),\n poolState: coinWethPoolSlot0,\n };\n}\n\nfunction convertEthOutput(amountETH: bigint, wethToUsdc: bigint | null) {\n return {\n eth: amountETH,\n ethDecimal: parseFloat(formatEther(amountETH)),\n usdc: wethToUsdc ? amountETH * wethToUsdc : null,\n usdcDecimal: wethToUsdc\n ? parseFloat(formatEther((amountETH * wethToUsdc) / 10n ** 18n))\n : null,\n };\n}\n\nfunction uniswapV3SqrtPriceToBigIntScaled(\n sqrtPriceX96: bigint,\n token0Decimals: number,\n token1Decimals: number,\n isToken0Coin: boolean,\n scaleDecimals: number = 18,\n): bigint {\n // (sqrtPrice^2 / 2^192) => ratio\n // We'll do: ratioScaled = (sqrtPrice^2 * 10^scaleDecimals) / 2^192\n const numerator = sqrtPriceX96 * sqrtPriceX96;\n const denominator = 2n ** 192n;\n const scaleFactor = 10n ** BigInt(scaleDecimals);\n\n // raw ratioScaled\n let ratioScaled = (numerator * scaleFactor) / denominator; // BigInt\n\n // Adjust for difference in decimals:\n // ratioScaled *= 10^(dec0 - dec1)\n const decimalsDiff = BigInt(token0Decimals - token1Decimals);\n if (decimalsDiff > 0n) {\n ratioScaled *= 10n ** decimalsDiff;\n } else if (decimalsDiff < 0n) {\n ratioScaled /= 10n ** -decimalsDiff;\n }\n\n if (!isToken0Coin) {\n // We want the reciprocal: coin is token1 => coinPriceInToken0 = 1 / ratio\n // But we also want it scaled by 10^scaleDecimals\n // reciprocalScaled = (10^scaleDecimals * 10^(decimalsDiff)) / ratioScaled\n // (assuming ratioScaled != 0)\n if (ratioScaled === 0n) {\n return 0n; // or some huge number representing infinity\n }\n ratioScaled = (scaleFactor * scaleFactor) / ratioScaled;\n // or if we already included decimalsDiff above, handle carefully.\n }\n\n return ratioScaled;\n}\n","import { coinABI } from \"@zoralabs/coins\";\nimport { validateClientNetwork } from \"src/utils/validateClientNetwork\";\nimport {\n Address,\n parseEventLogs,\n PublicClient,\n SimulateContractParameters,\n WalletClient,\n} from \"viem\";\n\ntype UpdateCoinURIArgs = {\n coin: Address;\n newURI: string;\n};\n\nexport function updateCoinURICall({\n newURI,\n coin,\n}: UpdateCoinURIArgs): SimulateContractParameters {\n if (!newURI.startsWith(\"ipfs://\")) {\n throw new Error(\"URI needs to be an ipfs:// prefix uri\");\n }\n\n return {\n abi: coinABI,\n address: coin,\n functionName: \"setContractURI\",\n args: [newURI],\n };\n}\n\nexport async function updateCoinURI(\n args: UpdateCoinURIArgs,\n walletClient: WalletClient,\n publicClient: PublicClient,\n) {\n validateClientNetwork(publicClient);\n const call = updateCoinURICall(args);\n const { request } = await publicClient.simulateContract({\n ...call,\n account: walletClient.account!,\n });\n const hash = await walletClient.writeContract(request);\n const receipt = await publicClient.waitForTransactionReceipt({ hash });\n const eventLogs = parseEventLogs({ abi: coinABI, logs: receipt.logs });\n const uriUpdated = eventLogs.find(\n (log) => log.eventName === \"ContractURIUpdated\",\n );\n\n return { hash, receipt, uriUpdated };\n}\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { ClientOptions } from './types.gen';\nimport { type Config, type ClientOptions as DefaultClientOptions, createClient, createConfig } from '@hey-api/client-fetch';\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> = (override?: Config<DefaultClientOptions & T>) => Config<Required<DefaultClientOptions> & T>;\n\nexport const client = createClient(createConfig<ClientOptions>({\n baseUrl: 'https://api-sdk.zora.engineering/'\n}));","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';\nimport type { GetCoinDetailsData, GetCoinDetailsResponse, GetCoinCommentsData, GetCoinCommentsResponse, GetExploreData, GetExploreResponse } from './types.gen';\nimport { client as _heyApiClient } from './client.gen';\n\nexport type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client;\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: Record<string, unknown>;\n};\n\nexport const getCoinDetails = <ThrowOnError extends boolean = false>(options: Options<GetCoinDetailsData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetCoinDetailsResponse, unknown, ThrowOnError>({\n url: '/coinDetails',\n ...options\n });\n};\n\nexport const getCoinComments = <ThrowOnError extends boolean = false>(options: Options<GetCoinCommentsData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetCoinCommentsResponse, unknown, ThrowOnError>({\n url: '/coinComments',\n ...options\n });\n};\n\nexport const getExplore = <ThrowOnError extends boolean = false>(options: Options<GetExploreData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetExploreResponse, unknown, ThrowOnError>({\n url: '/explore',\n ...options\n });\n};","import { getExplore } from \"./sdk.gen\";\nimport type { GetExploreData } from \"./types.gen\";\nimport { Options } from \"@hey-api/client-fetch\";\n\ntype QueryInnerType = {\n query: Omit<GetExploreData[\"query\"], \"listType\">;\n} & Omit<GetExploreData, \"query\">;\n\nexport const getTopGainers = <ThrowOnError extends boolean = false>(\n options?: Options<QueryInnerType, ThrowOnError>,\n) =>\n getExplore({\n ...options,\n query: { ...options?.query, listType: \"TOP_GAINERS\" },\n });\n\nexport const getTopVolume24h = <ThrowOnError extends boolean = false>(\n options?: Options<QueryInnerType, ThrowOnError>,\n) =>\n getExplore({\n ...options,\n query: { ...options?.query, listType: \"TOP_VOLUME_24H\" },\n });\n\nexport const getMostValuable = <ThrowOnError extends boolean = false>(\n options?: Options<QueryInnerType, ThrowOnError>,\n) =>\n getExplore({\n ...options,\n query: { ...options?.query, listType: \"MOST_VALUABLE\" },\n });\n\nexport const getNew = <ThrowOnError extends boolean = false>(\n options?: Options<QueryInnerType, ThrowOnError>,\n) =>\n getExplore({\n ...options,\n query: { ...options?.query, listType: \"NEW\" },\n });\n\nexport const getLastTraded = <ThrowOnError extends boolean = false>(\n options?: Options<QueryInnerType, ThrowOnError>,\n) =>\n getExplore({\n ...options,\n query: { ...options?.query, listType: \"LAST_TRADED\" },\n });\n\nexport const getLastTradedUnique = <ThrowOnError extends boolean = false>(\n options?: Options<QueryInnerType, ThrowOnError>,\n) =>\n getExplore({\n ...options,\n query: { ...options?.query, listType: \"LAST_TRADED_UNIQUE\" },\n });\n"],"mappings":"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","names":["base","parseEventLogs","baseSepolia","parseEventLogs","coinABI","zeroAddress","coinABI","coinABI","parseEventLogs","coinABI"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zoralabs/coins-sdk",
3
- "version": "0.0.2-sdkalpha.2",
3
+ "version": "0.0.2-sdkalpha.3",
4
4
  "repository": "https://github.com/ourzora/zora-protocol",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,13 +22,15 @@
22
22
  }
23
23
  },
24
24
  "dependencies": {
25
+ "@hey-api/client-fetch": "^0.8.3",
25
26
  "@zoralabs/coins": "^0.5.1-sdkalpha.0"
26
27
  },
27
28
  "peerDependencies": {
28
- "viem": "^2.21.55",
29
- "abitype": "^1.0.8"
29
+ "abitype": "^1.0.8",
30
+ "viem": "^2.21.55"
30
31
  },
31
32
  "devDependencies": {
33
+ "@hey-api/openapi-ts": "^0.64.10",
32
34
  "@lavamoat/preinstall-always-fail": "2.0.0",
33
35
  "@types/node": "^20.13.0",
34
36
  "@types/semver": "^7.5.8",
@@ -48,6 +50,7 @@
48
50
  "test:js": "vitest src",
49
51
  "test:integration": "vitest test-integration",
50
52
  "prettier:write": "prettier --write 'src/**/*.ts' 'test-integration/**/*.ts'",
51
- "lint": "prettier --check 'src/**/*.ts' 'test-integration/**/*.ts'"
53
+ "lint": "prettier --check 'src/**/*.ts' 'test-integration/**/*.ts'",
54
+ "api-codegen": "openapi-ts"
52
55
  }
53
56
  }
@@ -90,6 +90,11 @@ export async function createCoin(
90
90
  ...createCoinCall(call),
91
91
  account: walletClient.account,
92
92
  });
93
+
94
+ // Add a 1/5th buffer on gas.
95
+ if (request.gas) {
96
+ request.gas = request.gas * 6n / 5n;
97
+ }
93
98
  const hash = await walletClient.writeContract(request);
94
99
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
95
100
  const deployment = getCoinCreateFromLogs(receipt);
@@ -1,8 +1,17 @@
1
1
  import { coinABI, iUniswapV3PoolABI } from "@zoralabs/coins";
2
- import { SUPERCHAIN_WETH_ADDRESS, USDC_WETH_POOLS_BY_CHAIN } from "src/constants";
2
+ import {
3
+ SUPERCHAIN_WETH_ADDRESS,
4
+ USDC_WETH_POOLS_BY_CHAIN,
5
+ } from "src/constants";
3
6
  import { validateClientNetwork } from "src/utils/validateClientNetwork";
4
- import { Address, erc20Abi, formatEther, isAddressEqual, PublicClient, zeroAddress } from "viem";
5
-
7
+ import {
8
+ Address,
9
+ erc20Abi,
10
+ formatEther,
11
+ isAddressEqual,
12
+ PublicClient,
13
+ zeroAddress,
14
+ } from "viem";
6
15
 
7
16
  type Slot0Result = {
8
17
  sqrtPriceX96: bigint;
@@ -15,15 +24,15 @@ type Slot0Result = {
15
24
  };
16
25
 
17
26
  type PricingResult = {
18
- eth: bigint,
19
- usdc: bigint | null,
20
- usdcDecimal: number | null,
21
- ethDecimal: number,
22
- }
27
+ eth: bigint;
28
+ usdc: bigint | null;
29
+ usdcDecimal: number | null;
30
+ ethDecimal: number;
31
+ };
23
32
 
24
33
  /**
25
34
  * Represents the current state of a coin
26
- * @typedef {Object} CoinDetails
35
+ * @typedef {Object} OnchainCoinDetails
27
36
  * @property {bigint} balance - The user's balance of the coin
28
37
  * @property {PricingResult} marketCap - The market cap of the coin
29
38
  * @property {PricingResult} liquidity - The liquidity of the coin
@@ -32,14 +41,14 @@ type PricingResult = {
32
41
  * @property {Address[]} owners - List of owners for the coin
33
42
  * @property {Address} payoutRecipient - The payout recipient address
34
43
  */
35
- export type CoinDetails = {
44
+ export type OnchainCoinDetails = {
36
45
  balance: bigint;
37
46
  marketCap: PricingResult;
38
47
  liquidity: PricingResult;
39
48
  pool: Address;
40
49
  poolState: Slot0Result;
41
- owners: readonly Address[],
42
- payoutRecipient: Address,
50
+ owners: readonly Address[];
51
+ payoutRecipient: Address;
43
52
  };
44
53
 
45
54
  /**
@@ -48,9 +57,9 @@ export type CoinDetails = {
48
57
  * @param {Address} params.coin - The coin contract address
49
58
  * @param {Address} params.user - The user address to check balance for
50
59
  * @param {PublicClient} params.publicClient - The viem public client instance
51
- * @returns {Promise<CoinDetails>} The coin's current state
60
+ * @returns {Promise<OnchainCoinDetails>} The coin's current state
52
61
  */
53
- export async function getCoinDetails({
62
+ export async function getOnchainCoinDetails({
54
63
  coin,
55
64
  user = zeroAddress,
56
65
  publicClient,
@@ -58,91 +67,108 @@ export async function getCoinDetails({
58
67
  coin: Address;
59
68
  user?: Address;
60
69
  publicClient: PublicClient;
61
- }): Promise<CoinDetails> {
70
+ }): Promise<OnchainCoinDetails> {
62
71
  validateClientNetwork(publicClient);
63
- const [balance, pool, owners, payoutRecipient] = await publicClient.multicall({
72
+ const [balance, pool, owners, payoutRecipient] = await publicClient.multicall(
73
+ {
74
+ contracts: [
75
+ {
76
+ address: coin,
77
+ abi: coinABI,
78
+ functionName: "balanceOf",
79
+ args: [user],
80
+ },
81
+ {
82
+ address: coin,
83
+ abi: coinABI,
84
+ functionName: "poolAddress",
85
+ },
86
+ {
87
+ address: coin,
88
+ abi: coinABI,
89
+ functionName: "owners",
90
+ },
91
+ {
92
+ address: coin,
93
+ abi: coinABI,
94
+ functionName: "payoutRecipient",
95
+ },
96
+ ],
97
+ allowFailure: false,
98
+ },
99
+ );
100
+
101
+ const USDC_WETH_POOL = USDC_WETH_POOLS_BY_CHAIN[publicClient.chain?.id || 0];
102
+
103
+ const [
104
+ coinWethPoolSlot0,
105
+ coinWethPoolToken0,
106
+ coinReservesRaw,
107
+ coinTotalSupply,
108
+ wethReservesRaw,
109
+ usdcWethSlot0,
110
+ ] = await publicClient.multicall({
64
111
  contracts: [
112
+ {
113
+ address: pool,
114
+ abi: iUniswapV3PoolABI,
115
+ functionName: "slot0",
116
+ },
117
+ {
118
+ address: pool,
119
+ abi: iUniswapV3PoolABI,
120
+ functionName: "token0",
121
+ },
65
122
  {
66
123
  address: coin,
67
- abi: coinABI,
124
+ abi: erc20Abi,
68
125
  functionName: "balanceOf",
69
- args: [user],
126
+ args: [pool],
70
127
  },
71
128
  {
72
129
  address: coin,
73
130
  abi: coinABI,
74
- functionName: "poolAddress",
131
+ functionName: "totalSupply",
75
132
  },
76
133
  {
77
- address: coin,
78
- abi: coinABI,
79
- functionName: 'owners',
134
+ address: SUPERCHAIN_WETH_ADDRESS,
135
+ abi: erc20Abi,
136
+ functionName: "balanceOf",
137
+ args: [pool],
80
138
  },
81
139
  {
82
- address: coin,
83
- abi: coinABI,
84
- functionName: 'payoutRecipient',
85
- }
140
+ address: USDC_WETH_POOL ?? coin,
141
+ abi: iUniswapV3PoolABI,
142
+ functionName: "slot0",
143
+ },
86
144
  ],
87
145
  allowFailure: false,
88
146
  });
89
147
 
90
- const USDC_WETH_POOL = USDC_WETH_POOLS_BY_CHAIN[publicClient.chain?.id || 0];
91
-
92
- const [coinWethPoolSlot0, coinWethPoolToken0, coinReservesRaw, coinTotalSupply, wethReservesRaw, usdcWethSlot0] = await publicClient.multicall({
93
- contracts: [{
94
- address: pool,
95
- abi: iUniswapV3PoolABI,
96
- functionName: "slot0",
97
- },
98
- {
99
- address: pool,
100
- abi: iUniswapV3PoolABI,
101
- functionName: 'token0'
102
- }, {
103
- address: coin,
104
- abi: erc20Abi,
105
- functionName: 'balanceOf',
106
- args: [pool],
107
- },
108
- {
109
- address: coin,
110
- abi: coinABI,
111
- functionName: 'totalSupply',
112
- }, {
113
- address: SUPERCHAIN_WETH_ADDRESS,
114
- abi: erc20Abi,
115
- functionName: 'balanceOf',
116
- args: [pool],
117
- }, {
118
- address: USDC_WETH_POOL ?? coin,
119
- abi: iUniswapV3PoolABI,
120
- functionName: 'slot0',
121
- }], allowFailure: false
122
- });
123
-
124
- const wethPriceInUsdc = USDC_WETH_POOL ? uniswapV3SqrtPriceToBigIntScaled(
125
- usdcWethSlot0.sqrtPriceX96,
126
- 18,
127
- 6,
128
- true,
129
- 18
130
- ) : null;
148
+ const wethPriceInUsdc = USDC_WETH_POOL
149
+ ? uniswapV3SqrtPriceToBigIntScaled(
150
+ usdcWethSlot0.sqrtPriceX96,
151
+ 18,
152
+ 6,
153
+ true,
154
+ 18,
155
+ )
156
+ : null;
131
157
 
132
158
  const coinPriceInWeth = uniswapV3SqrtPriceToBigIntScaled(
133
159
  coinWethPoolSlot0.sqrtPriceX96,
134
160
  18,
135
161
  18,
136
162
  isAddressEqual(coinWethPoolToken0, coin),
137
- 18
163
+ 18,
138
164
  );
139
165
 
140
166
  // Divide by 10^18 to remove percision from `coinPriceInWeth` after math since bigint is decimal.
141
- const marketCap = coinPriceInWeth * coinTotalSupply / 10n ** 18n;
167
+ const marketCap = (coinPriceInWeth * coinTotalSupply) / 10n ** 18n;
142
168
 
143
169
  const wethLiquidity = wethReservesRaw;
144
170
  // Divide by 10^18 to remove percision from `coinPriceInWeth` after math since bigint is decimal.
145
- const tokenLiquidity = coinReservesRaw * coinPriceInWeth / 10n ** 18n;
171
+ const tokenLiquidity = (coinReservesRaw * coinPriceInWeth) / 10n ** 18n;
146
172
 
147
173
  return {
148
174
  balance,
@@ -150,14 +176,23 @@ export async function getCoinDetails({
150
176
  owners,
151
177
  payoutRecipient,
152
178
  marketCap: convertEthOutput(marketCap, wethPriceInUsdc),
153
- liquidity: convertEthOutput(wethLiquidity + tokenLiquidity, wethPriceInUsdc),
179
+ liquidity: convertEthOutput(
180
+ wethLiquidity + tokenLiquidity,
181
+ wethPriceInUsdc,
182
+ ),
154
183
  poolState: coinWethPoolSlot0,
155
184
  };
156
185
  }
157
186
 
158
-
159
187
  function convertEthOutput(amountETH: bigint, wethToUsdc: bigint | null) {
160
- return { eth: amountETH, ethDecimal: parseFloat(formatEther(amountETH)), usdc: wethToUsdc ? amountETH * wethToUsdc : null, usdcDecimal: wethToUsdc ? parseFloat(formatEther(amountETH * wethToUsdc / 10n ** 18n)) : null }
188
+ return {
189
+ eth: amountETH,
190
+ ethDecimal: parseFloat(formatEther(amountETH)),
191
+ usdc: wethToUsdc ? amountETH * wethToUsdc : null,
192
+ usdcDecimal: wethToUsdc
193
+ ? parseFloat(formatEther((amountETH * wethToUsdc) / 10n ** 18n))
194
+ : null,
195
+ };
161
196
  }
162
197
 
163
198
  function uniswapV3SqrtPriceToBigIntScaled(
@@ -165,7 +200,7 @@ function uniswapV3SqrtPriceToBigIntScaled(
165
200
  token0Decimals: number,
166
201
  token1Decimals: number,
167
202
  isToken0Coin: boolean,
168
- scaleDecimals: number = 18
203
+ scaleDecimals: number = 18,
169
204
  ): bigint {
170
205
  // (sqrtPrice^2 / 2^192) => ratio
171
206
  // We'll do: ratioScaled = (sqrtPrice^2 * 10^scaleDecimals) / 2^192
@@ -182,7 +217,7 @@ function uniswapV3SqrtPriceToBigIntScaled(
182
217
  if (decimalsDiff > 0n) {
183
218
  ratioScaled *= 10n ** decimalsDiff;
184
219
  } else if (decimalsDiff < 0n) {
185
- ratioScaled /= 10n ** (-decimalsDiff);
220
+ ratioScaled /= 10n ** -decimalsDiff;
186
221
  }
187
222
 
188
223
  if (!isToken0Coin) {