# ZORA Docs ## Agents Use the Zora Coins SDK skill to give your AI agent full context on the Zora Coins Protocol. Add the skill to any tool-use capable LLM and it can help you create, trade, and query coins. ### Quick Start Copy and paste the following prompt into your agent's configuration: ``` Fetch and follow the Zora Coins SDK skill from https://docs.zora.co/skill.md ``` ### What's in the Skill The skill file covers: * **Protocol overview** — Coin types, fee structures, reward distribution * **SDK reference** — Creating, trading, updating, and querying coins with `@zoralabs/coins-sdk` * **REST API** — HTTP endpoints for non-TypeScript languages * **Contract reference** — Factory addresses, deployment functions, hook system * **Links** — Direct links to full documentation for each topic ### Integration #### Claude Code Add to your project's `CLAUDE.md`: ```markdown Fetch and follow the Zora Coins SDK skill from https://docs.zora.co/skill.md ``` #### Cursor Add to `.cursorrules` in your project root: ``` Fetch and follow the Zora Coins SDK skill from https://docs.zora.co/skill.md ``` #### Custom Agents Include the skill URL in your system prompt. The agent needs the ability to fetch URLs and parse markdown. ``` You have access to the Zora Coins SDK. Reference: https://docs.zora.co/skill.md ``` ### Resources * [View the skill file](https://docs.zora.co/skill.md) * [LLM-readable docs index](https://docs.zora.co/llms.txt) * [Getting Started with the SDK](/coins/sdk) ## Zora Coins Protocol The Zora Coins Protocol is a way to participate in the new creator economy—one where users trade on attention, creativity, and cultural momentum. Every post becomes an instantly tradeable cryptocurrency token, transforming social media content into a tradeable asset. This is the first time creators earn across posts, creators, and the platform. **Open, free, and valuable.** ### How It Works Every coin has a **backing currency** and trades through a dedicated Uniswap V4 pool with a custom hook that: * **Protects against sniping** with a [Sniper Tax](/coins/contracts/rewards#early-launch-fee) that decays from 99% over 10 seconds * **Distributes rewards** to creators, referrers, and the protocol on every trade * **Preserves liquidity** by locking 20% of trading fees as permanent pool depth (Creator/Content Coins) * **Converts fees** through multi-hop swaps to ensure all rewards are paid in ZORA * **Deposits initial liquidity** using [Doppler protocol](https://www.doppler.lol/) for optimized multi-curve positioning ### How Coins Work The protocol supports three coin types, each designed for a different use case. #### Creator Coins **Profile-level tokens on Zora** — each account has its own coin where the username becomes the ticker ($username). * **One coin per profile** - Each creator gets a single coin representing their brand * **Fixed supply** - 1 billion total per coin * **50% to creator** - Automatically distributed over 5 years * **50% tradeable** - Instantly available on the open market * **Earn from every trade** - Creators earn $ZORA from trade activity * **1% trading fee** - Split across creator, referrers, protocol, and LP #### Content Coins * **Post-level tokens** - Every post becomes an instantly tradeable coin * **Creator-backed** - Uses the creator's coin as backing currency * **Instant creator allocation** - 10M tokens go directly to creators at launch * **990M tradeable** - Available on the market immediately * **1% trading fee** - Same split as Creator Coins #### Trend Coins **Lightweight tokens for trending topics, memes, and cultural moments** — optimized for high-frequency, low-friction trading. * **Ultra-low fees** - 0.01% (1 bps) trading fee, 100x lower than standard coins * **Sniper Tax** - 99% fee at launch decaying linearly to 0.01% over 10 seconds * **100% liquidity** - Entire 1B supply goes into the pool, no creator allocation * **Unique tickers** - Case-insensitive ticker uniqueness enforced on-chain * **Protocol fees only** - All collected fees go to the protocol Learn more in the [Trend Coins](/coins/contracts/trend-coins) documentation. ![Zora Coins Protocol Overview](/coins-overview.png) ### Token Supply Distribution All coins have a **1 billion token supply** with different allocation strategies: #### CreatorCoin Distribution | Allocation | Amount | Details | | ------------------- | ----------- | --------------------------------- | | **Liquidity Pool** | 500M tokens | Available for trading immediately | | **Creator Vesting** | 500M tokens | Linear vesting over 5 years | | **Total Supply** | 1B tokens | Fixed maximum supply | #### ContentCoin Distribution | Allocation | Amount | Details | | ------------------ | ----------- | --------------------------------- | | **Liquidity Pool** | 990M tokens | Available for trading immediately | | **Creator Reward** | 10M tokens | Instant allocation to creator | | **Total Supply** | 1B tokens | Fixed maximum supply | #### TrendCoin Distribution | Allocation | Amount | Details | | ------------------ | --------- | --------------------------------- | | **Liquidity Pool** | 1B tokens | Full supply available for trading | | **Total Supply** | 1B tokens | Fixed maximum supply | > **Vesting Details**: Creator coins vest linearly over 5 years, meaning creators can claim their tokens gradually using the `claimVesting()` function. ### Developer Resources #### SDK Integration * **[Getting Started](/coins/sdk)** - JavaScript SDK for creating and managing coins * **[Create Coin](/coins/sdk/create-coin)** - Deploy coins programmatically * **[Metadata Builder](/coins/sdk/metadata-builder)** - Generate valid metadata URIs #### Contract Integration * **[Creating a Coin](/coins/contracts/creating-a-coin)** - Deploy coins using the factory contract * **[Contract Architecture](/coins/contracts/architecture)** - Deep dive into the protocol design #### Protocol Information * **[Coin Rewards](/coins/contracts/rewards)** - How automatic reward distribution works * **[Earning Rewards as a Developer](/coins/contracts/earning-referral-rewards)** - How to earn referral rewards from coin creation and trading * **[Metadata Standards](/coins/contracts/metadata)** - EIP-7572 metadata format specification ## ZORA Coins License {/* This license text is directly from packages/coins/LICENSE */} All source code specified as: SPDX-Identifier: ZORA-DELAYED-OSL-v1 follows this license. Other licenses are specified on a file by file basis #### Definitions: "Licensed Work" means the software, code, or content distributed under this License, including any copies or derivative works thereof. "Licensor" means Zora Labs, Inc., a Delaware corporation. "Commercial Purpose" means any use that generates, or is intended to generate, revenue, monetary value, or other commercial benefit, whether through fees, subscriptions, token issuance, staking incentives, or other monetization mechanisms. "Competitive Product" means a Product provided for Commercial Purposes, and provides functionality substantially similar to or substitutable for, in whole or in part, the Licensed Work, and that is made available to third parties directly or indirectly, whether operated independently or as part of a broader offering. "Product" means any software application, protocol, service, or system that (i) makes the Licensed Work (or any derivative work thereof) available for third-party interaction, directly or indirectly, including but not limited to through interfaces, middleware, aggregators, composable integrations, or smart contract deployment; (ii) uses the Licensed Work (or any derivative work thereof) in a production environment or mainnet context; (iii) integrates or incorporates the Licensed Work as part of a broader software or financial service offering; or (iv) is operated for a Commercial Purpose, whether or not publicly accessible. "Open Date" means the earlier of: (i) the third anniversary of the first public distribution of the Licensed Work, and (ii) the date specified by the Licensor as the official date the Licensed Work shall become available under the MIT License. #### Terms: The Licensor hereby grants you a non-exclusive, non-transferable, worldwide, royalty-free license to (i) use, copy, modify, and create derivative works of the Licensed Work; (ii) distribute the Licensed Work (or any derivative works thereof), in each of (i) and (ii), solely for purposes other than (a) Commercial Purposes, or (b) as a Competitive Product. You are not granted rights to, and you may not exploit, the Licensed Work for Commercial Purposes or as a Competitive Product. For the avoidance of doubt, deploying modified versions of the Licensed Work that preserve the core functionality or interface of the Licensed Work shall be considered a derivative work and subject to this License. This License governs your use even if you receive the Licensed Work from a third party, whether in its original form or in a derivative or modified form. You must retain, in all copies and substantial portions of the Licensed Work and in all derivative works, (i) all copyright notices, author credits, and licensing notices included by the Licensor, and (ii) a notice stating, "This software includes original work licensed under the Delayed Open Source License by Zora Labs, Inc." Your rights under this License terminate immediately for all versions of the Licensed Work if you violate its terms. THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK. Effective on the Open Date, the Licensed Work becomes available under the MIT License (attached hereto as Appendix A). #### Contact: To request written consent for unlicensed uses, please contact: [support@zora.co](mailto\:support@zora.co) #### Appendix A – MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Metadata Builder The ZORA SDK supports handling metadata when using an SDK API key. This utilizes ZORA's internal IPFS pinning and delivery infastructure. You are welcome to implement your own uploader or connect another IPFS provider to the uploader infastructure. You'll get performant uploads and more reliable metadata indexing using this service. You also can utilize a `multiUploader` interface to upload to both your own service and ZORA's service. ### Example Usage ```ts twoslash import { createMetadataBuilder, createZoraUploaderForCreator } from "@zoralabs/coins-sdk"; import { Address } from "viem"; const creatorAddress = "0x17cd072cBd45031EFc21Da538c783E0ed3b25DCc"; const { createMetadataParameters } = await createMetadataBuilder() .withName("Test Base ZORA Coin") .withSymbol("TBZC") .withDescription("Test Description") .withImage( new File([/* data for png as bytes or file from user */ ""], "test.png", { type: "image/png" }), ) .upload(createZoraUploaderForCreator(creatorAddress as Address)); // Use this directly with the create coin APIs: // metadata: createMetadataParameters.metadata const metadata = createMetadataParameters.metadata; ``` ### Metadata Validation The metadata builder has basic validation for metadata including: 1. Name, symbol, image are required at minimum. 2. URLs cannot be submitted when files are submitted. 3. Either URLs or Files can be submitted for both media and image. 4. Image mime type is restricted to what displays on zora.co. Errors are fairly specific and emitted as exceptions when using the builder interface usually when calling `validate`. ### Uploader Interface ```ts /** * Result from uploading a file to a storage provider */ export type UploadResult = { url: string; size: number | undefined; mimeType: string | undefined; }; /** * Interface for file uploaders (IPFS, Arweave, etc.) */ export interface Uploader { upload(file: File): Promise; } ``` Any uploader supporting this interface can work with this builder pattern. One key note is only the `url` in the response is required, everything else is optional. ## Coins Queries ### API Queries #### Getting a Specific Coin To fetch detailed information about a specific coin: ```typescript import { getCoin } from "@zoralabs/coins-sdk"; async function fetchCoin() { try { const response = await getCoin({ address: "0xCoinContractAddress", chain: 8453, // Optional: defaults to Base (8453) }); const coin = response.data?.zora20Token; console.log("Coin name:", coin?.name); console.log("Coin symbol:", coin?.symbol); console.log("Total supply:", coin?.totalSupply); console.log("Market cap:", coin?.marketCap); console.log("24h volume:", coin?.volume24h); return response; } catch (error) { console.error("Error fetching coin:", error); throw error; } } ``` #### Getting Multiple Coins To fetch information about multiple coins at once: ```typescript import { getCoins } from "@zoralabs/coins-sdk"; import { Address } from "viem"; async function fetchMultipleCoins() { const response = await getCoins({ coinAddresses: [ "0xFirstCoinAddress" as Address, "0xSecondCoinAddress" as Address, "0xThirdCoinAddress" as Address ], chainId: 8453, // Optional: defaults to Base (8453) }); response.data?.zora20Tokens?.forEach((coin, index) => { console.log(`Coin ${index + 1}:`); console.log(`- Name: ${coin.name}`); console.log(`- Symbol: ${coin.symbol}`); console.log(`- Market Cap: ${coin.marketCap}`); }); return response; } ``` #### Getting Coin Comments To fetch comments for a specific coin: ```typescript import { getCoinComments } from "@zoralabs/coins-sdk"; import { Address } from "viem"; async function fetchCoinComments() { const response = await getCoinComments({ address: "0xCoinContractAddress" as Address, chain: 8453, // Optional: defaults to Base (8453) after: "cursor-value", // Optional: for pagination count: 20, // Optional: number of comments to return }); response.data?.zora20Token?.zoraComments?.edges?.forEach((edge, index) => { console.log(`Comment ${index + 1}:`); console.log(`- Text: ${edge.node.text}`); console.log(`- Created at: ${edge.node.createdAt}`); console.log(`- Author: ${edge.node.author?.handle || edge.node.author?.address}`); }); // For pagination console.log("Next cursor:", response.data?.pagination?.cursor); return response.data; } ``` #### Getting Profile Data To fetch information about a user profile: ```typescript import { getProfile } from "@zoralabs/coins-sdk"; async function fetchProfile() { const response = await getProfile({ address: "0xUserAddress", }); const profile = response.data?.profile; console.log("Profile handle:", profile?.handle); console.log("Profile display name:", profile?.displayName); console.log("Profile bio:", profile?.bio); return profile; } ``` #### Getting Profile Balances To fetch a user's coin balances: ```typescript import { getProfileBalances } from "@zoralabs/coins-sdk"; import { Address } from "viem"; async function fetchProfileBalances() { const response = await getProfileBalances({ address: "0xUserAddress" as Address, after: "cursor-value", // Optional: for pagination count: 20, // Optional: number of balances to return }); response.data?.profile?.balances?.forEach((balance, index) => { console.log(`Balance ${index + 1}:`); console.log(`- Coin: ${balance.token?.name} (${balance.token?.symbol})`); console.log(`- Amount: ${balance.amount?.amountDecimal}`); console.log(`- Value: ${balance.valueUsd}`); }); // For pagination console.log("Next cursor:", response.data?.pagination?.cursor); return response.data; } ``` ### Explore Queries The SDK also provides several exploration queries to discover coins based on different criteria: #### Top Gainers ```typescript import { getCoinsTopGainers } from "@zoralabs/coins-sdk"; async function fetchTopGainers() { try { const response = await getCoinsTopGainers(); response.zora20Tokens?.forEach((coin, index) => { console.log(`Top Gainer ${index + 1}:`); console.log(`- Name: ${coin.name}`); console.log(`- 24h Change: ${coin.marketCapDelta24h}`); }); return response; } catch (error) { console.error("Error fetching top gainers:", error); throw error; } } ``` #### Top 24h Volume ```typescript import { getCoinsTopVolume24h } from "@zoralabs/coins-sdk"; async function fetchTopVolume() { try { const response = await getCoinsTopVolume24h(); response.zora20Tokens?.forEach((coin, index) => { console.log(`Top Volume ${index + 1}:`); console.log(`- Name: ${coin.name}`); console.log(`- 24h Volume: ${coin.volume24h}`); }); return response; } catch (error) { console.error("Error fetching top volume coins:", error); throw error; } } ``` #### Most Valuable Coins ```typescript import { getCoinsMostValuable } from "@zoralabs/coins-sdk"; async function fetchMostValuable() { try { const response = await getCoinsMostValuable(); response.zora20Tokens?.forEach((coin, index) => { console.log(`Most Valuable ${index + 1}:`); console.log(`- Name: ${coin.name}`); console.log(`- Market Cap: ${coin.marketCap}`); }); return response; } catch (error) { console.error("Error fetching most valuable coins:", error); throw error; } } ``` #### New Coins ```typescript import { getCoinsNew } from "@zoralabs/coins-sdk"; async function fetchNewCoins() { try { const response = await getCoinsNew(); response.zora20Tokens?.forEach((coin, index) => { console.log(`New Coin ${index + 1}:`); console.log(`- Name: ${coin.name}`); console.log(`- Created At: ${coin.createdAt}`); }); return response; } catch (error) { console.error("Error fetching new coins:", error); throw error; } } ``` ### Pagination Many API queries support pagination through `after` and `count` parameters. Here's how to implement pagination: ```typescript import { getCoinComments } from "@zoralabs/coins-sdk"; async function paginateThroughComments() { let cursor = null; const allComments = []; const pageSize = 20; do { const response = await getCoinComments({ address: "0xCoinContractAddress", count: pageSize, after: cursor, }); // Add comments to our collection if (response.data?.zora20Token?.zoraComments.edges) { allComments.push(...response.data.zora20Token.zoraComments.edges.map((edge) => edge.node)); } // Update cursor for next page cursor = response.pagination?.cursor; // Break if no more pages if (!cursor) break; } while (true); console.log(`Fetched ${allComments.length} total comments`); return allComments; } ``` #### Creating Coins The Coins SDK provides functions to create new coins on the Zora protocol. #### Overview Creating a coin involves generating calldata through the SDK and sending a transaction that deploys the ERC20 with protocol integrations. Use the high‑level `createCoin` helper to send and wait for the tx, or the low‑level `createCoinCall` to get raw `to/data/value` for your own tx flow. #### Parameters ```ts import { Address } from "viem"; import { CreateConstants, ContentCoinCurrency, StartingMarketCap, } from "@zoralabs/coins-sdk"; type MetadataType = { type: "RAW_URI"; uri: string; // e.g., an IPFS URI }; type CreateCoinArgs = { creator: Address; // Creator address name: string; // Coin name (e.g., "My Awesome Coin") symbol: string; // Ticker (e.g., "MAC") metadata: MetadataType; // Metadata descriptor currency: ContentCoinCurrency; // CREATOR_COIN | CREATOR_COIN_OR_ZORA | ZORA | ETH chainId?: number; // Chain ID to deploy on (defaults to Base mainnet `8453`) startingMarketCap?: StartingMarketCap; // LOW | HIGH (defaults to LOW) platformReferrer?: Address; // Optional referral address additionalOwners?: Address[]; payoutRecipientOverride?: Address; skipMetadataValidation?: boolean; // Skip URI validation (not recommended) }; ``` ##### Metadata * The `metadata.uri` should point to valid metadata as described in the [Metadata](/coins/contracts/metadata) section. * You can use the [Metadata Builder](/coins/sdk/metadata-builder) to upload assets and produce a URI. Example: ```ts twoslash import { Address } from "viem"; import { createMetadataBuilder, createZoraUploaderForCreator, } from "@zoralabs/coins-sdk"; const creatorAddress = "0xYourAddress" as Address; const { createMetadataParameters } = await createMetadataBuilder() .withName("Test ZORA Coin") .withSymbol("TZC") .withDescription("Test Description") .withImage(new File(["FILE"], "test.png", { type: "image/png" })) .upload(createZoraUploaderForCreator(creatorAddress)); // createMetadataParameters can be used to spread in the createCoin call to handle metadata (name, symbol, and uri) ``` ##### Currency ```ts enum ContentCoinCurrencies { CREATOR_COIN = "CREATOR_COIN", CREATOR_COIN_OR_ZORA = "CREATOR_COIN_OR_ZORA", // If no creator coin is deployed, use ZORA ZORA = "ZORA", ETH = "ETH", } ``` Choose the denomination for the coin’s market. Note that `ZORA`, `CREATOR_COIN`, and `CREATOR_COIN_OR_ZORA` are not available on Base Sepolia. ##### Starting Market Cap Starting market cap is the initial liquidity/market configuration for the coin. By default and for most coins on Zora, the starting market cap is `LOW`. If the coin is from a known creator or brand it is recommended to use `HIGH` to prevent sniping in the initial market by setting a higher initial purchase price. ##### Chain ID Provide the exact `chainId` you intend to deploy on (e.g., Base mainnet `8453`). #### Usage ##### High‑level: send transaction and wait for receipt ```ts twoslash import { createCoin, CreateConstants, ContentCoinCurrency, } from "@zoralabs/coins-sdk"; import { Hex, Address, createWalletClient, createPublicClient, http, } from "viem"; import { base } from "viem/chains"; const publicClient = createPublicClient({ chain: base, transport: http(""), }); const walletClient = createWalletClient({ account: "0x" as Hex, chain: base, transport: http(""), }); const args = { creator: "0xYourAddress" as Address, name: "My Awesome Coin", symbol: "MAC", metadata: { type: "RAW_URI" as const, uri: "ipfs://bafy..." }, currency: CreateConstants.ContentCoinCurrencies.ZORA, chainId: base.id, startingMarketCap: CreateConstants.StartingMarketCaps.LOW, platformReferrerAddress: "0xOptionalReferrer" as Address, }; const result = await createCoin({ call: args, walletClient, publicClient, options: { // account: optional override // skipValidateTransaction: false by default }, }); console.log("Transaction hash:", result.hash); console.log("Coin address:", result.address); console.log("Deployment details:", result.deployment); console.log("Chain info:", result.chain); ``` ##### Response Structure The `createCoin` function returns an object with the following properties: ```ts type CreateCoinResult = { hash: string; // Transaction hash receipt: TransactionReceipt; // Full transaction receipt from the blockchain address?: string; // Deployed coin contract address (extracted from logs) deployment?: { // Detailed deployment information from CoinCreatedV4 event coin: string; // Coin contract address creator: string; // Creator address poolAddress: string; // Uniswap pool address // ... additional deployment details }; chain: Chain; // Chain object (e.g., base, baseSepolia) }; ``` **Key Fields:** * `address`: The newly deployed coin's contract address - use this to interact with the coin * `hash`: Transaction hash for tracking the deployment transaction * `receipt`: Full transaction receipt containing all logs and events * `deployment`: Complete deployment details parsed from the `CoinCreatedV4` event, including pool information * `chain`: Chain configuration object for the network where the coin was deployed ##### Low‑level: integrate with WAGMI using a raw transaction `createCoinCall` returns an object with transaction parameters and the predicted coin address: ```ts type CreateCoinCallResponse = { calls: Array<{ to: Address; // Target contract address (coin factory) data: Hex; // Encoded function call data value: bigint; // ETH value to send (typically 0n for coin creation) }>; predictedCoinAddress: Address; // Deterministic address where coin will be deployed }; ``` The `calls` array contains the transaction parameters that can be passed to your tx‑sending flow (e.g., WAGMI `useSendTransaction`). The `predictedCoinAddress` provides the coin's address before the transaction is sent, allowing immediate UI updates or address storage. ```tsx import * as React from "react"; import { createCoinCall, CreateConstants } from "@zoralabs/coins-sdk"; import { Address } from "viem"; import { useSendTransaction } from "wagmi"; import { base } from "viem/chains"; function CreateCoinButton() { const { sendTransaction, status } = useSendTransaction(); const [coinAddress, setCoinAddress] = React.useState
(null); const handleCreate = async () => { const args = { creator: "0xYourAddress" as Address, name: "My Awesome Coin", symbol: "MAC", metadata: { type: "RAW_URI" as const, uri: "ipfs://bafy..." }, currency: CreateConstants.ContentCoinCurrencies.ZORA, chainId: base.id, startingMarketCap: CreateConstants.StartingMarketCaps.LOW, }; const { calls, predictedCoinAddress } = await createCoinCall(args); // Store predicted address immediately for UI updates setCoinAddress(predictedCoinAddress); console.log("Coin will be deployed at:", predictedCoinAddress); // Send transaction with the first call parameters sendTransaction({ to: calls[0].to, data: calls[0].data, value: calls[0].value, }); }; return (
{coinAddress &&

Coin address: {coinAddress}

}
); } ``` #### Metadata Validation By default, the SDK validates `metadata.uri` content. You can disable with `skipMetadataValidation: true` if you already ensured validity. ```ts import { validateMetadataURIContent } from "@zoralabs/coins-sdk"; // Optional manual validation await validateMetadataURIContent("ipfs://..."); ``` #### Getting Coin Address from Transaction Receipt Once the transaction is confirmed, extract the deployed coin address from logs using `getCoinCreateFromLogs`. This is already done for you in the high‑level `createCoin` function. ```ts import { getCoinCreateFromLogs } from "@zoralabs/coins-sdk"; const coinDeployment = getCoinCreateFromLogs(receipt); console.log("Deployed coin address:", coinDeployment?.coin); ``` #### More Information See [Creating a Coin](/coins/contracts/creating-a-coin) and [Contract Architecture](/coins/contracts/architecture) for protocol‑level details. ## Coins SDK ### Getting started The Coins SDK is a library that allows you to create, manage, and query data for Zora coins. Most features available on the Zora product on web and native mobile apps are available in the SDK and API. ### Installation This SDK is designed to work with both client and server environments running both js and typescript. The SDK can be installed from NPM by running: :::code-group ```bash [npm] npm install @zoralabs/coins-sdk ``` ```bash [pnpm] pnpm install @zoralabs/coins-sdk ``` ```bash [yarn] yarn add @zoralabs/coins-sdk ``` ```bash [bun] bun add @zoralabs/coins-sdk ``` ::: Additionally, the SDK requires `viem` to be installed as a peer dependency: :::code-group ```bash [npm] npm install viem ``` ```bash [pnpm] pnpm install viem ``` ```bash [yarn] yarn add viem ``` ```bash [bun] bun add viem ``` ::: On-chain write operations will not work without `viem` installed. ### Usage The SDK integrates with `fetch` and `viem` for on-chain interactions and writes. It can be used on both client and server environments. ### API Key The Coins SDK should be used with an API key to prevent rate limiting and unlock all features. The API key can be set using the `setApiKey` function: ```ts twoslash import { setApiKey } from "@zoralabs/coins-sdk"; // Set up your API key before making any SDK requests setApiKey("your-api-key-here"); ``` To obtain an API key: 1. Log in or create an account on [Zora](https://zora.co) 2. Navigate to [Developer Settings](https://zora.co/settings/developer) 3. Create an API key For REST API usage from other programming languages, see the [Public REST API documentation](/coins/sdk/public-rest-api). ## Public REST API The Coins SDK provides a REST API that can be accessed from any programming language that supports HTTP requests. This allows developers to query coin data, profile information, and market metrics without needing to use JavaScript. ### API Documentation Full interactive API documentation with a dynamic editor and OpenAPI definition file is available at: **[https://api-sdk.zora.engineering/docs](https://api-sdk.zora.engineering/docs)** The documentation includes: * Interactive API explorer * Request/response examples * OpenAPI specification download * Real-time testing capabilities ### Authentication #### API Key Setup Authentication is strongly recommended for all API requests to prevent rate limiting and ensure reliability in production environments. To obtain an API key: 1. Log in or create an account on [Zora](https://zora.co) 2. Navigate to [Developer Settings on Zora](https://zora.co/settings/developer) 3. Create an API key 4. Use the API key in the `api-key` header with all requests #### Using the API Key Include the API key in the request header: ```bash curl -H "api-key: your-api-key-here" \ https://api-sdk.zora.engineering/api/endpoint ``` ### API Endpoints The REST API provides the same functionality as the SDK functions. The API paths and function names map directly to the SDK functions documented in [Coin Queries](/coins/sdk/queries). #### Main Endpoint Categories 1. **Coin Data**: Retrieve information about specific coins including metadata, market data, and comments 2. **Profile Data**: Access user/wallet information including holdings and activity 3. **Explore Data**: Discover coins through curated lists (new, trending, top gainers, etc.) #### Example Request ```bash # Get coin information curl -H "api-key: your-api-key-here" \ "https://api-sdk.zora.engineering/coin?address=0xCoinContractAddress&chain=8453" ``` ```bash # Get profile balances curl -H "api-key: your-api-key-here" \ "https://api-sdk.zora.engineering/profile?identifier=0xUserAddress" ``` ### Using with Different Languages #### Python Example ```python import requests API_KEY = "your-api-key-here" BASE_URL = "https://api-sdk.zora.engineering/api" headers = { "api-key": API_KEY } # Get coin data response = requests.get( f"{BASE_URL}/coin", headers=headers, params={ "address": "0xCoinContractAddress", "chain": 8453 } ) coin_data = response.json() print(coin_data) ``` #### Go Example ```go package main import ( "encoding/json" "fmt" "io" "net/http" ) const ( APIKey = "your-api-key-here" BaseURL = "https://api-sdk.zora.engineering/api" ) func getCoin(address string, chain int) (map[string]interface{}, error) { url := fmt.Sprintf("%s/coin?address=%s&chain=%d", BaseURL, address, chain) req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } req.Header.Set("api-key", APIKey) client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } var result map[string]interface{} err = json.Unmarshal(body, &result) return result, err } ``` #### Ruby Example ```ruby require 'net/http' require 'json' require 'uri' API_KEY = 'your-api-key-here' BASE_URL = 'https://api-sdk.zora.engineering/api' def get_coin(address, chain = 8453) uri = URI("#{BASE_URL}/coin") uri.query = URI.encode_www_form(address: address, chain: chain) request = Net::HTTP::Get.new(uri) request['api-key'] = API_KEY response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end JSON.parse(response.body) end coin_data = get_coin('0xCoinContractAddress') puts coin_data ``` ### Rate Limiting Without an API key, requests are subject to high rate limiting. Using an API key significantly increases the available rate limit for users. If your use case exceeds this, please contact the team and discuss enterprise access. ### Related Documentation * [Coin Queries](/coins/sdk/queries) - Complete reference for all available queries * [SDK Getting Started](/coins/sdk) - Using the JavaScript/TypeScript SDK * [Interactive API Docs](https://api-sdk.zora.engineering/docs) - Test and explore the API ## Trading Coins The Coins SDK provides powerful trading functionality through the `tradeCoin` function, which enables swapping between ETH and ERC20 tokens (including Creator Coins) using Externally Owned Accounts (EOAs) with permit signatures for secure, gasless approvals. ### Overview The `tradeCoin` function supports: * **ETH ↔ ERC20 token swaps** with semi-automatic routing * **Creator Coin ↔ Creator Coin swaps** with semi-automatic routing * **Content Coin ↔ Creator Coin swaps** with semi-automatic routing * **ERC20 ↔ ERC20 token swaps** using permit signatures * **Permit-based approvals** (via permit2) for secure token spending without separate approval transactions * **Slippage protection** and customizable trade parameters * **EOA wallet support** with smart wallet support coming soon Currently, only the Base mainnet network is supported. Plans to add base sepolia are coming soon. ### Basic Usage #### Import the Function ```typescript import { tradeCoin, TradeParameters } from "@zoralabs/coins-sdk"; ``` #### Trading ETH for Creator Coins ```typescript import { parseEther } from "viem"; import { privateKeyToAccount } from "viem/accounts"; // Set up your account const account = privateKeyToAccount("0x..."); const tradeParameters: TradeParameters = { sell: { type: "eth" }, buy: { type: "erc20", address: "0x4e93a01c90f812284f71291a8d1415a904957156", // Creator Coin address }, amountIn: parseEther("0.001"), // 0.001 ETH slippage: 0.05, // 5% slippage tolerance sender: account.address, }; const receipt = await tradeCoin({ tradeParameters, walletClient, account, publicClient, }); ``` #### Trading Creator Coin for ETH ```typescript const tradeParameters: TradeParameters = { sell: { type: "erc20", address: "0x4e93a01c90f812284f71291a8d1415a904957156" // Creator Coin address }, buy: { type: "eth" }, amountIn: parseEther("100"), // 100 tokens (adjust decimals as needed) slippage: 0.15, // 15% slippage tolerance sender: account.address, }; const receipt = await tradeCoin({ tradeParameters, walletClient, account, publicClient, }); ``` #### Trading USDC for Creator Coin (with Permits) When trading ERC20 tokens, the function automatically handles permit signatures for secure approvals: ```typescript import { TradeParameters, tradeCoin } from "@zoralabs/coins-sdk"; const tradeParameters: TradeParameters = { sell: { type: "erc20", address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC address }, buy: { type: "erc20", address: "0x9b13358e3a023507e7046c18f508a958cda75f54", // @jacob Creator Coin }, amountIn: BigInt(4 * 10 ** 6), // 4 USDC (6 decimals) slippage: 0.05, // 5% slippage sender: account.address, }; const receipt = await tradeCoin({ tradeParameters, walletClient, account, publicClient, }); ``` #### Trading Between ERC20 Tokens Only Creator Coins, USDC, and ZORA are supported for trading between ERC20 tokens. Content Coins *can* currently be traded when the creator is the same but the current flow requires selling for ZORA, USDC, or ETH, then buying the new coin separately. ```typescript import { TradeParameters, tradeCoin } from "@zoralabs/coins-sdk"; const tradeParameters: TradeParameters = { sell: { type: "erc20", address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC }, buy: { type: "erc20", address: "0x9b13358e3a023507e7046c18f508a958cda75f54", // @jacob Creator Coin }, amountIn: BigInt(4 * 10 ** 6), // 4 USDC (6 decimals) slippage: 0.04, // 4% slippage sender: account.address, }; const receipt = await tradeCoin({ tradeParameters, walletClient, account, publicClient, }); ``` #### Disabling Transaction Validation By default, `tradeCoin` validates transactions before execution. You can disable this for faster execution: ```typescript const receipt = await tradeCoin({ tradeParameters, walletClient, account, publicClient, validateTransaction: false, // Skip validation and gas estimation }); ``` ### Function Signature ```typescript async function tradeCoin({ tradeParameters, walletClient, account, publicClient, validateTransaction = true, }: { tradeParameters: TradeParameters; walletClient: WalletClient; account: Account; publicClient: GenericPublicClient; validateTransaction?: boolean; }) ``` ### Trade Parameters The `TradeParameters` interface supports the following options: ```typescript type TradeParameters = { sell: TradeCurrency; // Token to sell buy: TradeCurrency; // Token to buy amountIn: bigint; // Amount to sell (in token's smallest unit) slippage?: number; // Slippage tolerance (0-0.99, default: 5%) sender: Address; // Sender address (can be smart wallet or EOA) signer?: Address; // Must be EOA, defaults to sender if blank recipient?: Address; // Recipient address (optional, defaults to sender) signatures?: SignatureWithPermit[]; // Pre-signed permits (optional) permitActiveSeconds?: number; // Permit validity duration (optional, defaults to 20 minutes) }; // Trade currency can be ETH or an ERC20 token type TradeCurrency = | { type: "eth" } | { type: "erc20"; address: Address }; ``` ### How Permits Work When trading ERC20 tokens, `tradeCoin` automatically: 1. **Checks existing allowances** for the token being sold 2. **Requests approval** if insufficient allowance exists 3. **Generates permit signatures** using EIP-2612 standard 4. **Signs typed data** with your EOA for secure, gasless approvals 5. **Includes permits** in the trade transaction This eliminates the need for separate approval transactions while maintaining security. ### Direct ETH Calls with createTradeCall For direct ETH trades without the full `tradeCoin` workflow, you can use `createTradeCall`: ```typescript import { createTradeCall } from "@zoralabs/coins-sdk"; // Get trade call data without executing const quote = await createTradeCall(tradeParameters); const walletClient = createWalletClient({/* ... */}); // Execute the call directly const tx = await walletClient.sendTransaction({ to: quote.call.target as Address, data: quote.call.data as Hex, value: BigInt(quote.call.value), account, }); ``` This is useful when you need more control over transaction execution or want to batch multiple operations. This flow does not currently support the permits feature for selling ERC20 tokens. ### Error Handling The function validates parameters and throws descriptive errors: ```typescript // Invalid slippage (must be less than 1.0) const invalidSlippage: TradeParameters = { // ... other parameters slippage: 1.5, // > 1.0 }; // Throws: "Slippage must be less than 1, max 0.99" // Zero amount const zeroAmount: TradeParameters = { // ... other parameters amountIn: BigInt(0), }; // Throws: "Amount in must be greater than 0" ``` ### Smart Wallet Support Smart wallet support is coming soon. Currently, the SDK works with: * ✅ **EOA wallets** (MetaMask, WalletConnect, etc.) * 🔄 **Smart wallets** (coming soon) ### Best Practices 1. **Set appropriate slippage** based on market conditions and token liquidity 2. **Use permit signatures** for ERC20 trades to save gas on approvals 3. **Validate transactions** by keeping `validateTransaction: true` (default) 4. **Handle errors gracefully** with proper try-catch blocks 5. **Test with small amounts** before executing large trades 6. **Account for token decimals** when setting `amountIn` values ### Network Support Currently only supports **Base mainnet**. ## Updating Coins The Coins SDK provides functionality to update existing coin properties. This page details how to update a coin's metadata URI and other properties. ### Overview After creating a coin, you might need to update various properties such as the metadata URI or payout recipient. The SDK provides functions to handle these updates securely. ### Updating Coin URI The most common update you might want to make is changing a coin's metadata URI. ### Access Control It's important to note that update functions like `updateCoinURI` and `setPayoutRecipient` can only be called by the coin's owner(s). If the account used to sign the transaction is not an owner, the transaction will revert with an `OnlyOwner` error. ### URI Requirements The `newURI` parameter must meet these requirements: 1. It is recommended to point to an `ipfs://`, `https://` is also supported but not recommended. 2. It should point to a valid metadata JSON file. If these requirements are not met, the update will fail with an error message. #### Update Coin URI Parameters ```ts twoslash import { Address } from "viem"; type UpdateCoinURIArgs = { coin: Address; // The coin contract address newURI: string; // The new URI for the coin metadata (must start with "ipfs://") }; ``` #### Basic URI Update ```ts twoslash import { updateCoinURI } from "@zoralabs/coins-sdk"; import { createWalletClient, createPublicClient, http } from "viem"; import { base } from "viem/chains"; import { Address, Hex } from "viem"; // Set up viem clients const publicClient = createPublicClient({ chain: base, transport: http(""), }); const walletClient = createWalletClient({ account: "0x" as Hex, chain: base, transport: http(""), }); // Define update parameters const updateParams = { coin: "0xCoinContractAddress" as Address, newURI: "ipfs://bafkreihz5knnvvsvmaxlpw3kout23te6yboquyvvs72wzfulgrkwj7r7dm", }; // Execute the update async function updateCoinMetadata() { const result = await updateCoinURI(updateParams, walletClient, publicClient); console.log("Transaction hash:", result.hash); console.log("URI updated event:", result.uriUpdated); return result; } ``` #### Using with WAGMI If you're using WAGMI in your frontend application, you can use the lower-level `updateCoinURICall` function: ```typescript import { updateCoinURICall } from "@zoralabs/coins-sdk"; import { useContractWrite, useSimulateContract } from "wagmi"; // Define update parameters const updateParams = { coin: "0xCoinContractAddress", newURI: "ipfs://bafkreihz5knnvvsvmaxlpw3kout23te6yboquyvvs72wzfulgrkwj7r7dm", }; // Create configuration for wagmi const contractCallParams = updateCoinURICall(updateParams); // In your component function UpdateCoinURIComponent() { const { data: config } = useSimulateContract({ ...contractCallParams, }); const { data, status, writeContract } = useContractWrite(config); return ( ); } ``` ### Other Coin Updates #### Updating Payout Recipient After coin creation, the payout recipient (who receives creator rewards) can be updated using the SDK's `updatePayoutRecipient` function: ```ts twoslash import { updatePayoutRecipient } from "@zoralabs/coins-sdk"; import { Address, Hex, createWalletClient, createPublicClient, http } from "viem"; import { base } from "viem/chains"; // Set up viem clients const publicClient = createPublicClient({ chain: base, transport: http(""), }); const walletClient = createWalletClient({ account: "0x" as Hex, // Must be an owner of the coin chain: base, transport: http(""), }); // Update the payout recipient const result = await updatePayoutRecipient({ coin: "0xCoinContractAddress" as Address, newPayoutRecipient: "0xNewPayoutRecipientAddress" as Address, }, walletClient, publicClient); console.log("Transaction hash:", result.hash); console.log("Receipt:", result.receipt); ``` Note: Only owners of the coin can update the payout recipient. If the account used to sign the transaction is not an owner, the transaction will revert with an `OnlyOwner` error. ## Coin Queries The Coins SDK provides several query functions to fetch information about specific coins. This page details the available coin query functions, their parameters, and includes usage examples. ### Available Queries #### getCoin The `getCoin` function retrieves detailed information about a specific coin, including its metadata, market data, and creator information. ##### Parameters ```ts twoslash type GetCoinParams = { address: string; // The coin contract address chain?: number; // Optional: The chain ID (defaults to Base: 8453) }; ``` ##### Usage Example ```ts twoslash // [!include ~/snippets/coins/queries/getCoin.ts] ``` ##### Response Structure The response includes a `data` object containing a `zora20Token` object with the following properties: ```ts twoslash import { GetCoinResponse } from "@zoralabs/coins-sdk"; // The Zora20Token type is imported from the SDK's generated types. // It includes detailed information about a specific coin, such as its metadata, market data, and creator information. type Zora20Token = GetCoinResponse["zora20Token"]; // ^? // ``` **Key Response Fields:** * `platformBlocked`: Boolean indicating whether the coin is blocked on the platform (most applications should exclude blocked coins from visibility) * `creatorProfile.platformBlocked`: Boolean indicating whether the creator's profile is blocked on the platform (most applications should exclude blocked profiles from visibility) * `address`: The coin's contract address * `name`, `symbol`: Coin identification * `marketCap`, `totalSupply`, `volume24h`: Market metrics * `tokenPrice`: Pricing information in USDC and pool token * `creatorProfile`: Profile information for the coin creator, including social accounts and avatar * `mediaContent`: Associated media like images or videos * `uniqueHolders`: Number of unique token holders * `uniswapV4PoolKey`: Uniswap V4 pool configuration details #### getCoins The `getCoins` function retrieves information about multiple coins at once, useful for batch processing or displaying multiple coins. ##### Parameters ```ts twoslash type GetCoinsParams = { coins: { collectionAddress: string; chainId: number; }[]; }; ``` ##### Usage Example ```ts twoslash // [!include ~/snippets/coins/queries/getCoins.ts] ``` ##### Response Structure The response includes a `zora20Tokens` array containing objects with the same structure as the `zora20Token` object in the `getCoin` response. #### getCoinHolders The `getCoinHolders` function retrieves information about who holds a specific coin, including their balances and profile information. ##### Parameters ```ts twoslash type GetCoinHoldersParams = { chainId: number; // The chain ID address: string; // The coin contract address after?: string; // Optional: Pagination cursor for fetching next page count?: number; // Optional: Number of holders to return per page }; ``` ##### Usage Example ```ts twoslash import { getCoinHolders } from "@zoralabs/coins-sdk"; const response = await getCoinHolders({ chainId: 8453, // Base mainnet address: "0x1234567890123456789012345678901234567890", count: 20, // Get first 20 holders }); if (response.data?.zora20Token?.tokenBalances) { const holders = response.data.zora20Token.tokenBalances.edges; console.log(`Found ${holders.length} holders`); holders.forEach(({ node }) => { console.log(`Address: ${node.ownerAddress}`); console.log(`Balance: ${node.balance}`); console.log(`Profile: ${node.ownerProfile?.handle || "No profile"}`); }); } ``` ##### Response Structure The response includes holder information with balances and profile data, plus pagination support. #### getCoinSwaps The `getCoinSwaps` function retrieves swap activities for a specific coin, showing buy/sell transactions and trading activity. ##### Parameters ```ts twoslash type GetCoinSwapsParams = { address: string; // The coin contract address chain?: number; // Optional: The chain ID (defaults to Base: 8453) after?: string; // Optional: Pagination cursor for fetching next page first?: number; // Optional: Number of swaps to return per page }; ``` ##### Usage Example ```ts twoslash import { getCoinSwaps } from "@zoralabs/coins-sdk"; const response = await getCoinSwaps({ address: "0x1234567890123456789012345678901234567890", chain: 8453, // Base mainnet first: 10, // Get first 10 swaps }); if (response.data?.zora20Token?.swapActivities) { const swaps = response.data.zora20Token.swapActivities.edges; console.log(`Found ${swaps.length} swaps`); swaps.forEach(({ node }) => { console.log(`Activity: ${node.activityType}`); // "BUY" or "SELL" console.log(`Amount: ${node.coinAmount}`); console.log(`From: ${node.senderAddress}`); console.log(`Timestamp: ${node.blockTimestamp}`); }); } ``` ##### Response Structure The response includes swap activity data with transaction details, amounts, and user information. #### getCoinComments The `getCoinComments` function retrieves comments associated with a specific coin, useful for displaying community engagement. ##### Parameters ```ts twoslash type GetCoinCommentsParams = { address: string; // The coin contract address chain?: number; // Optional: The chain ID (defaults to Base: 8453) after?: string; // Optional: Pagination cursor for fetching next page count?: number; // Optional: Number of comments to return per page }; ``` ##### Usage Example ```ts twoslash // [!include ~/snippets/coins/queries/getCoinComments.ts] ``` ##### Paginating Through All Comments To fetch all comments for a coin, you can use pagination: ```ts twoslash // [!include ~/snippets/coins/queries/getCoinCommentsPagination.ts] ``` ##### Response Structure The response includes a `comments` array and pagination information: ### Error Handling All query functions follow the same error handling pattern. When an error occurs, the promise is rejected with an error object that includes details about what went wrong. ```ts twoslash // [!include ~/snippets/coins/queries/queryErrors.ts] ``` ## Explore Queries The Coins SDK provides several explore functions to discover coins based on different criteria such as market performance, volume, recency, and creator activity. These queries are useful for building discovery interfaces, trending sections, and leaderboards. #### Queries: * [`getCoinsTopGainers`](#getcoinstopgainers) * [`getCoinsTopVolume24h`](#getcoinstopvolume24h) * [`getCoinsMostValuable`](#getcoinsmostvaluable) * [`getCoinsNew`](#getcoinsnew) * [`getCoinsLastTraded`](#getcoinslasttraded) * [`getCoinsLastTradedUnique`](#getcoinslasttradedunique) * [`getCreatorCoins`](#getcreatorcoins) * [`getMostValuableCreatorCoins`](#getmostvaluablecreatorcoins) * [`getMostValuableCreatorCoins`](#getmostvaluablecreatorcoins) ### Available Explore Queries #### getCoinsTopGainers The `getCoinsTopGainers` function retrieves coins that have increased the most in market cap over the last 24 hours. ##### Parameters ```ts twoslash type ExploreQueryOptions = { after?: string; // Optional: Pagination cursor for fetching next page count?: number; // Optional: Number of coins to return per page (default: 20) }; ``` ##### Usage Example ```ts twoslash import { getCoinsTopGainers } from "@zoralabs/coins-sdk"; async function fetchTopGainers() { const response = await getCoinsTopGainers({ count: 10, // Optional: number of coins per page after: undefined, // Optional: for pagination }); const tokens = response.data?.exploreList?.edges?.map((edge: any) => edge.node); console.log(`Top Gainers (${tokens?.length || 0} coins):`); tokens?.forEach((coin: any, index: number) => { const percentChange = coin.marketCapDelta24h ? `${parseFloat(coin.marketCapDelta24h).toFixed(2)}%` : "N/A"; console.log(`${index + 1}. ${coin.name} (${coin.symbol})`); console.log(` 24h Change: ${percentChange}`); console.log(` Market Cap: ${coin.marketCap}`); console.log(` Volume 24h: ${coin.volume24h}`); console.log('-----------------------------------'); }); // For pagination if (response.data?.exploreList?.pageInfo?.endCursor) { console.log("Next page cursor:", response.data?.exploreList?.pageInfo?.endCursor); } return response; } ``` #### getCoinsTopVolume24h The `getCoinsTopVolume24h` function retrieves coins with the highest trading volume in the last 24 hours. ##### Usage Example ```ts twoslash import { getCoinsTopVolume24h } from "@zoralabs/coins-sdk"; async function fetchTopVolumeCoins() { const response = await getCoinsTopVolume24h({ count: 10, // Optional: number of coins per page after: undefined, // Optional: for pagination }); const tokens = response.data?.exploreList?.edges?.map((edge: any) => edge.node); console.log(`Top Volume Coins (${tokens?.length || 0} coins):`); tokens?.forEach((coin: any, index: number) => { console.log(`${index + 1}. ${coin.name} (${coin.symbol})`); console.log(` Volume 24h: ${coin.volume24h}`); console.log(` Market Cap: ${coin.marketCap}`); console.log(` Holders: ${coin.uniqueHolders}`); console.log('-----------------------------------'); }); // For pagination if (response.data?.exploreList?.pageInfo?.endCursor) { console.log("Next page cursor:", response.data?.exploreList?.pageInfo?.endCursor); } return response; } ``` #### getCoinsMostValuable The `getCoinsMostValuable` function retrieves coins with the highest market capitalization. ##### Usage Example ```ts twoslash import { getCoinsMostValuable } from "@zoralabs/coins-sdk"; async function fetchMostValuableCoins() { const response = await getCoinsMostValuable({ count: 10, // Optional: number of coins per page after: undefined, // Optional: for pagination }); console.log(`Most Valuable Coins (${response.data?.exploreList?.edges?.length || 0} coins):`); response.data?.exploreList?.edges?.forEach((coin: any, index: number) => { console.log(`${index + 1}. ${coin.node.name} (${coin.node.symbol})`); console.log(` Market Cap: ${coin.node.marketCap}`); console.log(` Volume 24h: ${coin.node.volume24h}`); console.log(` Created: ${coin.node.createdAt}`); console.log('-----------------------------------'); }); // For pagination if (response.data?.exploreList?.pageInfo?.endCursor) { console.log("Next page cursor:", response.data?.exploreList?.pageInfo?.endCursor); } return response; } ``` #### getCoinsNew The `getCoinsNew` function retrieves the most recently created coins. ##### Usage Example ```ts twoslash import { getCoinsNew } from "@zoralabs/coins-sdk"; async function fetchNewCoins() { const response = await getCoinsNew({ count: 10, // Optional: number of coins per page after: undefined, // Optional: for pagination }); console.log(`New Coins (${response.data?.exploreList?.edges?.length || 0} coins):`); response.data?.exploreList?.edges?.forEach((coin: any, index: number) => { // Format the creation date for better readability const creationDate = new Date(coin.node.createdAt || ""); const formattedDate = creationDate.toLocaleString(); console.log(`${index + 1}. ${coin.node.name} (${coin.node.symbol})`); console.log(` Created: ${formattedDate}`); console.log(` Creator: ${coin.node.creatorAddress}`); console.log(` Market Cap: ${coin.node.marketCap}`); console.log('-----------------------------------'); }); // For pagination if (response.data?.exploreList?.pageInfo?.endCursor) { console.log("Next page cursor:", response.data?.exploreList?.pageInfo?.endCursor); } return response; } ``` #### getCoinsLastTraded The `getCoinsLastTraded` function retrieves coins that have been traded most recently. ##### Usage Example ```ts twoslash import { getCoinsLastTraded } from "@zoralabs/coins-sdk"; async function fetchLastTradedCoins() { const response = await getCoinsLastTraded({ count: 10, // Optional: number of coins per page after: undefined, // Optional: for pagination }); console.log(`Recently Traded Coins (${response.data?.exploreList?.edges?.length || 0} coins):`); response.data?.exploreList?.edges?.forEach((coin: any, index: number) => { console.log(`${index + 1}. ${coin.node.name} (${coin.node.symbol})`); console.log(` Market Cap: ${coin.node.marketCap}`); console.log(` Volume 24h: ${coin.node.volume24h}`); console.log('-----------------------------------'); }); // For pagination if (response.data?.exploreList?.pageInfo?.endCursor) { console.log("Next page cursor:", response.data?.exploreList?.pageInfo?.endCursor); } return response; } ``` #### getCoinsLastTradedUnique The `getCoinsLastTradedUnique` function retrieves coins that have been traded by unique traders most recently. ##### Usage Example ```ts twoslash import { getCoinsLastTradedUnique } from "@zoralabs/coins-sdk"; async function fetchLastTradedUniqueCoins() { const response = await getCoinsLastTradedUnique({ count: 10, // Optional: number of coins per page after: undefined, // Optional: for pagination }); console.log(`Recently Traded Coins by Unique Traders (${response.data?.exploreList?.edges?.length || 0} coins):`); response.data?.exploreList?.edges?.forEach((coin: any, index: number) => { console.log(`${index + 1}. ${coin.node.name} (${coin.node.symbol})`); console.log(` Market Cap: ${coin.node.marketCap}`); console.log(` Volume 24h: ${coin.node.volume24h}`); console.log(` Unique Holders: ${coin.node.uniqueHolders}`); console.log('-----------------------------------'); }); // For pagination if (response.data?.exploreList?.pageInfo?.endCursor) { console.log("Next page cursor:", response.data?.exploreList?.pageInfo?.endCursor); } return response; } ``` #### getCreatorCoins Retrieves coins launched by new creators. ```ts twoslash import { getCreatorCoins } from "@zoralabs/coins-sdk"; async function fetchCreatorCoins() { const response = await getCreatorCoins({ count: 10, }); const tokens = response.data?.exploreList?.edges?.map((edge: any) => edge.node); return tokens; } ``` #### getMostValuableCreatorCoins Retrieves the most valuable creator coins. ```ts twoslash import { getMostValuableCreatorCoins } from "@zoralabs/coins-sdk"; async function fetchMostValuableCreatorCoins() { const response = await getMostValuableCreatorCoins({ count: 10, }); const tokens = response.data?.exploreList?.edges?.map((edge: any) => edge.node); return tokens; } ``` ### Response Structure All explore queries return a similar response structure: ```ts twoslash type Response = { zora20Tokens?: Array<{ // Same structure as the coin object in getCoin response id?: string; name?: string; description?: string; address?: string; symbol?: string; totalSupply?: string; totalVolume?: string; volume24h?: string; createdAt?: string; creatorAddress?: string; marketCap?: string; marketCapDelta24h?: string; chainId?: number; uniqueHolders?: number; // ... other coin properties }>; pagination?: { cursor?: string; // Cursor for the next page }; } ``` ### listType values for `/explore` The underlying `/explore` endpoint supports the following `listType` values via `getExplore`: ```ts type ListType = | "TOP_GAINERS" | "TOP_VOLUME_24H" | "MOST_VALUABLE" | "NEW" | "OLD" | "LAST_TRADED" | "LAST_TRADED_UNIQUE" | "FEATURED" | "FEATURED_VIDEOS" | "NEW_CREATORS" | "MOST_VALUABLE_CREATORS" | "FEATURED_CREATORS"; ``` ### Pagination Most explore queries support pagination to handle large result sets. Here's an example of how to implement pagination to fetch all coins that match a particular explore query: ```ts twoslash import { getCoinsTopGainers } from "@zoralabs/coins-sdk"; async function fetchAllTopGainers() { let allCoins: any[] = []; let cursor = undefined; const pageSize = 20; // Continue fetching until no more pages do { const response = await getCoinsTopGainers({ count: pageSize, after: cursor, }); // Add coins to our collection if (response.data?.exploreList && response.data?.exploreList?.edges?.length || 0 > 0) { allCoins = [...allCoins, ...(response.data?.exploreList?.edges?.map((edge: any) => edge.node) || [])]; } // Update cursor for next page cursor = response.data?.exploreList?.pageInfo?.endCursor; // Break if no more results if (!cursor || response.data?.exploreList?.edges?.length === 0) { break; } } while (true); console.log(`Fetched ${allCoins.length} total top gaining coins`); return allCoins; } ``` {/* ### Trending Section */} ## Coin Queries The Coins SDK provides a comprehensive set of query functions to fetch information about coins, profiles, and related data. ### Overview The query functions are divided into several categories: 1. **[Coin Queries](/coins/sdk/queries/coin)**: Retrieve information on specific coins such as metadata, market data, and comments 2. **[Profile Queries](/coins/sdk/queries/profile)**: Retrieve information associated with users/wallets like holdings and activity 3. **[Explore Queries](/coins/sdk/queries/explore)**: Retrieve information about all coins (new, trending, top gainers, etc.) 4. **[Leaderboard](/coins/sdk/queries/leaderboard)**: Featured creators and weekly trader leaderboard (defaults to current week/year if not specified) ### Using the REST API The Coins SDK can be used from any programming language via the **[Public REST API](/coins/sdk/public-rest-api)**. This includes: * Interactive API documentation with live testing * Authentication with API keys * Code examples in multiple languages (Python, Go, Ruby, etc.) * OpenAPI specification For JavaScript/TypeScript usage, continue reading below. For other languages, see the [Public REST API documentation](/coins/sdk/public-rest-api). ### API Key Setup Before using the API queries in a high-usage production environment, set up an API key: ```ts twoslash import { setApiKey } from "@zoralabs/coins-sdk"; // Set up your API key setApiKey("your-api-key-here"); ``` To obtain an API key: 1. Log in or create an account on [Zora](https://zora.co) 2. Navigate to [Developer Settings](https://zora.co/settings/developer) 3. Create an API key 4. Use the API key in the SDK For detailed authentication instructions and REST API usage, see the [Public REST API documentation](/coins/sdk/public-rest-api). ## Leaderboard Queries The Coins SDK exposes queries for weekly Featured Creators and the Trader Leaderboard. * These queries support optional `year` and `week` parameters. * Weeks use ISO week numbering (starting at 1). * If `year` and `week` are not provided, the current ISO week and year are used. * Passing a specific `year` and `week` retrieves data for that week of that year. ### getFeaturedCreators Retrieves a weekly featured creators list. Supports optional `year`, `week`, and pagination via `first` and `after`. ```ts twoslash import { getFeaturedCreators } from "@zoralabs/coins-sdk"; async function fetchFeaturedCreators() { // If year/week not passed, uses the current week/year by default const response = await getFeaturedCreators({ year: undefined, // optional week: undefined, // optional first: 10, // optional: page size }); return response.data?.traderLeaderboardFeaturedCreators?.edges?.map((e: any) => e.node); } ``` ### getTraderLeaderboard Retrieves the weekly trader leaderboard. Supports optional `year`, `week`, `first`, and `after`. Passing in a `year` and `week` will return the leaderboard for that specific week of the year. If no year or week is passed in, it will return the current week's leaderboard. ```ts twoslash import { getTraderLeaderboard } from "@zoralabs/coins-sdk"; async function fetchTraderLeaderboard() { // Defaults to the current week/year when omitted const response = await getTraderLeaderboard({ year: undefined, // optional week: undefined, // optional first: 10, // optional: page size }); return response.data?.exploreTraderLeaderboard?.edges?.map((e: any) => e.node); } ``` ## Profile Queries The Coins SDK provides several query functions to retrieve information about user profiles and their coin holdings. This page details the available profile query functions, their parameters, and includes usage examples. Queries: * [`getProfile`](#getprofile) * [`getProfileCoins`](#getprofilecoins) * [`getProfileBalances`](#getprofilebalances) ### Available Queries #### getProfile The `getProfile` function retrieves detailed information about a user's profile, including their handle, display name, bio, and profile image. ##### Parameters ```ts twoslash type GetProfileParams = { identifier: string; // The user's wallet address or zora handle }; ``` ##### Usage Example ```ts twoslash // @errors: 2307 import { getProfile } from "@zoralabs/coins-sdk"; async function fetchUserProfile() { const response = await getProfile({ identifier: "0xUserWalletAddress", }); // TODO: fix profile graphql types const profile: any = response?.data?.profile; if (profile) { console.log("Profile Details:"); console.log("- Handle:", profile.handle); console.log("- Display Name:", profile.displayName); console.log("- Bio:", profile.bio); // Access profile image if available if (profile.avatar?.medium) { console.log("- Profile Image:", profile.avatar.medium); } // Access linked wallets if available if ( (profile?.linkedWallets && profile?.linkedWallets?.edges?.length) || 0 > 0 ) { console.log("Linked Wallets:"); profile?.linkedWallets?.edges?.forEach((link: any) => { console.log( `- ${link?.node?.walletType}: ${link?.node?.walletAddress}`, ); }); } // Access Creator Coin if available if (profile?.creatorCoin) { console.log("Creator Coin:"); console.log("- Address:", profile.creatorCoin.address); console.log("- Market Cap:", profile.creatorCoin.marketCap); console.log( "- 24h Market Cap Change:", profile.creatorCoin.marketCapDelta24h, ); } } else { console.log("Profile not found or user has not set up a profile"); } return response; } ``` ##### Response Structure The response includes a `profile` object with the following properties: ```ts twoslash type ProfileData = { profile?: { id?: string; // Globally unique ID for the profile handle?: string; // Username/handle platformBlocked?: boolean; // Whether the profile is blocked on the platform (most applications should exclude blocked profiles from visibility) displayName?: string; // User's display name bio?: string; // User's biography/description username?: string; // Username website?: string; // User's website URL avatar?: { // Profile image data small?: string; // Small version of profile image medium?: string; // Medium version of profile image blurhash?: string; // Blurhash for image loading }; publicWallet?: { // Public wallet information walletAddress?: string; // User's wallet address }; socialAccounts?: { // Connected social accounts (followerCount available for each platform - see API types for details) instagram?: { username?: string; // Instagram username displayName?: string; // Instagram display name followerCount?: number; // Instagram follower count }; tiktok?: { username?: string; // TikTok username displayName?: string; // TikTok display name followerCount?: number; // TikTok follower count }; twitter?: { username?: string; // Twitter/X username displayName?: string; // Twitter/X display name followerCount?: number; // Twitter/X follower count }; farcaster?: { username?: string; // Farcaster username displayName?: string; // Farcaster display name followerCount?: number; // Farcaster follower count id?: string; // Farcaster ID (FID) }; }; linkedWallets?: { // Connected wallets edges?: Array<{ node?: { walletType?: "PRIVY" | "EXTERNAL" | "SMART_WALLET"; walletAddress?: string; }; }>; }; creatorCoin?: { // User's Creator Coin (if they have one) address?: string; // Creator Coin contract address marketCap?: string; // Current market capitalization marketCapDelta24h?: string; // 24-hour market cap change }; }; }; ``` #### getProfileCoins The `getProfileCoins` function retrieves information about coins created by a specific user, including detailed coin metadata and trading information. ##### Parameters ```ts twoslash type GetProfileCoinsParams = { identifier: string; // The user's wallet address or zora handle count?: number; // Optional: Number of coins to return per page (default: 20) after?: string; // Optional: Pagination cursor for fetching next page chainIds?: Array; // Optional: Filter by specific chain IDs platformReferrerAddress?: Array; // Optional: Filter by platform referrer addresses }; ``` ##### Usage Example ```ts twoslash // @errors: 2307 import { getProfileCoins } from "@zoralabs/coins-sdk"; async function fetchUserCreatedCoins() { const response = await getProfileCoins({ identifier: "0xUserWalletAddress", // Can also be zora user profile handle count: 20, // Optional: number of coins per page after: undefined, // Optional: for pagination }); const profile = response.data?.profile; if (profile?.createdCoins) { console.log(`Found ${profile.createdCoins.count} created coins`); profile.createdCoins.edges?.forEach((edge, index) => { const coin = edge.node; console.log(`Coin ${index + 1}:`); console.log("- Name:", coin.name); console.log("- Symbol:", coin.symbol); console.log("- Description:", coin.description); console.log("- Market Cap:", coin.marketCap); console.log("- Total Supply:", coin.totalSupply); console.log("- Unique Holders:", coin.uniqueHolders); if (coin.mediaContent?.previewImage?.medium) { console.log("- Image:", coin.mediaContent.previewImage.medium); } }); } else { console.log("User has not created any coins"); } return response; } ``` ##### Response Structure The response includes a `profile` object containing `createdCoins`: ```ts twoslash type ProfileCoinsData = { profile?: { id?: string; // Globally unique ID for the profile handle?: string; // Username/handle platformBlocked?: boolean; // Whether the profile is blocked on the platform (most applications should exclude blocked profiles from visibility) avatar?: { // Profile avatar previewImage?: { blurhash?: string; // Blurhash for image loading medium?: string; // Medium version of profile image small?: string; // Small version of profile image }; }; createdCoins?: { // Coins created by this user count?: number; // Total number of created coins edges?: Array<{ node?: { id?: string; // Coin ID name?: string; // Coin name symbol?: string; // Trading symbol description?: string; // Coin description address?: string; // Coin contract address platformBlocked?: boolean; // Whether the coin is blocked on the platform (most applications should exclude blocked coins from visibility) chainId?: number; // Chain ID where coin exists totalSupply?: string; // Total supply of the coin totalVolume?: string; // Total trading volume volume24h?: string; // 24-hour trading volume marketCap?: string; // Current market capitalization marketCapDelta24h?: string; // 24h market cap change uniqueHolders?: number; // Number of unique holders createdAt?: string; // Creation timestamp creatorAddress?: string; // Creator's wallet address tokenUri?: string; // Token metadata URI mediaContent?: { // Associated media mimeType?: string; originalUri?: string; previewImage?: { small?: string; medium?: string; blurhash?: string; }; }; uniswapV4PoolKey?: { // Uniswap V4 pool information token0Address?: string; token1Address?: string; fee?: number; tickSpacing?: number; hookAddress?: string; }; uniswapV3PoolAddress?: string; // Uniswap V3 pool address }; }>; pageInfo?: { // Pagination information hasNextPage?: boolean; // Whether more results exist endCursor?: string; // Cursor for next page }; }; }; }; ``` #### getProfileBalances The `getProfileBalances` function retrieves a list of all coin balances held by a specific user, including the coin details and current value. ##### Parameters ```ts twoslash type GetProfileBalancesParams = { address: string; // The user's wallet address after?: string; // Optional: Pagination cursor for fetching next page count?: number; // Optional: Number of balances to return per page }; ``` ##### Usage Example ```ts twoslash // @errors: 2307 import { getProfileBalances } from "@zoralabs/coins-sdk"; async function fetchUserBalances() { const response = await getProfileBalances({ identifier: "0xUserWalletAddress", // Can also be zora user profile handle count: 20, // Optional: number of balances per page after: undefined, // Optional: for pagination }); const profile: any = response.data?.profile; console.log(`Found ${profile.coinBalances?.length || 0} coin balances`); profile.coinBalances?.forEach((balance: any, index: number) => { console.log(balance); }); // For pagination if (profile.coinBalances?.pageInfo?.endCursor) { console.log("Next page cursor:", profile.coinBalances?.pageInfo?.endCursor); } return response; } ``` ##### Paginating Through All Balances If a user holds many coins, you might need to paginate through all of their balances: ```ts twoslash // @errors: 2307 import { getProfileBalances } from "@zoralabs/coins-sdk"; async function fetchAllUserBalances(userAddress: string) { let allBalances: any[] = []; let cursor = undefined; const pageSize = 20; // Continue fetching until no more pages do { const response = await getProfileBalances({ identifier: userAddress, // UserAddress or zora handle count: pageSize, after: cursor, }); const profile: any = response.data?.profile; // Add balances to our collection if (profile && profile.coinBalances) { allBalances = [ ...allBalances, ...profile.coinBalances.edges.map((edge: any) => edge.node), ]; } // Update cursor for next page cursor = profile?.coinBalances?.pageInfo?.endCursor; // Break if no more results if (!cursor || profile?.coinBalances?.edges?.length === 0) { break; } } while (true); console.log(`Fetched ${allBalances.length} total coin balances`); return allBalances; } ``` ##### Response Structure The response includes a `balances` array and pagination information: ```ts twoslash type Response = { balances?: Array<{ id?: string; // Unique identifier for this balance token?: { // Coin information id?: string; // Coin ID name?: string; // Coin name symbol?: string; // Trading symbol address?: string; // Coin contract address chainId?: number; // Chain ID totalSupply?: string; // Total supply of the coin marketCap?: string; // Current market capitalization volume24h?: string; // 24-hour trading volume createdAt?: string; // Creation timestamp uniqueHolders?: number; // Number of unique holders media?: { // Media associated with the coin previewImage?: string; medium?: string; blurhash?: string; }; }; amount?: { // Balance amount amountRaw?: string; // Raw amount (in base units) amountDecimal?: number; // Decimal representation }; valueUsd?: string; // Estimated USD value timestamp?: string; // Last updated timestamp }>; pagination?: { cursor?: string; // Cursor for the next page }; }; ``` ## Contract Architecture This page provides a technical overview of how the Coins protocol contracts work together to enable coin creation, trading, and automatic reward distribution. ### Architecture Overview ```mermaid classDiagram %% Uniswap V4 Package class IPoolManager { +initialize() +modifyLiquidity() +swap() +take() } %% Factory Package class ZoraFactoryImpl { +deploy(payoutRecipient, owners, uri, name, symbol, poolConfig, platformReferrer, postDeployHook, postDeployHookData, coinSalt) +deployCreatorCoin(payoutRecipient, owners, uri, name, symbol, poolConfig, platformReferrer, coinSalt) +deployTrendCoin(symbol, postDeployHook, postDeployHookData) +coinAddress(msgSender, name, symbol, poolConfig, platformReferrer, coinSalt) +trendCoinAddress(symbol) +coinImpl() +trendCoinImpl() } %% Coins Package class BaseCoinV4 { <> #poolManager: IPoolManager #poolKey: PoolKey +migrateLiquidity() +getPayoutSwapPath() } class CreatorCoin { -currency: ZORA -vestingSchedule: VestingSchedule +claimVesting() +getClaimableAmount() } class ContentCoin { -backingCurrency: CreatorCoin +rewardsDistributionMethodology() } class TrendCoin { -currency: ZORA -fee: 0.01% (1 bps) +initializeTrendCoin() +coinType() Trend } %% Hooks Package class ZoraV4CoinHook { +afterInitialize() +beforeSwap() +afterSwap() -collectFees() -mintLpReward() -_calculateLaunchFee() +_distributeMarketRewards() } class ZORAToken { ZORA Token } %% Inheritance relationships BaseCoinV4 <|-- CreatorCoin BaseCoinV4 <|-- ContentCoin BaseCoinV4 <|-- TrendCoin %% Factory relationships ZoraFactoryImpl ..> CreatorCoin : creates ZoraFactoryImpl ..> ContentCoin : creates ZoraFactoryImpl ..> TrendCoin : creates %% Hook relationships ZoraV4CoinHook --> IPoolManager : uses ZoraV4CoinHook --> BaseCoinV4 : manages rewards %% Pool Manager relationships BaseCoinV4 --> IPoolManager : integrates with CreatorCoin --> ZoraV4CoinHook : uses hook ContentCoin --> ZoraV4CoinHook : uses hook TrendCoin --> ZoraV4CoinHook : uses hook %% Currency relationships ContentCoin --> CreatorCoin : backed by CreatorCoin --> ZORAToken : backed by TrendCoin --> ZORAToken : backed by ``` *Visual overview of how contracts work together in the Zora Coins system* ### Core Components #### Coins Contracts **BaseCoinV4 (Abstract)** * Base implementation for all coin types * Integrates with Uniswap V4 PoolManager * Handles liquidity migration between hook versions * Manages pool key and basic coin functionality **CreatorCoin** * One per creator, backed by ZORA tokens * 1 billion total supply with 5-year vesting schedule * 500M tokens vest to creator, 500M available for trading * 1% trading fee split across creator, referrers, protocol, and LP **ContentCoin** * Multiple per creator, backed by creator's coin * 1 billion total supply with instant creator allocation * 10M tokens to creator immediately, 990M available for trading * 1% trading fee with the same reward split as Creator Coins **[TrendCoin](/coins/contracts/trend-coins)** * Lightweight coins for trending topics and cultural moments * 1 billion total supply, 100% allocated to liquidity pool * No creator allocation, no payout recipient, no platform referrer * 0.01% (1 bps) trading fee — 100x lower than Creator/Content Coins * Sniper Tax: 99% fee at launch decaying to 0.01% over 10 seconds * All fees go to protocol; no LP remint * Unique, case-insensitive tickers enforced on-chain #### Factory Contract **ZoraFactoryImpl** * Deploys new coins with deterministic addresses * Supports custom pool configurations and post-deployment hooks * Creates Uniswap V4 pools automatically with appropriate hook contracts * Provides address prediction before deployment Key functions: * `deploy()` - General coin deployment with full customization * `deployCreatorCoin()` - Simplified Creator Coin deployment * `deployTrendCoin()` - Trend Coin deployment with unique ticker enforcement * `coinAddress()` - Predict deployment address for Content/Creator Coins * `trendCoinAddress()` - Predict deployment address for Trend Coins #### Hook System The protocol uses a unified hook architecture: **BaseZoraV4CoinHook (Abstract)** * Contains all shared hook functionality for both coin types * Implements Uniswap V4 hook interface (`afterSwap`, `afterInitialize`) * Handles pool initialization, fee collection, and currency conversion * Supports migration to new hook versions while preserving liquidity Core functionality: * Collects trading fees from liquidity positions * Splits fees between LP rewards and market rewards * Converts fees to backing currency via multi-hop swaps * Distributes rewards based on coin type via unified logic > History: Prior to v2.3.0 the protocol used two hooks (`ContentCoinHook` and `CreatorCoinHook`). This was consolidated into `ZoraV4CoinHook` for a single, unified implementation. import { ContractAddress } from '@components/ContractAddress' ## Creating a Coin This guide covers how to create coins directly using the ZoraFactory contract. ### Factory Contract Address The ZoraFactory is deployed at the same address across all supported chains: | Chain | Chain ID | Factory Address | | ------------ | -------- | --------------------------------------------------------------------------------------------- | | Base | 8453 | | | Base Sepolia | 84532 | | ### Key Components ```mermaid classDiagram class ZoraFactory { +deploy() +deployCreatorCoin() +deployTrendCoin() } class Coin { +mint() +burn() } class UniswapV4Pool { +swap() +initialize() } class ZoraHook { +afterSwap() +distributeRewards() } ZoraFactory ..> Coin : creates ZoraFactory ..> UniswapV4Pool : initializes UniswapV4Pool --> ZoraHook : uses ZoraHook --> Coin : manages rewards ``` The **Factory** creates coins and sets up Uniswap V4 pools. The **Hook** automatically manages converting fees to rewards and paying out, plus reminting liquidity on every trade. Each **Coin** is configured to have a primary Uniswap pool with a coin pair of its backing currency. It deposits initial liquidity along multicurve positions to obtain optimized price and curve discovery. Initial liquidity positions are configured using the [Doppler protocol](https://whetstone.cc/doppler), which provides sophisticated tooling for optimizing Uniswap V4 position strategies and market curves. ### Deployment Methods #### Using the SDK (Recommended) For most developers, use the [Coins SDK](/coins/sdk/create-coin) which provides a higher-level interface: * **[`createCoin()`](/coins/sdk/create-coin#basic-creation)** - Main function for creating coins with the SDK * **[`createCoinCall()`](/coins/sdk/create-coin#using-with-wagmi)** - Lower-level function for WAGMI integration * **[Metadata Builder](/coins/sdk/metadata-builder)** - Helper for creating valid metadata URIs #### Direct Contract Integration Use the `deploy` function for new deployments when integrating directly with contracts. This method supports deterministic addressing and post-deployment hooks: > **Note**: The `msg.sender` that calls the deployment function is considered the creator of the coin. ```solidity function deploy( address payoutRecipient, address[] memory owners, string memory uri, string memory name, string memory symbol, bytes memory poolConfig, address platformReferrer, address postDeployHook, bytes calldata postDeployHookData, bytes32 coinSalt ) external payable returns (address coin, bytes memory postDeployHookDataOut); ``` #### Creator Coin Deployment For Creator Coins specifically, use the `deployCreatorCoin` function: > **Important**: The `msg.sender` that calls the deployment function is considered the creator. While the protocol technically allows `deployCreatorCoin` to be called multiple times by the same address, the Zora indexer considers only the **first coin created** as the official creator coin for that address. ```solidity function deployCreatorCoin( address payoutRecipient, address[] memory owners, string memory uri, string memory name, string memory symbol, bytes memory poolConfig, address platformReferrer, bytes32 coinSalt ) external returns (address); ``` #### Trend Coin Deployment For Trend Coins, use the `deployTrendCoin` function. Trend Coins have a simplified creation flow with unique, case-insensitive tickers and no creator/referrer parameters: ```solidity function deployTrendCoin( string calldata symbol, address postDeployHook, bytes calldata postDeployHookData ) external payable returns (address coin, bytes memory postDeployHookDataOut); ``` Trend Coin addresses are deterministic based on the ticker — use `trendCoinAddress()` to predict: ```solidity function trendCoinAddress(string calldata symbol) external view returns (address); ``` For full details on Trend Coins (0.01% fee, sniper tax, supply distribution, pool config), see [Trend Coins](/coins/contracts/trend-coins). ### Parameters #### Required Parameters (Content/Creator Coins) * **`payoutRecipient`**: Address that receives creator rewards from trading activity * **`owners`**: Array of addresses with permission to manage the coin (update metadata, change payout recipient) * **`uri`**: Metadata URI for the coin (typically an IPFS URL) * **`name`**: Human-readable name of the coin * **`symbol`**: Trading symbol for the coin (e.g., "MYCOIN") * **`poolConfig`**: Encoded configuration determining coin version and pool parameters * **`platformReferrer`**: Address that receives platform referral rewards (use `address(0)` if none) * **`coinSalt`**: Salt for deterministic deployment (enables predictable addresses) #### Optional Parameters * **`postDeployHook`**: Contract address to call after deployment (use `address(0)` if none) * **`postDeployHookData`**: Data to pass to the post-deployment hook (use empty bytes if none) ### Pool Configuration The `poolConfig` parameter determines the coin type, pool settings, and market curve characteristics. This configuration defines: * **Coin version** - Protocol version for backwards compatibility * **Currency backing** - What token the coin is paired against (ETH, ZORA, or another Creator Coin) * **Liquidity curves** - Multi-curve position ranges for optimized price discovery * **Supply distribution** - How initial supply is allocated across liquidity positions #### Recommended Approach For most use cases, we recommend using our upcoming API endpoints to generate pool configurations. These will provide: * **Validated configurations** - Pre-tested parameter combinations * **Optimal curve settings** - Market-tested liquidity distribution strategies * **Security safeguards** - Protection against parameter manipulation * **Dynamic updates** - Configurations that evolve with market conditions #### Configuration Types * **Creator Coins** - ZORA-backed coins with vesting schedules, optimized for creator economies * **Content Coins** - Flexible backing currency (ETH, ZORA, or Creator Coins), designed for content monetization * **Trend Coins** - ZORA-backed with pre-configured multi-curve pools, 0.01% fee, managed by the factory owner * **Custom Configurations** - Specialized setups for advanced use cases Contact the Zora team for early access to configuration APIs or custom pool parameter consultation. ### Address Prediction You can predict the coin address before deployment using the `coinAddress` function: ```solidity function coinAddress( address msgSender, string memory name, string memory symbol, bytes memory poolConfig, address platformReferrer, bytes32 coinSalt ) external view returns (address); ``` This is useful for: * Preparing integrations before deployment * Verifying deployment parameters * Creating deterministic deployment scripts ### Example Deployment #### Complete Deployment Example ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {IZoraFactory} from "@zoralabs/coins/src/interfaces/IZoraFactory.sol"; import {CoinConfigurationVersions} from "@zoralabs/coins/src/libs/CoinConfigurationVersions.sol"; contract CoinDeployer { address constant FACTORY_ADDRESS = 0x777777751622c0d3258f214F9DF38E35BF45baF3; address constant ZORA_TOKEN_ADDRESS = 0x1111111111166b7FE7bd91427724B487980aFc69; function deployMyCoin() external returns (address coin) { IZoraFactory factory = IZoraFactory(FACTORY_ADDRESS); // Set up coin owners address[] memory owners = new address[](1); owners[0] = msg.sender; // Pool configuration bytes (get from Zora configuration API) bytes memory poolConfig = hex"..."; // Replace with actual configuration bytes // Generate unique salt for deterministic deployment bytes32 salt = keccak256(abi.encodePacked("MyCoin", msg.sender, block.timestamp)); // Deploy the coin (coin, ) = factory.deploy( msg.sender, // payoutRecipient - receives creator rewards owners, // owners - can update metadata/payout "ipfs://your-metadata-hash", // uri - metadata URI "My Creator Coin", // name - full name "MYCOIN", // symbol - trading symbol poolConfig, // poolConfig - pool settings address(0), // platformReferrer - no referrer address(0), // postDeployHook - no post-deploy hook "", // postDeployHookData - empty salt // coinSalt - for deterministic address ); return coin; } } ``` ### Post-Deployment After successful deployment, the coin will: * Be deployed at the predicted address * Have a Uniswap V4 pool created with the singleton hook * Be ready for trading immediately * Begin [distributing rewards on trades automatically](/coins/contracts/rewards) Learn more about [managing coins](/coins/sdk/update-coin) after deployment. ### Events The factory emits different events based on the coin type: #### Content Coins ```solidity event CoinCreatedV4( address indexed caller, address indexed payoutRecipient, address indexed platformReferrer, address currency, string uri, string name, string symbol, address coin, PoolKey poolKey, bytes32 poolKeyHash, string version ); ``` #### Creator Coins ```solidity event CreatorCoinCreated( address indexed caller, address indexed payoutRecipient, address indexed platformReferrer, address currency, string uri, string name, string symbol, address coin, PoolKey poolKey, bytes32 poolKeyHash, string version ); ``` #### Trend Coins ```solidity event TrendCoinCreated( address indexed caller, string symbol, address coin, PoolKey poolKey, bytes32 poolKeyHash, bytes poolConfig, string version ); ``` #### Legacy (V3) Coins ```solidity event CoinCreated( address indexed caller, address indexed payoutRecipient, address indexed platformReferrer, address currency, string uri, string name, string symbol, address coin, address pool, string version ); ``` ### Indexing Guidance * **Why multiple events?** * **`CoinCreated` (legacy)**: Emitted by early releases that used Uniswap V3 and returned a pool address. * **`CoinCreatedV4`**: Emitted for Content Coins on Uniswap V4 and includes a full `PoolKey` plus `poolKeyHash`. * **`CreatorCoinCreated`**: Emitted for Creator Coins on Uniswap V4 and includes the same data shape as `CoinCreatedV4`. * **`TrendCoinCreated`**: Emitted for Trend Coins on Uniswap V4. Has a different shape — keyed by `symbol` instead of `name`/`payoutRecipient`/`platformReferrer`. * **Index all coins**: Indexers should listen to all four events to build a complete list of coins across protocol versions. * **Suggested filter set** * Contract: `ZoraFactoryImpl` * Events: `CoinCreated`, `CoinCreatedV4`, `CreatorCoinCreated`, `TrendCoinCreated` * **Field differences** * Legacy `CoinCreated` returns a `pool` address (Uniswap V3). V4 events return a `PoolKey` and `poolKeyHash` instead of a pool address (pool address is derived by Uniswap V4). * **Normalizing into a single record** * Use common fields across events: `caller`, `payoutRecipient`, `platformReferrer`, `currency`, `uri`, `name`, `symbol`, `coin`, `version`. * For V3: store `poolAddress` from `CoinCreated`. * For V4: store `poolKey` (currencies, fee, tickSpacing, hooks), and `poolKeyHash`. If you need the V4 pool address, derive it using the Uniswap V4 formula from `PoolKey`. * **Coin type identification** * Creator coins are emitted via `CreatorCoinCreated`. * Content coins are emitted via `CoinCreatedV4`. * Trend coins are emitted via `TrendCoinCreated`. * **Example (pseudocode)** ```ts onEvent(evt) { switch (evt.name) { case 'CoinCreated': upsertCoin({ type: 'legacy', coin: evt.args.coin, poolAddress: evt.args.pool, version: evt.args.version, meta: baseFields(evt.args) }); break; case 'CoinCreatedV4': upsertCoin({ type: 'content', coin: evt.args.coin, poolKey: evt.args.poolKey, poolKeyHash: evt.args.poolKeyHash, version: evt.args.version, meta: baseFields(evt.args) }); break; case 'CreatorCoinCreated': upsertCoin({ type: 'creator', coin: evt.args.coin, poolKey: evt.args.poolKey, poolKeyHash: evt.args.poolKeyHash, version: evt.args.version, meta: baseFields(evt.args) }); break; case 'TrendCoinCreated': upsertCoin({ type: 'trend', coin: evt.args.coin, symbol: evt.args.symbol, poolKey: evt.args.poolKey, poolKeyHash: evt.args.poolKeyHash, version: evt.args.version, poolConfig: evt.args.poolConfig }); break; } } ``` ## Earning Rewards as a Developer Earn automatic rewards by facilitating coin creation and trading on the [Zora Coins Protocol](/coins). Developers can earn from both creating coins and facilitating trades, with rewards distributed automatically in the backing currency. ### SDK Integration For the easiest implementation, use the Zora SDK: * [Creating Coins](/coins/sdk/create-coin) - SDK guide for coin creation with referrals * [Trading Coins](/coins/sdk/trade-coin) - SDK guide for trading with referrals ### Reward Types and Distribution There are two types of referral rewards available to developers: #### Platform Referral Rewards * **Set once** during coin creation * **Earns from all future trades** for the coin's entire lifespan * **Sticky** - permanently associated with the coin #### Trade Referral Rewards * **Set per individual swap** * **Earns only from that specific trade** * Can be different for each transaction #### Reward Percentages **For detailed reward percentages and distribution breakdown, see [Coin Rewards](/coins/contracts/rewards).** Both Content Coins and Creator Coins now offer the same referral reward structure (as of version 2.2.0): * **Platform Referral**: 20% of total fees (25% of market rewards) * **Trade Referral**: 4% of total fees (5% of market rewards) This unified structure means developers can earn referral rewards from **both coin types**. ### Technical Implementation #### Platform Referral Setup Set the `platformReferrer` parameter when creating coins to earn from all future trades. This address is permanently set for the coin's entire lifespan: ```solidity // Deploy a Content Coin with create referral address coin = factory.deploy( payoutRecipient, owners, uri, name, symbol, poolConfig, YOUR_PLATFORM_ADDRESS, // 🎯 This address earns platform referral rewards postDeployHook, postDeployHookData, coinSalt ); ``` #### Trade Referral Setup Include your address in the `hookData` parameter when facilitating swaps. Unlike create referrals, trade referrals are set on a per-swap basis. ##### Building Hook Data When executing swaps through Uniswap V4, encode your platform address as the hook data: ```solidity // Encode your platform address as hookData bytes memory hookData = abi.encode(YOUR_PLATFORM_ADDRESS); ``` This `hookData` should be included in your swap parameters when calling the Uniswap V4 router. The hook data tells the Zora Coins hook which address should receive trade referral rewards for that specific swap. ### How Rewards Work * **Automatic Distribution**: Rewards are distributed automatically on every swap - no manual claiming required * **Multi-Hop Conversion**: All rewards are automatically converted to the backing currency (typically ZORA) before distribution * **Immediate Payout**: Rewards are sent directly to recipient addresses with each trade For complete information about reward distribution, fee structures, and economics, see [Coin Rewards](/coins/contracts/rewards). ## Hook Registry A canonical registry of Zora Uniswap V4 hook addresses to discover and track changes. ### Overview * Tracks Uniswap V4 hook contract addresses used by Zora Coins * Onchain lookup of hooks, tags, and versions * Emits events on add/remove (includes tag and version) * `tag` is a label set to distinguish hook types (e.g. `CONTENT` vs `CREATOR`) * `version` is read via `contractVersion()` on the hook contract if it exists ### Deployment import { ContractAddress } from '@components/ContractAddress' | Chain | Chain ID | Hook Contract | Address | | ----- | -------- | ---------------- | ------------------------------------------------------------------------------------- | | Base | 8453 | ZoraHookRegistry | | ### Interface #### Events ```solidity event ZoraHookRegistered(address indexed hook, string tag, string version); event ZoraHookRemoved(address indexed hook, string tag, string version); ``` #### Structs ```solidity struct ZoraHook { address hook; string tag; string version; } ``` #### Read Functions ```solidity function isRegisteredHook(address hook) external view returns (bool); function getHooks() external view returns (ZoraHook[] memory); function getHookAddresses() external view returns (address[] memory); function getHookTag(address hook) external view returns (string memory); function getHookVersion(address hook) external view returns (string memory); ``` ## Hook System The Zora protocol uses a unified Uniswap V4 hook to automatically manage pool interactions and reward distribution for all coin types. ### Overview The hook system uses a single implementation, `ZoraV4CoinHook`, which encapsulates the full logic for pool initialization, fee collection, dynamic fee calculation, multi-hop payout conversion, and reward distribution across all coin types (Content Coins, Creator Coins, and Trend Coins). Previously, two specialized hook contracts were used (`ContentCoinHook` and `CreatorCoinHook`). As of coins v2.3.0, these have been consolidated into the single `ZoraV4CoinHook` for simplicity and maintainability while preserving identical external behavior. ### Inheritance Structure The unified hook centralizes shared functionality and derives reward behavior from coin configuration: #### ZoraV4CoinHook Contains all core functionality used by all coin types: **Automated Operations:** * Pool initialization and automatic liquidity position creation * Automatic fee collection from all LP positions on every swap * Dynamic fee calculation via `beforeSwap` (Sniper Tax + coin-type-based base fees) * Multi-hop currency conversion through optimal swap paths * Hook upgrade and [migration support](/coins/contracts/liquidity-migration) * Comprehensive event emission and transaction logging **Technical Features:** * Uniswap V4 `beforeSwap`, `afterInitialize`, and `afterSwap` hook permissions * Doppler multi-curve liquidity positioning * Trusted message sender validation * Pool-to-coin mapping and position tracking **Dynamic Fee Logic:** The hook uses `beforeSwap` to calculate per-swap fees based on coin type and age: * **First 10 seconds** (all coin types): Sniper Tax — 99% decaying linearly to the base fee * **After 10 seconds**: Base fee by coin type — 1% for Creator/Content Coins, 0.01% for [Trend Coins](/coins/contracts/trend-coins) Reward distribution is unified and determined at runtime from the coin type via `CoinRewardsV4`. **Key Insight**: Logic that was previously split across two hooks is now implemented in one place; fee calculation and reward behavior are selected based on the coin type and configuration. ### Deployment Addresses import { ContractAddress } from '@components/ContractAddress' | Chain | Chain ID | Hook Contract | Address | | ----- | -------- | -------------- | ------------------------------------ | | Base | 8453 | ZoraV4CoinHook | See `@zoralabs/protocol-deployments` | ### Hook Permissions The unified hook has the following Uniswap V4 permissions: ```solidity function getHookPermissions() external pure override returns (Hooks.Permissions memory) { return Hooks.Permissions({ beforeInitialize: false, afterInitialize: true, // ✅ Enabled - pool setup and liquidity positioning beforeAddLiquidity: false, afterAddLiquidity: false, beforeRemoveLiquidity: false, afterRemoveLiquidity: false, beforeSwap: true, // ✅ Enabled - dynamic fee calculation (Sniper Tax) afterSwap: true, // ✅ Enabled - fee collection and reward distribution beforeDonate: false, afterDonate: false, beforeSwapReturnDelta: false, afterSwapReturnDelta: false, afterAddLiquidityReturnDelta: false, afterRemoveLiquidityReturnDelta: false }); } ``` ### Core Functionality #### After Initialize Hook When a new pool is initialized, the hook automatically: 1. **Validate Pool Setup**: Ensure the pool is properly configured for the coin type 2. **Create Initial Positions**: Set up liquidity positions based on the coin's configuration 3. **Register Pool**: Link the pool to the appropriate coin contract 4. **Configure Reward Distribution**: Set up the reward distribution mechanism #### After Swap Hook On every swap, the hook automatically: 1. **Collect LP Fees**: Gather accrued fees from all liquidity positions 2. **Convert to Payout Currency**: Swap collected fees through optimal paths 3. **Distribute Rewards**: Allocate rewards based on coin type and configuration 4. **Emit Events**: Log detailed swap and reward information ### Reward Distribution The unified hook implements the same reward distribution mechanism across coin types, with the specific split determined by the coin type via `CoinRewardsV4`. **For detailed reward percentages and distribution breakdown, see [Coin Rewards](/coins/contracts/rewards).** #### Key Details * Content Coins and Creator Coins share a unified 1% fee structure and support platform referral, trade referral, creator, protocol, and Doppler distributions (as of v2.2.0+). A 20% LP remint preserves pool liquidity. * [Trend Coins](/coins/contracts/trend-coins) use a 0.01% (1 bps) fee with 100% of fees going to the protocol. No LP remint is performed. ### Multi-Hop Reward Swapping The hook automatically supports complex swap paths for coins that aren't directly paired with the final payout currency: #### Example: Content Coin → Creator Coin → ZORA 1. **Content Coin fees** automatically collected in Content Coin tokens 2. **First hop**: Content Coin → Creator Coin (backing currency) 3. **Second hop**: Creator Coin → ZORA token (final payout currency) 4. **Distribution**: ZORA tokens automatically distributed to reward recipients This automatically enables complex token economies where Content Coins can be backed by Creator Coins, which are in turn backed by ZORA tokens. ### Liquidity Management The hook automatically manages liquidity positions throughout the pool lifecycle: #### Automatic Position Creation During pool initialization, the hook automatically creates: * **Discovery Positions**: Initial price discovery ranges * **Market Positions**: Main trading ranges * **Multi-Position Support**: Complex liquidity curves with multiple ranges #### Position Structure ```solidity struct LiquidityPosition { int24 tickLower; // Lower price bound int24 tickUpper; // Upper price bound uint128 liquidity; // Liquidity amount uint256 feeGrowthInside0X128; // Fee tracking uint256 feeGrowthInside1X128; // Fee tracking } ``` ### Migration Support The hook supports controlled liquidity migration to enable upgrades to new hook versions while preserving all existing liquidity. **Migration Resources:** * [Complete Migration Guide](/coins/contracts/liquidity-migration) - Step-by-step migration process and security considerations * [Migration Flow Diagram](/coins/contracts/liquidity-migration#how-it-works) - Visual sequence diagram of the migration process * [Migration Events](/coins/contracts/liquidity-migration#events) - Event emission details for tracking migrations ### Events #### Swapped Event ```solidity event Swapped( address indexed sender, address indexed swapSender, bool isTrustedSwapSenderAddress, PoolKey key, bytes32 indexed poolKeyHash, SwapParams params, int128 amount0, int128 amount1, bool isCoinBuy, bytes hookData, uint160 sqrtPriceX96 ); ``` Emitted on every swap with detailed transaction information including: * **sender**: The address that initiated the swap transaction * **swapSender**: The original message sender (may differ from sender if using trusted message senders) * **isTrustedSwapSenderAddress**: Whether the sender is registered as a trusted message sender * **key**: The complete pool key identifying the pool * **poolKeyHash**: Indexed hash of the pool key for efficient filtering * **params**: The swap parameters (amount, direction, etc.) * **amount0/amount1**: The actual token amounts exchanged * **isCoinBuy**: Whether this swap is purchasing the coin (true) or selling it (false) * **hookData**: Additional data passed to the hook (often contains referral information) * **sqrtPriceX96**: The final sqrt price after the swap #### CoinMarketRewardsV4 Event ```solidity event CoinMarketRewardsV4( address coin, address currency, address payoutRecipient, address platformReferrer, address tradeReferrer, address protocolRewardRecipient, address dopplerRecipient, MarketRewardsV4 marketRewards ); ``` Emitted when market rewards are distributed from collected fees, showing exact amounts to each recipient: * **coin**: The coin contract that generated the rewards * **currency**: The currency in which rewards are paid out * **payoutRecipient**: The creator's reward recipient address * **platformReferrer**: Address receiving platform referral rewards * **tradeReferrer**: Address receiving trade referral rewards * **protocolRewardRecipient**: Protocol treasury address * **dopplerRecipient**: Doppler rewards recipient * **marketRewards**: Detailed breakdown of reward amounts for each recipient #### LpReward Event ### Historical Note Prior to v2.3.0, the system used two hooks (`ContentCoinHook` and `CreatorCoinHook`). With the introduction of the unified `ZoraV4CoinHook`, all behavior is consolidated. Existing pools can migrate liquidity using the [liquidity migration](/coins/contracts/liquidity-migration) flow. ```solidity event LpReward( address indexed coin, address indexed currency, uint256 amountCurrency, int24 tick, uint128 liquidity ); ``` Emitted when liquidity provider rewards are reminted back into the pool: * **coin**: The coin contract generating the LP rewards * **currency**: The currency of the reminted LP position * **amountCurrency**: The amount of currency reminted as new liquidity * **tick**: The current pool tick when the reward was reminted * **liquidity**: The amount of liquidity reminted back into the pool This event tracks the portion of collected fees that are automatically reminted as liquidity rather than distributed as market rewards. ## Liquidity Migration The liquidity migration system allows users to upgrade their coins to use new hook versions while preserving all existing liquidity positions. Since both coin contracts and [hooks are immutable smart contracts](/coins/contracts/hook) that cannot be modified once deployed, this migration system enables users to benefit from bug fixes and improvements released by Zora without having to create entirely new coins. ### Overview Both coin contracts and hook contracts are immutable once deployed - they cannot be upgraded or modified. This immutability provides security guarantees but means that improvements, bug fixes, and new features cannot be added to the existing contracts. Liquidity migration gives users control to upgrade their hook logic to access new functionality and improvements. Only coin owners can initiate migrations, and as a security measure, upgrades can only be performed to hooks in registered upgrade paths that have been approved by the Zora team. When a coin migrates from one hook to another, all liquidity positions from the initial market liquidity created on coin initialization are burned and reminted in the new hook, preserving the same liquidity positions as before. This migration system works for both Content Coins and Creator Coins, allowing any coin owner to upgrade their hook implementation. ### How It Works The migration process is initiated by the coin creator and involves interactions between multiple contracts: ```mermaid sequenceDiagram participant Owner as Coin Owner participant Coin as Coin Contract participant OldHook as Current Hook participant UpgradeGate as HookUpgradeGate participant PoolManager as Pool Manager participant NewHook as New Hook Note over UpgradeGate: Prerequisites: Zora team registers upgrade path Note over Owner, NewHook: Migration Process Owner->>Coin: migrateLiquidity(newHook, additionalData) Note right of Owner: Only coin owner can initiate Coin->>OldHook: migrateLiquidity(newHook, poolKey, additionalData) OldHook->>UpgradeGate: Verify upgrade path is registered UpgradeGate-->>OldHook: ✓ Approved OldHook->>PoolManager: Burn all liquidity positions Note right of PoolManager: Collect tokens from burned positions OldHook->>NewHook: initializeFromMigration(burnedPositions, ...) Note right of NewHook: Transfer coins to new hook for liquidity deposits NewHook->>PoolManager: Create new pool and recreate positions Note right of PoolManager: Same liquidity, new hook implementation NewHook-->>OldHook: New pool key OldHook-->>Coin: New pool key Coin->>Coin: Update pool key to point to new hook Coin->>Coin: Emit LiquidityMigrated event Coin-->>Owner: Migration complete ``` ### Events When a migration is successful, the coin contract emits a `LiquidityMigrated` event: ```solidity event LiquidityMigrated( PoolKey oldPoolKey, bytes32 indexed oldPoolKeyHash, PoolKey newPoolKey, bytes32 indexed newPoolKeyHash ); ``` ## Coins Metadata Coins follow the [EIP-7572](https://eips.ethereum.org/EIPS/eip-7572) standard for metadata. This is based off of the `EIP721` and `EIP1155` metadata standards. The metadata URI is specified during [coin deployment](/coins/contracts/creating-a-coin#required-parameters) and can be [updated by coin owners](/coins/sdk/update-coin) after deployment. We have a guide below for recommended format along with ZORA extensions and validator tools: ### Metadata JSON Format Your metadata JSON file should follow this format: ```json { "name": "horse", "description": "boundless energy", "image": "ipfs://bafkreifch6stfh3fn3nqv5tpxnknjpo7zulqav55f2b5pryadx6hldldwe", "properties": { "category": "social" } } ``` Optionally, for non-image assets, the `animation_url` property can be used to link an audio or video file preferably on IPFS. The `content` property extension is an object that contains the mime type and uri of the asset to help with better indexing and is more consistent than the opensea-specific animation\_url field. ```json { "name": "boundless horse", "description": "boundless horse", "image": "ipfs://bafkreifch6stfh3fn3nqv5tpxnknjpo7zulqav55f2b5pryadx6hldldwe", "animation_url": "ipfs://bafybeiatmngyt4wwu6mla27523qk33klxopycomegris3n25y6rcqs27c4", "content": { "mime": "video/mp4", "uri": "ipfs://bafybeiatmngyt4wwu6mla27523qk33klxopycomegris3n25y6rcqs27c4" }, "properties": { "category": "social" } } ``` ### Metadata JSON Validator We have a validator that can be used to check your metadata JSON. The two supported functions are: * `validateMetadata` * `validateMetadataURI` #### validateMetadata This function validates the metadata JSON file. ```ts twoslash import { validateMetadataJSON } from "@zoralabs/coins-sdk"; validateMetadataJSON({ name: "horse", description: "boundless energy", image: 123, foo: "bar" }) ``` This function will throw an error if the metadata is invalid and return `true` if it is valid. #### validateMetadataURI This function validates the metadata URI. ```ts twoslash function assertTrue(condition: boolean) { } // ---cut--- import { validateMetadataURIContent } from "@zoralabs/coins-sdk"; assertTrue(await validateMetadataURIContent("https://theme.wtf/metadata/metadata.json")); // This will throw an error await validateMetadataURIContent("data:foo"); // This will succeed :) await validateMetadataURIContent("ipfs://bafybeigoxzqzbnxsn35vq7lls3ljxdcwjafxvbvkivprsodzrptpiguysy"); ``` This function will throw an error if the metadata URI is invalid and return `true` if it is valid. import { Callout } from "vocs/components"; ## Coin Rewards ### Introduction At Zora, we are passionate about providing the best experience to create and earn onchain. **Coin Rewards** is a split of the Zora fee allowing: * Creators to monetize their work * Developers to earn from facilitating coin creation and trading ### Sniper Tax (Early Launch Fee) All new coins have a **time-based dynamic fee** (Sniper Tax) that protects against sniping bots immediately after creation. The fee decays linearly from **99%** to the coin's base fee over **10 seconds**. #### How It Works The sniper tax starts at 99% and decays linearly to the coin type's base fee: | Time After Creation | Creator/Content Coins | Trend Coins | | ------------------- | --------------------- | ----------- | | 0 seconds | 99% | 99% | | 2.5 seconds | \~74.5% | \~74.5% | | 5 seconds | \~50% | \~50% | | 7.5 seconds | \~25.5% | \~25.5% | | 10+ seconds | 1% | 0.01% | The fee calculation uses a linear decay formula: ``` fee = 99% - (elapsed_seconds / 10) × (99% - 1%) ``` After 10 seconds, the fee settles to the coin type's base rate: * **Creator/Content Coins**: 1% (10,000 pips) * **Trend Coins**: 0.01% / 1 bps (100 pips) #### Key Details * **Initial supply bypass**: When a coin is deployed with an initial supply purchase, that purchase uses the normal 1% fee (not the sniper tax) * **Legacy coins**: Coins created before version 2.5.0 that don't support the `IHasCreationInfo` interface receive the normal 1% fee * **Purpose**: The sniper tax discourages bots from front-running coin launches by making immediate purchases prohibitively expensive The sniper tax applies to all buys and sells in the first 10 seconds after coin creation. After this period, the normal fee structure applies as described below. ### Fee Structure by Coin Type | Coin Type | Base Trading Fee | Sniper Tax | LP Remint | Fee Recipients | | ------------ | ---------------- | ----------------- | --------- | ------------------------------------------------------------- | | Creator Coin | 1% | 99% → 1% / 10s | 20% | Creator, Platform Referral, Trade Referral, Doppler, Protocol | | Content Coin | 1% | 99% → 1% / 10s | 20% | Creator, Platform Referral, Trade Referral, Doppler, Protocol | | Trend Coin | 0.01% (1 bps) | 99% → 0.01% / 10s | None | Protocol (100%) | For detailed Trend Coin documentation, see [Trend Coins](/coins/contracts/trend-coins). ### Coin Trading Rewards (V4) Coin trading rewards for Creator and Content Coins are distributed to the creator, create referral, trade referral, protocol, and doppler. All coins created on the Zora app including web and mobile after June 6th 2025 use the V4 configuration. The latest V4 coins use a UniswapV4 hook to collect fees, swap to a backing currency, and distribute rewards to recipients on every swap. ### How V4 Rewards Work V4 coins generate rewards through a sophisticated automated system that operates on every swap: #### Fee Collection and Distribution When users trade coins, the Uniswap V4 hook automatically: 1. **Collects LP fees** (1% total fees for v2.2.0+) from all liquidity positions 2. **Splits fees** into two parts: * **20% for LP Rewards** - Used to create new liquidity positions * **80% for Market Rewards** - Distributed to stakeholders #### LP Reward Mechanism: Liquidity Preservation The 20% allocated to LP rewards doesn't go to liquidity providers directly. Instead, it's used to **mint new single-sided liquidity positions** that are strategically placed outside the current trading range: * **Token0 fees** → New position created **above** current price (inactive until price moves up) * **Token1 fees** → New position created **below** current price (inactive until price moves down) These positions are essentially **locked and burned** - they don't earn future fees but serve a crucial purpose: **maintaining pool liquidity**. Instead of extracting 20% of fees from the pool, this mechanism keeps them as permanent liquidity, ensuring the pool becomes deeper and more liquid over time. #### Market Reward Distribution The remaining portion of collected fees becomes "market rewards" and is distributed to stakeholders. #### V4 Market Reward Distribution (Current - Since 2.2.0) As of version 2.2.0, the fee structure has been unified with a total fee of 1% on pools (was 3% previously) and consistent distribution across both coin types. All coins with hooks on version 2.2.0 or higher use the unified fee structure. **Existing Coins**: Coins deployed before version 2.2.0 continue to use their original fee structure unless the coin owner migrates their liquidity to a 2.2.0+ hook. Migration to newer hooks adopts the new unified fee structure automatically. For information on liquidity migration, see [Liquidity Migration](/coins/contracts/liquidity-migration). ##### Content Coins & Creator Coins (1% total fee on pools) | Recipient | % of Market Rewards | % of Total Fees | | ----------------- | ------------------- | --------------- | | Creator | 62.5% | 50% | | Platform Referral | 25% | 20% | | Trade Referral | 5% | 4% | | Doppler | 1.25% | 1% | | Protocol | 6.25% | 5% | | ----------------- | ------------------- | --------------- | | LP Rewards | - | 20% | #### Fee Structure Comparison (Pre-2.2.0 vs Current) ##### Content Coins | Recipient | Before (Pre-2.2.0) (3% total fee) | After (2.2.0 and later) (1% total fee) | | ----------------- | --------------------------------- | -------------------------------------- | | | % of Fee | % of Fee | | Creator | 33.33% | 50% | | Platform Referral | 10% | 20% | | Trade Referral | 10% | 4% | | Doppler | 3.33% | 1% | | Protocol | 10% | 5% | | LP Rewards | 33.33% | 20% | ##### Creator Coins | Recipient | Before (3% total fee) | After (1% total fee) | | ----------------- | --------------------- | -------------------- | | | % of Fee | % of Fee | | Creator | 33.33% | 50% | | Platform Referral | - | 20% | | Trade Referral | - | 4% | | Doppler | - | 1% | | Protocol | 33.33% | 5% | | LP Rewards | 33.33% | 20% | #### Trend Coin Rewards (0.01% fee) Trend Coins use a fundamentally different reward model. With a 0.01% (1 bps) trading fee — 100x lower than Creator/Content Coins — and no creator or referral recipients, **100% of collected fees go directly to the protocol**. There is no LP remint for Trend Coins; fees are not recycled back into the pool as liquidity. | Recipient | % of Fees | | --------- | --------- | | Protocol | 100% | #### Multi-Hop Currency Conversion All market rewards are automatically converted to the final backing currency before distribution: ##### Currency Hierarchy * **Content Coins** are paired with **Creator Coins** (configured during [deployment](/coins/contracts/creating-a-coin#content-coin-configurable-currency)) * **Creator Coins** are paired with **ZORA** (configured during [deployment](/coins/contracts/creating-a-coin#creator-coin-zora-paired)) ##### Conversion Process When fees are collected, the hook automatically performs multi-hop swaps to reach the final payout currency: 1. **Content Coin fees** → **Creator Coin** (first hop) 2. **Creator Coin** → **ZORA** (second hop) This ensures that all stakeholders receive rewards in **ZORA**, regardless of which coin type generated the fees. ##### Example Flow ``` Content Coin Trading → Fees Collected → Multi-hop Swap → All Recipients Receive ZORA ↓ Content Coin → Creator Coin → ZORA ``` #### Key V4 Features * **Automated Distribution**: Rewards are distributed on every single swap, no manual claiming required * **Multi-Hop Conversion**: Automatically converts rewards through intermediate tokens to reach ZORA * **Unified Currency**: All recipients receive rewards in the same target currency (ZORA) * **Liquidity Preservation**: 20% of fees remain in pools as permanent liquidity ### Coin Rewards Terminology **Trade Referral**: The platform or address that referred a specific trade/swap of a coin. In V4, this is passed through hook data and can trigger referral rewards. **Platform Referral**: The platform that referred the creator to deploy the coin. This is set at coin creation time and earns a percentage of all trading fees. (Previously called "Create Referral" in versions prior to 2.2.0) **Creator/Payout Recipient**: The address designated to receive creator rewards from trading activity. This can be updated by coin owners. **Protocol**: The Zora protocol treasury that receives a portion of trading fees. **Doppler**: The Doppler protocol treasury that receives a portion of trading fees. ### How It Works: Creator 1. Creator selects coin creation parameters including payout recipient 2. Creator specifies a wallet address eligible to claim their rewards 3. Creator launches their coin -- **that's it!** The creator's total rewards are automatically distributed with each trade: * **V4**: Converted to target currency and sent directly to payout recipient * **V3**: Accumulated in escrow and can be withdrawn at any time ### How It Works: Developer #### Platform Referral Reward The Platform Referral Reward is paid out to the developer or platform that referred the creator to deploy their coin using Zora's contracts. ##### Creating a Coin with Rewards The `platformReferrer` address is specified upon coin creation through the factory's deploy function. ```solidity function deploy( address payoutRecipient, address[] memory owners, string memory uri, string memory name, string memory symbol, bytes memory poolConfig, address platformReferrer, // This is the platform referral address postDeployHook, bytes calldata postDeployHookData, bytes32 coinSalt ) external payable returns (address coin, bytes memory postDeployHookDataOut); ``` #### Trade Referral Reward The Trade Referral Reward is paid out to the platform that referred a specific trade. ##### Trading with Referrals Trade referrals are passed through the hook data when executing swaps via the Universal Router or other compatible interfaces. import { Callout } from "vocs/components"; ## Trend Coins Trend Coins are a lightweight coin type designed for trading on trending topics, memes, and cultural moments. They feature ultra-low fees (0.01%) and a sniper tax that decays from 99% to the base fee over 10 seconds. ### Overview Unlike Creator Coins and Content Coins, Trend Coins have: * **0.01% trading fee** (1 basis point) — 100x lower than standard coins * **Sniper Tax** — 99% fee at launch, decaying linearly to 0.01% over 10 seconds * **100% liquidity** — entire 1B token supply goes into the pool, no creator allocation * **Unique tickers** — case-insensitive ticker uniqueness enforced on-chain * **Simplified creation** — no payout recipient or platform referrer required ### Fee Structure #### Sniper Tax (Launch Fee) Trend Coins share the same anti-sniping mechanism as other coin types. In the first 10 seconds after creation, a dynamic fee decays linearly from **99% to the base fee**: | Time After Creation | Fee | | ------------------- | ------- | | 0 seconds | 99% | | 2.5 seconds | \~74.5% | | 5 seconds | \~50% | | 7.5 seconds | \~25.5% | | 10+ seconds | 0.01% | ``` fee = 99% - (elapsed_seconds / 10) × (99% - 1%) ``` The initial supply purchase during deployment bypasses the sniper tax entirely and uses the standard 1% fee. This ensures fair initial liquidity setup. #### Post-Launch Fee: 0.01% (1 bps) After the 10-second sniper tax period, Trend Coins settle to a **0.01% fee** — significantly lower than the 1% fee on Creator and Content Coins. This makes Trend Coins optimized for high-frequency, low-friction trading. | Coin Type | Post-Launch Fee | | ------------ | ---------------- | | Creator Coin | 1% (10,000 pips) | | Content Coin | 1% (10,000 pips) | | Trend Coin | 0.01% (100 pips) | #### Reward Distribution Trend Coin fees are distributed differently from Creator and Content Coins. Since there is no creator, platform referrer, or LP remint, **100% of collected fees go to the protocol**: | Recipient | % of Fees | | --------- | --------- | | Protocol | 100% | This contrasts with Creator/Content Coins where fees are split across creator, platform referral, trade referral, Doppler, protocol, and LP rewards. ### Token Supply Trend Coins allocate **100% of their 1 billion token supply** to the liquidity pool: | Allocation | Amount | Details | | ------------------ | --------- | --------------------------------- | | **Liquidity Pool** | 1B tokens | Full supply available for trading | | **Creator** | 0 tokens | No creator allocation or vesting | | **Total Supply** | 1B tokens | Fixed maximum supply | ### Deployment #### Factory Function Trend Coins are deployed through the `deployTrendCoin` function on the ZoraFactory: ```solidity function deployTrendCoin( string calldata symbol, address postDeployHook, bytes calldata postDeployHookData ) external payable returns (address coin, bytes memory postDeployHookDataOut); ``` #### Parameters * **`symbol`**: The ticker symbol for the coin (also used as the name). Must contain only valid ticker characters and must be unique (case-insensitive). * **`postDeployHook`**: Optional contract address to call after deployment (`address(0)` if none) * **`postDeployHookData`**: Data to pass to the post-deployment hook (empty bytes if none) #### Ticker Uniqueness Trend Coin tickers are **globally unique** and **case-insensitive**. Attempting to deploy a Trend Coin with a ticker already in use (regardless of casing) will revert with `TickerAlreadyUsed`. The ticker hash is also used as the deployment salt, making Trend Coin addresses deterministic based on the ticker. #### Address Prediction You can predict the address of a Trend Coin before deployment: ```solidity function trendCoinAddress(string calldata symbol) external view returns (address); ``` #### Metadata Trend Coin metadata is derived automatically from the ticker: * **Name**: same as the ticker symbol * **Token URI**: `https://trends.theme.wtf/trend/{symbol}` Metadata can only be updated by the designated metadata manager contract. ### Pool Configuration Trend Coins use a pre-configured multi-curve Doppler pool optimized for trend-style trading. The pool is backed by ZORA and uses three liquidity curves with different price ranges and supply allocations: | Curve | Supply Share | Description | | ----- | ------------ | -------------------- | | 1 | 5% | Wide discovery range | | 2 | 12.5% | Medium trading range | | 3 | 20% | Tight price range | The pool configuration for Trend Coins is managed by the factory owner via `setTrendCoinPoolConfig`. Individual deployers do not need to provide pool configuration bytes. ### Events The factory emits a `TrendCoinCreated` event on deployment: ```solidity event TrendCoinCreated( address indexed caller, string symbol, address coin, PoolKey poolKey, bytes32 poolKeyHash, bytes poolConfig, string version ); ``` #### Indexing * Trend Coins are identified by the `TrendCoinCreated` event (distinct from `CoinCreatedV4` and `CreatorCoinCreated`) * The `caller` is the `msg.sender` that triggered deployment * No `payoutRecipient` or `platformReferrer` fields (these are always `address(0)` for Trend Coins) ### Comparison with Other Coin Types | Feature | Creator Coin | Content Coin | Trend Coin | | -------------------- | ----------------------------------------- | ----------------- | ---------------------- | | **Trading Fee** | 1% | 1% | 0.01% (1 bps) | | **Sniper Tax** | 99% → 1% over 10s | 99% → 1% over 10s | 99% → 0.01% over 10s | | **Liquidity Supply** | 500M (50%) | 990M (99%) | 1B (100%) | | **Creator Alloc.** | 500M vesting (5 yrs) | 10M instant | None | | **Fee Recipients** | Creator, referrers, protocol, Doppler, LP | Same | Protocol only | | **LP Remint** | 20% of fees | 20% of fees | None | | **Backing Currency** | ZORA | Creator Coin | ZORA | | **Ticker Unique** | No | No | Yes (case-insensitive) | | **Deploy Function** | `deployCreatorCoin()` | `deploy()` | `deployTrendCoin()` | ## Zora 1155 Contracts Changelog ### 2.13.2 #### Patch Changes * [1fd92cc8](https://github.com/ourzora/zora-protocol/commit/1fd92cc8): Add contractName field. ### 2.13.1 #### Patch Changes * [ad707434](https://github.com/ourzora/zora-protocol/commit/ad707434): Updated the 1155 Implementation reduceSupply function to be only allowed to be called by the known `TimedSaleStrategy` address to prevent supply from being reduced in the incorrect matter which would prevent markets from being launched. ### 2.13.0 #### Minor Changes * [737fbef9](https://github.com/ourzora/zora-protocol/commit/737fbef9): Mint fee on the 1155 contract changed to 0.000111 eth ### 2.12.4 #### Patch Changes * [82f63033](https://github.com/ourzora/zora-protocol/commit/82f63033): Remove unused canMintQuantity modifier from 1155 contracts ### 2.12.3 #### Patch Changes * [2fce20f4](https://github.com/ourzora/zora-protocol/commit/2fce20f4): Adding a new getOrCreateFactory function for the 1155 contracts. ### 2.12.2 #### Patch Changes * [cf108bdb](https://github.com/ourzora/zora-protocol/commit/cf108bdb): 1155 mint fee hardcoded to 0.000777 eth ### 2.12.1 #### Patch Changes * [527aa518](https://github.com/ourzora/zora-protocol/commit/527aa518): Move from yarn to pnpm properly pinning deps packages. ### 2.12.0 #### Minor Changes * [0ec838a4](https://github.com/ourzora/zora-protocol/commit/0ec838a4): 1155 contracts have a hardcoded mint fee of 0.000111 ether, and no longer have a fee that is determined by the MintsManager contract #### Patch Changes * [898c84a7](https://github.com/ourzora/zora-protocol/commit/898c84a7): \[chore] Update dependencies and runtime scripts This ensures jobs do not match binary names to make runs less ambigious and also that all deps are accounted for. * [2677c896](https://github.com/ourzora/zora-protocol/commit/2677c896): Add reduceSupply interface check to 1155 ### 2.11.0 #### Minor Changes * [d460e79c](https://github.com/ourzora/zora-protocol/commit/d460e79c): - Introduced a `reduceSupply` function allowing an approved minter or admin to reduce the supply for a given token id. New supply must be less than the current maxSupply, and greater than or equal to the total minted so far. * Removed the deprecated `mintWithRewards` function ### 2.10.1 #### Patch Changes * [368940ba](https://github.com/ourzora/zora-protocol/commit/368940ba): Change removePermission behavior to allow a user to remove their own permission ### 2.10.0 #### Minor Changes * [43a394ab](https://github.com/ourzora/zora-protocol/commit/43a394ab): `ERC20PremintConfig` replaced by a more general purpose `PremintConfigV3`, which instead of having erc20 premint specific properties, as an abi encoded `premintSalesConfig`, that is passed to the function `setPremintSale` on the corresponding minter contract. The new `TokenCreationConfigV3` looks like: ```solidity struct TokenCreationConfigV3 { // Metadata URI for the created token string tokenURI; // Max supply of the created token uint256 maxSupply; // RoyaltyBPS for created tokens. The royalty amount in basis points for secondary sales. uint32 royaltyBPS; // The address that the will receive rewards/funds/royalties. address payoutRecipient; // The address that referred the creation of the token. address createReferral; // The start time of the mint, 0 for immediate. uint64 mintStart; // The address of the minter module. address minter; // The abi encoded data to be passed to the minter to setup the sales config for the premint. bytes premintSalesConfig; } ``` where the `premintSalesConfig` is an abi encoded struct that is passed to the minter's function `setPremintSale`: ```solidity ERC20Minter.PremintSalesConfig memory premintSalesConfig = ERC20Minter.PremintSalesConfig({ currency: address(mockErc20), pricePerToken: 1e18, maxTokensPerAddress: 5000, duration: 1000, payoutRecipient: collector }); // this would be set as the property `premintSalesConfig` in the `TokenCreationConfigV3` bytes memory encodedPremintSalesConfig = abi.encode(premintSalesConfig); ``` Correspondingly, new minters must implement the new interface `ISetPremintSale` to be compatible with the new `TokenCreationConfigV3`: ```solidity interface ISetPremintSale { function setPremintSale( uint256 tokenId, bytes calldata salesConfig ) external; } // example implementation: contract ERC20Minter is ISetPremintSale { struct PremintSalesConfig { address currency; uint256 pricePerToken; uint64 maxTokensPerAddress; uint64 duration; address payoutRecipient; } function buildSalesConfigForPremint( PremintSalesConfig memory config ) public view returns (ERC20Minter.SalesConfig memory) { uint64 saleStart = uint64(block.timestamp); uint64 saleEnd = config.duration == 0 ? type(uint64).max : saleStart + config.duration; return IERC20Minter.SalesConfig({ saleStart: saleStart, saleEnd: saleEnd, maxTokensPerAddress: config.maxTokensPerAddress, pricePerToken: config.pricePerToken, fundsRecipient: config.payoutRecipient, currency: config.currency }); } function toSaleConfig( bytes calldata encodedPremintSalesConfig ) private returns (IERC20Minter.SalesConfig memory) { PremintSalesConfig memory premintSalesConfig = abi.decode( encodedPremintSalesConfig, (PremintSalesConfig) ); return buildSalesConfigForPremint(premintSalesConfig); } mapping(address => mapping(uint256 => IERC20Minter.SalesConfig)) public sale; function setPremintSale( uint256 tokenId, bytes calldata premintSalesConfig ) external override { IERC20Minter.SalesConfig memory salesConfig = toSaleConfig( premintSalesConfig ); sale[msg.sender][tokenId] = salesConfig; } } ``` * [2475a4c9](https://github.com/ourzora/zora-protocol/commit/2475a4c9): Updates to Premint that enables preminting against contracts that were not created via premint, as well as adding collaborators to premint contracts by being able specify an array of additionalAdmins in a premint's contract creation config. ##### No breaking changes These updates are fully backwards compatible; the old functions on the contracts are still intact and will work. Additionally, these updates dont require a new premint config version to be signed; the only thing that could be affected is the deterministic address to be signed against, in the case there are additional contract admins. ##### Ability to add contract-wide additional admins with premint There is a new struct called `ContractWithAdditionalAdminsCreationConfig` that replaces `ContractCreationConfig`. This contains, in addition to the existing fields, a new array `address[] additionalAdmins` - these addresses are added as additional admins when a contract is created by converting each address into a setup action that adds the contract-wide role `PERMISSION_BIT_ADMIN` to that account. ```solidity // new struct: struct ContractWithAdditionalAdminsCreationConfig { // Creator/admin of the created contract. Must match the account that signed the message address contractAdmin; // Metadata URI for the created contract string contractURI; // Name of the created contract string contractName; // additional accounts that will be added as admins // to the contract address[] additionalAdmins; } // existing struct that is replaced: struct ContractCreationConfig { address contractAdmin; string contractURI; string contractName; } ``` Having a list of `additionalAdmins` results in the 1155 contract having a different deterministic address, based on a `salt` made from a hash of the array of `setupActions` that are generated to add those additional accounts as admins. As a result, the creator and additional admins would be signing a message against an address expected to be deterministic with consideration for those additional admins. To get the address in consideration of the new admins, there is a new function on the preminter contract: ```solidity // new function that takes into consideration the additional admins: function getContractWithAdditionalAdminsAddress( ContractWithAdditionalAdminsCreationConfig calldata contractConfig ) public view override returns (address); // existing function can be called if there are no additional admins: function getContractAddress( ContractCreationConfig calldata contractConfig ) public view override returns (address); ``` This should be called to get the expected contract address when there are additional admins. To determine if an address is authorized to create a premint when there are additional admins, there is a new function: ```solidity // new function that takes into consideration the additional admins: function isAuthorizedToCreatePremintWithAdditionalAdmins( address signer, address premintContractConfigContractAdmin, address contractAddress, address[] calldata additionalAdmins ) public view returns (bool isAuthorized); // existing function can be called if there are no additional admins: function isAuthorizedToCreatePremint( address signer, address premintContractConfigContractAdmin, address contractAddress ) public view returns (bool isAuthorized); ``` If any account in those `additionalAdmins`, it is considered authorized and can also sign a premint against the contract address of the original premint, before the contract is created. The collaborator's premint can be brought onchain first, and the original admin will be set as the admin along with all the `additionalAdmins`. ##### New ability to do premints against existing contracts Executing premint against contracts not created via premint can be done with by passing a `premintCollection` argument to the new `premint` function: ```solidity function premint( ContractWithAdditionalAdminsCreationConfig memory contractConfig, address premintCollection, PremintConfigEncoded calldata encodedPremintConfig, bytes calldata signature, uint256 quantityToMint, MintArguments calldata mintArguments, address firstMinter, address signerContract ) external payable returns (uint256 tokenId); ``` This premint collection's address must be a zora creator 1155 contract that already supports premint, which is version 2.0.0 and up. ##### New single shared function for executing a premint, which works with all versions of premint configs In order to avoid having to create one function each for premint v1, v2, and future versions of premint, the new function `premint` takes a struct `PremintConfigEncoded` that contains common properties for premint: `uid`, `version`, and `deleted`, an abi encoded `tokenConfig` and a `premintConfigVersion`; the abi encoded token config can be a `TokenCreationConfigV1`, `TokenCreationConfigV2`, or `TokenCreationConfigV3`. Correspondingly the existing `premintV1/premintV2/premintERC20` functions are deprecated in favor of this new function `premint` that takes a `PremintConfigEncoded` for the premintConfig, and the `contractCreationConfig` as the first argument. If the `premintCollection` parameter is set to a zeroAddress, the function will get or create a contract with an address determined by the contractCreationConfig. This single function works with all versions of premint configs: ```solidity struct PremintConfigEncoded { // Unique id of the token, used to ensure that multiple signatures can't be used to create the same intended token. // only one signature per token id, scoped to the contract hash can be executed. uint32 uid; // Version of this premint, scoped to the uid and contract. Not used for logic in the contract, but used externally to track the newest version uint32 version; // If executing this signature results in preventing any signature with this uid from being minted. bool deleted; // abi encoded token creation config bytes tokenConfig; // hashed premint config version bytes32 premintConfigVersion; } function premint( ContractWithAdditionalAdminsCreationConfig memory contractConfig, address premintCollection, PremintConfigEncoded calldata encodedPremintConfig, bytes calldata signature, uint256 quantityToMint, MintArguments calldata mintArguments, address firstMinter, address signerContract ) external payable returns (uint256 tokenId); ``` `premintV2WithSignerContract` has been removed from the preminter contract to save contract size. ##### 1155 factory's createContractDeterministic resulting address is affected by `setupActions` The FactoryProxy's `createContractDeterministic` function now takes into consideration the `bytes[] calldata setupActions` when creating the contract at the deterministic address. This won't affect contracts that don't have any setup actions, as their address will be the same as it was before. ### 2.9.1 #### Patch Changes * [cd6c6361](https://github.com/ourzora/zora-protocol/commit/cd6c6361): ERC20 Minter V2 Changes: * Adds a flat ETH fee that goes to Zora (currently this fee is 0.000111 ETH but the contract owner can change this fee at any time) * Reward recipients will still receive ERC20 rewards however this percentage can now be changed at any time by the contract owner * Adds an `ERC20MinterConfig` struct which contains `zoraRewardRecipientAddress`, `rewardRecipientPercentage`, and `ethReward` * Zora Reward Recipient Address can now be changed at any time by the contract owner as well * `mint` function is now payable * New functions: * `function ethRewardAmount() external view returns (uint256)` * `function setERC20MinterConfig(ERC20MinterConfig memory config) external` * `function getERC20MinterConfig() external view returns (ERC20MinterConfig memory)` * New events: * `event ERC20MinterConfigSet(ERC20MinterConfig config)` * Removed events: * `event ZoraRewardsRecipientSet(address indexed prevRecipient, address indexed newRecipient)` * `event ERC20MinterInitialized(uint256 rewardPercentage)` ### 2.9.0 #### Minor Changes * 50a4e09: * Zora Creator 1155 contracts use the MINTs contracts to get the mint fee, mint, and redeem a mint ticket upon minting. * `ZoraCreator1155Impl` adds a new method `mintWithMints` that allows for minting with MINTs that are already owned. * 50a4e09: - Zora Creator 1155 contracts no longer have a public facing function `computeFreeMintRewards` and `computePaidMintRewards` * protocol rewards calculation logic has been refactored and moved from the RewardSplits contract to the ZoraCreator1155Impl itself to save on contract size. * remove `ZoraCreator1155Impl.adminMintBatch` to save contract size * 50a4e09: - To support the MINTs contract passing the first minter as an argument to `premintV2WithSignerContract` - we add the field `firstMinter` to `premintV2WithSignerContract`, and then in the 1155 check that the firstMinter argument is not address(0) since it now can be passed in manually. #### ZoraCreator1155Impl rewards splits are percentage based instead of a fixed value. Prior to 2.9.0, rewards were distributed based on a fixed value in ETH per token minted. From 2.9.0 rewards are distributed based on a percentage of the total reward collected for a mint. The following table breaks down the reward splits for both free and paid mints before and after 2.9.0: | Reward Type | Free Mints (Prior to 2.9.0) | Paid Mints (Prior to 2.9.0) | Free Mints (After 2.9.0) | Paid Mints (After 2.9.0) | | ---------------------- | --------------------------- | --------------------------- | ------------------------ | ------------------------ | | Creator Reward | 0.000333 ETH per token | - | 42.8571% of total reward | - | | First Minter Reward | 0.000111 ETH | 0.000111 ETH per token | 14.2285% | 28.5714% of total reward | | Create Referral Reward | 0.000111 ETH | 0.000222 ETH | 14.2285% | 28.5714% | | Mint Referral Reward | 0.000111 ETH | 0.000222 ETH | 14.2285% | 28.5714% | | Zora Platform Reward | 0.000111 ETH | 0.000222 ETH | 14.2285% | 28.5714% | ### 2.8.1 #### Patch Changes * c2a0a2b: Moved dev time dependencies to devDependencies since they are not needed by external users of the package, they are only used for codegen ### 2.8.0 #### Minor Changes * 13a4785: Adds ERC20 Minter contract which enables zora 1155 creator NFTs to be minted with ERC20 tokens #### Patch Changes * 13a4785: Adds first minter reward to ERC20 Minter * 1cf02a4: Add ERC7572 ContractURIUpdated() event for indexing * 079a596: Moved shared functionality into shared-contracts. premintWithSignerContract takes firstMinter as an argument ### 2.8 * 13a4785: Adds ERC20 Minter which allows users to mint NFTs with ERC20 tokens. ### 2.7.3 #### Patch Changes * 52b16aa: Publishing package in format that supports commonjs imports by specifying exports. ### 2.7.2 #### Patch Changes * acf21c0: * `ZoraCreator1155PremintExecutorImpl` and `ZoraCreator1155Impl` support EIP-1271 based signatures for premint token creation, by taking in an extra param indicating the signing contract, and if that parameter is passed, calling a function on that contract address to validate the signature. EIP-1271 is not supported with PremintV1 signatures. * `ZoraCreator1155Impl` splits out `supportsInterface` check for premint related functionality into two separate interfaces to check for, allowing each interface to be updated independently. ### 2.7.1 #### Patch Changes * 8107ffe: Preminter impl disables initializers ### 2.7.0 #### Minor Changes * e990b9d: Remove platform referral from RewardsSplits. Use new signature for 1155 for `mint` which takes an array of reward recipients. #### Patch Changes * Updated dependencies \[e990b9d] * @zoralabs/protocol-rewards\@1.2.3 ### 2.5.4 #### Patch Changes * 7e00197: \* For premintV1 and V2 - mintReferrer has been changed to an array `mintRewardsRecipients` - which the first element in array is `mintReferral`, and second element is `platformReferral`. `platformReferral is not used by the premint contract yet`. ### 2.5.3 #### Patch Changes * d9f3596: For premint - fix bug where fundsRecipient was not set on the fixed price minter. Now it is properly set to the royaltyRecipient/payoutRecipient ### 2.5.2 #### Patch Changes * e4edaac: fixed bug where premint config v2 did not have correct eip-712 domain. fixed bug in CreatorAttribution event where structHash was not included in it ### 2.5.1 #### Patch Changes * 18de283: Fixed setting uid when doing a premint v1 ### 2.5.0 #### Minor Changes * d84721a: # Premint v2 #### New fields on signature Adding a new `PremintConfigV2` struct that can be signed, that now contains a `createReferral`. `ZoraCreator1155PremintExecutor` recognizes new version of the premint config, and still works with the v1 (legacy) version of the `PremintConfig`. Version one of the premint config still works and is still defined in the `PremintConfig` struct. Additional changes included in `PremintConfigV2`: * `tokenConfig.royaltyMintSchedule` has been removed as it is deprecated and no longer recognized by new versions of the 1155 contract * `tokenConfig.royaltyRecipient` has been renamed to `tokenConfig.payoutRecipient` to better reflect the fact that this address is used to receive creator rewards, secondary royalties, and paid mint funds. This is the address that will be set on the `royaltyRecipient` for the created token on the 1155 contract, which is the address that receives creator rewards and secondary royalties for the token, and on the `fundsRecipient` on the ZoraCreatorFixedPriceSaleStrategy contract for the token, which is the address that receives paid mint funds for the token. #### New MintArguments on premint functions, specifying `mintRecipient` and `mintReferral` `mintReferral` and `mintRecipient` are now specified in the premint functions on the `ZoraCreator1155PremintExecutor`, via the `MintArguments mintArguments` param; new `premintV1` and `premintV2` functions take a `MintArguments` struct as an argument which contains `mintRecipient`, defining which account will receive the minted tokens, `mintComment`, and `mintReferral`, defining which account will receive a mintReferral reward, if any. `mintRecipient` must be specified or else it reverts. #### Replacing external signature validation and authorization check with just authorization check `ZoraCreator1155PremintExecutor`'s function `isValidSignature(contractConfig, premintConfig)` is deprecated in favor of: ```solidity isAuthorizedToCreatePremint( address signer, address premintContractConfigContractAdmin, address contractAddress ) public view returns (bool isAuthorized) ``` which instead of validating signatures and checking if the signer is authorized to create premints, just checks if an signer is authorized to create premints on the contract. This offloads signature decoding/validation to calling clients offchain, and reduces needing to create different signatures for this function on the contract for each version of the premint config. It also allows Premints to be validated on contracts that were not created using premints, such as contracts that are upgraded, and contracts created directly via the factory. #### Changes to handling of setting of fundsRecipient Previously the `fundsRecipient` on the fixed priced minters' sales config for the token was set to the signer of the premint. This has been changed to be set to the `payoutRecipient` of the premint config on `PremintConfigV2`, and to the `royaltyRecipient` of the premint config for v1 of the premint config, for 1155 contracts that are to be newly created, and for existing 1155 contracts that are upgraded to the latest version. #### Changes to 1155's `delegateSetupNewToken` `delegateSetupNewToken` on 1155 contract has been updated to now take an abi encoded premint config, premint config version, and send it to an external library to decode the config, the signer, and setup actions. Previously it took a non-encoded PremintConfig. This new change allows this function signature to support multiple versions of a premint config, while offloading decoding of the config and the corresponding setup actions to the external library. This ultimately allows supporting multiple versions of a premint config and corresponding signature without increasing codespace. `PremintConfigV2` are updated to contain `createReferral`, and now look like: ```solidity struct PremintConfigV2 { // The config for the token to be created TokenCreationConfigV2 tokenConfig; // Unique id of the token, used to ensure that multiple signatures can't be used to create the same intended token. // only one signature per token id, scoped to the contract hash can be executed. uint32 uid; // Version of this premint, scoped to the uid and contract. Not used for logic in the contract, but used externally to track the newest version uint32 version; // If executing this signature results in preventing any signature with this uid from being minted. bool deleted; } struct TokenCreationConfigV2 { // Metadata URI for the created token string tokenURI; // Max supply of the created token uint256 maxSupply; // Max tokens that can be minted for an address, 0 if unlimited uint64 maxTokensPerAddress; // Price per token in eth wei. 0 for a free mint. uint96 pricePerToken; // The start time of the mint, 0 for immediate. Prevents signatures from being used until the start time. uint64 mintStart; // The duration of the mint, starting from the first mint of this token. 0 for infinite uint64 mintDuration; // RoyaltyBPS for created tokens. The royalty amount in basis points for secondary sales. uint32 royaltyBPS; // The address that will receive creatorRewards, secondary royalties, and paid mint funds. This is the address that will be set on the `royaltyRecipient` for the created token on the 1155 contract, which is the address that receives creator rewards and secondary royalties for the token, and on the `fundsRecipient` on the ZoraCreatorFixedPriceSaleStrategy contract for the token, which is the address that receives paid mint funds for the token. address payoutRecipient; // Fixed price minter address address fixedPriceMinter; // create referral address createReferral; } ``` `PremintConfig` fields are **the same as they were before, but are treated as a version 1**: ```solidity struct PremintConfig { // The config for the token to be created TokenCreationConfig tokenConfig; // Unique id of the token, used to ensure that multiple signatures can't be used to create the same intended token. // only one signature per token id, scoped to the contract hash can be executed. uint32 uid; // Version of this premint, scoped to the uid and contract. Not used for logic in the contract, but used externally to track the newest version uint32 version; // If executing this signature results in preventing any signature with this uid from being minted. bool deleted; } struct TokenCreationConfig { // Metadata URI for the created token string tokenURI; // Max supply of the created token uint256 maxSupply; // Max tokens that can be minted for an address, 0 if unlimited uint64 maxTokensPerAddress; // Price per token in eth wei. 0 for a free mint. uint96 pricePerToken; // The start time of the mint, 0 for immediate. Prevents signatures from being used until the start time. uint64 mintStart; // The duration of the mint, starting from the first mint of this token. 0 for infinite uint64 mintDuration; // deprecated field; will be ignored. uint32 royaltyMintSchedule; // RoyaltyBPS for created tokens. The royalty amount in basis points for secondary sales. uint32 royaltyBPS; // The address that will receive creatorRewards, secondary royalties, and paid mint funds. This is the address that will be set on the `royaltyRecipient` for the created token on the 1155 contract, which is the address that receives creator rewards and secondary royalties for the token, and on the `fundsRecipient` on the ZoraCreatorFixedPriceSaleStrategy contract for the token, which is the address that receives paid mint funds for the token. address royaltyRecipient; // Fixed price minter address address fixedPriceMinter; } ``` #### Changes to `ZoraCreator1155PremintExecutorImpl`: * new function `premintV1` - takes a `PremintConfig`, and premint v1 signature, and executes a premint, with added functionality of being able to specify mint referral and mint recipient * new function `premintV2` - takes a `PremintConfigV2` signature and executes a premint, with being able to specify mint referral and mint recipient * deprecated function `premint` - call `premintV1` instead * new function ```solidity isAuthorizedToCreatePremint( address signer, address premintContractConfigContractAdmin, address contractAddress ) public view returns (bool isAuthorized) ``` takes a signer, contractConfig.contractAdmin, and 1155 address, and determines if the signer is authorized to sign premints on the given contract. Replaces `isValidSignature` - by putting the burden on clients to first decode the signature, then pass the recovered signer to this function to determine if the signer has premint authorization on the contract. * deprecated function `isValidSignature` - call `isAuthorizedToCreatePremint` instead #### Patch Changes * 885ffa4: Premint executor can still execute premint mints that were created with V1 signatures for `delegateSetupNewToken` * ffb5cb7: Premint - added method getSupportedPremintSignatureVersions(contractAddress) that returns an array of the premint signature versions an 1155 contract supports. If the contract hasn't been created yet, assumes that when it will be created it will support the latest versions of the signatures, so the function returns all versions. * ffb5cb7: Added method `IZoraCreator1155PremintExecutor.supportedPremintSignatureVersions(contractAddress)` that tells what version of the premint signature the contract supports, and added corresponding method `ZoraCreator1155Impl.supportedPremintSignatureVersions()` to fetch supported version. If premint not supported, returns an empty array. * cacb543: Added impl getter to premint executor ### 2.4.1 #### Patch Changes * 63ef7f6: Added missing functions to IZoraCreator1155 ### 2.4.0 #### Minor Changes * 366ac20: Fix broken storage layout by not including an interface on CreatorRoyaltiesControl * e25ac54: ignore nonzero supply royalty schedule ### 2.3.1 #### Patch Changes * e6f61a9: Include all minter and royalty errors in erc1155 and premint executor abis ### 2.3.0 #### Minor Changes * 4afa879: Creator reward recipient can now be defined on a token by token basis. This allows for multiple creators to collaborate on a contract and each to receive rewards for the token they created. The royaltyRecipient storage field is now used to determine the creator reward recipient for each token. If that's not set for a token, it falls back to use the contract wide fundsRecipient. ### 2.1.0 #### Minor Changes * 9495c34: Supply royalties are no longer supported ### 2.0.4 #### Patch Changes * 64da698: Exporting abi ### 2.0.3 #### Patch Changes * d3ddfbb: fix version packages tests ### 2.0.2 #### Patch Changes * 9207e8f: Deployed deterministic proxies and latest versions to mainnet, goerli, base, base goerli, optimism, optimism goerli ### 2.0.1 #### Patch Changes * 35db763: Adding in built artifacts to package ### 2.0.0 #### Major Changes * 82f6506: Premint with Delegated Minting Deterministic Proxy Addresses Premint deployed to zora and zora goerli ### 1.6.1 #### Patch Changes * b83e1b6: Add first minter payouts as chain sponsor ### 1.6.0 #### Minor Changes * 399b8e6: Adds first minter rewards to zora 1155 contracts. * 399b8e6: Added deterministic contract creation from the Zora1155 factory, Preminter, and Upgrade Gate * 399b8e6: Added the PremintExecutor contract, and updated erc1155 to support delegated minting - Add first minter rewards - [Separate upgrade gate into new contract](https://github.com/ourzora/zora-1155-contracts/pull/204) ### 1.5.0 #### Minor Changes * 1bf2d52: Add TokenId to redeemInstructionsHashIsAllowed for Redeem Contracts * a170f1f: - Patches the 1155 `callSale` function to ensure that the token id passed matches the token id encoded in the generic calldata to forward * Updates the redeem minter to v1.1.0 to support b2r per an 1155 token id #### Patch Changes * b1dbb47: Fix types reference for package export * 4cb56d4: - Ensures sales configs can only be updated for the token ids specified * Deprecates support with 'ZoraCreatorRedeemMinterStrategy' v1.0.1 ### 1.4.0 #### Minor Changes * 5b3fafd: Change permission checks for contracts – fix allowing roles that are not admin assigned to tokenid 0 to apply those roles to any token in the contract. * 9f6510d: Add support for rewards * Add new minting functions supporting rewards * Add new "rewards" library ### 1.3.3 #### Patch Changes * 498998f: Added pgn sepolia Added pgn mainnet * cc3b55a: New base mainnet deploy ## Coins SDK Changelog ### 0.8.0 #### Minor Changes * 0ce51caec: Add `getCoinMergedComments` for a coin's unified comment feed. It returns on-chain, backfilled, and off-chain comments pre-sorted newest-first under a single cursor — mirroring the `GraphQLMergedComment` union the Zora web and mobile apps consume. The existing `getCoinComments` is unchanged (on-chain `zoraComments` only). ### 0.7.1 #### Patch Changes * fbb389583: Bump viem to 2.53.1 Raise the pinned viem version from 2.22.12 to 2.53.1 across the monorepo to pick up newer chain definitions and support the latest x402 v2 client packages. * Updated dependencies \[fbb389583] * @zoralabs/protocol-deployments\@0.7.6 ### 0.7.0 #### Minor Changes * c8374a6a7: Add smart wallet variants for all four SDK actions — createCoinSmartWallet, tradeCoinSmartWallet, updateCoinURISmartWallet, and updatePayoutRecipientSmartWallet — alongside a new enableSmartWalletRouting flag on CreateCoinArgs * 663820551: handle bundler client gas errors explicitly so they can be surfaced to users and become actionable * 1121bfefe: Move action validation into explicit validation helpers and export them from the sdk, add a consolidated GenericCall type to support future user operation execution flow. * e1fa9e73c: Add `apiUrl` helper to allow consumers to construct full api urls. ### 0.6.0 #### Minor Changes * 8baf100b2: Add getCoinPriceHistory and getCreatorLivestreamComments query functions * getCoinPriceHistory retrieves historical price data across multiple time periods * getCreatorLivestreamComments fetches paginated comments from creator livestreams #### Patch Changes * bcfc04153: Add `getWalletTradeActivity` query to fetch trade activity for a wallet address ### 0.5.2 #### Patch Changes * 278d7705e: Add new Valuation fields to coin balances endpoint, coin price history endpoint, and creator livestream comments endpoint Only works with api-key authenticated calls otherwise valuation response is null. * b41ed41f9: Fix JWT refresh loop on uploads ### 0.5.1 #### Patch Changes * [78df4fc6](https://github.com/ourzora/zora-protocol/commit/78df4fc6): Updated to allow for a different base URL for testing ### 0.5.0 #### Minor Changes * [e174b53f](https://github.com/ourzora/zora-protocol/commit/e174b53f): Add `getTrend` and `getTrends` for looking up trend coins * `getTrend({ ticker })` — look up a single trend coin by ticker (case-insensitive, server-side) * `getTrends({ name })` — search trend coins by name with pagination * Also exports `TrendCoinResponse` and `TrendsByNameResponse` types for consumers ### 0.4.9 #### Patch Changes * [ef523acf](https://github.com/ourzora/zora-protocol/commit/ef523acf): Add new endpoints for trend coins ### 0.4.8 #### Patch Changes * [7dda692d](https://github.com/ourzora/zora-protocol/commit/7dda692d): Add a top-level `getTokenInfo` query export to the coins SDK ### 0.4.7 #### Patch Changes * [0c0d8e85](https://github.com/ourzora/zora-protocol/commit/0c0d8e85): Add explore wrappers for trending and trend list types Add `getMostValuableAll` wrapper for querying most valuable coins across all coin types ### 0.4.6 #### Patch Changes * Updated dependencies [625684d2](https://github.com/ourzora/zora-protocol/commit/625684d2) * Updated dependencies [50134ebc](https://github.com/ourzora/zora-protocol/commit/50134ebc) * @zoralabs/protocol-deployments\@0.7.5 ### 0.4.5 #### Patch Changes * Updated dependencies [78dffbdc](https://github.com/ourzora/zora-protocol/commit/78dffbdc) * @zoralabs/protocol-deployments\@0.7.4 ### 0.4.4 #### Patch Changes * Updated dependencies [67d27f1d](https://github.com/ourzora/zora-protocol/commit/67d27f1d) * Updated dependencies [27f588b2](https://github.com/ourzora/zora-protocol/commit/27f588b2) * @zoralabs/protocol-deployments\@0.7.3 ### 0.4.3 #### Patch Changes * Updated dependencies [668bfa3c](https://github.com/ourzora/zora-protocol/commit/668bfa3c) * @zoralabs/protocol-deployments\@0.7.2 ### 0.4.2 #### Patch Changes * Updated dependencies [9af2904a](https://github.com/ourzora/zora-protocol/commit/9af2904a) * @zoralabs/protocol-deployments\@0.7.1 ### 0.4.1 #### Patch Changes * Updated dependencies [5d656794](https://github.com/ourzora/zora-protocol/commit/5d656794) * @zoralabs/protocol-deployments\@0.7.0 ### 0.4.0 #### Minor Changes * [40af75bc](https://github.com/ourzora/zora-protocol/commit/40af75bc): Added new profileSocial endpoint, moved poolConfig endpoints to standard queries, and updated docs on smart wallet create key #### Patch Changes * [9f74986f](https://github.com/ourzora/zora-protocol/commit/9f74986f): Add new leaderboard and featured creators queries * Updated dependencies [9391359c](https://github.com/ourzora/zora-protocol/commit/9391359c) * @zoralabs/protocol-deployments\@0.6.5 ### 0.3.3 #### Patch Changes * Updated dependencies [3c274d9d](https://github.com/ourzora/zora-protocol/commit/3c274d9d) * @zoralabs/protocol-deployments\@0.6.4 ### 0.3.2 #### Patch Changes * Updated dependencies [131c719a](https://github.com/ourzora/zora-protocol/commit/131c719a) * Updated dependencies [cdaa9d25](https://github.com/ourzora/zora-protocol/commit/cdaa9d25) * @zoralabs/protocol-deployments\@0.6.3 ### 0.3.1 #### Patch Changes * [1bd2452c](https://github.com/ourzora/zora-protocol/commit/1bd2452c): Fix chainId default setting logic ### 0.3.0 #### Minor Changes * [4819056e](https://github.com/ourzora/zora-protocol/commit/4819056e): Creator coins can only be created via the Zora app. This SDK allows you to create content coins paired with existing creator coins. Create content flow uses server-generated calldata via the SDK API. * **Server-generated calldata**: `createCoinCall` now requests calldata from the SDK API and returns an array of transaction parameters `{ to, data, value }[]` instead of a Viem `SimulateContractParameters` object. * **Direct transaction sending**: `createCoin` constructs and sends the transaction using `walletClient.sendTransaction` with manual gas estimation and an option to skip validation. * **Sanity checks**: Ensures the call targets the expected factory for the specified `chainId` and that no ETH value is sent with this SDK version. * **Smart accounts support**: Compatible with smart accounts thanks to server-generated calldata. API changes (breaking changes): * **Args shape updated** * Removed: `initialPurchase`, and `currency: DeployCurrency`. * Renamed: `owners` to `additionalOwners` - adds additional owners to the coin, `payoutRecipient` to `payoutRecipientOverride` overrides the creator as the payout recipient. * Added: `creator: string`, `metadata: { type: 'RAW_URI'; uri: string }`, `currency: ContentCoinCurrency`, `chainId?: number`, `startingMarketCap?: StartingMarketCap`, `platformReferrer?: string`, `skipMetadataValidation?: boolean`. * New types/constants: `ContentCoinCurrency` with runtime constants `CreateConstants.ContentCoinCurrencies` (`CREATOR_COIN`, `ETH`, `ZORA`, `CREATOR_COIN_OR_ZORA`) and `StartingMarketCap` with runtime constants `CreateConstants.StartingMarketCaps` (`LOW`, `HIGH`). * **Removed local pool/hook logic**: Internal pool config selection and prepurchase hook generation are removed and handled by the API. * **Options updated**: `createCoin({ ..., options })` adds `skipValidateTransaction?: boolean` (skips a dry-run call and uses a fixed gas fallback) and continues to accept `account`. Migration example Before (main): ```ts await createCoin( { name, symbol, uri, payoutRecipient, chainId, currency }, walletClient, publicClient, ); ``` After (new): ```ts await createCoin({ call: { creator, name, symbol, metadata: { type: "RAW_URI", uri }, currency: CreateConstants.ContentCoinCurrencies.CREATOR_COIN, chainId, startingMarketCap: CreateConstants.StartingMarketCaps.LOW, platformReferrer, }, walletClient, publicClient, options: { skipValidateTransaction: false }, }); ``` ### 0.2.11 #### Patch Changes * [a60f441b](https://github.com/ourzora/zora-protocol/commit/a60f441b): Adding new getCoinSwaps and getCoinHolders endpoints ### 0.2.10 #### Patch Changes * Updated dependencies [262d1539](https://github.com/ourzora/zora-protocol/commit/262d1539) * @zoralabs/protocol-deployments\@0.6.2 ### 0.2.9 #### Patch Changes * [3c36f8ed](https://github.com/ourzora/zora-protocol/commit/3c36f8ed): Small documentation and types fixes ### 0.2.8 #### Patch Changes * [d8f29ef0](https://github.com/ourzora/zora-protocol/commit/d8f29ef0): Fixed import paths ### 0.2.7 #### Patch Changes * [bd371420](https://github.com/ourzora/zora-protocol/commit/bd371420): Small trade types fixes ### 0.2.6 #### Patch Changes * [86a3d4f3](https://github.com/ourzora/zora-protocol/commit/86a3d4f3): Add tradeCoin function to trade creator and content coins ### 0.2.5 #### Patch Changes * [4153eddc](https://github.com/ourzora/zora-protocol/commit/4153eddc): Added metadata uploading feature ### 0.2.4 #### Patch Changes * [3d5f9152](https://github.com/ourzora/zora-protocol/commit/3d5f9152): Removing `tradeCoin` function as its currently incompatible with UniswapV4 backed coins * [d8727949](https://github.com/ourzora/zora-protocol/commit/d8727949): Add create coin $ZORA initial buy ### 0.2.3 #### Patch Changes * Updated dependencies [9035ce3b](https://github.com/ourzora/zora-protocol/commit/9035ce3b) * @zoralabs/protocol-deployments\@0.6.1 ### 0.2.2 #### Patch Changes * Updated dependencies [73784d07](https://github.com/ourzora/zora-protocol/commit/73784d07) * Updated dependencies [9adcb702](https://github.com/ourzora/zora-protocol/commit/9adcb702) * Updated dependencies [9adcb702](https://github.com/ourzora/zora-protocol/commit/9adcb702) * @zoralabs/protocol-deployments\@0.6.0 ### 0.2.1 #### Patch Changes * [aa2bc7cd](https://github.com/ourzora/zora-protocol/commit/aa2bc7cd): Add new backend queries to SDK ### 0.2.0 #### Minor Changes * [74885b84](https://github.com/ourzora/zora-protocol/commit/74885b84): Support creating uniswap v4 coins ### 0.1.3 #### Patch Changes * Updated dependencies [8cd56863](https://github.com/ourzora/zora-protocol/commit/8cd56863) * @zoralabs/protocol-deployments\@0.5.10 ### 0.1.2 #### Patch Changes * Updated dependencies [73e95f69](https://github.com/ourzora/zora-protocol/commit/73e95f69) * Updated dependencies [0c50e8e7](https://github.com/ourzora/zora-protocol/commit/0c50e8e7) * @zoralabs/protocol-deployments\@0.5.6 ### 0.1.1 #### Patch Changes * [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76): - Publishing new coins hooks in `@zoralabs/protocol-deployments` * In coins, pulling ISwapRouter from `@zoralabs/shared-contracts`, and updated the shared interface to match the full interface of the ISwapRouter. This new interface is published in `@zoralabs/protocol-deployments`. * Removed publishing of the factory addresses directly in the wagmi config of the coins package, as that's inconsistent with the rest of the packages. * Updated the `@zoralabs/coins-sdk` to use `@zoralabs/protocol-deployments` for abis and addresses, which significantly reduces the dependency tree of it and has it follow the patterns of the other sdk packages. * Updated dependencies [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76) * Updated dependencies [ce3022d8](https://github.com/ourzora/zora-protocol/commit/ce3022d8) * Updated dependencies [ce3022d8](https://github.com/ourzora/zora-protocol/commit/ce3022d8) * Updated dependencies [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76) * Updated dependencies [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76) * @zoralabs/protocol-deployments\@0.5.5 ### 0.1.0 #### Minor Changes * [67356470](https://github.com/ourzora/zora-protocol/commit/67356470): Updated to use new low market cap settings on ZORA.co ### 0.0.8 #### Patch Changes * Updated dependencies [265dcbeb](https://github.com/ourzora/zora-protocol/commit/265dcbeb) * @zoralabs/coins\@0.7.1 ### 0.0.7 #### Patch Changes * [529fe6f2](https://github.com/ourzora/zora-protocol/commit/529fe6f2): Fix coin create default value ### 0.0.6 #### Patch Changes * Updated dependencies [23f723dd](https://github.com/ourzora/zora-protocol/commit/23f723dd) * @zoralabs/coins\@0.7.0 ### 0.0.5 #### Patch Changes * [514f8dd4](https://github.com/ourzora/zora-protocol/commit/514f8dd4): Added validation to URI used to create a coin matching a JSON object with URIs ### 0.0.4 #### Patch Changes * [de700d12](https://github.com/ourzora/zora-protocol/commit/de700d12): Updated intermediary types in coins-sdk to better handle nulls * [b08b33ae](https://github.com/ourzora/zora-protocol/commit/b08b33ae): Fix multiple coins get and update types ### 0.0.3 #### Patch Changes * Updated dependencies [b9f717db](https://github.com/ourzora/zora-protocol/commit/b9f717db) * @zoralabs/coins\@0.6.1 ### 0.0.2 #### Patch Changes * [d9eb5a40](https://github.com/ourzora/zora-protocol/commit/d9eb5a40): Initial release ### 0.0.2-sdkalpha.8 #### Patch Changes * Update export pattern for types on queries ### 0.0.2-sdkalpha.7 #### Patch Changes * [8f5d9185](https://github.com/ourzora/zora-protocol/commit/8f5d9185): Fix types and exports ### 0.0.2-sdkalpha.6 #### Patch Changes * Properly export set api key ### 0.0.2-sdkalpha.5 #### Patch Changes * Release API changes ### 0.0.2-sdkalpha.4 #### Patch Changes * [d8cbf6ea](https://github.com/ourzora/zora-protocol/commit/d8cbf6ea): Update coin sdk structure and offchain functions ### 0.0.2-sdkalpha.3 #### Patch Changes * [60568036](https://github.com/ourzora/zora-protocol/commit/60568036): Add offchain data ### 0.0.2-sdkalpha.2 #### Patch Changes * SDK Update ### 0.0.2-sdkalpha.1 #### Patch Changes * Fix package json inclusion ### 0.0.2-sdkalpha.0 #### Patch Changes * [29a34eaf](https://github.com/ourzora/zora-protocol/commit/29a34eaf): Introduce Coins SDK * Updated dependencies [29a34eaf](https://github.com/ourzora/zora-protocol/commit/29a34eaf) * @zoralabs/coins\@0.5.1-sdkalpha.0 ## Coins Changelog ### 2.6.1 #### Patch Changes * fbb389583: Bump viem to 2.53.1 Raise the pinned viem version from 2.22.12 to 2.53.1 across the monorepo to pick up newer chain definitions and support the latest x402 v2 client packages. ### 2.6.0 #### Minor Changes * [50134ebc](https://github.com/ourzora/zora-protocol/commit/50134ebc): Add TrendCoin support * New `TrendCoin` contract: 100% supply in liquidity pool, 0% swap fees * `deployTrendCoin` factory method with ticker uniqueness enforcement and post-deploy hook support * Owner-configurable pool parameters via `setTrendCoinPoolConfig()` * Metadata manager role for updatable contract URIs * Ticker validation and URI encoding for trend coin symbols ### 2.5.1 #### Patch Changes * [78dffbdc](https://github.com/ourzora/zora-protocol/commit/78dffbdc): Including uniswap v4 errors in lob and swap router abis, and including some uniswap v4 contracts and abis. * [1ccca8ef](https://github.com/ourzora/zora-protocol/commit/1ccca8ef): Fix swap fee distribution when price limits cause partial execution When swapping large fee amounts, swaps can hit sqrtPriceLimit and only partially execute, leaving unsettled currency deltas. The hook now checks all currencies in the payout swap path (both the input currency and all intermediates) and takes/distributes any positive deltas as rewards. This ensures all collected fees are properly distributed even when swaps don't fully execute due to price constraints. ### 2.5.0 #### Minor Changes * [816ceb35](https://github.com/ourzora/zora-protocol/commit/816ceb35): Add launch fee: time-based dynamic fee that decays from 99% to 1% over 10 seconds after coin creation * New coins record creation timestamp and expose it via `IHasCreationInfo` interface * Hook calculates dynamic fee based on elapsed time since creation * Initial supply purchase bypasses the fee via transient storage flag * Legacy coins without the interface receive normal 1% LP fee ### 2.4.2 #### Patch Changes * [479df7f0](https://github.com/ourzora/zora-protocol/commit/479df7f0): Fix ETH settlement by adding missing sync before settle in V3ToV4SwapLib Added a `poolManager.sync(inputCurrency)` call before settling when the input currency is ETH. This ensures the pool state is properly synchronized before the settlement occurs, making the behavior consistent with the ERC20 handling path which already includes this sync step. ### 2.4.1 #### Patch Changes * [cf172fdb](https://github.com/ourzora/zora-protocol/commit/cf172fdb): Make call to calculatePositions external to save on contract size ### 2.4.0 #### Minor Changes * [09fb2528](https://github.com/ourzora/zora-protocol/commit/09fb2528): Make trusted senders in coin hooks modifiable Trusted message senders can now be added or removed after hook deployment instead of being hardcoded at deployment time. #### Patch Changes * [b41a2773](https://github.com/ourzora/zora-protocol/commit/b41a2773): Fix double-counting of fees in burnPositions during liquidity migration Previously, the `burnPositions()` function was incorrectly adding `feesAccrued` to `callerDelta` when recording burned position amounts. Since `callerDelta` already includes accrued fees, this caused fees to be double-counted. This resulted in inflated token amounts being recorded in `BurnedPosition` structs, which could lead to `ERC20InsufficientBalance` errors when attempting to mint positions on a new hook during migration. The fix: * Use only `callerDelta` values directly without adding `feesAccrued` * Add defensive balance checking in `mintPositions()` to cap liquidity at available token amounts * Prevents migration failures from any remaining rounding discrepancies between burn and mint operations * [8dc766eb](https://github.com/ourzora/zora-protocol/commit/8dc766eb): Fix incorrect senderIsTrusted logic for address(0) in ZoraV4CoinHook Removes the special case handling for address(0) in the \_getOriginalMsgSender function that was incorrectly setting senderIsTrusted to true. This behavior was unintentionally changed in commit 09fb2528 which added special handling for address(0). This fix restores the original behavior where address(0) returns false for senderIsTrusted, ### 2.3.1 #### Patch Changes * [3c274d9d](https://github.com/ourzora/zora-protocol/commit/3c274d9d): Created a buy supply with v4 hook, for buying initial supply of a creator coin, supporting doing a v3 and v4 swap to buy the creator coin. updated the encoding function for buying initial supply to work with the v3 to v4 swap ### 2.3.0 #### Minor Changes * [7df94915](https://github.com/ourzora/zora-protocol/commit/7df94915): Enable buying initial supply when deploying creator coin and refactor factory internals * Add new `deployCreatorCoin` overload with `postDeployHook` parameter that supports ETH transfers * Refactored internal factory implementation to share more code between deployment methods * Enables buying initial supply during creator coin deployment via post-deploy hooks #### Patch Changes * [6a7e2b7b](https://github.com/ourzora/zora-protocol/commit/6a7e2b7b): Fix LP position duplication when deploying coins. If two positions are created with the same tick ranges, they are merged and stored as one position. This reduces gas costs during swapping as there are less LP positions to iterate through when collecting fees. * [5093c5ef](https://github.com/ourzora/zora-protocol/commit/5093c5ef): Add bounds checking to prevent risky forced downcasting of currency deltas * [9c6d241a](https://github.com/ourzora/zora-protocol/commit/9c6d241a): Fix ETH transfer failures in reward distribution when platform referrers cannot accept ETH * Prevent swaps from reverting when platform referrers cannot accept ETH - in this case, the rewards are redirected to the protocol recipient as backup. * Ensures coin functionality remains intact even with ETH-incompatible platform referrers * [44a179b0](https://github.com/ourzora/zora-protocol/commit/44a179b0): Flatten hooks into single hook implementation Consolidates multiple hook contracts into a single unified hook for simplified architecture and better maintainability. * [d3808d55](https://github.com/ourzora/zora-protocol/commit/d3808d55): Adjust creator coin vesting duration to account for leap years * Changed CREATOR\*VESTING\_DURATION from 5 \* 365 days to 5 \_ 365.25 days * Addresses Cantina audit finding about 1.25 day shortfall in 5-year vesting period * [b571fe54](https://github.com/ourzora/zora-protocol/commit/b571fe54): Consolidate and clarify coin constants * Renamed `CREATOR_LAUNCH_REWARD` to `CONTENT_COIN_INITIAL_CREATOR_SUPPLY` for clarity * Renamed `CREATOR_VESTING_SUPPLY` to `CREATOR_COIN_CREATOR_VESTING_SUPPLY` for consistency * Removed redundant `POOL_LAUNCH_SUPPLY` constant (use `CONTENT_COIN_MARKET_SUPPLY` instead) * Changed library constants from `public` to `internal` * Made supply constants derived from calculations to show relationships clearly * [32d683d6](https://github.com/ourzora/zora-protocol/commit/32d683d6): Fix stale PoolKey mapping after migration in ZoraV4CoinHook Delete the old pool key from the poolCoins mapping after successful liquidity migration to prevent future operations on migrated pools. * [44a179b0](https://github.com/ourzora/zora-protocol/commit/44a179b0): Ignore collecting from liquidity positions with empty fee growth * [00b982bb](https://github.com/ourzora/zora-protocol/commit/00b982bb): Fix liquidity migration bug: when migrating liquidity to a hook with a different fee, the old fee was kept. This will now make sure that the new fee is used after migration. Also make sure to use the new tick spacing after migration. ### 2.2.1 #### Patch Changes * [c96e0c5e](https://github.com/ourzora/zora-protocol/commit/c96e0c5e): Fix bug where liquidity cannot be migrated if there is a position with 0 liquidity ### 2.2.0 #### Minor Changes * [adf98059](https://github.com/ourzora/zora-protocol/commit/adf98059): Adds platform referral and trade referral functionality to creator coins, and unifies the fee structure between content and creator coins with a simplified 1% total fee. ### New Features: * Platform referral and trade referral functionality for creator coins (previously only supported on content coins) * Unified fee structure: Both content and creator coins use identical 1% fee distribution #### Fee Changes - Content Coins | Recipient | Before (3% total fee) | After (1% total fee) | | ----------------- | --------------------- | -------------------- | | | % of Fee | % of Fee | | Creator | 33.33% | 50% | | Platform Referral | 10% | 20% | | Trade Referral | 10% | 4% | | Doppler | 3.33% | 1% | | Protocol | 10% | 5% | | LP Rewards | 33.33% | 20% | #### Fee Changes - Creator Coins | Recipient | Before (3% total fee) | After (1% total fee) | | ----------------- | --------------------- | -------------------- | | | % of Fee | % of Fee | | Creator | 33.33% | 50% | | Platform Referral | - | 20% | | Trade Referral | - | 4% | | Doppler | - | 1% | | Protocol | 33.33% | 5% | | LP Rewards | 33.33% | 20% | **Implementation Changes:** * Consolidated reward logic into `CoinRewardsV4.distributeMarketRewards()` **Backwards Compatibility:** * Existing `CreatorCoinRewards` event is still emitted for backwards compatibility when rewards are distributed for a CreatorCoin * Additionally, when market rewards are distributed for a CreatorCoin, the same `CoinMarketRewardsV4` event that is already emitted for ContentCoins is now also emitted ### 2.1.2 #### Patch Changes * [8b85ab94](https://github.com/ourzora/zora-protocol/commit/8b85ab94): Removed some unused constants ### 2.1.1 #### Patch Changes * [498e5c9d](https://github.com/ourzora/zora-protocol/commit/498e5c9d): Consolidated POOL\_LAUNCH\_SUPPLY into a single constant ### 2.1.0 #### Minor Changes * [dac72691](https://github.com/ourzora/zora-protocol/commit/dac72691): Remove Uniswap V3 support and refactor coin architecture **Removal of V3 Support:** * Removed support for creating coins based on Uniswap V3 - only V4 coins are supported * Default coin deployment now creates Uniswap V4 coins when no config is provided (previously created V3) * Removed V3-specific test files and utilities * Updated remaining tests to use V4 deployment methods * Removed V3 configuration functions and encoders * Added revert logic for V3 deployment attempts in factory deploy functions **Architecture Refactoring:** * Merged BaseCoinV4 functionality into BaseCoin.sol to consolidate Uniswap V4 integration * Combined ICoinV4 interface with ICoin interface to simplify the interface hierarchy * Updated ContentCoin and CreatorCoin to inherit directly from BaseCoin * Removed duplicate files: BaseCoinV4.sol and ICoinV4.sol * Updated all imports and references throughout the codebase * This is an internal refactoring that doesn't change external functionality #### Patch Changes * [deb9175b](https://github.com/ourzora/zora-protocol/commit/deb9175b): Enforce 32 bytes for decoding trade referral address from hook data ### 2.0.0 #### Major Changes * [acb9ff94](https://github.com/ourzora/zora-protocol/commit/acb9ff94): Move ZoraFactoryImpl to 2-step ownable with same storage slots This change updates the factory contract to use Ownable2StepUpgradeable instead of OwnableUpgradeable. The change maintains storage slot compatibility while adding the two-step ownership transfer pattern for enhanced security. Key changes: * ZoraFactoryImpl now inherits from Ownable2StepUpgradeable * Adds pendingOwner() function * Requires acceptOwnership() call to complete ownership transfers * Maintains storage slot compatibility for upgrades #### Patch Changes * [65d36dbb](https://github.com/ourzora/zora-protocol/commit/65d36dbb): Refactor coinv4 into basecoinv4 and content coin This refactoring splits the coinv4 implementation into a base coin contract and content coin contract for better modularity and separation of concerns. ### 1.1.2 #### Patch Changes * [522a7c33](https://github.com/ourzora/zora-protocol/commit/522a7c33): Update LICENSE for coins * [5c561b01](https://github.com/ourzora/zora-protocol/commit/5c561b01): Fixed bug where hooks could not receive taken eth for paying out rewards ### 1.1.1 #### Patch Changes * [604cd3ab](https://github.com/ourzora/zora-protocol/commit/604cd3ab): When migrating liquidity to a new hook, dont execute any after swap logic in the original hook * [588da84e](https://github.com/ourzora/zora-protocol/commit/588da84e): Fix market supply calculation * [f6300031](https://github.com/ourzora/zora-protocol/commit/f6300031): Added ability for hooks to have liquidity be migrated to ### 1.1.0 #### Minor Changes * [73784d07](https://github.com/ourzora/zora-protocol/commit/73784d07): Added creator coins, contracts and hooks, enabling creator coins with vesting to be created. #### Patch Changes * [3d5e77fe](https://github.com/ourzora/zora-protocol/commit/3d5e77fe): Coin name and symbol can be updated by an owner * [9adcb702](https://github.com/ourzora/zora-protocol/commit/9adcb702): Added the AutoSwapper contract * [52edc9d5](https://github.com/ourzora/zora-protocol/commit/52edc9d5): Don't auto-withdraw vested creator coins on every swap * [73784d07](https://github.com/ourzora/zora-protocol/commit/73784d07): A coins initial liquidity can be migrated from one hook to the next, given that the upgrade path is approved ### 1.0.1 #### Patch Changes * [8cd56863](https://github.com/ourzora/zora-protocol/commit/8cd56863): BuySupplyWithSwapRouterHook supports v4 coins ### 1.0.0 #### Major Changes * [73e95f69](https://github.com/ourzora/zora-protocol/commit/73e95f69): Upgraded coins to use Uniswap V4: **New CoinV4 Implementation:** * Migrated from Uniswap V3 to Uniswap V4, with logic moved into a hook. * Automatic LP fee collection and multi-hop reward distribution on every swap * New `ZoraV4CoinHook` handles afterSwap operations * Support for complex multi-position liquidity curves and discovery positions * Multi-hop fee swapping through intermediate currencies (e.g., ContentCoin → BackingCoin → Zora) **Factory Updates:** * Updated `deploy()` function signature with new `poolConfig`, `message`, and `salt` parameters * Automatic V3/V4 version selection based on pool configuration * Deterministic coin deployment with salt support * New `CoinCreatedV4` event for V4 coin deployments **Reward System Changes:** * Increased trade referral rewards from 10% to 15% (1500 basis points) * Automatic reward distribution in single backing currency **New Interfaces and Events:** * Added `IHasPoolKey` and `IHasSwapPath` interfaces for V4 functionality * New `Swapped` event with detailed swap and price information * New `CoinMarketRewardsV4` event for reward distribution tracking **Breaking Changes:** * New deterministic factory deploy function with salt #### Patch Changes * [6b8bdd9d](https://github.com/ourzora/zora-protocol/commit/6b8bdd9d): Remove ability to create coin with legacy pool config ### 0.9.0 #### Minor Changes * [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76): - Publishing new coins hooks in `@zoralabs/protocol-deployments` * In coins, pulling ISwapRouter from `@zoralabs/shared-contracts`, and updated the shared interface to match the full interface of the ISwapRouter. This new interface is published in `@zoralabs/protocol-deployments`. * Removed publishing of the factory addresses directly in the wagmi config of the coins package, as that's inconsistent with the rest of the packages. * Updated the `@zoralabs/coins-sdk` to use `@zoralabs/protocol-deployments` for abis and addresses, which significantly reduces the dependency tree of it and has it follow the patterns of the other sdk packages. * [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76): added deployWithHook to the coin factory #### Patch Changes * [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76): Refactored some reusable code into helper functions for the Coin factory ### 0.8.0 #### Minor Changes * [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76): - Publishing new coins hooks in `@zoralabs/protocol-deployments` * In coins, pulling ISwapRouter from `@zoralabs/shared-contracts`, and updated the shared interface to match the full interface of the ISwapRouter. This new interface is published in `@zoralabs/protocol-deployments`. * Removed publishing of the factory addresses directly in the wagmi config of the coins package, as that's inconsistent with the rest of the packages. * Updated the `@zoralabs/coins-sdk` to use `@zoralabs/protocol-deployments` for abis and addresses, which significantly reduces the dependency tree of it and has it follow the patterns of the other sdk packages. * [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76): added deployWithHook to the coin factory #### Patch Changes * [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76): Refactored some reusable code into helper functions for the Coin factory ### 0.7.1 #### Patch Changes * [265dcbeb](https://github.com/ourzora/zora-protocol/commit/265dcbeb): Fixed factory address for wagmi ### 0.7.0 #### Minor Changes * [23f723dd](https://github.com/ourzora/zora-protocol/commit/23f723dd): Integrate doppler for liquidity management with uniswap v3 ### 0.7.0-doppler.0 #### Minor Changes * [96ab8907](https://github.com/ourzora/zora-protocol/commit/96ab8907): Integrate doppler for liquidity management with uniswap v3 ### 0.6.1 #### Patch Changes * [b9f717db](https://github.com/ourzora/zora-protocol/commit/b9f717db): Export IUniswapV3Pool interface ### 0.6.0 #### Minor Changes * [55bc4bf3](https://github.com/ourzora/zora-protocol/commit/55bc4bf3): Update WETH tick and use as the minimum ### 0.5.0 #### Minor Changes * [39ffa77c](https://github.com/ourzora/zora-protocol/commit/39ffa77c): Add coin refunds for large sells with little liquidity ### 0.4.0 #### Minor Changes * [e6ee19ce](https://github.com/ourzora/zora-protocol/commit/e6ee19ce): Updated launch rewards - 10m coins for creator; remaining 990m for market ### 0.3.1 #### Patch Changes * [11854bbe](https://github.com/ourzora/zora-protocol/commit/11854bbe): Updated factory impl abi to return coins purchased on deploy ### 0.3.0 #### Minor Changes * [e1a3d68f](https://github.com/ourzora/zora-protocol/commit/e1a3d68f): Refactored coin interface imports ### 0.2.0 #### Minor Changes * [9fa218c9](https://github.com/ourzora/zora-protocol/commit/9fa218c9): - Final events in preparation for V1 release * Updated the starting tick for WETH pools ### 0.1.1 #### Patch Changes * [1e10ac74](https://github.com/ourzora/zora-protocol/commit/1e10ac74): - Fixed coins package visibility * Renamed export to `coinFactory*` ### 0.1.0 #### Minor Changes * [e42eb013](https://github.com/ourzora/zora-protocol/commit/e42eb013): Initial setup ## Cointags Changelog ### 0.1.2 #### Patch Changes * [066c289a](https://github.com/ourzora/zora-protocol/commit/066c289a): Ensure that cointags can only be created with v3 Uniswap pools ### 0.1.1 #### Patch Changes * [5da3d1b0](https://github.com/ourzora/zora-protocol/commit/5da3d1b0): Removed transient storage as it's no longer used * [9ccd40bb](https://github.com/ourzora/zora-protocol/commit/9ccd40bb): Update cointags with erc7201 storage slots for contract variables ### 0.1.0 #### Patch Changes * [1bc855fd](https://github.com/ourzora/zora-protocol/commit/1bc855fd): Don't revert buyburn if transfer to dead address fails * [669c1834](https://github.com/ourzora/zora-protocol/commit/669c1834): Added upgrade gate and upgradeability to the cointag contract * [1bc855fd](https://github.com/ourzora/zora-protocol/commit/1bc855fd): Recover if transferring erc20s to dead addresses reverts * [f2e523f3](https://github.com/ourzora/zora-protocol/commit/f2e523f3): Removed TWAP based slippage protection * [f30466a8](https://github.com/ourzora/zora-protocol/commit/f30466a8): feat: add check to validate one token in the uniswap pool must be WETH * [036b69e8](https://github.com/ourzora/zora-protocol/commit/036b69e8): Allow direct ETH deposits via the receive() - allowing deposit to happen separately from pull() and eth to be deposited by anyone. ### 0.0.2 #### Patch Changes * [dc84793a](https://github.com/ourzora/zora-protocol/commit/dc84793a): * Set TWAP period to be 10 minutes * Safe transfer of WETH in swap callback * Fix burn error handling weth distribution * [9b1bb9d1](https://github.com/ourzora/zora-protocol/commit/9b1bb9d1): Using transient storage variable for isPulling ## @zoralabs/protocol-deployments Changelog ### 0.7.6 #### Patch Changes * fbb389583: Bump viem to 2.53.1 Raise the pinned viem version from 2.22.12 to 2.53.1 across the monorepo to pick up newer chain definitions and support the latest x402 v2 client packages. ### 0.7.5 #### Patch Changes * [625684d2](https://github.com/ourzora/zora-protocol/commit/625684d2): Deploy Coin hook and implementations v2.5.1 to Base * [50134ebc](https://github.com/ourzora/zora-protocol/commit/50134ebc): Add TrendCoin support * New `TrendCoin` contract: 100% supply in liquidity pool, 0% swap fees * `deployTrendCoin` factory method with ticker uniqueness enforcement and post-deploy hook support * Owner-configurable pool parameters via `setTrendCoinPoolConfig()` * Metadata manager role for updatable contract URIs * Ticker validation and URI encoding for trend coin symbols ### 0.7.4 #### Patch Changes * [78dffbdc](https://github.com/ourzora/zora-protocol/commit/78dffbdc): Including uniswap v4 errors in lob and swap router abis, and including some uniswap v4 contracts and abis. ### 0.7.3 #### Patch Changes * [67d27f1d](https://github.com/ourzora/zora-protocol/commit/67d27f1d): Deploy upgraded coin implementations for limit-orders v0.2.7 to Base * Deploy ContentCoin to 0x9dE4D209B34b6121C3533Ab1B35236aCC6453fF3 (production) * Deploy CreatorCoin to 0xE305FAA8d197f360Da45fE253B709CA373eDe337 (production) * Deploy ZoraV4CoinHook to 0xF6d0A13609bb5779Bc5D639F2bA3Bfda83D4D0C0 (production) * Deploy ZoraFactoryImpl to 0x5eD16Aa75831210793Db14523cf64F43c7F8a159 (production) * Deploy ContentCoin to 0x888A2bFbE54C33b75b87701D50dd520248078DD7 (dev) * Deploy CreatorCoin to 0x82F6177e6344c9Fb49A9379D1fFf8466a0ad1943 (dev) * Deploy ZoraV4CoinHook to 0x6DA72eD8725Af7824A16Cce07A15e4a849c650C0 (dev) * Deploy ZoraFactoryImpl to 0xAEB677F11dfF19BF4b593f67D5CcD32730069D13 (dev) * [27f588b2](https://github.com/ourzora/zora-protocol/commit/27f588b2): Deploy ZoraLimitOrderBook version 0.2.7 to Base mainnet * Deploy ZoraLimitOrderBook version 0.2.7 to 0x7777777C783bAD88daCaf9A19E04238341E4497B (production) * Deploy SwapWithLimitOrders version 0.2.7 to 0x77777777Eb762Cf86F634763e79d17dE44330887 (production) ### 0.7.2 #### Patch Changes * [668bfa3c](https://github.com/ourzora/zora-protocol/commit/668bfa3c): Deploy limit orders version 0.2.6 to Base * Deploy ZoraLimitOrderBook version 0.2.6 to 0x7777777A5906659b67CE61511489Ae76DA63920f (production) * Deploy SwapWithLimitOrders version 0.2.6 to 0x7777777f62529Ea64736E24ad9ad3E4a39eB97c2 (production) * Deploy ZoraLimitOrderBook version 0.2.6 to 0xCe2C8032F85aB6a7148138F8a1235d2b17D53Dc5 (dev) * Deploy SwapWithLimitOrders version 0.2.6 to 0x1F35FB3E07e68bC1Bf020c2d59cBF91Ccf5736b8 (dev) ### 0.7.1 #### Patch Changes * [9af2904a](https://github.com/ourzora/zora-protocol/commit/9af2904a): Deploy limit order contracts version 0.2.5 to Base mainnet * Deploy ZoraLimitOrderBook version 0.2.5 to 0x77777774d70B1E9D6f705f99dA7c02e4E768dF09 (production) * Deploy SwapWithLimitOrders version 0.2.5 to 0x7777777A1F22faaB216f502B5D0BAAdE8c734F30 (production) * Deploy ZoraLimitOrderBook version 0.2.5 to 0xA017F02f8307759bf2c305eA84D5d23529937EfF (dev) * Deploy SwapWithLimitOrders version 0.2.5 to 0x0C4a29c2256aF82107f413bAa44e687ba2930414 (dev) ### 0.7.0 #### Minor Changes * [5d656794](https://github.com/ourzora/zora-protocol/commit/5d656794): Add dev contract exports for Base mainnet development deployments * Add `devCoinFactoryAddress` and `devCoinFactoryABI` exports for dev Coin factory * Add `devZoraLimitOrderBookAddress` and `devZoraLimitOrderBookABI` exports for dev limit order book * Add `devZoraRouterAddress` and `devZoraRouterABI` exports for dev router * Add `devBuySupplyWithSwapRouterHookABI` export (address empty due to zero address in deployment) * Fix bug in getLimitOrdersContracts that was not filtering out dev files ### 0.6.5 #### Patch Changes * [9391359c](https://github.com/ourzora/zora-protocol/commit/9391359c): Reduced hook code size by removing extra liquidity minting step during migration. Small leftover token amounts from rounding are now left as burned rather than being minted into the last position. ### 0.6.4 #### Patch Changes * [3c274d9d](https://github.com/ourzora/zora-protocol/commit/3c274d9d): Created a buy supply with v4 hook, for buying initial supply of a creator coin, supporting doing a v3 and v4 swap to buy the creator coin. updated the encoding function for buying initial supply to work with the v3 to v4 swap ### 0.6.3 #### Patch Changes * [131c719a](https://github.com/ourzora/zora-protocol/commit/131c719a): Deployed v2.2.0 of coins to Base * [cdaa9d25](https://github.com/ourzora/zora-protocol/commit/cdaa9d25): Fix critical security vulnerabilities with pnpm overrides * Added pnpm overrides to eliminate critical vulnerabilities * Fixed vitest RCE vulnerability (^2.1.9) * Fixed elliptic private key extraction vulnerability (^6.6.1) * Fixed ejs template injection vulnerability (^3.1.7) * Fixed pbkdf2 input validation vulnerability (^3.1.3) * Fixed form-data boundary generation vulnerability (^4.0.4) * Fixed braces ReDoS vulnerability (^3.0.3) * Fixed sha.js type checking vulnerability (^2.4.12) ### 0.6.2 #### Patch Changes * [262d1539](https://github.com/ourzora/zora-protocol/commit/262d1539): updating deployments abis for new factory functions for coins ### 0.6.1 #### Patch Changes * [9035ce3b](https://github.com/ourzora/zora-protocol/commit/9035ce3b): Upgrade coins factory to support creator coins ### 0.6.0 #### Minor Changes * [73784d07](https://github.com/ourzora/zora-protocol/commit/73784d07): Deployed latest coins and hooks, including creator coins. #### Patch Changes * [9adcb702](https://github.com/ourzora/zora-protocol/commit/9adcb702): Added AutoSwapper * [9adcb702](https://github.com/ourzora/zora-protocol/commit/9adcb702): Added uniswap QuoterV2 to protocol-deployments ### 0.5.10 #### Patch Changes * [8cd56863](https://github.com/ourzora/zora-protocol/commit/8cd56863): BuySupplyWithSwapRouterHook supports v4 coins ### 0.5.6 #### Patch Changes * [73e95f69](https://github.com/ourzora/zora-protocol/commit/73e95f69): Published CoinsV4 pool config encoding helper * [0c50e8e7](https://github.com/ourzora/zora-protocol/commit/0c50e8e7): Published uniswap v4 abis and addresses. Fixed encoding of v4 coin config ### 0.5.5 #### Patch Changes * [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76): - Publishing new coins hooks in `@zoralabs/protocol-deployments` * In coins, pulling ISwapRouter from `@zoralabs/shared-contracts`, and updated the shared interface to match the full interface of the ISwapRouter. This new interface is published in `@zoralabs/protocol-deployments`. * Removed publishing of the factory addresses directly in the wagmi config of the coins package, as that's inconsistent with the rest of the packages. * Updated the `@zoralabs/coins-sdk` to use `@zoralabs/protocol-deployments` for abis and addresses, which significantly reduces the dependency tree of it and has it follow the patterns of the other sdk packages. * [ce3022d8](https://github.com/ourzora/zora-protocol/commit/ce3022d8): Deployed latest Coins and Deployment hooks to base mainnet * [ce3022d8](https://github.com/ourzora/zora-protocol/commit/ce3022d8): Fix hook return value from encode hook generators * [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76): Added helper methods to encode data for the post deploy hooks when creating coins * [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76): Deployed latest coin factory and hooks to base-sepolia ### 0.5.4 #### Patch Changes * [23f723dd](https://github.com/ourzora/zora-protocol/commit/23f723dd): Integrate doppler for liquidity management with uniswap v3 ### 0.5.4-doppler.0 #### Patch Changes * [96ab8907](https://github.com/ourzora/zora-protocol/commit/96ab8907): Integrate doppler for liquidity management with uniswap v3 ### 0.5.3 #### Patch Changes * [70b039ce](https://github.com/ourzora/zora-protocol/commit/70b039ce): Deployed ZoraFactory for coins to deterministic 7777777 addresses on base and base sepolia ### 0.5.2 #### Patch Changes * [ed9f7741](https://github.com/ourzora/zora-protocol/commit/ed9f7741): Updated coin ABI for updated buy/sell return values ### 0.5.1 #### Patch Changes * [11854bbe](https://github.com/ourzora/zora-protocol/commit/11854bbe): Updated factory impl abi to return coins purchased on deploy ### 0.5.0 #### Minor Changes * [e1a3d68f](https://github.com/ourzora/zora-protocol/commit/e1a3d68f): Refactored coin interface imports ### 0.4.2 #### Patch Changes * [1e10ac74](https://github.com/ourzora/zora-protocol/commit/1e10ac74): - Fixed coins package visibility * Renamed export to `coinFactory*` ### 0.4.1 #### Patch Changes * [855112de](https://github.com/ourzora/zora-protocol/commit/855112de): Add initial coins ### 0.4.0 #### Minor Changes * [fc8e86a8](https://github.com/ourzora/zora-protocol/commit/fc8e86a8): - Added Cointags addresses and abis. * Added IUniswapV3Pool ABI. ### 0.3.11 #### Patch Changes * [ff8084fe](https://github.com/ourzora/zora-protocol/commit/ff8084fe): Update implementation contract versions and addresses for erc20z ### 0.3.10 #### Patch Changes * [abbd6333](https://github.com/ourzora/zora-protocol/commit/abbd6333): Added smart wallet factory deployment and abi ### 0.3.9 #### Patch Changes * [4928687d](https://github.com/ourzora/zora-protocol/commit/4928687d): - Include the `Comments` and `CallerAndCommenter` abis and deployed addresses. * Added new exports for Comments contract cross-chain functionality: * Introduced `permitCommentTypedDataDefinition` function to generate typed data for cross-chain permit commenting * Introduced `permitSparkCommentTypedDataDefinition` function to generate typed data for cross-chain permit sparking * Introduced `permitTimedSaleMintAndCommentTypedDataType` to generate typed data for cross-chain permit minting and commenting. * Introduced `permitBuyOnSecondaryAndCommentTypedDataDefinition` function to generate typed data for cross-chain permit buying on secondary and commenting. * Added `sparkValue` helper function to get the value of a Spark ### 0.3.8 #### Patch Changes * [ad707434](https://github.com/ourzora/zora-protocol/commit/ad707434): Updated the 1155 Implementation reduceSupply function to be gated to the `TimedSaleStrategy` constructor argument to ensure markets are launched when desired. * [2e68a87c](https://github.com/ourzora/zora-protocol/commit/2e68a87c): Updated 1155 impl versions and addresses * [17cc9821](https://github.com/ourzora/zora-protocol/commit/17cc9821): Publishing `SponsoredSparksSpender` addresses and abi ### 0.3.7 #### Patch Changes * [c08ec3b3](https://github.com/ourzora/zora-protocol/commit/c08ec3b3): Deployed SponsoredSparksSpender to more chains ### 0.3.6 #### Patch Changes * [d6aa9a00](https://github.com/ourzora/zora-protocol/commit/d6aa9a00): Fixed the minter address for ZoraTimedSaleStrategy to point to the deterministically deployed address with the correct contract version. ### 0.3.5 #### Patch Changes * [4a29c2b9](https://github.com/ourzora/zora-protocol/commit/4a29c2b9): Bump viem to 2.21.21 ### 0.3.4 #### Patch Changes * [66f33bbb](https://github.com/ourzora/zora-protocol/commit/66f33bbb): fix: update secondary swap helper contract address ### 0.3.3 #### Patch Changes * [b885539f](https://github.com/ourzora/zora-protocol/commit/b885539f): Publish weth addresses ### 0.3.2 #### Patch Changes * [247ebc86](https://github.com/ourzora/zora-protocol/commit/247ebc86): update for timed sales v2 * [24520e9a](https://github.com/ourzora/zora-protocol/commit/24520e9a): Fix sdk setSale for v2 params ### 0.3.1 #### Patch Changes * [d221894d](https://github.com/ourzora/zora-protocol/commit/d221894d): Fix royalties contract address. Include secondary swap address * [f94e5f03](https://github.com/ourzora/zora-protocol/commit/f94e5f03): Deployed secondary swap to rest of chains ### 0.3.0 #### Minor Changes * [58f59243](https://github.com/ourzora/zora-protocol/commit/58f59243): Including erc20z contracts in protocol-deployments #### Patch Changes * [b5a7fac4](https://github.com/ourzora/zora-protocol/commit/b5a7fac4): Deployed latest 1155 to base and base sepolia ### 0.2.2 #### Patch Changes * [12909b5b](https://github.com/ourzora/zora-protocol/commit/12909b5b): Export sparks sponsored mints spender abi, address, and typed data definition * [58914a0c](https://github.com/ourzora/zora-protocol/commit/58914a0c): Deployed latest 1155 version to zora mainnet, zora sepolia, sepolia ### 0.2.1 #### Patch Changes * [527aa518](https://github.com/ourzora/zora-protocol/commit/527aa518): Move from yarn to pnpm properly pinning deps packages ### 0.2.0 #### Minor Changes * [0ec838a4](https://github.com/ourzora/zora-protocol/commit/0ec838a4): Publishing Sparks contracts abis and addresses. #### Patch Changes * [898c84a7](https://github.com/ourzora/zora-protocol/commit/898c84a7): \[chore] Update dependencies and runtime scripts This ensures jobs do not match binary names to make runs less ambigious and also that all deps are accounted for. * [e0b5074d](https://github.com/ourzora/zora-protocol/commit/e0b5074d): Updated mainnet 1155 addresses and versions ### 0.1.13 #### Patch Changes * [9cdd81ac](https://github.com/ourzora/zora-protocol/commit/9cdd81ac): Deployed latest version of 1155 contracts, 1155 factory, preminter, and mints manager to: * blast * Optimism mainnet * Base * Arbitrum One * Arbitrum Sepolia * Sepolia ### 0.1.12 #### Patch Changes * [7af9c4db](https://github.com/ourzora/zora-protocol/commit/7af9c4db): Deployed 1155 version 2.9.0 to mainnet, optimism, base, arbitrum one, arbitrum sepolia, blast ### 0.1.11 #### Patch Changes * [399ba552](https://github.com/ourzora/zora-protocol/commit/399ba552): Deployed deterministic proxies to base sepolia. Deployed latest versions to base sepolia. ### 0.1.10 #### Patch Changes * [16deff0c](https://github.com/ourzora/zora-protocol/commit/16deff0c): Moved typed data definitions from `@zoralabs/protocol-sdk` to `@zoralabs/protocol-deployments` ### 0.1.9 #### Patch Changes * [f4641f4b](https://github.com/ourzora/zora-protocol/commit/f4641f4b): Removed dependencies from `zora-1155-contracts`, `1155-deployments`, `mints-contracts`, and `mints-deployments` ### 0.1.8 #### Patch Changes * 8e514b7: Deployed lateset MintsEthUnwrapperAndCaller to chains ### 0.1.7 #### Patch Changes * b6fc3a4: Deployed latest ZoraMintsManagerImpl to zora and zora-sepolia * 5e6a4b0: Added Protocol Rewards and ERC20 Minter abis and addresses to protocol-deployments ### 0.1.6 #### Patch Changes * 9a16b81: Remove graphql-request from hard dependencies in protocol sdk ### 0.1.5 #### Patch Changes * 042edbe: Chain ids in published protocol-deployments package are now numbers instead of strings * 50a4e09: Includes MINTs contracts abis and addresses ### 0.1.4 #### Patch Changes * c2a0a2b: Moved dependencies to devDependencies since they are not needed by external users of the package, they are only used for codegen ### 0.1.3 #### Patch Changes * bb163d3: New preminter impl deployed to mainnet chains ### 0.1.2 #### Patch Changes * 52b16aa: Publishing package in format that supports commonjs imports by specifying exports * Updated dependencies \[52b16aa] * @zoralabs/zora-1155-contracts\@2.7.3 ### 0.1.1 #### Patch Changes * 8d6163c: Deployed to blast & blast sepolia. ### 0.1.0 #### Minor Changes * 653f625: * Configs & addresses bundled in the following format: `contracts{contractName}/addresses|chainConfigs/{chainId}/config` * Including bundled json output for each set of configs/addresses for a contract in the folder `bundled-configs` ### 0.0.14 #### Patch Changes * Added back protocol-deployments - bundling 1155-deployments into it ### 0.0.13 #### Patch Changes * f3332ee: Remove pgn chain configs and addresses * d2085fd: Deployed to Arbitrum One & Arbitrum Sepolia * a51a0cb: Renamed protocol-deployments to 1155-deployments * Updated dependencies \[8107ffe] * @zoralabs/zora-1155-contracts\@2.7.1 ### 0.0.12 #### Patch Changes * 3af77cf: Deploy 2.7.0 to mainnet, zora mainnet, zora sepolia, zora goerli, optimism, base * 23dba1c: Deployed all contracts to sepolia ### 0.0.11 #### Patch Changes * bff853a: Include latest abi in protocol deployments ### 0.0.10 #### Patch Changes * 68c70a9: Tie protocol deployments to v2.5.4 of 1155 * Updated dependencies \[f0c380d] * Updated dependencies \[98e78d7] * Updated dependencies \[050b689] * Updated dependencies \[3f8b18f] * @zoralabs/zora-1155-contracts\@2.6.0 ### 0.0.9 #### Patch Changes * 5156b9e: Deploy latest premint executor to zora sepolia and goerli * Updated dependencies \[7e00197] * @zoralabs/zora-1155-contracts\@2.5.4 ### 0.0.8 #### Patch Changes * 4b77307: Deployed 3.5.3 to zora sepolia and goerli ### 0.0.7 #### Patch Changes * 128b05c: Updated determinstic preminter deployment script to not fail if already deployed * 1d58cd1: Deployed 2.5.2 to zora sepolia and zora goerli * 128b05c: Deployed 2.5.1 to zora sepolia and zora goerli * Updated dependencies \[e4edaac] * @zoralabs/zora-1155-contracts\@2.5.2 ### 0.0.6 #### Patch Changes * f3b7df8: Deployed 2.4.0 with collaborators to zora-goerli, zora-sepolia, base, optimism, mainnet * Updated dependencies \[885ffa4] * Updated dependencies \[ffb5cb7] * Updated dependencies \[ffb5cb7] * Updated dependencies \[d84721a] * Updated dependencies \[cacb543] * @zoralabs/zora-1155-contracts\@2.5.0 ### 0.0.5 #### Patch Changes * 293e2c0: Moved deployment related code from 1155 to protocol-deployments package ### 0.0.4 #### Patch Changes * 6cfb6f9: Add Zora mainnet 1155 v2.3.1 deploy ### 0.0.3 #### Patch Changes * 85bdd23: Update Zora Network addresses to v2.3.0 ### 0.0.2 #### Patch Changes * 4d79b49: Deployed to zora sepolia * b62e471: created new package `protocol-deployments` that includes the deployed contract addresses. * 1155-contracts js no longer exports deployed addresses, just the abis * premint-sdk imports deployed addresses from \`protocol-deployments * 7d1a4c1: Deployed 2.3.0 to zora goerli ### 0.0.2-premint-api.2 #### Patch Changes * c29e080: Update retry and error reporting ### 0.0.2-premint-api.1 #### Patch Changes * 6eaf7bb: add retries ### 0.0.2-premint-api.0 #### Patch Changes * Updated dependencies \[8395b8e] * Updated dependencies \[aae756b] * Updated dependencies \[cf184b3] * @zoralabs/zora-1155-contracts\@2.1.1-premint-api.0 ## @zoralabs/protocol-sdk Changelog ### 0.13.22 #### Patch Changes * fbb389583: Bump viem to 2.53.1 Raise the pinned viem version from 2.22.12 to 2.53.1 across the monorepo to pick up newer chain definitions and support the latest x402 v2 client packages. * Updated dependencies \[fbb389583] * @zoralabs/protocol-deployments\@0.7.6 ### 0.13.21 #### Patch Changes * Updated dependencies [625684d2](https://github.com/ourzora/zora-protocol/commit/625684d2) * Updated dependencies [50134ebc](https://github.com/ourzora/zora-protocol/commit/50134ebc) * @zoralabs/protocol-deployments\@0.7.5 ### 0.13.20 #### Patch Changes * Updated dependencies [78dffbdc](https://github.com/ourzora/zora-protocol/commit/78dffbdc) * @zoralabs/protocol-deployments\@0.7.4 ### 0.13.19 #### Patch Changes * Updated dependencies [67d27f1d](https://github.com/ourzora/zora-protocol/commit/67d27f1d) * Updated dependencies [27f588b2](https://github.com/ourzora/zora-protocol/commit/27f588b2) * @zoralabs/protocol-deployments\@0.7.3 ### 0.13.18 #### Patch Changes * Updated dependencies [668bfa3c](https://github.com/ourzora/zora-protocol/commit/668bfa3c) * @zoralabs/protocol-deployments\@0.7.2 ### 0.13.17 #### Patch Changes * Updated dependencies [9af2904a](https://github.com/ourzora/zora-protocol/commit/9af2904a) * @zoralabs/protocol-deployments\@0.7.1 ### 0.13.16 #### Patch Changes * Updated dependencies [5d656794](https://github.com/ourzora/zora-protocol/commit/5d656794) * @zoralabs/protocol-deployments\@0.7.0 ### 0.13.15 #### Patch Changes * Updated dependencies [9391359c](https://github.com/ourzora/zora-protocol/commit/9391359c) * @zoralabs/protocol-deployments\@0.6.5 ### 0.13.14 #### Patch Changes * Updated dependencies [3c274d9d](https://github.com/ourzora/zora-protocol/commit/3c274d9d) * @zoralabs/protocol-deployments\@0.6.4 ### 0.13.13 #### Patch Changes * Updated dependencies [131c719a](https://github.com/ourzora/zora-protocol/commit/131c719a) * Updated dependencies [cdaa9d25](https://github.com/ourzora/zora-protocol/commit/cdaa9d25) * @zoralabs/protocol-deployments\@0.6.3 ### 0.13.12 #### Patch Changes * [37006b7d](https://github.com/ourzora/zora-protocol/commit/37006b7d): Rewriting account input for SDK calls ### 0.13.11 #### Patch Changes * Updated dependencies [262d1539](https://github.com/ourzora/zora-protocol/commit/262d1539) * @zoralabs/protocol-deployments\@0.6.2 ### 0.13.10 #### Patch Changes * Updated dependencies [9035ce3b](https://github.com/ourzora/zora-protocol/commit/9035ce3b) * @zoralabs/protocol-deployments\@0.6.1 ### 0.13.9 #### Patch Changes * Updated dependencies [73784d07](https://github.com/ourzora/zora-protocol/commit/73784d07) * Updated dependencies [9adcb702](https://github.com/ourzora/zora-protocol/commit/9adcb702) * Updated dependencies [9adcb702](https://github.com/ourzora/zora-protocol/commit/9adcb702) * @zoralabs/protocol-deployments\@0.6.0 ### 0.13.8 #### Patch Changes * Updated dependencies [8cd56863](https://github.com/ourzora/zora-protocol/commit/8cd56863) * @zoralabs/protocol-deployments\@0.5.10 ### 0.13.7 #### Patch Changes * Updated dependencies [73e95f69](https://github.com/ourzora/zora-protocol/commit/73e95f69) * Updated dependencies [0c50e8e7](https://github.com/ourzora/zora-protocol/commit/0c50e8e7) * @zoralabs/protocol-deployments\@0.5.6 ### 0.13.6 #### Patch Changes * Updated dependencies [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76) * Updated dependencies [ce3022d8](https://github.com/ourzora/zora-protocol/commit/ce3022d8) * Updated dependencies [ce3022d8](https://github.com/ourzora/zora-protocol/commit/ce3022d8) * Updated dependencies [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76) * Updated dependencies [9ed0ce76](https://github.com/ourzora/zora-protocol/commit/9ed0ce76) * @zoralabs/protocol-deployments\@0.5.5 ### 0.13.5 #### Patch Changes * Updated dependencies [23f723dd](https://github.com/ourzora/zora-protocol/commit/23f723dd) * @zoralabs/protocol-deployments\@0.5.4 ### 0.13.4 #### Patch Changes * Updated dependencies [70b039ce](https://github.com/ourzora/zora-protocol/commit/70b039ce) * @zoralabs/protocol-deployments\@0.5.3 ### 0.13.3 #### Patch Changes * Updated dependencies [ed9f7741](https://github.com/ourzora/zora-protocol/commit/ed9f7741) * @zoralabs/protocol-deployments\@0.5.2 ### 0.13.2 #### Patch Changes * Updated dependencies [11854bbe](https://github.com/ourzora/zora-protocol/commit/11854bbe) * @zoralabs/protocol-deployments\@0.5.1 ### 0.13.1 #### Patch Changes * Updated dependencies [e1a3d68f](https://github.com/ourzora/zora-protocol/commit/e1a3d68f) * @zoralabs/protocol-deployments\@0.5.0 ### 0.13.0 #### Minor Changes * [cf90efbc](https://github.com/ourzora/zora-protocol/commit/cf90efbc): Remove ability to create and update premints ### 0.12.2 #### Patch Changes * Updated dependencies [1e10ac74](https://github.com/ourzora/zora-protocol/commit/1e10ac74) * @zoralabs/protocol-deployments\@0.4.2 ### 0.12.1 #### Patch Changes * Updated dependencies [855112de](https://github.com/ourzora/zora-protocol/commit/855112de) * @zoralabs/protocol-deployments\@0.4.1 ### 0.12.0 #### Minor Changes * [2a9d2e86](https://github.com/ourzora/zora-protocol/commit/2a9d2e86): Changed how we determine which ERC20Z tokens have secondary royalties by querying the royalties contract directly instead of using the subgraph's secondaryActivated field. BREAKING: The `withdrawRewards` and `getRewardsBalances` functions now require a `publicClient` parameter to query the royalties contract. Update your calls to include the publicClient when using these functions. * [615d81cf](https://github.com/ourzora/zora-protocol/commit/615d81cf): Deprecated createCreatorClient and createCollectorClient in favor of using functions directly ### 0.11.12 #### Patch Changes * Updated dependencies [fc8e86a8](https://github.com/ourzora/zora-protocol/commit/fc8e86a8) * @zoralabs/protocol-deployments\@0.4.0 ### 0.11.11 #### Patch Changes * [ff8084fe](https://github.com/ourzora/zora-protocol/commit/ff8084fe): Updates `minimumMintsForCountdown` and `mintCount` calculations to use the updated 0.0000222 ETH market reward live in v2.2.0 of the timed sale strategy * [2ce16ac7](https://github.com/ourzora/zora-protocol/commit/2ce16ac7): Move from allowlist.zora.co to lanyard.org for allowlist manager service * Updated dependencies [ff8084fe](https://github.com/ourzora/zora-protocol/commit/ff8084fe) * @zoralabs/protocol-deployments\@0.3.11 ### 0.11.10 #### Patch Changes * [a1137e35](https://github.com/ourzora/zora-protocol/commit/a1137e35): saleStart defaults to current timestamp in seconds * Updated dependencies [abbd6333](https://github.com/ourzora/zora-protocol/commit/abbd6333) * @zoralabs/protocol-deployments\@0.3.10 ### 0.11.9 #### Patch Changes * [9d5d1638](https://github.com/ourzora/zora-protocol/commit/9d5d1638): When minting + commenting, and using the timed sale strategy, protocol sdk will call the CallerAndCommenter contract * [088ec6fb](https://github.com/ourzora/zora-protocol/commit/088ec6fb): When buying on secondary, you can now add a comment, which will call the CallerAndCommenter's buyOnSecondaryAndComment function. * Updated dependencies [4928687d](https://github.com/ourzora/zora-protocol/commit/4928687d) * @zoralabs/protocol-deployments\@0.3.9 ### 0.11.8 #### Patch Changes * [330f1131](https://github.com/ourzora/zora-protocol/commit/330f1131): Fix royalties queries to filter by erc20z that have secondary activated ### 0.11.7 #### Patch Changes * [041871d7](https://github.com/ourzora/zora-protocol/commit/041871d7): Fix royalties query for secondary tokens to query subgraph for royaltyRecipient instead of user. ### 0.11.6 #### Patch Changes * Updated dependencies [ad707434](https://github.com/ourzora/zora-protocol/commit/ad707434) * Updated dependencies [2e68a87c](https://github.com/ourzora/zora-protocol/commit/2e68a87c) * Updated dependencies [17cc9821](https://github.com/ourzora/zora-protocol/commit/17cc9821) * @zoralabs/protocol-deployments\@0.3.8 ### 0.11.5 #### Patch Changes * [85d09fa5](https://github.com/ourzora/zora-protocol/commit/85d09fa5): - Adds new fields to `SecondaryInfo` type to expose more information about the secondary market configuration: * `name`: The ERC20Z token name * `symbol`: The ERC20Z token symbol * `saleStart`: Earliest time tokens can be minted * `marketCountdown`: Time after minimum mints reached until secondary market launches * `minimumMintsForCountdown`: Minimum mints required to start countdown * `mintCount`: Total number of tokens minted so far * Deprecates `minimumMarketEth` parameter in favor of `minimumMintsForCountdown` when creating tokens: * `minimumMintsForCountdown` directly specifies minimum number of mints (defaults to `1111`) * `minimumMarketEth` is still supported but calculated internally as `minimumMintsForCountdown * 0.0000111 ETH` * Updated dependencies [c08ec3b3](https://github.com/ourzora/zora-protocol/commit/c08ec3b3) * @zoralabs/protocol-deployments\@0.3.7 ### 0.11.4 #### Patch Changes * Updated dependencies [d6aa9a00](https://github.com/ourzora/zora-protocol/commit/d6aa9a00) * @zoralabs/protocol-deployments\@0.3.6 ### 0.11.3 #### Patch Changes * [364d7906](https://github.com/ourzora/zora-protocol/commit/364d7906): Change DEFAULT\_MINIMUM\_MARKET\_ETH to 0.0123321 eth (1,111 mints) to match default that is set on zora.co * [e68ce881](https://github.com/ourzora/zora-protocol/commit/e68ce881): Fix filtering for active markets * [4a29c2b9](https://github.com/ourzora/zora-protocol/commit/4a29c2b9): Bump viem to 2.21.21 * Updated dependencies [4a29c2b9](https://github.com/ourzora/zora-protocol/commit/4a29c2b9) * @zoralabs/protocol-deployments\@0.3.5 ### 0.11.2 #### Patch Changes * [66f33bbb](https://github.com/ourzora/zora-protocol/commit/66f33bbb): fix: update secondary swap helper contract address * [8d7fdc02](https://github.com/ourzora/zora-protocol/commit/8d7fdc02): For the functions `getToken` and `getTokensOfContract`, the returned `MintableReturn` type has been updated to provide more information about the primary mint status: * Added `primaryMintActive` boolean to indicate if the primary mint is currently active. * Added `primaryMintEnd` optional `bigint` to show the end time of the primary mint, if applicable. * Added `secondaryMarketActive` boolean to indicate if the secondary market is currently active. * Modified `prepareMint` to be conditionally available: * When `primaryMintActive` is `true`, `prepareMint` is available as a `PrepareMint` function. * When `primaryMintActive` is `false`, `prepareMint` is set to `undefined`. This allows for developers to know if the primary mint is active or not, and if not, if they should buy on secondary. * Updated dependencies [66f33bbb](https://github.com/ourzora/zora-protocol/commit/66f33bbb) * @zoralabs/protocol-deployments\@0.3.4 ### 0.11.1 #### Patch Changes * Updated dependencies [b885539f](https://github.com/ourzora/zora-protocol/commit/b885539f) * @zoralabs/protocol-deployments\@0.3.3 ### 0.11.0 #### Minor Changes * [21247473](https://github.com/ourzora/zora-protocol/commit/21247473): Added new functions `buy1155OnSecondary` and `sell1155OnSecondary` to the collector client in the protocol SDK. These functions enable users to buy and sell ERC1155 tokens on the secondary market. Key features include: * Slippage protection for both buying and selling operations * Detailed price breakdowns in wei, sparks, and USDC * Support for specifying recipient addresses * Error handling and simulation parameters ### 0.10.0 #### Minor Changes * [fc4a7f65](https://github.com/ourzora/zora-protocol/commit/fc4a7f65): Support viewing and withdrawing protocol rewards and secondary royalties balances from the sdk, using the new methods `getRewardsBalances` and `withdrawRewards`. ### 0.9.6 #### Patch Changes * [24520e9a](https://github.com/ourzora/zora-protocol/commit/24520e9a): Fix sdk setSale for v2 params * Updated dependencies [247ebc86](https://github.com/ourzora/zora-protocol/commit/247ebc86) * Updated dependencies [24520e9a](https://github.com/ourzora/zora-protocol/commit/24520e9a) * @zoralabs/protocol-deployments\@0.3.2 ### 0.9.5 #### Patch Changes * [879a019a](https://github.com/ourzora/zora-protocol/commit/879a019a): - Fixed types, defaults, and queries for v2 timed sales ### 0.9.4 #### Patch Changes * [b9fcab20](https://github.com/ourzora/zora-protocol/commit/b9fcab20): Removed unneeded async in token setup * Updated dependencies [d221894d](https://github.com/ourzora/zora-protocol/commit/d221894d) * Updated dependencies [f94e5f03](https://github.com/ourzora/zora-protocol/commit/f94e5f03) * Updated dependencies [1b4d5ee7](https://github.com/ourzora/zora-protocol/commit/1b4d5ee7) * @zoralabs/protocol-deployments\@0.3.1 ### 0.9.3 #### Patch Changes * [c75eb65b](https://github.com/ourzora/zora-protocol/commit/c75eb65b): Fix bug where for timed sale strategy, sales settings were not being set. For getting default erc20 name, get it from the contract name instead of fetching from ipfs. ### 0.9.2 #### Patch Changes * [5f964909](https://github.com/ourzora/zora-protocol/commit/5f964909): To speed up performance for `create1155OnExistingContract`, use subgraph to get contract info and reduce quantity of rpc reads. ### 0.9.1 #### Patch Changes * [f40c4a8f](https://github.com/ourzora/zora-protocol/commit/f40c4a8f): `create1155` and `create1155OnExistingContract` return an async `prepareMint` function, enabling to mint right after creating without needing to rely on the subgraph. ### 0.9.0 #### Minor Changes * [8c50a99c](https://github.com/ourzora/zora-protocol/commit/8c50a99c): Add support for creating 1155s and collecting using the new ZoraTimedSaleStrategy. Default to using the new ZoraTimedSaleStrategy as a minter for new 1155s. #### Patch Changes * [47c20f4d](https://github.com/ourzora/zora-protocol/commit/47c20f4d): - Added support for allowlist mint creation and collection * For creating an erc20 mint, the parameter `type` must be set to `erc20Mint` on the `token.salesConfig` object ### 0.8.0 #### Minor Changes * [5417f4dd](https://github.com/ourzora/zora-protocol/commit/5417f4dd): ProtocolSdk `create1155` can only be used for new contracts, and returns the correct deterministic contract address. A new function `create1155OnExistingContract` is added to support creating 1155 tokens on existing contracts ### 0.7.6 #### Patch Changes * Updated dependencies [58f59243](https://github.com/ourzora/zora-protocol/commit/58f59243) * Updated dependencies [b5a7fac4](https://github.com/ourzora/zora-protocol/commit/b5a7fac4) * @zoralabs/protocol-deployments\@0.3.0 ### 0.7.5 #### Patch Changes * [12909b5b](https://github.com/ourzora/zora-protocol/commit/12909b5b): Renamed Mints to Sparks * Updated dependencies [12909b5b](https://github.com/ourzora/zora-protocol/commit/12909b5b) * Updated dependencies [58914a0c](https://github.com/ourzora/zora-protocol/commit/58914a0c) * @zoralabs/protocol-deployments\@0.2.2 ### 0.7.4 #### Patch Changes * [527aa518](https://github.com/ourzora/zora-protocol/commit/527aa518): Move from yarn to pnpm properly pinning deps packages * Updated dependencies [527aa518](https://github.com/ourzora/zora-protocol/commit/527aa518) * @zoralabs/protocol-deployments\@0.2.1 ### 0.7.3 #### Patch Changes * [898c84a7](https://github.com/ourzora/zora-protocol/commit/898c84a7): \[chore] Update dependencies and runtime scripts This ensures jobs do not match binary names to make runs less ambigious and also that all deps are accounted for. * Updated dependencies [898c84a7](https://github.com/ourzora/zora-protocol/commit/898c84a7) * Updated dependencies [0ec838a4](https://github.com/ourzora/zora-protocol/commit/0ec838a4) * Updated dependencies [e0b5074d](https://github.com/ourzora/zora-protocol/commit/e0b5074d) * @zoralabs/protocol-deployments\@0.2.0 ### 0.7.2 #### Patch Changes * [cd5ac235](https://github.com/ourzora/zora-protocol/commit/cd5ac235): protocol sdk gets mint price from the default mint price entity on the subgraph ### 0.7.1 #### Patch Changes * [5c009569](https://github.com/ourzora/zora-protocol/commit/5c009569): Added metadata builder methods to sdk. sdk's method createPremint returns collect/manage urls ### 0.7.0 #### Minor Changes * [f52f28f3](https://github.com/ourzora/zora-protocol/commit/f52f28f3): Added methods to Collector Client: getToken, getTokensOfContract ### 0.6.0 #### Minor Changes * [8c23f05b](https://github.com/ourzora/zora-protocol/commit/8c23f05b): - new high-level sdks: `createCreatorClient` and `createCollectorClient`. `createPremintClient`, `createMintClient`, `create1155CreatorClient`, and `createPremintClient` are removed. * external apis, such as the premint api can be stubbed/replaced/mocked. * new function `mint` on the collector sdk that works with `1155`, `premint`, and `721`s. * `create1155` now supports creating erc20, free, and paid mints. Setup actions now mimic what's on zora.co. #### Patch Changes * [b0f0fb74](https://github.com/ourzora/zora-protocol/commit/b0f0fb74): premintClient - fix default mint duration to be unlimited (it was one week before) ### 0.5.17 #### Patch Changes * [b16078bc](https://github.com/ourzora/zora-protocol/commit/b16078bc): * premintClient now supports creating/minting premints with additional admins. * premint client supports creating premints with just a collection address, as long as the premint has been brought onchain * [502f3295](https://github.com/ourzora/zora-protocol/commit/502f3295): premint sdk - on createPremint, `payoutRecipient` argument moved to `tokenCreationConfig`. premintConfigVersion is no longer an argument; the sdk automatically figures out which is the appropriate version * Updated dependencies [9cdd81ac](https://github.com/ourzora/zora-protocol/commit/9cdd81ac) * @zoralabs/protocol-deployments\@0.1.13 ### 0.5.16 #### Patch Changes * [12387133](https://github.com/ourzora/zora-protocol/commit/12387133): `create1155CreatorClient` requires `chain` to be passed as a default argument instead of a `publicClient` * Updated dependencies [7af9c4db](https://github.com/ourzora/zora-protocol/commit/7af9c4db) * @zoralabs/protocol-deployments\@0.1.12 ### 0.5.15 #### Patch Changes * [888168b8](https://github.com/ourzora/zora-protocol/commit/888168b8): Fix protocol-sdk to point to `isAuthorizedToCreatePremint` * [344f452b](https://github.com/ourzora/zora-protocol/commit/344f452b): Add support for ERC-20 minting on 1155s using ERC20 minters within the function `makePrepareMintTokenParams`. ### 0.5.14 #### Patch Changes * [1a4aa02d](https://github.com/ourzora/zora-protocol/commit/1a4aa02d): Remove graphql-request library and add base sepolia * Updated dependencies [399ba552](https://github.com/ourzora/zora-protocol/commit/399ba552) * @zoralabs/protocol-deployments\@0.1.11 ### 0.5.13 #### Patch Changes * [16deff0c](https://github.com/ourzora/zora-protocol/commit/16deff0c): Moved typed data definitions from protocol-sdk to protocol-deployments * Updated dependencies [16deff0c](https://github.com/ourzora/zora-protocol/commit/16deff0c) * @zoralabs/protocol-deployments\@0.1.10 ### 0.5.12 #### Patch Changes * [e2452f7d](https://github.com/ourzora/zora-protocol/commit/e2452f7d): Removed `zora-1155-contracts`, `1155-deployments`, `mints-contracts`, and `mints-deployments` from devDependencies hierarchy. ### 0.5.11 #### Patch Changes * 8e514b7: Cleanup protocol-sdk to have better docs around all methods, and remove methods that do not need to be exported and are not used. * 598a95b: Bumps protocol-sdk to use viem\@2.x- see the [viem 2.X.X migration guide](https://viem.sh/docs/migration-guide#2xx-breaking-changes) for breaking changes when migratring from viem 1.X.X to 2.X.X * Updated dependencies \[8e514b7] * @zoralabs/protocol-deployments\@0.1.8 ### 0.5.10 #### Patch Changes * Updated dependencies \[9a16b81] * @zoralabs/protocol-deployments\@0.1.6 ### 0.5.9 #### Patch Changes * 825e5f7: Adds optional `createReferral` to `createNew1155Token` params ### 0.5.8 #### Patch Changes * 50a4e09: Added sdk method to get total MINT balance * Updated dependencies \[042edbe] * Updated dependencies \[50a4e09] * @zoralabs/protocol-deployments\@0.1.5 ### 0.5.7 #### Patch Changes * 2eda168: Update default premint version to v2 * 4066420: Adding protocol SDK to base and sepolia networks * Updated dependencies \[bb163d3] * @zoralabs/protocol-deployments\@0.1.3 ### 0.5.6 #### Patch Changes * 52b16aa: Publishing package in format that supports commonjs imports by specifying exports * Updated dependencies \[52b16aa] * @zoralabs/protocol-deployments\@0.1.2 ### 0.5.5 #### Patch Changes * 8a87809: Undo changes to package export because it didn't properly bundle all files in `dist` ### 0.5.4 #### Patch Changes * 9710e5e: Defining exports in protocol-sdk ### 0.5.3 #### Patch Changes * a07499d: Allows an `Account` object to be passed for `signTypedData` compatiblity with Local Accounts ### 0.5.2 #### Patch Changes * 5c536dc: Update optimism eth constant * Updated dependencies \[f3332ee] * Updated dependencies \[d2085fd] * Updated dependencies \[a51a0cb] * @zoralabs/1155-deployments\@0.0.13 ### 0.5.1 #### Patch Changes * 73070c0: * Fix types export - make sure that types are exported to the correct directory. Broken by commit 627f8c37716f0b5c201f75ab1d025ae878be0ae29e7a269d21185fa04e4bcf93 * Exclude tests from built bundle * Fixes #396 ### 0.5.0 #### Minor Changes * a52d245: Fix premint v2 support in premint client and add support for sepolia to SDK: * Fix chain constants config for Zora Goerli. * Support Zora-Sepolia for premint client. * Fix passing of `config_version` to and from the backend API. * Change parameter on `makeMintParameters` from `account` to `minterAccount`. * Fix price minter address for premint client by chain, since it is not the same on all chains (yet). #### Patch Changes * Updated dependencies \[3af77cf] * Updated dependencies \[23dba1c] * @zoralabs/protocol-deployments\@0.0.12 ### 0.4.3 #### Patch Changes * 92b1b0e: Export premint conversions ### 0.4.2 #### Patch Changes * 9b03ed2: Support premint v2 in sdk * Updated dependencies \[bff853a] * @zoralabs/protocol-deployments\@0.0.11 ### 0.4.1 #### Patch Changes * 7e00197: \* For premintV1 and V2 - mintReferrer has been changed to an array `mintRewardsRecipients` - which the first element in array is `mintReferral`, and second element is `platformReferral`. `platformReferral is not used by the premint contract yet`. * 0ceb709: Add mint costs getter for premint to protocol sdk * Updated dependencies \[5156b9e] * @zoralabs/protocol-deployments\@0.0.9 ### 0.4.0 #### Minor Changes * 28884c9: \* `PremintClient` now takes a premint config v1 or v2, and a premint config version, for every call to create/update/delete a premint. PremintClient methods have been simplified and are easier to use - for example `createPremint` no longer allows to specify `deleted` = true. For `makeMintParameters` - it now just takes the uid and contract address (instead of full premint config) * `PremintAPIClient` now converts entities to contract entities before returning them, and correspondingly expects them as contract entities when passed in. It internally converts them to backend entities before sending them to the backend. #### Patch Changes * Updated dependencies \[4b77307] * @zoralabs/protocol-deployments\@0.0.8 ### 0.3.5 #### Patch Changes * 7eb5e3f: ### Changes to `preminter` lower level `preminter.ts` now supports premint v2 by defining v2 typed data defintions. * `isValidSignature` now takes either v1 or v2 of a premint config, along with the premint config version. and both recovers the signer address and validates if the signer can create a premint on the given contract. * new function `premintTypedDataDefinition` which takes a premint config version and returns the signable typed data definition for that version * new function `recoverCreatorFromCreatorAttribution` which recovers the creator address from a `CreatorAttribution` event * new function `supportsPremintVersion` which checks if a given token contract supports a given premint config version * new function `tryRecoverPremintSigner` which takes a premint config version and a premint signature, and tries to recover the signer address from the signature. If the signature is invalid, it returns undefined. #### Changes to PremintClient `PremintClient` creation, updating, and deletion now take both premint config v1 and v2, but currently rejects them until the backend api supports creating v2 premints. * `isValidSignature` now just takes the data directly as a param, instead of `{data}` * 27a2e23: Fix reading the FIXED\_PRICE\_MINTER from the subgraph ### 0.3.4 #### Patch Changes * ea27f01: Fix reading the FIXED\_PRICE\_MINTER from the subgraph ### 0.3.3 #### Patch Changes * 97f58b3: `MintAPIClient` is now a class, that takes a chain id and httpClient in the constructor, enabling the httpClient methods `fetch`, `post`, and `retries` to be overridden. new methods on `MintAPIClient`: `getMintableForToken` - takes a token id and token contract address and returns the mintable for it. Easier to use for fetching specific tokens than `getMintable`. `MintClient` now takes the optional `PublicClient` in the constructor instead of in each function, and stores it or creates a default one if none is provided in the constructor. It also takes an optional `httpClient` param in the constructor, allowing the `fetch`, `post`, and `retries` methods to be overridden when using the api. It now internally creates the MintAPIClient. `MintClient.makePrepareMintTokenParams` has the following changes: * returns a `SimulateContractParams`, instead of an object containing it indexed by key * no longer takes a `PublicClient` as an argument (it should be specified in the constructor instead) new function `MintClient.getMintCosts` takes a mintable and quantity to mint and returns the mintFee, paidMintPrice, and totalCost. * d02484e: premintClient can have http methods overridable via DI, and now takes publicClient and http overrides in `createPremintClient` function. it no longer takes `publicClient` as an argument in functions, and rather uses them from the constructor. `executePremint` has been renamed ot `makeMintParameters` ### 0.3.2 #### Patch Changes * de0b0b7: `preminter` exposes new function isValidSignatureV1 that recovers a signer from a signed premint and determines if that signer is authorized to sign * Updated dependencies \[f3b7df8] * @zoralabs/protocol-deployments\@0.0.6 ### 0.3.1 #### Patch Changes * 92da3ed: Exporting mint client * Updated dependencies \[293e2c0] * @zoralabs/protocol-deployments\@0.0.5 ### 0.3.0 #### Minor Changes * 40e0b32: * rename premint-sdk to protocol-sdk * added minting sdk, usable with `createMintClient` * added 1155 creation sdk, usable with `create1155CreatorClient` * premint sdk is now useable with `createPremintClient` ### 0.1.1 #### Patch Changes * b62e471: created new package `protocol-deployments` that includes the deployed contract addresses. * 1155-contracts js no longer exports deployed addresses, just the abis * premint-sdk imports deployed addresses from \`protocol-deployments * Updated dependencies \[4d79b49] * Updated dependencies \[b62e471] * Updated dependencies \[7d1a4c1] * @zoralabs/protocol-deployments\@0.0.2 ### 0.1.0 #### Minor Changes * 4afa879: Added new premint api that abstracts out calls to the chain signature and submission logic around submitting a premint. This change also incorporates test helpers for premints and introduces docs and an api client for the zora api's premint module. #### Patch Changes * Updated dependencies \[4afa879] * @zoralabs/zora-1155-contracts\@2.3.0 ### 0.0.2-premint-api.2 #### Patch Changes * c29e080: Update retry and error reporting ### 0.0.2-premint-api.1 #### Patch Changes * 6eaf7bb: add retries ### 0.0.2-premint-api.0 #### Patch Changes * Updated dependencies \[8395b8e] * Updated dependencies \[aae756b] * Updated dependencies \[cf184b3] * @zoralabs/zora-1155-contracts\@2.1.1-premint-api.0 ## Bug Bounty Program *Updated August 2026* :::warning **Program status: paused as of August 10, 2026.** The Zora Bug Bounty Program is not accepting new submissions while paused, and reports submitted during this period are not eligible for rewards. Security remains a priority. If you believe you have found a vulnerability that puts user funds at active and immediate risk, please still email [security@zora.co](mailto\:security@zora.co) with full reproduction details. ::: #### Security at Zora At Zora, we prioritize the safety and security for all of our users and community members. We encourage and value any feedback from our community to help us identify and promptly address any potential vulnerabilities in our product. #### Report Submission Guidelines To submit your report, please email [security@zora.co](mailto\:security@zora.co) and include the following information: * **Issue Description**: A clear explanation of the vulnerability and its potential impact. * **Location**: The exact location or component where the issue was found. * **Steps to Reproduce**: Include detailed steps to reproduce the issue. * **Proof of Concept**: Include proof-of-concept code, screenshots, videos, logs, etc. demonstrating the vulnerability. Upon receiving your report, a member of our security team will confirm receipt and initiate an investigation into the reported issue. We are committed to keeping you informed with the progress of the investigation. If we require additional information or clarification, we will reach out to you directly. #### Bug Bounty Rewards * Critical vulnerabilities that could lead to loss of funds may earn up to $40,000. Rewards are paid in USDC (USD-denominated) and require: * An ERC20 compatible wallet address. * KYC verification in cases where a reward is issued. #### Scope The assets listed below are considered in-scope within our bug bounty program. If you discover a vulnerability outside these specified areas, please report it to our team for further investigation. | Asset | Type | Scope | Eligible Reward | | ---------------------------------------------------------------------------------------------------------------------- | ------------------------ | -------- | --------------- | | [zora.co/create](https://zora.co/create)
zora.co/coin/base:\[contract address]
zora.co/\[profile address] | Website and Applications | In scope | Up to $10,000 | | [api.zora.co](https://api.zora.co) | Website and Applications | In scope | Up to $2,000 | | [docs.zora.co](https://docs.zora.co) | Website and Applications | In scope | Up to $5,000 | | [zora protocol](https://github.com/ourzora/zora-protocol) | Smart Contracts | In scope | Up to $40,000 | | [Zora iOS App](https://apps.apple.com/us/app/zora-post-and-trade-content/id6474192103) | Mobile Applications | In scope | Up to $5,000 | | [Zora Android App](https://play.google.com/store/apps/details?id=co.ourzora.app\&hl=en_AU) | Mobile Applications | In scope | Up to $5,000 | #### Out of scope vulnerabilities The following issues are not eligible for rewards: * Denial-of-Service (DoS/DDoS) or any activity that disrupts service availability. * Vulnerabilities requiring physical access to a user’s device. * Theoretical or speculative issues without proof-of-concept. * Clickjacking on non-sensitive pages. * Attacks requiring leaked keys or compromised credentials. * Self-XSS issues. * Missing cookie flags on non-sensitive cookies. * Misconfigured or lack of SPF/DMARC/DNSSEC/CAA records without demonstrated impact. * Automated scanner output without demonstrated impact. * Issues that cannot be reliably reproduced or that present negligible security risk. * Best practice recommendations. #### Program Rules * Submit one vulnerability per report. * When duplicates occur, we will only accept the first report that was received, as long as it fulfills our submission criteria and can be fully reproduced. * Social engineering attacks targeting Zora staff are strictly prohibited. * Publishing sensitive information discovered during security testing is prohibited. * Vulnerabilities already known to Zora are ineligible for rewards. * Please provide thorough reports with clear steps that can be replicated. If your report lacks sufficient detail to reproduce the issue, it will not be accepted. #### Disclosure Policy For responsible management of vulnerability disclosures, keep all discussions related to these vulnerabilities, including resolved ones, strictly within the program. Additionally, do not disclose them externally within 90 days of remediation or without Zora's explicit consent. Failure to comply with the Disclosure Policy may result in the loss of any potential reward. Your adherence to this policy greatly enhances the program's safety and integrity.