Skip to content

Commit 8ef81af

Browse files
authored
feat: add wallet command group (#624)
1 parent 4cf0441 commit 8ef81af

File tree

6 files changed

+190
-0
lines changed

6 files changed

+190
-0
lines changed

src/command/wallet/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { GroupCommand } from 'furious-commander'
2+
import { Status } from './status'
3+
import { WithdrawBZZ } from './withdraw-bzz'
4+
import { WithdrawDAI } from './withdraw-dai'
5+
6+
export class Wallet implements GroupCommand {
7+
public readonly name = 'wallet'
8+
9+
public readonly description = 'Manages node wallet'
10+
11+
public subCommandClasses = [Status, WithdrawBZZ, WithdrawDAI]
12+
}

src/command/wallet/status.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import chalk from 'chalk'
2+
import { LeafCommand } from 'furious-commander'
3+
import { createKeyValue } from '../../utils/text'
4+
import { RootCommand } from '../root-command'
5+
6+
export class Status extends RootCommand implements LeafCommand {
7+
public readonly name = 'status'
8+
9+
public readonly description = `Prints node wallet balance`
10+
11+
public async run(): Promise<void> {
12+
super.init()
13+
14+
const { bzzBalance, nativeTokenBalance } = await this.bee.getWalletBalance()
15+
16+
this.console.all(chalk.bold('Wallet'))
17+
this.console.all(createKeyValue('xBZZ', bzzBalance.toDecimalString()))
18+
this.console.all(createKeyValue('xDAI', nativeTokenBalance.toDecimalString()))
19+
}
20+
}

src/command/wallet/withdraw-bzz.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { BZZ } from '@ethersphere/bee-js'
2+
import { LeafCommand, Option } from 'furious-commander'
3+
import { createKeyValue } from '../../utils/text'
4+
import { RootCommand } from '../root-command'
5+
6+
export class WithdrawBZZ extends RootCommand implements LeafCommand {
7+
public readonly name = 'withdraw-bzz'
8+
9+
@Option({
10+
key: 'address',
11+
type: 'hex-string',
12+
description: 'Target wallet address, must be allowlisted in Bee config',
13+
required: true,
14+
})
15+
public address!: string
16+
17+
@Option({
18+
key: 'bzz',
19+
description: 'Amount of xBZZ to withdraw to the external wallet',
20+
type: 'string',
21+
required: true,
22+
})
23+
public amountBzz!: string
24+
25+
public readonly description = `Withdraw xBZZ to a whitelisted wallet address`
26+
27+
public async run(): Promise<void> {
28+
super.init()
29+
30+
const amount = BZZ.fromDecimalString(this.amountBzz)
31+
32+
this.console.log('The address you are withdrawing to must be whitelisted in the Bee config.')
33+
this.console.log('If you receive status code 400, the address may not be whitelisted.')
34+
this.console.log('')
35+
36+
if (!this.quiet && !this.yes) {
37+
this.yes = await this.console.confirm(
38+
`You are about to withdraw ${amount.toDecimalString()} xBZZ to ${
39+
this.address
40+
}, are you sure you wish to proceed?`,
41+
)
42+
}
43+
44+
if (!this.yes && !this.quiet) {
45+
return
46+
}
47+
48+
const transaction = await this.bee.withdrawBZZToExternalWallet(amount, this.address)
49+
this.console.log(createKeyValue('Transaction', transaction.represent()))
50+
this.console.log(createKeyValue('URL', `https://gnosisscan.io/tx/0x${transaction.represent()}`))
51+
}
52+
}

src/command/wallet/withdraw-dai.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { DAI } from '@ethersphere/bee-js'
2+
import { LeafCommand, Option } from 'furious-commander'
3+
import { createKeyValue } from '../../utils/text'
4+
import { RootCommand } from '../root-command'
5+
6+
export class WithdrawDAI extends RootCommand implements LeafCommand {
7+
public readonly name = 'withdraw-dai'
8+
9+
@Option({
10+
key: 'address',
11+
type: 'hex-string',
12+
description: 'Target wallet address, must be allowlisted in Bee config',
13+
required: true,
14+
})
15+
public address!: string
16+
17+
@Option({
18+
key: 'dai',
19+
description: 'Amount of xDAI to withdraw to the external wallet',
20+
type: 'string',
21+
required: true,
22+
})
23+
public amountDai!: string
24+
25+
public readonly description = `Withdraw xDAI to a whitelisted wallet address`
26+
27+
public async run(): Promise<void> {
28+
super.init()
29+
30+
const amount = DAI.fromDecimalString(this.amountDai)
31+
32+
this.console.log('The address you are withdrawing to must be whitelisted in the Bee config.')
33+
this.console.log('If you receive status code 400, the address may not be whitelisted.')
34+
this.console.log('')
35+
36+
if (!this.quiet && !this.yes) {
37+
this.yes = await this.console.confirm(
38+
`You are about to withdraw ${amount.toDecimalString()} xDAI to ${
39+
this.address
40+
}, are you sure you wish to proceed?`,
41+
)
42+
}
43+
44+
if (!this.yes && !this.quiet) {
45+
return
46+
}
47+
48+
const transaction = await this.bee.withdrawDAIToExternalWallet(amount, this.address)
49+
this.console.log(createKeyValue('Transaction', transaction.represent()))
50+
this.console.log(createKeyValue('URL', `https://gnosisscan.io/tx/0x${transaction.represent()}`))
51+
}
52+
}

src/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { Stamp } from './command/stamp'
1515
import { Status } from './command/status'
1616
import { Upload } from './command/upload'
1717
import { Utility } from './command/utility'
18+
import { Wallet } from './command/wallet'
1819

1920
export const beeApiUrl: IOption<string> = {
2021
key: 'bee-api-url',
@@ -127,6 +128,7 @@ export const rootCommandClasses = [
127128
Addresses,
128129
Manifest,
129130
Stake,
131+
Wallet,
130132
Utility,
131133
Grantee,
132134
]

test/command/wallet.spec.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { toMatchLinesInOrder } from '../custom-matcher'
2+
import { describeCommand, invokeTestCli } from '../utility'
3+
import { getBeeDevOption } from '../utility/stamp'
4+
5+
expect.extend({
6+
toMatchLinesInOrder,
7+
})
8+
9+
describeCommand('Test Wallet command', ({ consoleMessages }) => {
10+
test('should print wallet', async () => {
11+
await invokeTestCli(['wallet', 'status', ...getBeeDevOption()])
12+
expect(consoleMessages).toMatchLinesInOrder([['Wallet'], ['xBZZ'], ['xDAI']])
13+
})
14+
15+
test('should withdraw xdai', async () => {
16+
await invokeTestCli([
17+
'wallet',
18+
'withdraw-dai',
19+
'--address',
20+
'00'.repeat(20),
21+
'--dai',
22+
'0.01',
23+
'--yes',
24+
...getBeeDevOption(),
25+
])
26+
expect(consoleMessages).toMatchLinesInOrder([
27+
['must be whitelisted'],
28+
['status code 400'],
29+
['Transaction'],
30+
['URL', 'gnosisscan'],
31+
])
32+
})
33+
34+
test('should withdraw xbzz', async () => {
35+
await invokeTestCli([
36+
'wallet',
37+
'withdraw-bzz',
38+
'--address',
39+
'00'.repeat(20),
40+
'--bzz',
41+
'0.01',
42+
'--yes',
43+
...getBeeDevOption(),
44+
])
45+
expect(consoleMessages).toMatchLinesInOrder([
46+
['must be whitelisted'],
47+
['status code 400'],
48+
['Transaction'],
49+
['URL', 'gnosisscan'],
50+
])
51+
})
52+
})

0 commit comments

Comments
 (0)