@@ -2,6 +2,7 @@ package main
2
2
3
3
import (
4
4
"encoding/hex"
5
+ "errors"
5
6
"fmt"
6
7
"os"
7
8
"strconv"
@@ -173,6 +174,10 @@ var updateAccountCommand = cli.Command{
173
174
},
174
175
},
175
176
Action : updateAccount ,
177
+ Subcommands : []cli.Command {
178
+ creditCommand ,
179
+ debitCommand ,
180
+ },
176
181
}
177
182
178
183
func updateAccount (cli * cli.Context ) error {
@@ -232,6 +237,125 @@ func updateAccount(cli *cli.Context) error {
232
237
return nil
233
238
}
234
239
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
+
235
359
var listAccountsCommand = cli.Command {
236
360
Name : "list" ,
237
361
ShortName : "l" ,
@@ -348,6 +472,39 @@ func removeAccount(cli *cli.Context) error {
348
472
return err
349
473
}
350
474
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
+
351
508
// parseIDOrLabel parses either the id or label from the command line.
352
509
func parseIDOrLabel (ctx * cli.Context ) (string , string , cli.Args , error ) {
353
510
var (
0 commit comments