loopd: static address summary

pull/721/head
Slyghtning 2 weeks ago
parent 60db8bdb2d
commit dedf84850d
No known key found for this signature in database
GPG Key ID: F82D456EA023C9BF

@ -22,6 +22,7 @@ var staticAddressCommands = cli.Command{
newStaticAddressCommand,
listUnspentCommand,
withdrawalCommand,
summaryCommand,
},
}
@ -181,6 +182,83 @@ func withdraw(ctx *cli.Context) error {
return nil
}
var summaryCommand = cli.Command{
Name: "summary",
ShortName: "s",
Usage: "Display a summary of static address related data.",
Description: `
Displays various static address related data like deposits, withdrawals,
and statistics. The data can be filtered by state.
`,
Flags: []cli.Flag{
cli.StringFlag{
Name: "filter",
Usage: "specify a filter to only display deposits in " +
"the specified state. The state can be one " +
"of [deposited|withdrawing|withdrawn|" +
"publish_expired_deposit|" +
"wait_for_expiry_sweep|expired|failed].",
},
},
Action: summary,
}
func summary(ctx *cli.Context) error {
ctxb := context.Background()
if ctx.NArg() > 0 {
return cli.ShowCommandHelp(ctx, "summary")
}
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
var filterState looprpc.DepositState
switch ctx.String("filter") {
case "":
// If no filter is specified, we'll default to showing all.
case "deposited":
filterState = looprpc.DepositState_DEPOSITED
case "withdrawing":
filterState = looprpc.DepositState_WITHDRAWING
case "withdrawn":
filterState = looprpc.DepositState_WITHDRAWN
case "publish_expired_deposit":
filterState = looprpc.DepositState_PUBLISH_EXPIRED
case "wait_for_expiry_sweep":
filterState = looprpc.DepositState_WAIT_FOR_EXPIRY_SWEEP
case "expired":
filterState = looprpc.DepositState_EXPIRED
case "failed":
filterState = looprpc.DepositState_FAILED_STATE
default:
filterState = looprpc.DepositState_UNKNOWN_STATE
}
resp, err := client.GetStaticAddressSummary(
ctxb, &looprpc.StaticAddressSummaryRequest{
StateFilter: filterState,
},
)
if err != nil {
return err
}
printRespJSON(resp)
return nil
}
func utxosToOutpoints(utxos []string) ([]*looprpc.OutPoint, error) {
outpoints := make([]*looprpc.OutPoint, 0, len(utxos))
if len(utxos) == 0 {

@ -94,6 +94,13 @@ var RequiredPermissions = map[string][]bakery.Op{
Entity: "loop",
Action: "in",
}},
"/looprpc.SwapClient/GetStaticAddressSummary": {{
Entity: "swap",
Action: "read",
}, {
Entity: "loop",
Action: "in",
}},
"/looprpc.SwapClient/GetLsatTokens": {{
Entity: "auth",
Action: "read",

@ -19,6 +19,7 @@ import (
"github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/fsm"
"github.com/lightninglabs/loop/instantout"
"github.com/lightninglabs/loop/instantout/reservation"
"github.com/lightninglabs/loop/labels"
@ -1395,6 +1396,201 @@ func (s *swapClientServer) WithdrawDeposits(ctx context.Context,
return &clientrpc.WithdrawDepositsResponse{}, err
}
// GetStaticAddressSummary returns a summary static address related information.
// Amongst deposits and withdrawals and their total values it also includes a
// list of detailed deposit information filtered by their state.
func (s *swapClientServer) GetStaticAddressSummary(ctx context.Context,
req *clientrpc.StaticAddressSummaryRequest) (
*clientrpc.StaticAddressSummaryResponse, error) {
if req.StateFilter != clientrpc.DepositState_UNKNOWN_STATE &&
len(req.Outpoints) > 0 {
return nil, fmt.Errorf("can either filter by state or " +
"outpoints")
}
allDeposits, err := s.depositManager.GetAllDeposits()
if err != nil {
return nil, err
}
return s.depositSummary(
ctx, allDeposits, req.StateFilter, req.Outpoints,
)
}
func (s *swapClientServer) depositSummary(ctx context.Context,
deposits []*deposit.Deposit, stateFilter clientrpc.DepositState,
outpointsFilter []string) (*clientrpc.StaticAddressSummaryResponse,
error) {
var (
totalNumDeposits = len(deposits)
valueUnconfirmed int64
valueDeposited int64
valueExpired int64
valueWithdrawn int64
)
// Value unconfirmed.
utxos, err := s.staticAddressManager.ListUnspent(
ctx, 0, deposit.MinConfs-1,
)
if err != nil {
return nil, err
}
for _, u := range utxos {
valueUnconfirmed += int64(u.Value)
}
// Confirmed total values by category.
for _, d := range deposits {
value := int64(d.Value)
switch d.GetState() {
case deposit.Deposited:
valueDeposited += value
case deposit.Expired:
valueExpired += value
case deposit.Withdrawn:
valueWithdrawn += value
}
}
// Deposits filtered by state or outpoints.
var clientDeposits []*clientrpc.Deposit
if len(outpointsFilter) > 0 {
f := func(d *deposit.Deposit) bool {
for _, outpoint := range outpointsFilter {
if outpoint == d.OutPoint.String() {
return true
}
}
return false
}
clientDeposits = filter(deposits, f)
if len(outpointsFilter) != len(clientDeposits) {
return nil, fmt.Errorf("not all outpoints found in " +
"deposits")
}
} else {
f := func(d *deposit.Deposit) bool {
if stateFilter == clientrpc.DepositState_UNKNOWN_STATE {
// Per default, we return deposits in all
// states.
return true
}
return d.GetState() == toServerState(stateFilter)
}
clientDeposits = filter(deposits, f)
}
params, err := s.staticAddressManager.GetStaticAddressParameters(ctx)
if err != nil {
return nil, err
}
address, err := s.staticAddressManager.GetTaprootAddress(
params.ClientPubkey, params.ServerPubkey, int64(params.Expiry),
)
if err != nil {
return nil, err
}
return &clientrpc.StaticAddressSummaryResponse{
StaticAddress: address.String(),
TotalNumDeposits: uint32(totalNumDeposits),
ValueUnconfirmed: valueUnconfirmed,
ValueDeposited: valueDeposited,
ValueExpired: valueExpired,
ValueWithdrawn: valueWithdrawn,
FilteredDeposits: clientDeposits,
}, nil
}
type filterFunc func(deposits *deposit.Deposit) bool
func filter(deposits []*deposit.Deposit, f filterFunc) []*clientrpc.Deposit {
var clientDeposits []*clientrpc.Deposit
for _, d := range deposits {
if f(d) {
hash := d.Hash
outpoint := wire.NewOutPoint(&hash, d.Index).String()
deposit := &clientrpc.Deposit{
Id: d.ID[:],
State: toClientState(d.GetState()),
Outpoint: outpoint,
Value: int64(d.Value),
ConfirmationHeight: d.ConfirmationHeight,
}
clientDeposits = append(clientDeposits, deposit)
}
}
return clientDeposits
}
func toClientState(state fsm.StateType) clientrpc.DepositState {
switch state {
case deposit.Deposited:
return clientrpc.DepositState_DEPOSITED
case deposit.Withdrawing:
return clientrpc.DepositState_WITHDRAWING
case deposit.Withdrawn:
return clientrpc.DepositState_WITHDRAWN
case deposit.PublishExpiredDeposit:
return clientrpc.DepositState_PUBLISH_EXPIRED
case deposit.WaitForExpirySweep:
return clientrpc.DepositState_WAIT_FOR_EXPIRY_SWEEP
case deposit.Expired:
return clientrpc.DepositState_EXPIRED
case deposit.Failed:
return clientrpc.DepositState_FAILED_STATE
default:
return clientrpc.DepositState_UNKNOWN_STATE
}
}
func toServerState(state clientrpc.DepositState) fsm.StateType {
switch state {
case clientrpc.DepositState_DEPOSITED:
return deposit.Deposited
case clientrpc.DepositState_WITHDRAWING:
return deposit.Withdrawing
case clientrpc.DepositState_WITHDRAWN:
return deposit.Withdrawn
case clientrpc.DepositState_PUBLISH_EXPIRED:
return deposit.PublishExpiredDeposit
case clientrpc.DepositState_WAIT_FOR_EXPIRY_SWEEP:
return deposit.WaitForExpirySweep
case clientrpc.DepositState_EXPIRED:
return deposit.Expired
case clientrpc.DepositState_FAILED_STATE:
return deposit.Failed
default:
return fsm.EmptyState
}
}
func toServerOutpoints(outpoints []*clientrpc.OutPoint) ([]wire.OutPoint,
error) {

Loading…
Cancel
Save