Merge pull request #217 from public-awesome/batch-transfer-specific-addresses

Add multi-address batch transfers to collection actions
This commit is contained in:
Serkan Reis 2023-09-21 07:51:24 +03:00 committed by GitHub
commit 9d02f73347
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 90 additions and 5 deletions

View File

@ -1,4 +1,4 @@
APP_VERSION=0.7.6 APP_VERSION=0.7.9
NEXT_PUBLIC_PINATA_ENDPOINT_URL=https://api.pinata.cloud/pinning/pinFileToIPFS NEXT_PUBLIC_PINATA_ENDPOINT_URL=https://api.pinata.cloud/pinning/pinFileToIPFS
NEXT_PUBLIC_SG721_CODE_ID=2595 NEXT_PUBLIC_SG721_CODE_ID=2595

View File

@ -198,7 +198,12 @@ export const CollectionActions = ({
'batch_transfer', 'batch_transfer',
'batch_mint_for', 'batch_mint_for',
]) ])
const showAirdropFileField = isEitherType(type, ['airdrop', 'airdrop_open_edition', 'airdrop_specific']) const showAirdropFileField = isEitherType(type, [
'airdrop',
'airdrop_open_edition',
'airdrop_specific',
'batch_transfer_multi_address',
])
const showPriceField = isEitherType(type, ['update_mint_price', 'update_discount_price']) const showPriceField = isEitherType(type, ['update_mint_price', 'update_discount_price'])
const showDescriptionField = type === 'update_collection_info' const showDescriptionField = type === 'update_collection_info'
const showImageField = type === 'update_collection_info' const showImageField = type === 'update_collection_info'
@ -494,12 +499,14 @@ export const CollectionActions = ({
)} )}
{showAirdropFileField && ( {showAirdropFileField && (
<FormGroup <FormGroup
subtitle={`CSV file that contains the airdrop addresses and the ${ subtitle={`CSV file that contains the ${
type === 'batch_transfer_multi_address' ? '' : 'airdrop'
} addresses and the ${
type === 'airdrop' ? 'amount of tokens' : 'token ID' type === 'airdrop' ? 'amount of tokens' : 'token ID'
} allocated for each address. Should start with the following header row: ${ } allocated for each address. Should start with the following header row: ${
type === 'airdrop' ? 'address,amount' : 'address,tokenId' type === 'airdrop' ? 'address,amount' : 'address,tokenId'
}`} }`}
title="Airdrop File" title={`${type === 'batch_transfer_multi_address' ? 'Multi-Recipient Transfer File' : 'Airdrop File'}`}
> >
<AirdropUpload onChange={airdropFileOnChange} /> <AirdropUpload onChange={airdropFileOnChange} />
</FormGroup> </FormGroup>

View File

@ -31,6 +31,7 @@ export const ACTION_TYPES = [
'freeze_collection_info', 'freeze_collection_info',
'transfer', 'transfer',
'batch_transfer', 'batch_transfer',
'batch_transfer_multi_address',
'burn', 'burn',
'batch_burn', 'batch_burn',
'batch_mint_for', 'batch_mint_for',
@ -82,6 +83,11 @@ export const BASE_ACTION_LIST: ActionListItem[] = [
name: 'Batch Transfer Tokens', name: 'Batch Transfer Tokens',
description: `Transfer a list of tokens to a recipient`, description: `Transfer a list of tokens to a recipient`,
}, },
{
id: 'batch_transfer_multi_address',
name: 'Transfer Tokens to Multiple Recipients',
description: `Transfer a list of tokens to multiple addresses`,
},
{ {
id: 'burn', id: 'burn',
name: 'Burn Token', name: 'Burn Token',
@ -170,6 +176,11 @@ export const VENDING_ACTION_LIST: ActionListItem[] = [
name: 'Batch Transfer Tokens', name: 'Batch Transfer Tokens',
description: `Transfer a list of tokens to a recipient`, description: `Transfer a list of tokens to a recipient`,
}, },
{
id: 'batch_transfer_multi_address',
name: 'Transfer Tokens to Multiple Recipients',
description: `Transfer a list of tokens to multiple addresses`,
},
{ {
id: 'burn', id: 'burn',
name: 'Burn Token', name: 'Burn Token',
@ -258,6 +269,11 @@ export const OPEN_EDITION_ACTION_LIST: ActionListItem[] = [
name: 'Batch Transfer Tokens', name: 'Batch Transfer Tokens',
description: `Transfer a list of tokens to a recipient`, description: `Transfer a list of tokens to a recipient`,
}, },
{
id: 'batch_transfer_multi_address',
name: 'Transfer Tokens to Multiple Recipients',
description: `Transfer a list of tokens to multiple addresses`,
},
{ {
id: 'burn', id: 'burn',
name: 'Burn Token', name: 'Burn Token',
@ -405,6 +421,9 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
case 'batch_transfer': { case 'batch_transfer': {
return sg721Messages.batchTransfer(args.recipient, args.tokenIds) return sg721Messages.batchTransfer(args.recipient, args.tokenIds)
} }
case 'batch_transfer_multi_address': {
return sg721Messages.batchTransferMultiAddress(txSigner, args.tokenRecipients)
}
case 'burn': { case 'burn': {
return sg721Messages.burn(args.tokenId.toString()) return sg721Messages.burn(args.tokenId.toString())
} }
@ -512,6 +531,9 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => {
case 'batch_transfer': { case 'batch_transfer': {
return sg721Messages(sg721Contract)?.batchTransfer(args.recipient, args.tokenIds) return sg721Messages(sg721Contract)?.batchTransfer(args.recipient, args.tokenIds)
} }
case 'batch_transfer_multi_address': {
return sg721Messages(sg721Contract)?.batchTransferMultiAddress(args.tokenRecipients)
}
case 'burn': { case 'burn': {
return sg721Messages(sg721Contract)?.burn(args.tokenId.toString()) return sg721Messages(sg721Contract)?.burn(args.tokenId.toString())
} }

View File

@ -3,6 +3,7 @@ import { toBase64, toUtf8 } from '@cosmjs/encoding'
import type { Coin, logs } from '@cosmjs/stargate' import type { Coin, logs } from '@cosmjs/stargate'
import { coin } from '@cosmjs/stargate' import { coin } from '@cosmjs/stargate'
import { MsgExecuteContract } from 'cosmjs-types/cosmwasm/wasm/v1/tx' import { MsgExecuteContract } from 'cosmjs-types/cosmwasm/wasm/v1/tx'
import type { AirdropAllocation } from 'utils/isValidAccountsFile'
import type { RoyaltyInfo } from '../vendingMinter/contract' import type { RoyaltyInfo } from '../vendingMinter/contract'
@ -86,6 +87,7 @@ export interface SG721Instance {
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> batchTransfer: (recipient: string, tokenIds: string) => Promise<string>
batchTransferMultiAddress: (senderAddress: string, tokenRecipients: AirdropAllocation[]) => Promise<string>
updateTokenMetadata: (tokenId: string, tokenURI: string) => Promise<string> updateTokenMetadata: (tokenId: string, tokenURI: string) => Promise<string>
batchUpdateTokenMetadata: (tokenIds: string, tokenURI: string, jsonExtensions: boolean) => Promise<string> batchUpdateTokenMetadata: (tokenIds: string, tokenURI: string, jsonExtensions: boolean) => Promise<string>
freezeTokenMetadata: () => Promise<string> freezeTokenMetadata: () => Promise<string>
@ -103,6 +105,7 @@ export interface Sg721Messages {
burn: (tokenId: string) => BurnMessage burn: (tokenId: string) => BurnMessage
batchBurn: (tokenIds: string) => BatchBurnMessage batchBurn: (tokenIds: string) => BatchBurnMessage
batchTransfer: (recipient: string, tokenIds: string) => BatchTransferMessage batchTransfer: (recipient: string, tokenIds: string) => BatchTransferMessage
batchTransferMultiAddress: (tokenRecipients: AirdropAllocation[]) => BatchTransferMultiAddressMessage
updateCollectionInfo: (collectionInfo: CollectionInfo) => UpdateCollectionInfoMessage updateCollectionInfo: (collectionInfo: CollectionInfo) => UpdateCollectionInfoMessage
freezeCollectionInfo: () => FreezeCollectionInfoMessage freezeCollectionInfo: () => FreezeCollectionInfoMessage
updateTokenMetadata: (tokenId: string, tokenURI: string) => UpdateTokenMetadataMessage updateTokenMetadata: (tokenId: string, tokenURI: string) => UpdateTokenMetadataMessage
@ -227,6 +230,13 @@ export interface BatchTransferMessage {
funds: Coin[] funds: Coin[]
} }
export interface BatchTransferMultiAddressMessage {
sender: string
contract: string
msg: Record<string, unknown>[]
funds: Coin[]
}
export interface UpdateTokenMetadataMessage { export interface UpdateTokenMetadataMessage {
sender: string sender: string
contract: string contract: string
@ -601,6 +611,37 @@ export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Con
return res.transactionHash return res.transactionHash
} }
const batchTransferMultiAddress = async (
senderAddress: string,
recipients: AirdropAllocation[],
): Promise<string> => {
const executeContractMsgs: MsgExecuteContractEncodeObject[] = []
for (let i = 0; i < recipients.length; i++) {
const msg = {
transfer_nft: { recipient: recipients[i].address, token_id: recipients[i].tokenId as string },
}
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 transfer to multiple recipients',
)
return res.transactionHash
}
// eslint-disable-next-line @typescript-eslint/no-shadow // eslint-disable-next-line @typescript-eslint/no-shadow
const updateCollectionInfo = async (collectionInfo: CollectionInfo): Promise<string> => { const updateCollectionInfo = async (collectionInfo: CollectionInfo): Promise<string> => {
const res = await client.execute( const res = await client.execute(
@ -748,6 +789,7 @@ export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Con
burn, burn,
batchBurn, batchBurn,
batchTransfer, batchTransfer,
batchTransferMultiAddress,
updateCollectionInfo, updateCollectionInfo,
freezeCollectionInfo, freezeCollectionInfo,
updateTokenMetadata, updateTokenMetadata,
@ -950,6 +992,19 @@ export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Con
} }
} }
const batchTransferMultiAddress = (recipients: AirdropAllocation[]): BatchTransferMultiAddressMessage => {
const msg: Record<string, unknown>[] = []
for (let i = 0; i < recipients.length; i++) {
msg.push({ transfer_nft: { recipient: recipients[i].address, token_id: recipients[i].tokenId } })
}
return {
sender: txSigner,
contract: contractAddress,
msg,
funds: [],
}
}
const batchUpdateTokenMetadata = ( const batchUpdateTokenMetadata = (
tokenIds: string, tokenIds: string,
baseURI: string, baseURI: string,
@ -1055,6 +1110,7 @@ export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Con
burn, burn,
batchBurn, batchBurn,
batchTransfer, batchTransfer,
batchTransferMultiAddress,
updateCollectionInfo, updateCollectionInfo,
freezeCollectionInfo, freezeCollectionInfo,
updateTokenMetadata, updateTokenMetadata,

View File

@ -1,6 +1,6 @@
{ {
"name": "stargaze-studio", "name": "stargaze-studio",
"version": "0.7.8", "version": "0.7.9",
"workspaces": [ "workspaces": [
"packages/*" "packages/*"
], ],