diff --git a/cmd/loop/loopout.go b/cmd/loop/loopout.go index 73d50a3..a2ceb98 100644 --- a/cmd/loop/loopout.go +++ b/cmd/loop/loopout.go @@ -238,6 +238,7 @@ func loopOut(ctx *cli.Context) error { resp, err := client.LoopOut(context.Background(), &looprpc.LoopOutRequest{ Amt: int64(amt), Dest: destAddr, + IsExternalAddr: destAddr != "", Account: account, AccountAddrType: accountAddrType, MaxMinerFee: int64(limits.maxMinerFee), diff --git a/interface.go b/interface.go index 1a48492..17affe8 100644 --- a/interface.go +++ b/interface.go @@ -20,6 +20,11 @@ type OutRequest struct { // Destination address for the swap. DestAddr btcutil.Address + // IsExternalAddr indicates whether the provided destination address + // does not belong to the underlying wallet. This helps indicate + // whether the sweep of this swap can be batched or not. + IsExternalAddr bool + // MaxSwapRoutingFee is the maximum off-chain fee in msat that may be // paid for payment to the server. This limit is applied during path // finding. Typically this value is taken from the response of the diff --git a/liquidity/autoloop_test.go b/liquidity/autoloop_test.go index 3799748..561a0e1 100644 --- a/liquidity/autoloop_test.go +++ b/liquidity/autoloop_test.go @@ -422,6 +422,7 @@ func TestAutoloopAddress(t *testing.T) { Amount: amt, // Define the expected destination address. DestAddr: addr, + IsExternalAddr: true, MaxSwapRoutingFee: maxRouteFee, MaxPrepayRoutingFee: ppmToSat( quote1.PrepayAmount, prepayFeePPM, @@ -439,6 +440,7 @@ func TestAutoloopAddress(t *testing.T) { Amount: amt, // Define the expected destination address. DestAddr: addr, + IsExternalAddr: true, MaxSwapRoutingFee: maxRouteFee, MaxPrepayRoutingFee: ppmToSat( quote2.PrepayAmount, routeFeePPM, diff --git a/liquidity/liquidity.go b/liquidity/liquidity.go index d41b25e..acf01ef 100644 --- a/liquidity/liquidity.go +++ b/liquidity/liquidity.go @@ -450,6 +450,13 @@ func (m *Manager) autoloop(ctx context.Context) error { // Create a copy of our range var so that we can reference it. swap := swap + // Check if the parameter for custom address is defined for loop + // outs. + if m.params.DestAddr != nil { + swap.DestAddr = m.params.DestAddr + swap.IsExternalAddr = true + } + go m.dispatchStickyLoopOut( ctx, swap, defaultAmountBackoffRetry, defaultAmountBackoff, diff --git a/liquidity/loopout_builder.go b/liquidity/loopout_builder.go index 8048aea..b2c6040 100644 --- a/liquidity/loopout_builder.go +++ b/liquidity/loopout_builder.go @@ -138,6 +138,7 @@ func (b *loopOutBuilder) buildSwap(ctx context.Context, pubkey route.Vertex, // already validated them. request := loop.OutRequest{ Amount: amount, + IsExternalAddr: false, OutgoingChanSet: chanSet, MaxPrepayRoutingFee: prepayMaxFee, MaxSwapRoutingFee: routeMaxFee, @@ -160,9 +161,11 @@ func (b *loopOutBuilder) buildSwap(ctx context.Context, pubkey route.Vertex, if len(params.Account) > 0 { account = params.Account addrType = params.AccountAddrType + request.IsExternalAddr = true } if params.DestAddr != nil { request.DestAddr = params.DestAddr + request.IsExternalAddr = true } else { addr, err := b.cfg.Lnd.WalletKit.NextAddr( ctx, account, addrType, false, diff --git a/loopd/swapclient_server.go b/loopd/swapclient_server.go index 845885c..05f9156 100644 --- a/loopd/swapclient_server.go +++ b/loopd/swapclient_server.go @@ -100,6 +100,7 @@ func (s *swapClientServer) LoopOut(ctx context.Context, log.Infof("Loop out request received") var sweepAddr btcutil.Address + var isExternalAddr bool var err error //nolint:lll switch { @@ -117,6 +118,8 @@ func (s *swapClientServer) LoopOut(ctx context.Context, return nil, fmt.Errorf("decode address: %v", err) } + isExternalAddr = true + case in.Account != "" && in.AccountAddrType == clientrpc.AddressType_ADDRESS_TYPE_UNKNOWN: return nil, liquidity.ErrAccountAndAddrType @@ -141,6 +144,8 @@ func (s *swapClientServer) LoopOut(ctx context.Context, "%v", err) } + isExternalAddr = true + default: // Generate sweep address if none specified. sweepAddr, err = s.lnd.WalletKit.NextAddr( @@ -166,6 +171,7 @@ func (s *swapClientServer) LoopOut(ctx context.Context, req := &loop.OutRequest{ Amount: btcutil.Amount(in.Amt), DestAddr: sweepAddr, + IsExternalAddr: isExternalAddr, MaxMinerFee: btcutil.Amount(in.MaxMinerFee), MaxPrepayAmount: btcutil.Amount(in.MaxPrepayAmt), MaxPrepayRoutingFee: btcutil.Amount(in.MaxPrepayRoutingFee), diff --git a/loopout.go b/loopout.go index f1b1be2..f96265f 100644 --- a/loopout.go +++ b/loopout.go @@ -172,6 +172,7 @@ func newLoopOutSwap(globalCtx context.Context, cfg *swapConfig, contract := loopdb.LoopOutContract{ SwapInvoice: swapResp.swapInvoice, DestAddr: request.DestAddr, + IsExternalAddr: request.IsExternalAddr, MaxSwapRoutingFee: request.MaxSwapRoutingFee, SweepConfTarget: request.SweepConfTarget, HtlcConfirmations: confs,