Add batch transfer to sg721 collection actions (#40)

This commit is contained in:
Serkan Reis 2022-08-16 13:04:23 +03:00 committed by GitHub
parent 3b5f287715
commit 00960f429e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 4 deletions

View File

@ -14,6 +14,7 @@ export const ACTION_TYPES = [
'update_per_address_limit', 'update_per_address_limit',
'withdraw', 'withdraw',
'transfer', 'transfer',
'batch_transfer',
'burn', 'burn',
'batch_burn', 'batch_burn',
'shuffle', 'shuffle',
@ -66,6 +67,11 @@ export const ACTION_LIST: ActionListItem[] = [
name: 'Transfer Tokens', name: 'Transfer Tokens',
description: `Transfer tokens from one address to another`, description: `Transfer tokens from one address to another`,
}, },
{
id: 'batch_transfer',
name: 'Batch Transfer Tokens',
description: `Transfer a list of tokens to a recipient`,
},
{ {
id: 'burn', id: 'burn',
name: 'Burn Token', name: 'Burn Token',
@ -108,6 +114,7 @@ export type DispatchExecuteArgs = {
| { type: Select<'shuffle'> } | { type: Select<'shuffle'> }
| { type: Select<'withdraw'> } | { type: Select<'withdraw'> }
| { type: Select<'transfer'>; recipient: string; tokenId: number } | { type: Select<'transfer'>; recipient: string; tokenId: number }
| { type: Select<'batch_transfer'>; recipient: string; tokenIds: string }
| { type: Select<'burn'>; tokenId: number } | { type: Select<'burn'>; tokenId: number }
| { type: Select<'batch_burn'>; tokenIds: string } | { type: Select<'batch_burn'>; tokenIds: string }
) )
@ -145,6 +152,9 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
case 'transfer': { case 'transfer': {
return sg721Messages.transferNft(args.recipient, args.tokenId.toString()) return sg721Messages.transferNft(args.recipient, args.tokenId.toString())
} }
case 'batch_transfer': {
return sg721Messages.batchTransfer(args.recipient, args.tokenIds)
}
case 'burn': { case 'burn': {
return sg721Messages.burn(args.tokenId.toString()) return sg721Messages.burn(args.tokenId.toString())
} }
@ -191,6 +201,9 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => {
case 'transfer': { case 'transfer': {
return sg721Messages(sg721Contract)?.transferNft(args.recipient, args.tokenId.toString()) return sg721Messages(sg721Contract)?.transferNft(args.recipient, args.tokenId.toString())
} }
case 'batch_transfer': {
return sg721Messages(sg721Contract)?.batchTransfer(args.recipient, args.tokenIds)
}
case 'burn': { case 'burn': {
return sg721Messages(sg721Contract)?.burn(args.tokenId.toString()) return sg721Messages(sg721Contract)?.burn(args.tokenId.toString())
} }

View File

@ -69,6 +69,7 @@ export interface SG721Instance {
/// Burn an NFT the sender has access to /// Burn an NFT the sender has access to
burn: (tokenId: string) => Promise<string> burn: (tokenId: string) => Promise<string>
batchBurn: (tokenIds: string) => Promise<string> batchBurn: (tokenIds: string) => Promise<string>
batchTransfer: (recipient: string, tokenIds: string) => Promise<string>
} }
export interface Sg721Messages { export interface Sg721Messages {
@ -81,6 +82,7 @@ export interface Sg721Messages {
mint: (tokenId: string, owner: string, tokenURI?: string) => MintMessage mint: (tokenId: string, owner: string, tokenURI?: string) => MintMessage
burn: (tokenId: string) => BurnMessage burn: (tokenId: string) => BurnMessage
batchBurn: (tokenIds: string) => BatchBurnMessage batchBurn: (tokenIds: string) => BatchBurnMessage
batchTransfer: (recipient: string, tokenIds: string) => BatchTransferMessage
} }
export interface TransferNFTMessage { export interface TransferNFTMessage {
@ -188,6 +190,13 @@ export interface BatchBurnMessage {
funds: Coin[] funds: Coin[]
} }
export interface BatchTransferMessage {
sender: string
contract: string
msg: Record<string, unknown>[]
funds: Coin[]
}
export interface SG721Contract { export interface SG721Contract {
instantiate: ( instantiate: (
senderAddress: string, senderAddress: string,
@ -461,6 +470,49 @@ export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Con
return res.transactionHash return res.transactionHash
} }
const batchTransfer = async (recipient: string, tokenIds: string): Promise<string> => {
const executeContractMsgs: MsgExecuteContractEncodeObject[] = []
if (tokenIds.includes(':')) {
const [start, end] = tokenIds.split(':').map(Number)
for (let i = start; i <= end; i++) {
const msg = {
transfer_nft: { recipient, token_id: i.toString() },
}
const executeContractMsg: MsgExecuteContractEncodeObject = {
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
value: MsgExecuteContract.fromPartial({
sender: txSigner,
contract: contractAddress,
msg: toUtf8(JSON.stringify(msg)),
}),
}
executeContractMsgs.push(executeContractMsg)
}
} else {
const tokenNumbers = tokenIds.split(',').map(Number)
for (let i = 0; i < tokenNumbers.length; i++) {
const msg = {
transfer_nft: { recipient, token_id: tokenNumbers[i].toString() },
}
const executeContractMsg: MsgExecuteContractEncodeObject = {
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
value: MsgExecuteContract.fromPartial({
sender: txSigner,
contract: contractAddress,
msg: toUtf8(JSON.stringify(msg)),
}),
}
executeContractMsgs.push(executeContractMsg)
}
}
const res = await client.signAndBroadcast(txSigner, executeContractMsgs, 'auto', 'batch transfer')
return res.transactionHash
}
return { return {
contractAddress, contractAddress,
ownerOf, ownerOf,
@ -484,6 +536,7 @@ export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Con
mint, mint,
burn, burn,
batchBurn, batchBurn,
batchTransfer,
} }
} }
@ -643,6 +696,30 @@ export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Con
} }
} }
const batchTransfer = (recipient: string, tokenIds: string): BatchTransferMessage => {
const msg: Record<string, unknown>[] = []
if (tokenIds.includes(':')) {
const [start, end] = tokenIds.split(':').map(Number)
for (let i = start; i <= end; i++) {
msg.push({
trasnfer_nft: { recipient, token_id: i.toString() },
})
}
} else {
const tokenNumbers = tokenIds.split(',').map(Number)
for (let i = 0; i < tokenNumbers.length; i++) {
msg.push({ trasnfer_nft: { recipient, token_id: tokenNumbers[i].toString() } })
}
}
return {
sender: txSigner,
contract: contractAddress,
msg,
funds: [],
}
}
return { return {
transferNft, transferNft,
sendNft, sendNft,
@ -653,6 +730,7 @@ export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Con
mint, mint,
burn, burn,
batchBurn, batchBurn,
batchTransfer,
} }
} }

View File

@ -73,9 +73,9 @@ const CollectionActionsPage: NextPage = () => {
const tokenIdListState = useInputState({ const tokenIdListState = useInputState({
id: 'token-id-list', id: 'token-id-list',
name: 'tokenIdList', name: 'tokenIdList',
title: 'The list of token IDs', title: 'List of token IDs',
subtitle: subtitle:
'Specify individual token IDs separated by commas (e.g., 2, 4, 8) or a range of IDs separated by a colon (e.g, 8:13)', 'Specify individual token IDs separated by commas (e.g., 2, 4, 8) or a range of IDs separated by a colon (e.g., 8:13)',
}) })
const recipientState = useInputState({ const recipientState = useInputState({
@ -97,8 +97,8 @@ const CollectionActionsPage: NextPage = () => {
const showLimitField = type === 'update_per_address_limit' const showLimitField = type === 'update_per_address_limit'
const showTokenIdField = isEitherType(type, ['transfer', 'mint_for', 'burn']) const showTokenIdField = isEitherType(type, ['transfer', 'mint_for', 'burn'])
const showNumberOfTokensField = type === 'batch_mint' const showNumberOfTokensField = type === 'batch_mint'
const showTokenIdListField = type === 'batch_burn' const showTokenIdListField = isEitherType(type, ['batch_burn', 'batch_transfer'])
const showRecipientField = isEitherType(type, ['transfer', 'mint_to', 'mint_for', 'batch_mint']) const showRecipientField = isEitherType(type, ['transfer', 'mint_to', 'mint_for', 'batch_mint', 'batch_transfer'])
const minterMessages = useMemo( const minterMessages = useMemo(
() => minterContract?.use(minterContractState.value), () => minterContract?.use(minterContractState.value),