Merge pull request #217 from public-awesome/batch-transfer-specific-addresses
Add multi-address batch transfers to collection actions
This commit is contained in:
commit
9d02f73347
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "stargaze-studio",
|
"name": "stargaze-studio",
|
||||||
"version": "0.7.8",
|
"version": "0.7.9",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
|
Loading…
Reference in New Issue
Block a user