Create Onchain 1155 Contracts & Tokens
The Protocol SDK can be used to prepare transactions to create 1155 contracts and tokens, using the Creator Client.
Setup/Create the Creator Client
Initialize a Creator Client with a chain id and PublicClient
. The chain is used to determine the network to interact with.
import { createCreatorClient } from "@zoralabs/protocol-sdk";
import { createPublicClient, http, Chain } from 'viem';
import { zora } from "viem/chains";
const publicClient = createPublicClient({
chain: zora as Chain,
transport: http()
});
const creatorClient = createCreatorClient({ chainId: zora.id, publicClient });
Creating a new 1155 contract and token with Secondary Markets
The function create1155
is used to create a new 1155 contract and token. By default, the token will be created with the ZoraTimedSaleStrategyMinter
as the minter, meaning that after the primary sale is complete, a secondary market powered by Uniswap will begin.
The contract
argument needs to be contract creation parameters. Calling this function prepares a parameters for a transaction
that creates an 1155 contract at the deterministic address based on those parameters, and a token on that contract.
import {
useAccount,
useChainId,
usePublicClient,
useWriteContract,
} from "wagmi";
import { createCreatorClient } from "@zoralabs/protocol-sdk";
// use wagmi hooks to get the chainId, publicClient, and account
const chainId = useChainId();
const publicClient = usePublicClient()!;
const { address } = useAccount();
const creatorClient = createCreatorClient({ chainId, publicClient });
const { parameters, contractAddress } = await creatorClient.create1155({
// the contract will be created at a deterministic address
contract: {
// contract name
name: "testContract",
// contract metadata uri
uri: "ipfs://DUMMY/contract.json",
},
token: {
tokenMetadataURI: "ipfs://DUMMY/token.json",
},
// account to execute the transaction (the creator)
account: address!,
});
const { writeContract } = useWriteContract();
writeContract(parameters);
export { contractAddress };
Custom parameters for secondary markets
If you are wanting to customize the default configuration parameters such as saleStart
you can do that by passing in a salesConfig
struct.
import {
useAccount,
useChainId,
usePublicClient,
useWriteContract,
} from "wagmi";
import { createCreatorClient } from "@zoralabs/protocol-sdk";
// use wagmi hooks to get the chainId, publicClient, and account
const chainId = useChainId();
const publicClient = usePublicClient()!;
const { address } = useAccount();
const creatorClient = createCreatorClient({ chainId, publicClient });
const { parameters, contractAddress } = await creatorClient.create1155({
// the contract will be created at a deterministic address
contract: {
// contract name
name: "testContract",
// contract metadata uri
uri: "ipfs://DUMMY/contract.json",
},
token: {
tokenMetadataURI: "ipfs://DUMMY/token.json",
salesConfig: {
type: "timed",
erc20Name: "testToken", // If not provided, uses the contract name
erc20Symbol: "TEST", // If not provided, extracts it from the name.
saleStart: 0n, // If not provided, sets to 0
marketCountdown: BigInt(24 * 60 * 60), // If not provided, sets to 24 hours
minimumMarketEth: 2220000000000000n, // If not provided, sets to 200 mints worth of ETH
},
},
// account to execute the transaction (the creator)
account: address!,
});
const { writeContract } = useWriteContract();
writeContract(parameters);
export { contractAddress };
With the update to use the v2 sales config it introduces marketCountdown
and minimumMarketEth
in version 0.9.5 of the sdk.
Configuring the backing ERC20 Token Name and Symbol for the 1155 Secondary Market
When leveraging the secondary markets feature, a backing ERC20 token is created with a name and symbol for each minted 1155.
By default, the name is copied from the contract name, and the symbol is generated by converting the name into a 4 character symbol.
Alternatively these can be manually set by configuring the token.salesConfig.erc20Name
and token.salesConfig.erc20Symbol
properties correspondingly:
import { createCreatorClient } from "@zoralabs/protocol-sdk";
import { publicClient, chainId, creatorAccount } from "./config";
const creatorClient = createCreatorClient({ chainId, publicClient });
const { parameters } = await creatorClient.create1155({
contract: {
name: "testContract",
uri: "ipfs://DUMMY/contract.json",
},
token: {
tokenMetadataURI: "ipfs://DUMMY/token.json",
salesConfig: {
// manually specifying the erc20 name and symbol
erc20Name: "My Token Name",
erc20Symbol: "MTN",
},
},
account: creatorAccount,
});
// simulate the transaction
await publicClient.simulateContract(parameters);
Creating a token on an existing 1155 contract
To create a token on an existing 1155 contract, the function create1155OnExistingContract
must be called
with the 1155 contract address and the token creation parameters.
import { createCreatorClient } from "@zoralabs/protocol-sdk";
import { publicClient, walletClient, chainId, creatorAccount } from "./config";
import { contractAddress } from "./createNewContract";
const creatorClient = createCreatorClient({ chainId, publicClient });
const { parameters } = await creatorClient.create1155OnExistingContract({
// by providing a contract address, the token will be created on an existing contract
// at that address
contractAddress,
token: {
// token metadata uri
tokenMetadataURI: "ipfs://DUMMY/token.json",
},
// account to execute the transaction (the creator)
account: creatorAccount,
});
// simulate the transaction
const { request } = await publicClient.simulateContract(parameters);
// execute the transaction
const hash = await walletClient.writeContract(request);
// wait for the response
await publicClient.waitForTransactionReceipt({ hash });
Setting a price per token
A price per token can be optionally set to earn eth additional on the primary sale when each token is minted, by setting token.salesConfig.pricePerToken
.
If the pricePerToken
is set to more than 0, there will be no creatorReward
earned on the mint fee. If a pricePerToken is set to more than 0, then the token is setup with the ZoraCreatorFixedPriceSaleStrategy as its minter.
This will also result in not being able to leverage the onchain secondary market feature for tokens minted using
this minter.
import {
useAccount,
useChainId,
usePublicClient,
useWriteContract,
} from "wagmi";
import { parseEther } from "viem";
import { createCreatorClient } from "@zoralabs/protocol-sdk";
// use wagmi hooks to get the chainId, publicClient, and account
const chainId = useChainId();
const publicClient = usePublicClient()!;
const { address } = useAccount();
const creatorClient = createCreatorClient({ chainId, publicClient });
const { parameters, contractAddress } = await creatorClient.create1155({
// the contract will be created at a deterministic address
contract: {
// contract name
name: "testContract",
// contract metadata uri
uri: "ipfs://DUMMY/contract.json",
},
token: {
tokenMetadataURI: "ipfs://DUMMY/token.json",
salesConfig: {
// setting a price per token on the `salesConfig` will
// result in the token being created with a fixed price in addition
// to the mint fee. In this case, creator rewards will not be earned
// on the mint fee, the `ZoraCreatorFixedPriceSaleStrategy` is setup
// as the minter for this token, and correspondingly the onchain
// secondary market feature will NOT be used for tokens minted using
// that minter.
pricePerToken: parseEther("0.1"),
},
},
// account to execute the transaction (the creator)
account: address!,
});
const { writeContract } = useWriteContract();
writeContract(parameters);
export { contractAddress };
Minting a token after creating
Sometimes it is desired to be able to mint a token right after creating one. This can be done with the function prepareMint
that is returned from the creation functions. This function will prepare a transaction to mint a token on the token and/or contract that was created.
Note that this transaction can only be executed after the token has been created onchain.
import { createCreatorClient } from "@zoralabs/protocol-sdk";
import {
publicClient,
walletClient,
chainId,
creatorAccount,
minterAccount,
} from "./config";
import { contractAddress } from "./createNewContract";
const creatorClient = createCreatorClient({ chainId, publicClient });
const {
parameters: createParameters,
prepareMint,
} = await creatorClient.create1155OnExistingContract({
// by providing a contract address, the token will be created on an existing contract
// at that address
contractAddress,
token: {
// token metadata uri
tokenMetadataURI: "ipfs://DUMMY/token.json",
},
// account to execute the transaction (the creator)
account: creatorAccount,
});
const { request } = await publicClient.simulateContract(createParameters);
// execute the transaction
const hash = await walletClient.writeContract(request);
// wait for the response
const createReceipt = await publicClient.waitForTransactionReceipt({ hash });
if (createReceipt.status !== "success") {
throw new Error("create failed");
}
// the create function returns an async prepareMint function, which
// enables a mint call to be created on the token after it has been created.
// Note this can only be executed after the token has been brought onchain.
const { parameters: mintParams } = await prepareMint({
quantityToMint: 2n,
minterAccount,
});
// execute the mint transaction
const mintHash = await walletClient.writeContract(mintParams);
const mintReceipt = await publicClient.waitForTransactionReceipt({
hash: mintHash,
});
if (mintReceipt.status !== "success") {
throw new Error("mint failed");
}