Skip to content

Commit

Permalink
Merge pull request #205 from public-awesome/yubrew/bulk-transfer-file
Browse files Browse the repository at this point in the history
bulk transfer with file
  • Loading branch information
yubrew authored Oct 6, 2022
2 parents cf9b636 + 81d0c9c commit dd18f8e
Showing 1 changed file with 128 additions and 0 deletions.
128 changes: 128 additions & 0 deletions scripts/transfer-file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Transfer specific NFTs to recipient addresses using transfer.csv

// Requires transfer.csv with "recipient" and "token-id" columns
// Requires account have all the token-ids or it will error out
// Cycles through addresses and token ids to construct an array of messages to be broadcast

// Accepts cosmos, stars addresses.

import { coin, MsgExecuteContractEncodeObject } from 'cosmwasm';
import { toStars } from '../src/utils';
import inquirer from 'inquirer';
import { getClient } from '../src/client';
import { MsgExecuteContract } from 'cosmjs-types/cosmwasm/wasm/v1/tx';
import { toUtf8 } from '@cosmjs/encoding';
import * as fs from 'fs';
import * as path from 'path';
import { parse } from 'csv-parse';
import { assertIsDeliverTxSuccess } from '@cosmjs/stargate';

const config = require('../config');
const MSG_TRANSFER_LIMIT = 50;

async function addFile() {
interface TransferData {
recipient: string;
token_id: number;
}
const __dirname = process.cwd();
const csvFilePath = path.resolve(__dirname, './transfer.csv');
const headers = ['recipient', 'token_id'];
const fileContent = fs.readFileSync(csvFilePath, { encoding: 'utf-8' });
const addrs: Array<string> = [];
const tokens: Array<number> = [];
const executeContractMsgs: Array<MsgExecuteContractEncodeObject> = [];
const client = await getClient();
if (!config.minter) {
throw Error(
'"minter" must be set to a minter contract address in config.js'
);
}
const funds: never[] = [];
parse(
fileContent,
{
delimiter: ',',
columns: headers,
},
async (error, fileContents: TransferData[]) => {
if (error) {
throw error;
}
fileContents.map((row) => addrs.push(row.recipient));
fileContents.map((row) => tokens.push(row.token_id));
console.log(addrs);
console.log(tokens);

const validatedAddrs: Array<string> = [];
addrs.forEach((addr) => {
validatedAddrs.push(toStars(addr));
});
let uniqueValidatedAddrs = [...new Set(validatedAddrs)];
if (uniqueValidatedAddrs.length > MSG_TRANSFER_LIMIT) {
throw new Error(
'Too many addrs added in a transaction. Max ' +
MSG_TRANSFER_LIMIT +
' at a time.'
);
}
if (uniqueValidatedAddrs.length !== tokens.length) {
throw new Error('unique addrs length must equal token ids length');
}
console.log(
'Recipient addresses validated and deduped. count: ' +
uniqueValidatedAddrs.length
);

for (const idx in uniqueValidatedAddrs) {
console.log(
'transfer token id',
tokens[idx],
'to recipient address: ',
uniqueValidatedAddrs[idx]
);
const msg = {
transfer_nft: {
recipient: uniqueValidatedAddrs[idx],
token_id: tokens[idx],
},
};
const executeContractMsg: MsgExecuteContractEncodeObject = {
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
value: MsgExecuteContract.fromPartial({
sender: config.account,
contract: config.minter,
msg: toUtf8(JSON.stringify(msg)),
funds,
}),
};

executeContractMsgs.push(executeContractMsg);
}

// Get confirmation before preceding
console.log(
'WARNING: Transfer is not reverisble. Please confirm the settings for transferring tokens to addresses. THERE IS NO WAY TO UNDO THIS ONCE IT IS ON CHAIN.'
);
console.log(JSON.stringify(executeContractMsgs, null, 2));
const answer = await inquirer.prompt([
{
message: 'Ready to submit the transaction?',
name: 'confirmation',
type: 'confirm',
},
]);
if (!answer.confirmation) return;

const result = await client.signAndBroadcast(
config.account,
executeContractMsgs,
'auto',
'batch transfer'
);
assertIsDeliverTxSuccess(result);
}
);
}

addFile();

0 comments on commit dd18f8e

Please sign in to comment.