Using the SDK to Gaslessly Create 1155 Contracts and Tokens, aka Premints
Intro to Premints
The Zora Protocol allows creators to create 1155 contracts and tokens without needing to pay any gas or have eth in their wallet. This
is done by creating what's called a Premint
- a signed intent to create and setup an 1155 contract and/or token.
It is then uploading it to an API, where it can be retrieved later to bring onchain and mint by an account willing to pay the gas to do so. This can either be the first collector, or the
original creator of the Premint. The account that brings the Premint onchain will earn the first minter reward.
In order for the Premint to be discoverable in the Zora network, it must be signed by the creator's wallet and uploaded to the Zora Premint API. Before the Premint is brought onchain, the creator of the Premint can sign a message to update or delete it.
Creator Client for Premints
The Zora Protocol SDK encapsulates the complexity for creating, updating and deleting premints, by providing methods that handle building the Premint to sign, signing the Premint, and submitting the Premint and signature to the Zora Premint API so it can be fetched later.
Premints can be collected using the Collect Client's mint().
Setup the Creator Client
Initialize the Creator Client:
import { createCreatorClient } from "@zoralabs/protocol-sdk";
import { zora } from "viem/chains";
const creatorClient = createCreatorClient({ chain: zora });
creatorClient.create1155create1155OnExistingContractcreatePremintdeletePremintgetRewardsBalancesupdatePremintwithdrawRewards
Creating a Premint
The function createPremint
builds a new premint with sensible defaults, and provides methods to
sign and submit it to the Zora Premint API.
Just calling createPremint
does not actually submit the premint to the API; it just builds the premint object and corresponding data to sign.
One of the items returned from create
is signAndSubmit
which must be called with a WalletClient
to sign the premint and submit the premint and signature to the Zora Premint API.
import { createCreatorClient } from "@zoralabs/protocol-sdk";
import { walletClient, chainId, publicClient, creatorAccount } from "./config";
const creatorClient = createCreatorClient({ chainId, publicClient });
// create and sign the Premint, the Premint and signature will be uploaded to an api to be served later
const {
// used to sign and submit the premint to the Zora Premint API
signAndSubmit,
} = await creatorClient.createPremint({
// collection info of collection to create. The combination of these fields will determine the
// deterministic collection address.
contract: {
// the account that will be the admin of the collection. Must match the signer of the premint.
contractAdmin: creatorAccount,
contractName: "Testing Contract",
contractURI:
"ipfs://bafkreiainxen4b4wz4ubylvbhons6rembxdet4a262nf2lziclqvv7au3e",
},
// token info of token to create
token: {
tokenURI:
"ipfs://bafkreice23maski3x52tsfqgxstx3kbiifnt5jotg3a5ynvve53c4soi2u",
// address to get create referral reward
createReferral: "0x5843c8d6007813de3D2313fC55F2Fa1Cbbc394A6",
// maximum number of tokens that can be minted.
maxSupply: 50000n,
// the maximum number of tokens that can be minted to a single address.
maxTokensPerAddress: 10n,
// the earliest time the premint can be brought onchain. 0 for immediate.
mintStart: 0n,
// the duration of the mint. 0 for infinite.
mintDuration: 0n,
// the price in eth per token, for paid mints. 0 for it to be a free mint.
pricePerToken: 0n,
// address to receive creator rewards for free mints, or if its a paid mint, the paid mint sale proceeds.
payoutRecipient: creatorAccount,
},
});
// sign the new premint, and submit it to the Zora Premint API
await signAndSubmit({
// account to sign the premint
account: creatorAccount,
// the walletClient will be used to sign the message.
walletClient,
// if true, the signature will be checked before being submitted.
// this includes validating that the signer is authorized to create the premint.
checkSignature: true,
});
Signing and Submitting Premint using Wagmi
Sometimes it may be desirable to sign a premint with another library, and not using the sdk's signAndSubmit
method.
For this case, the createPremint
, updatePremint
, and deletePremint
functions return a typedDataDefinition
which is the typed data definition for the premint and must be signed.
Once the signature has been obtained, it can be submitted to the Zora Premint API using the submit
method:
import { createCreatorClient } from "@zoralabs/protocol-sdk";
import { useAccount, useChainId, usePublicClient, useSignTypedData } from "wagmi";
const chainId = useChainId();
const publicClient = usePublicClient()!;
const { address: creatorAddress } = useAccount();
const creatorClient = createCreatorClient({ chainId, publicClient });
const {
// data to sign
typedDataDefinition,
// submit will submit the signature and premint to the api
submit
} = await creatorClient.createPremint({
// info of the 1155 contract to create.
contract: {
// the account that will be the admin of the collection.
// Must match the signer of the premint.
contractAdmin: creatorAddress!,
contractName: "Testing Contract",
contractURI:
"ipfs://bafkreiainxen4b4wz4ubylvbhons6rembxdet4a262nf2lziclqvv7au3e",
},
// token info of token to create
token: {
tokenURI:
"ipfs://bafkreice23maski3x52tsfqgxstx3kbiifnt5jotg3a5ynvve53c4soi2u",
payoutRecipient: creatorAddress!,
},
});
const { signTypedData, data: signature } = useSignTypedData();
if (signature) {
submit({
signature
});
}
// when the user clicks to create, sign the typed data
<button onClick={() => signTypedData(typedDataDefinition)}>Create</button>
Updating a Premint
Before a Premint is brought onchain, it can be updated by the original creator of that premint, by having that creator sign a message indicating the update. This signature and updated premint is then submitted to the Zora Premint API and replaces the existing stored premint for the token with the same uid.
import { createCreatorClient } from "@zoralabs/protocol-sdk";
import { walletClient, chainId, creatorAccount, publicClient } from "./config";
import { collection, uid } from "./create";
const creatorClient = createCreatorClient({ chainId, publicClient });
const { signAndSubmit } = await creatorClient.updatePremint({
// the premint collection to update is returned from the `createPremint` call
collection,
// the id of the premint to update
uid,
// updates to the existing token on the premint
tokenConfigUpdates: {
maxTokensPerAddress: 100n,
},
});
// sign and submit the update to the Premint
await signAndSubmit({
walletClient,
account: creatorAccount,
});
Deleting a Premint
Before a premint is brought onchain, it can be deleted by the original creator of that premint, by having that creator sign a message indicating that the premint should be deleted. This signature and deleted premint is then submitted to the Zora Premint API and causes the API to no longer serve that premint.
import { createCreatorClient } from "@zoralabs/protocol-sdk";
import { walletClient, chainId, creatorAccount, publicClient } from "./config";
import { collection, uid } from "./create";
const creatorClient = createCreatorClient({ chainId, publicClient });
const { signAndSubmit } = await creatorClient.deletePremint({
// Premint collection address to delete the premint from
collection,
// id of the premint
uid,
});
// sign and submit the deletion of the Premint
await signAndSubmit({
account: creatorAccount,
// the walletClient will be used to sign the message.
walletClient,
});
Earning Create Referral Rewards
To earn a create referral reward, pass in the createReferral
argument when creating a Premint:
const creatorClient = createCreatorClient({ chainId, publicClient });
await creatorClient.createPremint({
// collection info of contract to create.
contract: {
contractAdmin: creatorAccount!,
contractName: "Testing Contract",
contractURI:
"ipfs://bafkreiainxen4b4wz4ubylvbhons6rembxdet4a262nf2lziclqvv7au3e",
},
token: {
tokenURI:
"ipfs://bafkreice23maski3x52tsfqgxstx3kbiifnt5jotg3a5ynvve53c4soi2u",
payoutRecipient: creatorAccount!,
// create referral address will get the create referral reward
// when the token is minted.
createReferral: "0x5843c8d6007813de3D2313fC55F2Fa1Cbbc394A6",
},
});