Skip to content

Commit f4f359e

Browse files
committed
litcli: add accounts credit & debit commands
This commit implements the `credit` and `debit` commands in `litcli`, allowing users to increase or decrease the balance of an existing off-chain account, respectively.
1 parent 8d5cf5a commit f4f359e

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

cmd/litcli/accounts.go

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"encoding/hex"
5+
"errors"
56
"fmt"
67
"os"
78
"strconv"
@@ -26,6 +27,8 @@ var accountsCommands = []cli.Command{
2627
Subcommands: []cli.Command{
2728
createAccountCommand,
2829
updateAccountCommand,
30+
creditCommand,
31+
debitCommand,
2932
listAccountsCommand,
3033
accountInfoCommand,
3134
removeAccountCommand,
@@ -232,6 +235,123 @@ func updateAccount(cli *cli.Context) error {
232235
return nil
233236
}
234237

238+
var creditCommand = cli.Command{
239+
Name: "credit",
240+
Usage: "Increase an account's balance by the given amount.",
241+
ArgsUsage: "[id | label] amount",
242+
Description: "Increases an existing off-chain account's balance by " +
243+
"the given amount.",
244+
Flags: []cli.Flag{
245+
cli.StringFlag{
246+
Name: idName,
247+
Usage: "The ID of the account to credit.",
248+
},
249+
cli.StringFlag{
250+
Name: labelName,
251+
Usage: "(optional) The unique label of the account.",
252+
},
253+
cli.Uint64Flag{
254+
Name: "amount",
255+
Usage: "The amount to credit the account.",
256+
},
257+
},
258+
Action: creditBalance,
259+
}
260+
261+
func creditBalance(cli *cli.Context) error {
262+
return updateBalance(cli, true)
263+
}
264+
265+
var debitCommand = cli.Command{
266+
Name: "debit",
267+
Usage: "Decrease an account's balance by the given amount.",
268+
ArgsUsage: "[id | label] amount",
269+
Description: "Decreases an existing off-chain account's balance by " +
270+
"the given amount.",
271+
Flags: []cli.Flag{
272+
cli.StringFlag{
273+
Name: idName,
274+
Usage: "The ID of the account to debit.",
275+
},
276+
cli.StringFlag{
277+
Name: labelName,
278+
Usage: "(optional) The unique label of the account.",
279+
},
280+
cli.Uint64Flag{
281+
Name: "amount",
282+
Usage: "The amount to debit the account.",
283+
},
284+
},
285+
Action: debitBalance,
286+
}
287+
288+
func debitBalance(cli *cli.Context) error {
289+
return updateBalance(cli, false)
290+
}
291+
292+
func updateBalance(cli *cli.Context, add bool) error {
293+
ctx := getContext()
294+
clientConn, cleanup, err := connectClient(cli, false)
295+
if err != nil {
296+
return err
297+
}
298+
defer cleanup()
299+
client := litrpc.NewAccountsClient(clientConn)
300+
301+
account, args, err := parseAccountIdentifier(cli)
302+
if err != nil {
303+
return err
304+
}
305+
306+
if (!cli.IsSet("amount") && len(args) != 1) ||
307+
(cli.IsSet("amount") && len(args) != 0) {
308+
309+
return errors.New("invalid number of arguments")
310+
}
311+
312+
var amount uint64
313+
switch {
314+
case cli.IsSet("amount"):
315+
amount = cli.Uint64("amount")
316+
case args.Present():
317+
amount, err = strconv.ParseUint(args.First(), 10, 64)
318+
if err != nil {
319+
return fmt.Errorf("unable to decode amount %v", err)
320+
}
321+
args = args.Tail()
322+
default:
323+
return errors.New("must set a value for amount")
324+
}
325+
326+
if add {
327+
req := &litrpc.CreditAccountRequest{
328+
Account: account,
329+
Amount: amount,
330+
}
331+
332+
resp, err := client.CreditAccount(ctx, req)
333+
if err != nil {
334+
return err
335+
}
336+
337+
printRespJSON(resp)
338+
} else {
339+
req := &litrpc.DebitAccountRequest{
340+
Account: account,
341+
Amount: amount,
342+
}
343+
344+
resp, err := client.DebitAccount(ctx, req)
345+
if err != nil {
346+
return err
347+
}
348+
349+
printRespJSON(resp)
350+
}
351+
352+
return nil
353+
}
354+
235355
var listAccountsCommand = cli.Command{
236356
Name: "list",
237357
ShortName: "l",
@@ -348,6 +468,39 @@ func removeAccount(cli *cli.Context) error {
348468
return err
349469
}
350470

471+
// parseAccountIdentifier parses either the id or label from the command line,
472+
// and returns the account identifier.
473+
func parseAccountIdentifier(ctx *cli.Context) (
474+
*litrpc.AccountIdentifier, cli.Args, error) {
475+
476+
id, label, args, err := parseIDOrLabel(ctx)
477+
if err != nil {
478+
return nil, nil, err
479+
}
480+
481+
if id == "" && label == "" {
482+
return nil, nil, fmt.Errorf("id argument missing")
483+
}
484+
485+
if id != "" {
486+
identifier := &litrpc.AccountIdentifier{
487+
Identifier: &litrpc.AccountIdentifier_Id{
488+
Id: id,
489+
},
490+
}
491+
492+
return identifier, args, nil
493+
} else {
494+
identifier := &litrpc.AccountIdentifier{
495+
Identifier: &litrpc.AccountIdentifier_Label{
496+
Label: label,
497+
},
498+
}
499+
500+
return identifier, args, nil
501+
}
502+
}
503+
351504
// parseIDOrLabel parses either the id or label from the command line.
352505
func parseIDOrLabel(ctx *cli.Context) (string, string, cli.Args, error) {
353506
var (

0 commit comments

Comments
 (0)