From c994411dfb3d023de804e152c627f64d0d9b4c30 Mon Sep 17 00:00:00 2001 From: name-user1 <101495985+name-user1@users.noreply.github.com> Date: Wed, 10 Aug 2022 10:25:23 +0300 Subject: [PATCH] Batch minting (#30) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bach Mint * Add mint_for for batch minting * Batch minting with mint to function with given number * Minor fixes * Update components/collections/actions/actions.ts Co-authored-by: name-user1 Co-authored-by: Serkan Reis Co-authored-by: Arda Nakışçı --- components/collections/actions/actions.ts | 13 ++++++ contracts/minter/contract.ts | 51 ++++++++++++++++++++++- pages/collections/actions.tsx | 12 +++++- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/components/collections/actions/actions.ts b/components/collections/actions/actions.ts index b02c93f..c980910 100644 --- a/components/collections/actions/actions.ts +++ b/components/collections/actions/actions.ts @@ -8,6 +8,7 @@ export type ActionType = typeof ACTION_TYPES[number] export const ACTION_TYPES = [ 'mint_to', 'mint_for', + 'batch_mint', 'set_whitelist', 'update_start_time', 'update_per_address_limit', @@ -33,6 +34,11 @@ export const ACTION_LIST: ActionListItem[] = [ name: 'Mint For', description: `Mint a token for a user with given token ID`, }, + { + id: 'batch_mint', + name: 'Batch Mint', + description: `Mint multiple tokens to a user with given token amount`, + }, { id: 'set_whitelist', name: 'Set Whitelist', @@ -83,6 +89,7 @@ export type DispatchExecuteArgs = { | { type: undefined } | { type: Select<'mint_to'>; recipient: string } | { type: Select<'mint_for'>; recipient: string; tokenId: number } + | { type: Select<'batch_mint'>; recipient: string; batchNumber: number } | { type: Select<'set_whitelist'>; whitelist: string } | { type: Select<'update_start_time'>; startTime: string } | { type: Select<'update_per_address_limit'>; limit: number } @@ -103,6 +110,9 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => { case 'mint_for': { return minterMessages.mintFor(txSigner, args.recipient, args.tokenId) } + case 'batch_mint': { + return minterMessages.batchMint(txSigner, args.recipient, args.batchNumber) + } case 'set_whitelist': { return minterMessages.setWhitelist(txSigner, args.whitelist) } @@ -140,6 +150,9 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => { case 'mint_for': { return minterMessages()?.mintFor(minterContract, args.recipient, args.tokenId) } + case 'batch_mint': { + return minterMessages()?.batchMint(minterContract, args.recipient, args.batchNumber) + } case 'set_whitelist': { return minterMessages()?.setWhitelist(minterContract, args.whitelist) } diff --git a/contracts/minter/contract.ts b/contracts/minter/contract.ts index 0261b6b..ba7069d 100644 --- a/contracts/minter/contract.ts +++ b/contracts/minter/contract.ts @@ -1,8 +1,10 @@ -import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate' +import type { MsgExecuteContractEncodeObject, SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate' +import { toUtf8 } from '@cosmjs/encoding' import type { Coin } from '@cosmjs/proto-signing' import { coin } from '@cosmjs/proto-signing' import type { logs } from '@cosmjs/stargate' import type { Timestamp } from '@stargazezone/types/contracts/minter/shared-types' +import { MsgExecuteContract } from 'cosmjs-types/cosmwasm/wasm/v1/tx' export interface InstantiateResponse { readonly contractAddress: string @@ -32,6 +34,7 @@ export interface MinterInstance { updatePerAddressLimit: (senderAddress: string, perAddressLimit: number) => Promise mintTo: (senderAddress: string, recipient: string) => Promise mintFor: (senderAddress: string, recipient: string, tokenId: number) => Promise + batchMint: (senderAddress: string, recipient: string, batchNumber: number) => Promise shuffle: (senderAddress: string) => Promise withdraw: (senderAddress: string) => Promise } @@ -43,6 +46,7 @@ export interface MinterMessages { updatePerAddressLimit: (contractAddress: string, perAddressLimit: number) => UpdatePerAddressLimitMessage mintTo: (contractAddress: string, recipient: string) => MintToMessage mintFor: (contractAddress: string, recipient: string, tokenId: number) => MintForMessage + batchMint: (contractAddress: string, recipient: string, batchNumber: number) => BatchMintMessage shuffle: (contractAddress: string) => ShuffleMessage withdraw: (contractAddress: string) => WithdrawMessage } @@ -110,6 +114,13 @@ export interface MintForMessage { funds: Coin[] } +export interface BatchMintMessage { + sender: string + contract: string + msg: Record[] + funds: Coin[] +} + export interface ShuffleMessage { sender: string contract: string @@ -267,6 +278,29 @@ export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterC return res.transactionHash } + const batchMint = async (senderAddress: string, recipient: string, batchNumber: number): Promise => { + const executeContractMsgs: MsgExecuteContractEncodeObject[] = [] + for (let i = 0; i < batchNumber; i++) { + const msg = { + mint_to: { recipient }, + } + const executeContractMsg: MsgExecuteContractEncodeObject = { + typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract', + value: MsgExecuteContract.fromPartial({ + sender: senderAddress, + contract: contractAddress, + msg: toUtf8(JSON.stringify(msg)), + }), + } + + executeContractMsgs.push(executeContractMsg) + } + + const res = await client.signAndBroadcast(senderAddress, executeContractMsgs, 'auto', 'batch mint') + + return res.transactionHash + } + const shuffle = async (senderAddress: string): Promise => { const res = await client.execute( senderAddress, @@ -308,6 +342,7 @@ export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterC updatePerAddressLimit, mintTo, mintFor, + batchMint, shuffle, withdraw, } @@ -406,6 +441,19 @@ export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterC } } + const batchMint = (contractAddress: string, recipient: string, batchNumber: number): BatchMintMessage => { + const msg: Record[] = [] + for (let i = 0; i < batchNumber; i++) { + msg.push({ mint_to: { recipient } }) + } + return { + sender: txSigner, + contract: contractAddress, + msg, + funds: [], + } + } + const shuffle = (contractAddress: string): ShuffleMessage => { return { sender: txSigner, @@ -435,6 +483,7 @@ export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterC updatePerAddressLimit, mintTo, mintFor, + batchMint, shuffle, withdraw, } diff --git a/pages/collections/actions.tsx b/pages/collections/actions.tsx index 7828881..324082f 100644 --- a/pages/collections/actions.tsx +++ b/pages/collections/actions.tsx @@ -61,6 +61,13 @@ const CollectionActionsPage: NextPage = () => { subtitle: 'Enter the token ID', }) + const batchNumberState = useNumberInputState({ + id: 'batch-number', + name: 'batchNumber', + title: 'Number of Tokens', + subtitle: 'Enter the number of tokens to mint', + }) + const recipientState = useInputState({ id: 'recipient-address', name: 'recipient', @@ -79,7 +86,8 @@ const CollectionActionsPage: NextPage = () => { const showDateField = type === 'update_start_time' const showLimitField = type === 'update_per_address_limit' const showTokenIdField = isEitherType(type, ['transfer', 'mint_for']) - const showRecipientField = isEitherType(type, ['transfer', 'mint_to', 'mint_for']) + const showTokenIdListField = type === 'batch_mint' + const showRecipientField = isEitherType(type, ['transfer', 'mint_to', 'mint_for', 'batch_mint']) const minterMessages = useMemo( () => minterContract?.use(minterContractState.value), @@ -96,6 +104,7 @@ const CollectionActionsPage: NextPage = () => { minterContract: minterContractState.value, sg721Contract: sg721ContractState.value, tokenId: tokenIdState.value, + batchNumber: batchNumberState.value, minterMessages, sg721Messages, recipient: recipientState.value, @@ -145,6 +154,7 @@ const CollectionActionsPage: NextPage = () => { {showWhitelistField && } {showLimitField && } {showTokenIdField && } + {showTokenIdListField && } setTimestamp(date)} value={timestamp} />