diff --git a/client/common.go b/client/common.go index 442d606..4f507ba 100644 --- a/client/common.go +++ b/client/common.go @@ -186,19 +186,21 @@ func getUnilateralExitDelay() (int64, error) { return int64(redeemDelay), nil } -func coinSelect(vtxos []vtxo, amount uint64) ([]vtxo, uint64, error) { +func coinSelect(vtxos []vtxo, amount uint64, sortByExpirationTime bool) ([]vtxo, uint64, error) { selected := make([]vtxo, 0) notSelected := make([]vtxo, 0) selectedAmount := uint64(0) - // sort vtxos by expiration (older first) - sort.SliceStable(vtxos, func(i, j int) bool { - if vtxos[i].expireAt == nil || vtxos[j].expireAt == nil { - return false - } + if sortByExpirationTime { + // sort vtxos by expiration (older first) + sort.SliceStable(vtxos, func(i, j int) bool { + if vtxos[i].expireAt == nil || vtxos[j].expireAt == nil { + return false + } - return vtxos[i].expireAt.Before(*vtxos[j].expireAt) - }) + return vtxos[i].expireAt.Before(*vtxos[j].expireAt) + }) + } for _, vtxo := range vtxos { if selectedAmount >= amount { diff --git a/client/redeem.go b/client/redeem.go index 126dc17..066e367 100644 --- a/client/redeem.go +++ b/client/redeem.go @@ -40,7 +40,7 @@ var ( var redeemCommand = cli.Command{ Name: "redeem", Usage: "Redeem your offchain funds, either collaboratively or unilaterally", - Flags: []cli.Flag{&addressFlag, &amountToRedeemFlag, &forceFlag}, + Flags: []cli.Flag{&addressFlag, &amountToRedeemFlag, &forceFlag, &enableExpiryCoinselectFlag}, Action: redeemAction, } @@ -68,15 +68,17 @@ func redeemAction(ctx *cli.Context) error { fmt.Printf("WARNING: unilateral exit (--force) ignores --amount flag, it will redeem all your VTXOs\n") } - return unilateralRedeem(client, ctx.Context) + return unilateralRedeem(ctx.Context, client) } - return collaborativeRedeem(client, ctx.Context, addr, amount) + return collaborativeRedeem(ctx, client, addr, amount) } func collaborativeRedeem( - client arkv1.ArkServiceClient, ctx context.Context, addr string, amount uint64, + ctx *cli.Context, client arkv1.ArkServiceClient, addr string, amount uint64, ) error { + withExpiryCoinselect := ctx.Bool("enable-expiry-coinselect") + if _, err := address.ToOutputScript(addr); err != nil { return fmt.Errorf("invalid onchain address") } @@ -109,12 +111,12 @@ func collaborativeRedeem( explorer := NewExplorer() - vtxos, err := getVtxos(ctx, explorer, client, offchainAddr, true) + vtxos, err := getVtxos(ctx.Context, explorer, client, offchainAddr, withExpiryCoinselect) if err != nil { return err } - selectedCoins, changeAmount, err := coinSelect(vtxos, amount) + selectedCoins, changeAmount, err := coinSelect(vtxos, amount, withExpiryCoinselect) if err != nil { return err } @@ -140,14 +142,14 @@ func collaborativeRedeem( return err } - registerResponse, err := client.RegisterPayment(ctx, &arkv1.RegisterPaymentRequest{ + registerResponse, err := client.RegisterPayment(ctx.Context, &arkv1.RegisterPaymentRequest{ Inputs: inputs, }) if err != nil { return err } - _, err = client.ClaimPayment(ctx, &arkv1.ClaimPaymentRequest{ + _, err = client.ClaimPayment(ctx.Context, &arkv1.ClaimPaymentRequest{ Id: registerResponse.GetId(), Outputs: receivers, }) @@ -156,7 +158,7 @@ func collaborativeRedeem( } poolTxID, err := handleRoundStream( - ctx, + ctx.Context, client, registerResponse.GetId(), selectedCoins, @@ -176,7 +178,7 @@ func collaborativeRedeem( return nil } -func unilateralRedeem(client arkv1.ArkServiceClient, ctx context.Context) error { +func unilateralRedeem(ctx context.Context, client arkv1.ArkServiceClient) error { offchainAddr, _, _, err := getAddress() if err != nil { return err diff --git a/client/send.go b/client/send.go index ce1259e..762da1d 100644 --- a/client/send.go +++ b/client/send.go @@ -36,13 +36,18 @@ var ( Name: "amount", Usage: "amount to send in sats", } + enableExpiryCoinselectFlag = cli.BoolFlag{ + Name: "enable-expiry-coinselect", + Usage: "select vtxos that are about to expire first", + Value: false, + } ) var sendCommand = cli.Command{ Name: "send", Usage: "Send your onchain or offchain funds to one or many receivers", Action: sendAction, - Flags: []cli.Flag{&receiversFlag, &toFlag, &amountFlag}, + Flags: []cli.Flag{&receiversFlag, &toFlag, &amountFlag, &enableExpiryCoinselectFlag}, } func sendAction(ctx *cli.Context) error { @@ -110,6 +115,8 @@ func sendAction(ctx *cli.Context) error { } func sendOffchain(ctx *cli.Context, receivers []receiver) error { + withExpiryCoinselect := ctx.Bool("enable-expiry-coinselect") + offchainAddr, _, _, err := getAddress() if err != nil { return err @@ -153,12 +160,11 @@ func sendOffchain(ctx *cli.Context, receivers []receiver) error { explorer := NewExplorer() - vtxos, err := getVtxos(ctx.Context, explorer, client, offchainAddr, true) + vtxos, err := getVtxos(ctx.Context, explorer, client, offchainAddr, withExpiryCoinselect) if err != nil { return err } - - selectedCoins, changeAmount, err := coinSelect(vtxos, sumOfReceivers) + selectedCoins, changeAmount, err := coinSelect(vtxos, sumOfReceivers, withExpiryCoinselect) if err != nil { return err } @@ -213,7 +219,7 @@ func sendOffchain(ctx *cli.Context, receivers []receiver) error { }) } -func sendOnchain(ctx *cli.Context, receivers []receiver) (string, error) { +func sendOnchain(_ *cli.Context, receivers []receiver) (string, error) { pset, err := psetv2.New(nil, nil, nil) if err != nil { return "", err