Skip to content

Commit 5a02019

Browse files
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 b2ec597 commit 5a02019

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed

cmd/litcli/accounts.go

Lines changed: 157 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"
@@ -173,6 +174,10 @@ var updateAccountCommand = cli.Command{
173174
},
174175
},
175176
Action: updateAccount,
177+
Subcommands: []cli.Command{
178+
creditCommand,
179+
debitCommand,
180+
},
176181
}
177182

178183
func updateAccount(cli *cli.Context) error {
@@ -232,6 +237,125 @@ func updateAccount(cli *cli.Context) error {
232237
return nil
233238
}
234239

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

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

0 commit comments

Comments
 (0)