Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: batch transfer #30

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
264 changes: 152 additions & 112 deletions bin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,145 +10,185 @@ import { deployCommand } from "../src/commands/deploy.js";
import { verifyCommand } from "../src/commands/verify.js";
import { ReadContract } from "../src/commands/contract.js";
import { bridgeCommand } from "../src/commands/bridge.js";
import { batchTransferCommand } from "../src/commands/batchTransfer.js";

interface CommandOptions {
testnet?: boolean;
address?: string;
value?: string;
txid?: string;
abi?: string;
bytecode?: string;
args?: any;
json?: any;
name?: string;
decodedArgs?: any;
testnet?: boolean;
address?: string;
value?: string;
txid?: string;
abi?: string;
bytecode?: string;
args?: any;
json?: any;
name?: string;
decodedArgs?: any;
file?: string;
interactive?: boolean;
}

const orange = chalk.rgb(255, 165, 0);

console.log(
orange(
figlet.textSync("Rootstock", {
font: "3D-ASCII",
horizontalLayout: "fitted",
verticalLayout: "fitted",
})
)
orange(
figlet.textSync("Rootstock", {
font: "3D-ASCII",
horizontalLayout: "fitted",
verticalLayout: "fitted",
})
)
);

const program = new Command();

program
.name("rsk-cli")
.description("CLI tool for interacting with Rootstock blockchain")
.version("1.0.4", "-v, --version", "Display the current version");
.name("rsk-cli")
.description("CLI tool for interacting with Rootstock blockchain")
.version("1.0.4", "-v, --version", "Display the current version");

program
.command("wallet")
.description(
"Manage your wallet: create a new one, use an existing wallet, or import a custom wallet"
)
.action(async () => {
await walletCommand();
});
.command("wallet")
.description(
"Manage your wallet: create a new one, use an existing wallet, or import a custom wallet"
)
.action(async () => {
await walletCommand();
});

program
.command("balance")
.description("Check the balance of the saved wallet")
.option("-t, --testnet", "Check the balance on the testnet")
.action(async (options: CommandOptions) => {
await balanceCommand(!!options.testnet);
});
.command("balance")
.description("Check the balance of the saved wallet")
.option("-t, --testnet", "Check the balance on the testnet")
.action(async (options: CommandOptions) => {
await balanceCommand(!!options.testnet);
});

program
.command("transfer")
.description("Transfer rBTC to the provided address")
.option("-t, --testnet", "Transfer on the testnet")
.requiredOption("-a, --address <address>", "Recipient address")
.requiredOption("-v, --value <value>", "Amount to transfer in rBTC")
.action(async (options: CommandOptions) => {
try {
const address = `0x${options.address!.replace(
/^0x/,
""
)}` as `0x${string}`;
await transferCommand(
!!options.testnet,
address,
parseFloat(options.value!)
);
} catch (error) {
console.error(chalk.red("Error during transfer:"), error);
}
});
.command("transfer")
.description("Transfer rBTC to the provided address")
.option("-t, --testnet", "Transfer on the testnet")
.requiredOption("-a, --address <address>", "Recipient address")
.requiredOption("-v, --value <value>", "Amount to transfer in rBTC")
.action(async (options: CommandOptions) => {
try {
const address = `0x${options.address!.replace(
/^0x/,
""
)}` as `0x${string}`;
await transferCommand(
!!options.testnet,
address,
parseFloat(options.value!)
);
} catch (error) {
console.error(chalk.red("Error during transfer:"), error);
}
});

program
.command("tx")
.description("Check the status of a transaction")
.option("-t, --testnet", "Check the transaction status on the testnet")
.requiredOption("-i, --txid <txid>", "Transaction ID")
.action(async (options: CommandOptions) => {
const formattedTxId = options.txid!.startsWith("0x")
? options.txid
: `0x${options.txid}`;

await txCommand(!!options.testnet, formattedTxId as `0x${string}`);
});
.command("tx")
.description("Check the status of a transaction")
.option("-t, --testnet", "Check the transaction status on the testnet")
.requiredOption("-i, --txid <txid>", "Transaction ID")
.action(async (options: CommandOptions) => {
const formattedTxId = options.txid!.startsWith("0x")
? options.txid
: `0x${options.txid}`;

await txCommand(!!options.testnet, formattedTxId as `0x${string}`);
});

program
.command("deploy")
.description("Deploy a contract")
.requiredOption("--abi <path>", "Path to the ABI file")
.requiredOption("--bytecode <path>", "Path to the bytecode file")
.option("--args <args...>", "Constructor arguments (space-separated)")
.option("-t, --testnet", "Deploy on the testnet")
.action(async (options: CommandOptions) => {
const args = options.args || [];
await deployCommand(
options.abi!,
options.bytecode!,
!!options.testnet,
args
);
});

program
.command("deploy")
.description("Deploy a contract")
.requiredOption("--abi <path>", "Path to the ABI file")
.requiredOption("--bytecode <path>", "Path to the bytecode file")
.option("--args <args...>", "Constructor arguments (space-separated)")
.option("-t, --testnet", "Deploy on the testnet")
.action(async (options: CommandOptions) => {
const args = options.args || [];
await deployCommand(
options.abi!,
options.bytecode!,
!!options.testnet,
args
);
});
.command("verify")
.description("Verify a contract")
.requiredOption("--json <path>", "Path to the JSON Standard Input")
.requiredOption("--name <name>", "Name of the contract")
.requiredOption(
"-a, --address <address>",
"Address of the deployed contract"
)
.option("-t, --testnet", "Deploy on the testnet")
.option(
"-da, --decodedArgs <args...>",
"Decoded Constructor arguments (space-separated)"
)
.action(async (options: CommandOptions) => {
const args = options.decodedArgs || [];
await verifyCommand(
options.json!,
options.address!,
options.name!,
!!options.testnet,

args
);
});

program
.command("verify")
.description("Verify a contract")
.requiredOption("--json <path>", "Path to the JSON Standard Input")
.requiredOption("--name <name>", "Name of the contract")
.requiredOption("-a, --address <address>", "Address of the deployed contract")
.option("-t, --testnet", "Deploy on the testnet")
.option(
"-da, --decodedArgs <args...>",
"Decoded Constructor arguments (space-separated)"
)
.action(async (options: CommandOptions) => {
const args = options.decodedArgs || [];
await verifyCommand(
options.json!,
options.address!,
options.name!,
!!options.testnet,
args
);
});
.command("contract")
.description("Interact with a contract")
.requiredOption("-a, --address <address>", "Address of a verified contract")
.option("-t, --testnet", "Deploy on the testnet")
.action(async (options: CommandOptions) => {
await ReadContract(
options.address! as `0x${string}`,
!!options.testnet
);
});

program
.command("contract")
.description("Interact with a contract")
.requiredOption("-a, --address <address>", "Address of a verified contract")
.option("-t, --testnet", "Deploy on the testnet")
.action(async (options: CommandOptions) => {
await ReadContract(options.address! as `0x${string}`, !!options.testnet);
});
.command("bridge")
.description("Interact with RSK bridge")
.option("-t, --testnet", "Deploy on the testnet")
.action(async (options: CommandOptions) => {
await bridgeCommand(!!options.testnet);
});

program
.command("bridge")
.description("Interact with RSK bridge")
.option("-t, --testnet", "Deploy on the testnet")
.action(async (options: CommandOptions) => {
await bridgeCommand(!!options.testnet);
});
.command("batch-transfer")
.description("Execute batch transactions interactively or from stdin")
.option("-i, --interactive", "Execute interactively and input transactions")
.option("-t, --testnet", "Execute on the testnet")
.option("-f, --file <file>", "Execute transactions from a file")
.action(async (options) => {
try {
const interactive = !!options.interactive;
const testnet = !!options.testnet;
const file = options.file;

if (interactive && file) {
console.error(
chalk.red(
"🚨 Cannot use both interactive mode and file input simultaneously."
)
);
return;
}

await batchTransferCommand(file, testnet, interactive);
} catch (error: any) {
console.error(
chalk.red("🚨 Error during batch transfer:"),
chalk.yellow(error.message || "Unknown error")
);
}
});

program.parse(process.argv);
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"wallet": "pnpm run build && node dist/bin/index.js wallet",
"balance": "pnpm run build && node dist/bin/index.js balance",
"transfer": "pnpm run build && node dist/bin/index.js transfer --testnet --address 0xa5f45f5bddefC810C48aCC1D5CdA5e5a4c6BC59E --value 0.001",
"tx-status": "pnpm run build && node dist/bin/index.js tx --testnet --txid 0x876a0a9b167889350c41930a4204e5d9acf5704a7f201447a337094189af961c4"
"tx-status": "pnpm run build && node dist/bin/index.js tx --testnet --txid 0x876a0a9b167889350c41930a4204e5d9acf5704a7f201447a337094189af961c4",
"batch-transfer": "pnpm run build && node dist/bin/index.js batch-transfer"
},
"keywords": [
"rootstock",
Expand Down
Loading