Skip to content

Commit 2005831

Browse files
feat: add wallet transfer command (#91)
Co-authored-by: ronibarylko <[email protected]>
1 parent c447667 commit 2005831

File tree

3 files changed

+120
-2
lines changed

3 files changed

+120
-2
lines changed

src/commands/wallet/balance.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import inquirer from "inquirer";
22

33
import Program from "./command.js";
4-
import { accountOption, chainOption, zeekOption } from "../../common/options.js";
4+
import { accountOption, chainOption, l2RpcUrlOption, zeekOption } from "../../common/options.js";
55
import { l2Chains } from "../../data/chains.js";
66
import { bigNumberToDecimal } from "../../utils/formatters.js";
77
import { getL2Provider, optionNameToParam } from "../../utils/helpers.js";
@@ -25,7 +25,7 @@ export const handler = async (options: BalanceOptions) => {
2525
message: chainOption.description,
2626
name: optionNameToParam(chainOption.long!),
2727
type: "list",
28-
choices: l2Chains.filter((e) => e.l1Chain).map((e) => ({ name: e.name, value: e.network })),
28+
choices: l2Chains.map((e) => ({ name: e.name, value: e.network })),
2929
required: true,
3030
when(answers: BalanceOptions) {
3131
if (answers.l2RpcUrl) {
@@ -68,6 +68,7 @@ export const handler = async (options: BalanceOptions) => {
6868
Program.command("balance")
6969
.description("Get balance of an L2 account")
7070
.addOption(chainOption)
71+
.addOption(l2RpcUrlOption)
7172
.addOption(accountOption)
7273
.addOption(zeekOption)
7374
.action(handler);

src/commands/wallet/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import "./transfer.js";
12
import "./balance.js";
23

34
import "./command.js"; // registers all the commands above

src/commands/wallet/transfer.ts

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import inquirer from "inquirer";
2+
import ora from "ora";
3+
4+
import Program from "./command.js";
5+
import {
6+
chainOption,
7+
zeekOption,
8+
privateKeyOption,
9+
recipientOptionCreate,
10+
amountOptionCreate,
11+
l2RpcUrlOption,
12+
} from "../../common/options.js";
13+
import { l2Chains } from "../../data/chains.js";
14+
import { bigNumberToDecimal, decimalToBigNumber } from "../../utils/formatters.js";
15+
import { getL2Provider, getL2Wallet, optionNameToParam } from "../../utils/helpers.js";
16+
import Logger from "../../utils/logger.js";
17+
import { isDecimalAmount, isAddress, isPrivateKey } from "../../utils/validators.js";
18+
import zeek from "../../utils/zeek.js";
19+
20+
import type { DefaultTransferOptions } from "../../common/options.js";
21+
22+
const amountOption = amountOptionCreate("transfer");
23+
const recipientOption = recipientOptionCreate("L2");
24+
25+
type TransferOptions = DefaultTransferOptions;
26+
27+
export const handler = async (options: TransferOptions) => {
28+
try {
29+
const answers: TransferOptions = await inquirer.prompt(
30+
[
31+
{
32+
message: chainOption.description,
33+
name: optionNameToParam(chainOption.long!),
34+
type: "list",
35+
choices: l2Chains.map((e) => ({ name: e.name, value: e.network })),
36+
required: true,
37+
when(answers: TransferOptions) {
38+
if (answers.l2RpcUrl) {
39+
return false;
40+
}
41+
return true;
42+
},
43+
},
44+
{
45+
message: amountOption.description,
46+
name: optionNameToParam(amountOption.long!),
47+
type: "input",
48+
required: true,
49+
validate: (input: string) => isDecimalAmount(input),
50+
},
51+
{
52+
message: privateKeyOption.description,
53+
name: optionNameToParam(privateKeyOption.long!),
54+
type: "password",
55+
required: true,
56+
validate: (input: string) => isPrivateKey(input),
57+
},
58+
{
59+
message: recipientOption.description,
60+
name: optionNameToParam(recipientOption.long!),
61+
type: "input",
62+
required: true,
63+
validate: (input: string) => isAddress(input),
64+
},
65+
],
66+
options
67+
);
68+
69+
options = {
70+
...options,
71+
...answers,
72+
};
73+
74+
const selectedChain = l2Chains.find((e) => e.network === options.chain);
75+
const l2Provider = getL2Provider(options.l2RpcUrl ?? selectedChain!.rpcUrl);
76+
const senderWallet = getL2Wallet(options.privateKey, l2Provider);
77+
78+
const transferHandle = await senderWallet.transfer({
79+
to: options.recipient,
80+
amount: decimalToBigNumber(options.amount),
81+
});
82+
const spinner = ora("Sending transfer...").start();
83+
try {
84+
const transferReceipt = await transferHandle.wait();
85+
spinner.stop();
86+
Logger.info("\nTransfer sent:");
87+
Logger.info(` Transaction hash: ${transferReceipt.transactionHash}`);
88+
if (selectedChain?.explorerUrl) {
89+
Logger.info(` Transaction link: ${selectedChain.explorerUrl}/tx/${transferReceipt.transactionHash}`);
90+
}
91+
92+
const senderBalance = await l2Provider.getBalance(senderWallet.address);
93+
Logger.info(`\nSender L2 balance after transaction: ${bigNumberToDecimal(senderBalance)} ETH`);
94+
} catch (error) {
95+
spinner.fail("Transfer failed");
96+
throw error;
97+
}
98+
99+
if (options.zeek) {
100+
zeek();
101+
}
102+
} catch (error) {
103+
Logger.error("There was an error while doing transfer");
104+
Logger.error(error);
105+
}
106+
};
107+
108+
Program.command("transfer")
109+
.description("Transfer ETH on L2 to another account")
110+
.addOption(amountOption)
111+
.addOption(chainOption)
112+
.addOption(recipientOption)
113+
.addOption(l2RpcUrlOption)
114+
.addOption(privateKeyOption)
115+
.addOption(zeekOption)
116+
.action(handler);

0 commit comments

Comments
 (0)