rpc: SendOutputs considers anchor reserve
This commit is contained in:
1 parent
3c8c057ea9
commit
903b5dde89
3 files changed
+59
-6
No files matched your search
@@ -0,0 +1,17 @@
|
|||||||
|
package walletrpc
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
|
||||||
|
// ErrZeroLabel is returned when an attempt is made to label a
|
||||||
|
// transaction with an empty label.
|
||||||
|
ErrZeroLabel = errors.New("cannot label transaction with empty " +
|
||||||
|
"label")
|
||||||
|
|
||||||
|
// ErrInsufficientReserve is returned when SendOutputs wouldn't leave
|
||||||
|
// enough funds in the wallet to cover for the anchor reserve.
|
||||||
|
ErrInsufficientReserve = errors.New("the outputs to be sent " +
|
||||||
|
"would leave insufficient reserves for anchor channels in " +
|
||||||
|
"the wallet")
|
||||||
|
)
|
||||||
@@ -222,10 +222,6 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrZeroLabel is returned when an attempt is made to label a transaction with
|
|
||||||
// an empty label.
|
|
||||||
var ErrZeroLabel = errors.New("cannot label transaction with empty label")
|
|
||||||
|
|
||||||
// ServerShell is a shell struct holding a reference to the actual sub-server.
|
// ServerShell is a shell struct holding a reference to the actual sub-server.
|
||||||
// It is used to register the gRPC sub-server with the root server before we
|
// It is used to register the gRPC sub-server with the root server before we
|
||||||
// have the necessary dependencies to populate the actual sub-server.
|
// have the necessary dependencies to populate the actual sub-server.
|
||||||
@@ -666,12 +662,14 @@ func (w *WalletKit) SendOutputs(ctx context.Context,
|
|||||||
// Before we can request this transaction to be created, we'll need to
|
// Before we can request this transaction to be created, we'll need to
|
||||||
// amp the protos back into the format that the internal wallet will
|
// amp the protos back into the format that the internal wallet will
|
||||||
// recognize.
|
// recognize.
|
||||||
|
var totalOutputValue int64
|
||||||
outputsToCreate := make([]*wire.TxOut, 0, len(req.Outputs))
|
outputsToCreate := make([]*wire.TxOut, 0, len(req.Outputs))
|
||||||
for _, output := range req.Outputs {
|
for _, output := range req.Outputs {
|
||||||
outputsToCreate = append(outputsToCreate, &wire.TxOut{
|
outputsToCreate = append(outputsToCreate, &wire.TxOut{
|
||||||
Value: output.Value,
|
Value: output.Value,
|
||||||
PkScript: output.PkScript,
|
PkScript: output.PkScript,
|
||||||
})
|
})
|
||||||
|
totalOutputValue += output.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, we'll extract the minimum number of confirmations that each
|
// Then, we'll extract the minimum number of confirmations that each
|
||||||
@@ -681,13 +679,36 @@ func (w *WalletKit) SendOutputs(ctx context.Context,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Before sending out funds we need to ensure that the remainder of our
|
||||||
|
// wallet funds would cover for the anchor reserve requirement. We'll
|
||||||
|
// also take unconfirmed funds into account.
|
||||||
|
walletBalance, err := w.cfg.Wallet.ConfirmedBalance(
|
||||||
|
0, lnwallet.DefaultAccountName,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// We'll get the currently required reserve amount.
|
||||||
|
reserve, err := w.RequiredReserve(ctx, &RequiredReserveRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then we check if our current wallet balance undershoots the required
|
||||||
|
// reserve if we'd send out the outputs specified in the request.
|
||||||
|
if int64(walletBalance)-totalOutputValue < reserve.RequiredReserve {
|
||||||
|
return nil, ErrInsufficientReserve
|
||||||
|
}
|
||||||
|
|
||||||
label, err := labels.ValidateAPI(req.Label)
|
label, err := labels.ValidateAPI(req.Label)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we have the outputs mapped, we can request that the wallet
|
// Now that we have the outputs mapped and checked for the reserve
|
||||||
// attempt to create this transaction.
|
// requirement, we can request that the wallet attempts to create this
|
||||||
|
// transaction.
|
||||||
tx, err := w.cfg.Wallet.SendOutputs(
|
tx, err := w.cfg.Wallet.SendOutputs(
|
||||||
outputsToCreate, chainfee.SatPerKWeight(req.SatPerKw), minConfs, label,
|
outputsToCreate, chainfee.SatPerKWeight(req.SatPerKw), minConfs, label,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -290,3 +290,18 @@ func (h *HarnessRPC) ImportTapscript(
|
|||||||
|
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequiredReserve makes a RPC call to the node's WalletKitClient and asserts.
|
||||||
|
//
|
||||||
|
//nolint:lll
|
||||||
|
func (h *HarnessRPC) RequiredReserve(
|
||||||
|
req *walletrpc.RequiredReserveRequest) *walletrpc.RequiredReserveResponse {
|
||||||
|
|
||||||
|
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
resp, err := h.WalletKit.RequiredReserve(ctxt, req)
|
||||||
|
h.NoError(err, "RequiredReserve")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
}
|
||||||
Reference in new issue
Block a user