From 3d1352cdce032b959e09c553e4ecb8efcd115995 Mon Sep 17 00:00:00 2001 From: Gustavo Stingelin Date: Mon, 5 Oct 2026 15:01:27 -0300 Subject: [PATCH 1/9] cmd/loop: fix label flag help text Add the missing space in the shared --label help, and give listswaps its own --label help since there it filters swaps instead of labeling one. --- cmd/loop/loopin.go | 2 +- cmd/loop/swaps.go | 5 +- .../static-loop-in/14_loop-static-in.json | 2 +- docs/loop.1 | 8 +-- docs/loop.md | 50 +++++++++---------- 5 files changed, 35 insertions(+), 32 deletions(-) diff --git a/cmd/loop/loopin.go b/cmd/loop/loopin.go index d29f1345c..3d694dbf1 100644 --- a/cmd/loop/loopin.go +++ b/cmd/loop/loopin.go @@ -26,7 +26,7 @@ var ( labelFlag = &cli.StringFlag{ Name: "label", - Usage: fmt.Sprintf("an optional label for this swap,"+ + Usage: fmt.Sprintf("an optional label for this swap, "+ "limited to %v characters. The label may not start "+ "with our reserved prefix: %v.", labels.MaxLength, labels.Reserved), diff --git a/cmd/loop/swaps.go b/cmd/loop/swaps.go index 419522b6e..1b47581d1 100644 --- a/cmd/loop/swaps.go +++ b/cmd/loop/swaps.go @@ -33,7 +33,10 @@ var listSwapsCommand = &cli.Command{ Name: "pending_only", Usage: "only list pending swaps", }, - labelFlag, + &cli.StringFlag{ + Name: labelFlag.Name, + Usage: "only list swaps with the given label", + }, channelFlag, lastHopFlag, &cli.Uint64Flag{ diff --git a/cmd/loop/testdata/sessions/static-loop-in/14_loop-static-in.json b/cmd/loop/testdata/sessions/static-loop-in/14_loop-static-in.json index ad2dfca0c..77803b511 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/14_loop-static-in.json +++ b/cmd/loop/testdata/sessions/static-loop-in/14_loop-static-in.json @@ -42,7 +42,7 @@ " --max_swap_fee_sat uint the maximum swap fee in satoshis. If set, the swap is rejected when the quoted fee exceeds this cap. The maximum allowed value is 10000000. On-chain fees for creating static deposits are unaffected. (default: 0)\n", " --max_swap_fee_ppm uint the maximum swap fee expressed in parts per million of the swap amount. If set together with --max_swap_fee_sat the tighter cap is used. (default: 0)\n", " --last_hop string the pubkey of the last hop to use for this swap\n", - " --label string an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved].\n", + " --label string an optional label for this swap, limited to 500 characters. The label may not start with our reserved prefix: [reserved].\n", " --route_hints string a JSON array of route hints that can each be individually used to assist in reaching the invoice's destination\n", " --private generates and passes routehints. Should be used if the connected node is only reachable via private channels (default: false)\n", " --force Assumes yes during confirmation. Using this option will result in an immediate swap (default: false)\n", diff --git a/docs/loop.1 b/docs/loop.1 index 3f72415ff..173d00fa7 100644 --- a/docs/loop.1 +++ b/docs/loop.1 @@ -89,7 +89,7 @@ perform an off-chain to on-chain swap (looping out) \fB--htlc_confs\fP="": the number of confirmations (in blocks) that we require for the htlc extended by the server before we reveal the preimage (default: 1) .PP -\fB--label\fP="": an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved]. +\fB--label\fP="": an optional label for this swap, limited to 500 characters. The label may not start with our reserved prefix: [reserved]. .PP \fB--max_swap_routing_fee\fP="": the max off-chain swap routing fee in satoshis, if not specified, a default max fee will be used (default: 0) @@ -119,7 +119,7 @@ perform an on-chain to off-chain swap (loop in) \fB--help, -h\fP: show help .PP -\fB--label\fP="": an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved]. +\fB--label\fP="": an optional label for this swap, limited to 500 characters. The label may not start with our reserved prefix: [reserved]. .PP \fB--last_hop\fP="": the pubkey of the last hop to use for this swap @@ -212,7 +212,7 @@ list traditional Loop In and Loop Out swaps \fB--help, -h\fP: show help .PP -\fB--label\fP="": an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved]. +\fB--label\fP="": only list swaps with the given label .PP \fB--last_hop\fP="": the pubkey of the last hop to use for this swap @@ -554,7 +554,7 @@ Loop in funds from static address deposits. \fB--help, -h\fP: show help .PP -\fB--label\fP="": an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved]. +\fB--label\fP="": an optional label for this swap, limited to 500 characters. The label may not start with our reserved prefix: [reserved]. .PP \fB--last_hop\fP="": the pubkey of the last hop to use for this swap diff --git a/docs/loop.md b/docs/loop.md index ab2bb1b87..5b77c0bd6 100644 --- a/docs/loop.md +++ b/docs/loop.md @@ -48,7 +48,7 @@ The following flags are supported: | `--asset_id="…"` | the asset ID of the asset to loop out, if this is set, the loop daemon will require a connection to a taproot assets daemon | string | | `--asset_edge_node="…"` | the pubkey of the edge node of the asset to loop out, this is required if the taproot assets daemon has multiple channels of the given asset id with different edge nodes | string | | `--force` | Assumes yes during confirmation. Using this option will result in an immediate swap | bool | `false` | -| `--label="…"` | an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved] | string | +| `--label="…"` | an optional label for this swap, limited to 500 characters. The label may not start with our reserved prefix: [reserved] | string | | `--verbose` (`-v`) | show expanded details | bool | `false` | | `--channel="…"` | the comma-separated list of short channel IDs of the channels to loop out | string | | `--help` (`-h`) | show help | bool | `false` | @@ -98,18 +98,18 @@ $ loop [GLOBAL FLAGS] in [COMMAND FLAGS] amt The following flags are supported: -| Name | Description | Type | Default value | -|---------------------|-------------------------------------------------------------------------------------------------------------------------|--------|:-------------:| -| `--amt="…"` | the amount in satoshis to loop in. To check for the minimum and maximum amounts to loop in please consult "loop terms" | uint | `0` | -| `--external` | expect htlc to be published externally | bool | `false` | -| `--conf_target="…"` | the target number of blocks the on-chain htlc broadcast by the swap client should confirm within | uint | `0` | -| `--last_hop="…"` | the pubkey of the last hop to use for this swap | string | -| `--label="…"` | an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved] | string | -| `--force` | Assumes yes during confirmation. Using this option will result in an immediate swap | bool | `false` | -| `--verbose` (`-v`) | show expanded details | bool | `false` | -| `--route_hints="…"` | a JSON array of route hints that can each be individually used to assist in reaching the invoice's destination | string | -| `--private` | generates and passes routehints. Should be used if the connected node is only reachable via private channels | bool | `false` | -| `--help` (`-h`) | show help | bool | `false` | +| Name | Description | Type | Default value | +|---------------------|--------------------------------------------------------------------------------------------------------------------------|--------|:-------------:| +| `--amt="…"` | the amount in satoshis to loop in. To check for the minimum and maximum amounts to loop in please consult "loop terms" | uint | `0` | +| `--external` | expect htlc to be published externally | bool | `false` | +| `--conf_target="…"` | the target number of blocks the on-chain htlc broadcast by the swap client should confirm within | uint | `0` | +| `--last_hop="…"` | the pubkey of the last hop to use for this swap | string | +| `--label="…"` | an optional label for this swap, limited to 500 characters. The label may not start with our reserved prefix: [reserved] | string | +| `--force` | Assumes yes during confirmation. Using this option will result in an immediate swap | bool | `false` | +| `--verbose` (`-v`) | show expanded details | bool | `false` | +| `--route_hints="…"` | a JSON array of route hints that can each be individually used to assist in reaching the invoice's destination | string | +| `--private` | generates and passes routehints. Should be used if the connected node is only reachable via private channels | bool | `false` | +| `--help` (`-h`) | show help | bool | `false` | ### `terms` command @@ -256,17 +256,17 @@ $ loop [GLOBAL FLAGS] listswaps [COMMAND FLAGS] [ARGUMENTS...] The following flags are supported: -| Name | Description | Type | Default value | -|-----------------------|-------------------------------------------------------------------------------------------------------------------------|--------|:-------------:| -| `--loop_out_only` | only list swaps that are loop out swaps | bool | `false` | -| `--loop_in_only` | only list swaps that are loop in swaps | bool | `false` | -| `--pending_only` | only list pending swaps | bool | `false` | -| `--label="…"` | an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved] | string | -| `--channel="…"` | the comma-separated list of short channel IDs of the channels to loop out | string | -| `--last_hop="…"` | the pubkey of the last hop to use for this swap | string | -| `--max_swaps="…"` | Max number of swaps to return after filtering | uint | `0` | -| `--start_time_ns="…"` | Unix timestamp in nanoseconds to select swaps initiated after this time | int | `0` | -| `--help` (`-h`) | show help | bool | `false` | +| Name | Description | Type | Default value | +|-----------------------|---------------------------------------------------------------------------|--------|:-------------:| +| `--loop_out_only` | only list swaps that are loop out swaps | bool | `false` | +| `--loop_in_only` | only list swaps that are loop in swaps | bool | `false` | +| `--pending_only` | only list pending swaps | bool | `false` | +| `--label="…"` | only list swaps with the given label | string | +| `--channel="…"` | the comma-separated list of short channel IDs of the channels to loop out | string | +| `--last_hop="…"` | the pubkey of the last hop to use for this swap | string | +| `--max_swaps="…"` | Max number of swaps to return after filtering | uint | `0` | +| `--start_time_ns="…"` | Unix timestamp in nanoseconds to select swaps initiated after this time | int | `0` | +| `--help` (`-h`) | show help | bool | `false` | ### `swapinfo` command @@ -716,7 +716,7 @@ The following flags are supported: | `--max_swap_fee_sat="…"` | the maximum swap fee in satoshis. If set, the swap is rejected when the quoted fee exceeds this cap. The maximum allowed value is 10000000. On-chain fees for creating static deposits are unaffected | uint | `0` | | `--max_swap_fee_ppm="…"` | the maximum swap fee expressed in parts per million of the swap amount. If set together with --max_swap_fee_sat the tighter cap is used | uint | `0` | | `--last_hop="…"` | the pubkey of the last hop to use for this swap | string | -| `--label="…"` | an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved] | string | +| `--label="…"` | an optional label for this swap, limited to 500 characters. The label may not start with our reserved prefix: [reserved] | string | | `--route_hints="…"` | a JSON array of route hints that can each be individually used to assist in reaching the invoice's destination | string | | `--private` | generates and passes routehints. Should be used if the connected node is only reachable via private channels | bool | `false` | | `--force` | Assumes yes during confirmation. Using this option will result in an immediate swap | bool | `false` | From 093ff3b8fb24e29bb9026b3ae54f4cb233b7d744 Mon Sep 17 00:00:00 2001 From: Gustavo Stingelin Date: Fri, 17 Jul 2026 17:37:25 -0300 Subject: [PATCH 2/9] loopdb: persist static address labels Add a label column to static_addresses and a query to update it, and select it wherever deposits and change addresses join their address. --- .../000024_static_address_label.down.sql | 2 + .../000024_static_address_label.up.sql | 4 ++ loopdb/sqlc/models.go | 1 + loopdb/sqlc/querier.go | 1 + .../sqlc/queries/static_address_deposits.sql | 9 +++-- loopdb/sqlc/queries/static_address_loopin.sql | 7 +++- loopdb/sqlc/queries/static_addresses.sql | 11 +++++- loopdb/sqlc/static_address_deposits.sql.go | 15 +++++-- loopdb/sqlc/static_address_loopin.sql.go | 13 ++++++- loopdb/sqlc/static_addresses.sql.go | 39 ++++++++++++++++--- 10 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 loopdb/sqlc/migrations/000024_static_address_label.down.sql create mode 100644 loopdb/sqlc/migrations/000024_static_address_label.up.sql diff --git a/loopdb/sqlc/migrations/000024_static_address_label.down.sql b/loopdb/sqlc/migrations/000024_static_address_label.down.sql new file mode 100644 index 000000000..adb7392de --- /dev/null +++ b/loopdb/sqlc/migrations/000024_static_address_label.down.sql @@ -0,0 +1,2 @@ +-- Drop local static-address label metadata. +ALTER TABLE static_addresses DROP COLUMN label; diff --git a/loopdb/sqlc/migrations/000024_static_address_label.up.sql b/loopdb/sqlc/migrations/000024_static_address_label.up.sql new file mode 100644 index 000000000..417289be4 --- /dev/null +++ b/loopdb/sqlc/migrations/000024_static_address_label.up.sql @@ -0,0 +1,4 @@ +-- label records local operator metadata for a static address. It is not part of +-- the address script or server protocol state; an empty value means the address +-- is unlabeled. +ALTER TABLE static_addresses ADD COLUMN label TEXT NOT NULL DEFAULT ''; diff --git a/loopdb/sqlc/models.go b/loopdb/sqlc/models.go index bb4244ea2..6b4f3de6e 100644 --- a/loopdb/sqlc/models.go +++ b/loopdb/sqlc/models.go @@ -135,6 +135,7 @@ type StaticAddress struct { Pkscript []byte ProtocolVersion int32 InitiationHeight int32 + Label string } type StaticAddressSwap struct { diff --git a/loopdb/sqlc/querier.go b/loopdb/sqlc/querier.go index 315767310..f78202209 100644 --- a/loopdb/sqlc/querier.go +++ b/loopdb/sqlc/querier.go @@ -78,6 +78,7 @@ type Querier interface { UpdateInstantOut(ctx context.Context, arg UpdateInstantOutParams) error UpdateLoopOutAssetOffchainPayments(ctx context.Context, arg UpdateLoopOutAssetOffchainPaymentsParams) error UpdateReservation(ctx context.Context, arg UpdateReservationParams) error + UpdateStaticAddressLabel(ctx context.Context, arg UpdateStaticAddressLabelParams) (int64, error) UpdateStaticAddressLoopIn(ctx context.Context, arg UpdateStaticAddressLoopInParams) error UpdateWithdrawal(ctx context.Context, arg UpdateWithdrawalParams) error UpsertLiquidityParams(ctx context.Context, params []byte) error diff --git a/loopdb/sqlc/queries/static_address_deposits.sql b/loopdb/sqlc/queries/static_address_deposits.sql index 0d58ba19f..58d70cd10 100644 --- a/loopdb/sqlc/queries/static_address_deposits.sql +++ b/loopdb/sqlc/queries/static_address_deposits.sql @@ -53,7 +53,8 @@ SELECT sa.client_key_index client_key_index, sa.pkscript pkscript, sa.protocol_version protocol_version, - sa.initiation_height initiation_height + sa.initiation_height initiation_height, + sa.label AS label FROM deposits d LEFT JOIN static_addresses sa ON sa.id = d.static_address_id @@ -70,7 +71,8 @@ SELECT sa.client_key_index client_key_index, sa.pkscript pkscript, sa.protocol_version protocol_version, - sa.initiation_height initiation_height + sa.initiation_height initiation_height, + sa.label AS label FROM deposits d LEFT JOIN static_addresses sa ON sa.id = d.static_address_id @@ -89,7 +91,8 @@ SELECT sa.client_key_index client_key_index, sa.pkscript pkscript, sa.protocol_version protocol_version, - sa.initiation_height initiation_height + sa.initiation_height initiation_height, + sa.label AS label FROM deposits d LEFT JOIN static_addresses sa ON sa.id = d.static_address_id diff --git a/loopdb/sqlc/queries/static_address_loopin.sql b/loopdb/sqlc/queries/static_address_loopin.sql index e38b0b405..8f4875ed6 100644 --- a/loopdb/sqlc/queries/static_address_loopin.sql +++ b/loopdb/sqlc/queries/static_address_loopin.sql @@ -74,7 +74,8 @@ SELECT change_address.client_key_index change_client_key_index, change_address.pkscript change_pkscript, change_address.protocol_version change_protocol_version, - change_address.initiation_height change_initiation_height + change_address.initiation_height change_initiation_height, + change_address.label change_label FROM swaps JOIN @@ -99,7 +100,8 @@ SELECT change_address.client_key_index change_client_key_index, change_address.pkscript change_pkscript, change_address.protocol_version change_protocol_version, - change_address.initiation_height change_initiation_height + change_address.initiation_height change_initiation_height, + change_address.label change_label FROM swaps JOIN @@ -179,6 +181,7 @@ SELECT sa.pkscript pkscript, sa.protocol_version protocol_version, sa.initiation_height initiation_height, + sa.label AS label, u.update_state, u.update_timestamp FROM diff --git a/loopdb/sqlc/queries/static_addresses.sql b/loopdb/sqlc/queries/static_addresses.sql index 42197b682..46a45b6d9 100644 --- a/loopdb/sqlc/queries/static_addresses.sql +++ b/loopdb/sqlc/queries/static_addresses.sql @@ -19,7 +19,8 @@ INSERT INTO static_addresses ( client_key_index, pkscript, protocol_version, - initiation_height + initiation_height, + label ) VALUES ( $1, $2, @@ -28,7 +29,8 @@ INSERT INTO static_addresses ( $5, $6, $7, - $8 + $8, + $9 ); -- name: GetLegacyAddress :one @@ -48,3 +50,8 @@ FROM htlc_keys JOIN static_address_swaps ON static_address_swaps.swap_hash = htlc_keys.swap_hash WHERE htlc_keys.client_key_family = $1; + +-- name: UpdateStaticAddressLabel :execrows +UPDATE static_addresses +SET label = $2 +WHERE pkscript = $1; diff --git a/loopdb/sqlc/static_address_deposits.sql.go b/loopdb/sqlc/static_address_deposits.sql.go index cd984355c..68a3490c1 100644 --- a/loopdb/sqlc/static_address_deposits.sql.go +++ b/loopdb/sqlc/static_address_deposits.sql.go @@ -21,7 +21,8 @@ SELECT sa.client_key_index client_key_index, sa.pkscript pkscript, sa.protocol_version protocol_version, - sa.initiation_height initiation_height + sa.initiation_height initiation_height, + sa.label AS label FROM deposits d LEFT JOIN static_addresses sa ON sa.id = d.static_address_id @@ -49,6 +50,7 @@ type AllDepositsRow struct { Pkscript []byte ProtocolVersion sql.NullInt32 InitiationHeight sql.NullInt32 + Label sql.NullString } func (q *Queries) AllDeposits(ctx context.Context) ([]AllDepositsRow, error) { @@ -80,6 +82,7 @@ func (q *Queries) AllDeposits(ctx context.Context) ([]AllDepositsRow, error) { &i.Pkscript, &i.ProtocolVersion, &i.InitiationHeight, + &i.Label, ); err != nil { return nil, err } @@ -155,7 +158,8 @@ SELECT sa.client_key_index client_key_index, sa.pkscript pkscript, sa.protocol_version protocol_version, - sa.initiation_height initiation_height + sa.initiation_height initiation_height, + sa.label AS label FROM deposits d LEFT JOIN static_addresses sa ON sa.id = d.static_address_id @@ -190,6 +194,7 @@ type DepositForOutpointRow struct { Pkscript []byte ProtocolVersion sql.NullInt32 InitiationHeight sql.NullInt32 + Label sql.NullString } func (q *Queries) DepositForOutpoint(ctx context.Context, arg DepositForOutpointParams) (DepositForOutpointRow, error) { @@ -215,6 +220,7 @@ func (q *Queries) DepositForOutpoint(ctx context.Context, arg DepositForOutpoint &i.Pkscript, &i.ProtocolVersion, &i.InitiationHeight, + &i.Label, ) return i, err } @@ -229,7 +235,8 @@ SELECT sa.client_key_index client_key_index, sa.pkscript pkscript, sa.protocol_version protocol_version, - sa.initiation_height initiation_height + sa.initiation_height initiation_height, + sa.label AS label FROM deposits d LEFT JOIN static_addresses sa ON sa.id = d.static_address_id @@ -257,6 +264,7 @@ type GetDepositRow struct { Pkscript []byte ProtocolVersion sql.NullInt32 InitiationHeight sql.NullInt32 + Label sql.NullString } func (q *Queries) GetDeposit(ctx context.Context, depositID []byte) (GetDepositRow, error) { @@ -282,6 +290,7 @@ func (q *Queries) GetDeposit(ctx context.Context, depositID []byte) (GetDepositR &i.Pkscript, &i.ProtocolVersion, &i.InitiationHeight, + &i.Label, ) return i, err } diff --git a/loopdb/sqlc/static_address_loopin.sql.go b/loopdb/sqlc/static_address_loopin.sql.go index 6c297f323..d74e54d86 100644 --- a/loopdb/sqlc/static_address_loopin.sql.go +++ b/loopdb/sqlc/static_address_loopin.sql.go @@ -54,6 +54,7 @@ SELECT sa.pkscript pkscript, sa.protocol_version protocol_version, sa.initiation_height initiation_height, + sa.label AS label, u.update_state, u.update_timestamp FROM @@ -91,6 +92,7 @@ type DepositsForSwapHashRow struct { Pkscript []byte ProtocolVersion sql.NullInt32 InitiationHeight sql.NullInt32 + Label sql.NullString UpdateState sql.NullString UpdateTimestamp sql.NullTime } @@ -124,6 +126,7 @@ func (q *Queries) DepositsForSwapHash(ctx context.Context, swapHash []byte) ([]D &i.Pkscript, &i.ProtocolVersion, &i.InitiationHeight, + &i.Label, &i.UpdateState, &i.UpdateTimestamp, ); err != nil { @@ -189,7 +192,8 @@ SELECT change_address.client_key_index change_client_key_index, change_address.pkscript change_pkscript, change_address.protocol_version change_protocol_version, - change_address.initiation_height change_initiation_height + change_address.initiation_height change_initiation_height, + change_address.label change_label FROM swaps JOIN @@ -245,6 +249,7 @@ type GetStaticAddressLoopInSwapRow struct { ChangePkscript []byte ChangeProtocolVersion sql.NullInt32 ChangeInitiationHeight sql.NullInt32 + ChangeLabel sql.NullString } func (q *Queries) GetStaticAddressLoopInSwap(ctx context.Context, swapHash []byte) (GetStaticAddressLoopInSwapRow, error) { @@ -292,6 +297,7 @@ func (q *Queries) GetStaticAddressLoopInSwap(ctx context.Context, swapHash []byt &i.ChangePkscript, &i.ChangeProtocolVersion, &i.ChangeInitiationHeight, + &i.ChangeLabel, ) return i, err } @@ -308,7 +314,8 @@ SELECT change_address.client_key_index change_client_key_index, change_address.pkscript change_pkscript, change_address.protocol_version change_protocol_version, - change_address.initiation_height change_initiation_height + change_address.initiation_height change_initiation_height, + change_address.label change_label FROM swaps JOIN @@ -375,6 +382,7 @@ type GetStaticAddressLoopInSwapsByStatesRow struct { ChangePkscript []byte ChangeProtocolVersion sql.NullInt32 ChangeInitiationHeight sql.NullInt32 + ChangeLabel sql.NullString } func (q *Queries) GetStaticAddressLoopInSwapsByStates(ctx context.Context, dollar_1 sql.NullString) ([]GetStaticAddressLoopInSwapsByStatesRow, error) { @@ -428,6 +436,7 @@ func (q *Queries) GetStaticAddressLoopInSwapsByStates(ctx context.Context, dolla &i.ChangePkscript, &i.ChangeProtocolVersion, &i.ChangeInitiationHeight, + &i.ChangeLabel, ); err != nil { return nil, err } diff --git a/loopdb/sqlc/static_addresses.sql.go b/loopdb/sqlc/static_addresses.sql.go index d6490b150..f08f7b677 100644 --- a/loopdb/sqlc/static_addresses.sql.go +++ b/loopdb/sqlc/static_addresses.sql.go @@ -10,7 +10,7 @@ import ( ) const allStaticAddresses = `-- name: AllStaticAddresses :many -SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height FROM static_addresses +SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height, label FROM static_addresses ORDER BY id ASC ` @@ -33,6 +33,7 @@ func (q *Queries) AllStaticAddresses(ctx context.Context) ([]StaticAddress, erro &i.Pkscript, &i.ProtocolVersion, &i.InitiationHeight, + &i.Label, ); err != nil { return nil, err } @@ -56,7 +57,8 @@ INSERT INTO static_addresses ( client_key_index, pkscript, protocol_version, - initiation_height + initiation_height, + label ) VALUES ( $1, $2, @@ -65,7 +67,8 @@ INSERT INTO static_addresses ( $5, $6, $7, - $8 + $8, + $9 ) ` @@ -78,6 +81,7 @@ type CreateStaticAddressParams struct { Pkscript []byte ProtocolVersion int32 InitiationHeight int32 + Label string } func (q *Queries) CreateStaticAddress(ctx context.Context, arg CreateStaticAddressParams) error { @@ -90,12 +94,13 @@ func (q *Queries) CreateStaticAddress(ctx context.Context, arg CreateStaticAddre arg.Pkscript, arg.ProtocolVersion, arg.InitiationHeight, + arg.Label, ) return err } const getLegacyAddress = `-- name: GetLegacyAddress :one -SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height FROM static_addresses +SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height, label FROM static_addresses ORDER BY id ASC LIMIT 1 ` @@ -113,6 +118,7 @@ func (q *Queries) GetLegacyAddress(ctx context.Context) (StaticAddress, error) { &i.Pkscript, &i.ProtocolVersion, &i.InitiationHeight, + &i.Label, ) return i, err } @@ -133,7 +139,7 @@ func (q *Queries) GetMaxStaticAddressHtlcKeyIndex(ctx context.Context, clientKey } const getStaticAddress = `-- name: GetStaticAddress :one -SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height FROM static_addresses +SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height, label FROM static_addresses WHERE pkscript=$1 ` @@ -150,6 +156,7 @@ func (q *Queries) GetStaticAddress(ctx context.Context, pkscript []byte) (Static &i.Pkscript, &i.ProtocolVersion, &i.InitiationHeight, + &i.Label, ) return i, err } @@ -167,7 +174,7 @@ func (q *Queries) GetStaticAddressID(ctx context.Context, pkscript []byte) (int3 } const listStaticAddresses = `-- name: ListStaticAddresses :many -SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height FROM static_addresses +SELECT id, client_pubkey, server_pubkey, expiry, client_key_family, client_key_index, pkscript, protocol_version, initiation_height, label FROM static_addresses WHERE id > $1 ORDER BY id ASC LIMIT $2 @@ -197,6 +204,7 @@ func (q *Queries) ListStaticAddresses(ctx context.Context, arg ListStaticAddress &i.Pkscript, &i.ProtocolVersion, &i.InitiationHeight, + &i.Label, ); err != nil { return nil, err } @@ -210,3 +218,22 @@ func (q *Queries) ListStaticAddresses(ctx context.Context, arg ListStaticAddress } return items, nil } + +const updateStaticAddressLabel = `-- name: UpdateStaticAddressLabel :execrows +UPDATE static_addresses +SET label = $2 +WHERE pkscript = $1 +` + +type UpdateStaticAddressLabelParams struct { + Pkscript []byte + Label string +} + +func (q *Queries) UpdateStaticAddressLabel(ctx context.Context, arg UpdateStaticAddressLabelParams) (int64, error) { + result, err := q.db.ExecContext(ctx, updateStaticAddressLabel, arg.Pkscript, arg.Label) + if err != nil { + return 0, err + } + return result.RowsAffected() +} From 17390d4b03278f9b7c5f44e137463c2cd0a143bc Mon Sep 17 00:00:00 2001 From: Gustavo Stingelin Date: Fri, 17 Jul 2026 17:37:57 -0300 Subject: [PATCH 3/9] staticaddr/script: track static address labels Add a Label field to the static address parameters. It is local metadata and not part of the script or server protocol. --- staticaddr/script/parameters.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/staticaddr/script/parameters.go b/staticaddr/script/parameters.go index 0fa1f73b4..98bea5043 100644 --- a/staticaddr/script/parameters.go +++ b/staticaddr/script/parameters.go @@ -37,4 +37,8 @@ type Parameters struct { // InitiationHeight is the height at which the address was initiated. InitiationHeight int32 + + // Label is local operator metadata for display, not part of the script or + // server protocol. Address-manager snapshots must not be mutated in place. + Label string } From eb5ae0659e36a771c69a7a444e766ab08a9f7fcc Mon Sep 17 00:00:00 2001 From: Gustavo Stingelin Date: Fri, 17 Jul 2026 17:39:20 -0300 Subject: [PATCH 4/9] staticaddr: store static address labels Read and write address labels in the address store, and load them with deposits and loop-in change addresses. --- loopd/swapclient_server_test.go | 26 +++++- staticaddr/address/interface.go | 6 ++ staticaddr/address/manager.go | 4 + staticaddr/address/sql_store.go | 28 ++++++- staticaddr/address/sql_store_test.go | 121 +++++++++++++++++++++++++++ staticaddr/deposit/sql_store.go | 5 ++ staticaddr/deposit/sql_store_test.go | 3 + staticaddr/loopin/sql_store.go | 2 + staticaddr/loopin/sql_store_test.go | 4 + 9 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 staticaddr/address/sql_store_test.go diff --git a/loopd/swapclient_server_test.go b/loopd/swapclient_server_test.go index 092f27b6b..bd53c0707 100644 --- a/loopd/swapclient_server_test.go +++ b/loopd/swapclient_server_test.go @@ -1917,7 +1917,9 @@ func (s *mockAddressStore) CreateStaticAddress(_ context.Context, if p.ID == 0 { p.ID = int32(len(s.params) + 1) } - s.params = append(s.params, p) + storedParams := *p + s.params = append(s.params, &storedParams) + return nil } @@ -1950,7 +1952,10 @@ func (s *mockAddressStore) ListStaticAddresses(_ context.Context, var page []*address.AddressParameters for i, p := range s.params { if p.ID == 0 { - p.ID = int32(i + 1) + updated := *p + updated.ID = int32(i + 1) + s.params[i] = &updated + p = &updated } if p.ID > afterID { page = append(page, p) @@ -1986,6 +1991,23 @@ func (s *mockAddressStore) GetMaxStaticAddressHtlcKeyIndex(_ context.Context, return 0, false, nil } +// UpdateStaticAddressLabel replaces the stored record without mutating cached +// address parameters that the manager may have already published. +func (s *mockAddressStore) UpdateStaticAddressLabel(_ context.Context, + pkScript []byte, label string) error { + + for i, params := range s.params { + if bytes.Equal(params.PkScript, pkScript) { + updated := *params + updated.Label = label + s.params[i] = &updated + return nil + } + } + + return address.ErrStaticAddressNotFound +} + // mockDepositStore implements deposit.Store minimally for DepositsForOutpoints. type mockDepositStore struct { byOutpoint map[string]*deposit.Deposit diff --git a/staticaddr/address/interface.go b/staticaddr/address/interface.go index 170e90f6b..24fa0619d 100644 --- a/staticaddr/address/interface.go +++ b/staticaddr/address/interface.go @@ -40,4 +40,10 @@ type Store interface { // is false if no such HTLC key exists. GetMaxStaticAddressHtlcKeyIndex(ctx context.Context, family keychain.KeyFamily) (uint32, bool, error) + + // UpdateStaticAddressLabel updates the local label for a static address by + // its pkScript so metadata changes never alter address scripts or server + // state. + UpdateStaticAddressLabel(ctx context.Context, pkScript []byte, + label string) error } diff --git a/staticaddr/address/manager.go b/staticaddr/address/manager.go index 3a90ff2bf..fb7404aad 100644 --- a/staticaddr/address/manager.go +++ b/staticaddr/address/manager.go @@ -42,6 +42,10 @@ var ( // ErrNoStaticAddress is returned when no static address parameters are // present in the store. ErrNoStaticAddress = errors.New("no static address parameters found") + + // ErrStaticAddressNotFound is returned when a static address to update + // is not in the store. + ErrStaticAddressNotFound = errors.New("static address not found") ) // ManagerConfig holds the configuration for the address manager. diff --git a/staticaddr/address/sql_store.go b/staticaddr/address/sql_store.go index 99818bf65..df5ad20e6 100644 --- a/staticaddr/address/sql_store.go +++ b/staticaddr/address/sql_store.go @@ -24,7 +24,7 @@ func NewSqlStore(db *loopdb.BaseDB) *SqlStore { } } -// CreateStaticAddress creates a static address record in the database. +// CreateStaticAddress creates a static address record. func (s *SqlStore) CreateStaticAddress(ctx context.Context, addrParams *AddressParameters) error { @@ -37,6 +37,7 @@ func (s *SqlStore) CreateStaticAddress(ctx context.Context, Pkscript: addrParams.PkScript, ProtocolVersion: int32(addrParams.ProtocolVersion), InitiationHeight: addrParams.InitiationHeight, + Label: addrParams.Label, } return s.baseDB.Queries.CreateStaticAddress(ctx, createArgs) @@ -127,6 +128,30 @@ func (s *SqlStore) GetMaxStaticAddressHtlcKeyIndex(ctx context.Context, return uint32(index), true, nil } +// UpdateStaticAddressLabel updates the local label for a static address by its +// pkScript, keeping relabeling a metadata-only database change that cannot +// create a new address record. +func (s *SqlStore) UpdateStaticAddressLabel(ctx context.Context, + pkScript []byte, label string) error { + + updateArgs := sqlc.UpdateStaticAddressLabelParams{ + Pkscript: pkScript, + Label: label, + } + + rowsAffected, err := s.baseDB.Queries.UpdateStaticAddressLabel( + ctx, updateArgs, + ) + if err != nil { + return err + } + if rowsAffected == 0 { + return ErrStaticAddressNotFound + } + + return nil +} + // toAddressParameters transforms a database representation of a static address // to an AddressParameters struct. func (s *SqlStore) toAddressParameters(row sqlc.StaticAddress) ( @@ -156,5 +181,6 @@ func (s *SqlStore) toAddressParameters(row sqlc.StaticAddress) ( row.ProtocolVersion, ), InitiationHeight: row.InitiationHeight, + Label: row.Label, }, nil } diff --git a/staticaddr/address/sql_store_test.go b/staticaddr/address/sql_store_test.go new file mode 100644 index 000000000..9ad15fe0e --- /dev/null +++ b/staticaddr/address/sql_store_test.go @@ -0,0 +1,121 @@ +package address + +import ( + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/lightninglabs/loop/loopdb" + "github.com/lightninglabs/loop/staticaddr/script" + "github.com/lightninglabs/loop/staticaddr/version" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" + "github.com/stretchr/testify/require" +) + +// TestSqlStoreStaticAddressLabel_whenCreatedAndUpdated proves labels survive +// the create and update path because operators rely on them after restarts. +func TestSqlStoreStaticAddressLabel_whenCreatedAndUpdated(t *testing.T) { + ctx := t.Context() + store := NewSqlStore(loopdb.NewTestDB(t).BaseDB) + addrParams := testAddressParams(t) + addrParams.Label = "first" + + err := store.CreateStaticAddress(ctx, addrParams) + require.NoError(t, err) + + params, err := store.GetAllStaticAddresses(ctx) + require.NoError(t, err) + require.Len(t, params, 1) + require.Equal(t, "first", params[0].Label) + + err = store.UpdateStaticAddressLabel(ctx, addrParams.PkScript, "second") + require.NoError(t, err) + + params, err = store.GetAllStaticAddresses(ctx) + require.NoError(t, err) + require.Len(t, params, 1) + require.Equal(t, "second", params[0].Label) +} + +// TestSqlStoreStaticAddressLabel_whenCleared ensures an empty label is persisted +// as the supported way to remove local operator metadata. +func TestSqlStoreStaticAddressLabel_whenCleared(t *testing.T) { + ctx := t.Context() + store := NewSqlStore(loopdb.NewTestDB(t).BaseDB) + addrParams := testAddressParams(t) + addrParams.Label = "first" + + err := store.CreateStaticAddress(ctx, addrParams) + require.NoError(t, err) + + err = store.UpdateStaticAddressLabel(ctx, addrParams.PkScript, "") + require.NoError(t, err) + + params, err := store.GetAllStaticAddresses(ctx) + require.NoError(t, err) + require.Len(t, params, 1) + require.Empty(t, params[0].Label) +} + +// TestSqlStoreStaticAddressLabel_whenCreatedWithoutLabel protects unlabeled +// static addresses so label support remains optional metadata. +func TestSqlStoreStaticAddressLabel_whenCreatedWithoutLabel(t *testing.T) { + ctx := t.Context() + store := NewSqlStore(loopdb.NewTestDB(t).BaseDB) + addrParams := testAddressParams(t) + + err := store.CreateStaticAddress(ctx, addrParams) + require.NoError(t, err) + + params, err := store.GetAllStaticAddresses(ctx) + require.NoError(t, err) + require.Len(t, params, 1) + require.Empty(t, params[0].Label) +} + +// TestSqlStoreStaticAddressLabel_whenAddressMissing ensures relabel requests do +// not silently create metadata for an address the wallet does not own. +func TestSqlStoreStaticAddressLabel_whenAddressMissing(t *testing.T) { + ctx := t.Context() + store := NewSqlStore(loopdb.NewTestDB(t).BaseDB) + addrParams := testAddressParams(t) + + err := store.UpdateStaticAddressLabel(ctx, addrParams.PkScript, "missing") + require.ErrorIs(t, err, ErrStaticAddressNotFound) +} + +// testAddressParams builds a valid static-address record so label tests vary +// only metadata while preserving real script and key material constraints. +func testAddressParams(t *testing.T) *script.Parameters { + t.Helper() + + clientKey, err := btcec.NewPrivateKey() + require.NoError(t, err) + + serverKey, err := btcec.NewPrivateKey() + require.NoError(t, err) + + staticAddress, err := script.NewStaticAddress( + input.MuSig2Version100RC2, int64(defaultExpiry), clientKey.PubKey(), + serverKey.PubKey(), + ) + require.NoError(t, err) + + pkScript, err := staticAddress.StaticAddressScript() + require.NoError(t, err) + + return &script.Parameters{ + ClientPubkey: clientKey.PubKey(), + ServerPubkey: serverKey.PubKey(), + PkScript: pkScript, + Expiry: defaultExpiry, + KeyLocator: keychain.KeyLocator{ + Family: keychain.KeyFamily(1), + Index: 2, + }, + ProtocolVersion: version.AddressProtocolVersion( + version.CurrentRPCProtocolVersion(), + ), + InitiationHeight: 100, + } +} diff --git a/staticaddr/deposit/sql_store.go b/staticaddr/deposit/sql_store.go index 2a28db930..7aab582ba 100644 --- a/staticaddr/deposit/sql_store.go +++ b/staticaddr/deposit/sql_store.go @@ -292,6 +292,7 @@ type depositRow struct { Pkscript []byte ProtocolVersion sql.NullInt32 InitiationHeight sql.NullInt32 + Label sql.NullString } func depositRowFromAll(row sqlc.AllDepositsRow) depositRow { @@ -314,6 +315,7 @@ func depositRowFromAll(row sqlc.AllDepositsRow) depositRow { Pkscript: row.Pkscript, ProtocolVersion: row.ProtocolVersion, InitiationHeight: row.InitiationHeight, + Label: row.Label, } } @@ -337,6 +339,7 @@ func depositRowFromGet(row sqlc.GetDepositRow) depositRow { Pkscript: row.Pkscript, ProtocolVersion: row.ProtocolVersion, InitiationHeight: row.InitiationHeight, + Label: row.Label, } } @@ -360,6 +363,7 @@ func depositRowFromOutpoint(row sqlc.DepositForOutpointRow) depositRow { Pkscript: row.Pkscript, ProtocolVersion: row.ProtocolVersion, InitiationHeight: row.InitiationHeight, + Label: row.Label, } } @@ -459,6 +463,7 @@ func toDeposit(row depositRow, lastUpdate sqlc.DepositUpdate) (*Deposit, row.ProtocolVersion.Int32, ), InitiationHeight: row.InitiationHeight.Int32, + Label: row.Label.String, } return deposit, nil diff --git a/staticaddr/deposit/sql_store_test.go b/staticaddr/deposit/sql_store_test.go index 3a1e182c6..9403b9680 100644 --- a/staticaddr/deposit/sql_store_test.go +++ b/staticaddr/deposit/sql_store_test.go @@ -56,6 +56,7 @@ func TestDepositAddressOwnershipRoundTrip(t *testing.T) { PkScript: []byte{0x51, 0x20, 0x01}, ProtocolVersion: version.ProtocolVersion_V0, InitiationHeight: 789, + Label: "treasury", } err := addressStore.CreateStaticAddress(ctx, addressParams) @@ -106,6 +107,8 @@ func TestDepositAddressOwnershipRoundTrip(t *testing.T) { restored.AddressParams.ProtocolVersion) require.Equal(t, addressParams.InitiationHeight, restored.AddressParams.InitiationHeight) + require.Equal(t, addressParams.Label, + restored.AddressParams.Label) } restored, err := store.GetDeposit(ctx, depositID) diff --git a/staticaddr/loopin/sql_store.go b/staticaddr/loopin/sql_store.go index 8d2f2689e..cb5119529 100644 --- a/staticaddr/loopin/sql_store.go +++ b/staticaddr/loopin/sql_store.go @@ -634,6 +634,7 @@ func toStaticAddressLoopIn(_ context.Context, network *chaincfg.Params, Pkscript: d.Pkscript, ProtocolVersion: d.ProtocolVersion, InitiationHeight: d.InitiationHeight, + Label: d.Label, } sqlcDepositUpdate := sqlc.DepositUpdate{ @@ -775,5 +776,6 @@ func toChangeAddressParameters(row sqlc.GetStaticAddressLoopInSwapRow) ( row.ChangeProtocolVersion.Int32, ), InitiationHeight: row.ChangeInitiationHeight.Int32, + Label: row.ChangeLabel.String, }, nil } diff --git a/staticaddr/loopin/sql_store_test.go b/staticaddr/loopin/sql_store_test.go index 692b44a2c..8204c6b0d 100644 --- a/staticaddr/loopin/sql_store_test.go +++ b/staticaddr/loopin/sql_store_test.go @@ -69,6 +69,7 @@ func TestLoopInChangeAddressRoundTrip(t *testing.T) { PkScript: []byte{0x51, 0x20, 0x04}, ProtocolVersion: version.ProtocolVersion_V0, InitiationHeight: 987, + Label: "ops, treasury", } require.NoError( t, addressStore.CreateStaticAddress(ctx, changeParams), @@ -121,6 +122,7 @@ func TestLoopInChangeAddressRoundTrip(t *testing.T) { require.Equal( t, changeParams.InitiationHeight, got.InitiationHeight, ) + require.Equal(t, changeParams.Label, got.Label) } restoredSwap, err := loopInStore.GetLoopInByHash(ctx, swapHash) @@ -239,6 +241,7 @@ func TestLoopInDepositAddressOwnershipRoundTrip(t *testing.T) { PkScript: []byte{0x51, 0x20, 0x02}, ProtocolVersion: version.ProtocolVersion_V0, InitiationHeight: 789, + Label: "treasury", } require.NoError(t, addressStore.CreateStaticAddress(ctx, addressParams)) @@ -306,6 +309,7 @@ func TestLoopInDepositAddressOwnershipRoundTrip(t *testing.T) { restoredParams.ProtocolVersion) require.Equal(t, addressParams.InitiationHeight, restoredParams.InitiationHeight) + require.Equal(t, addressParams.Label, restoredParams.Label) } // TestGetStaticAddressLoopInSwapsByStates tests that we can retrieve From 4067d7874ecfbdb272ead755e3f498f4b6abd813 Mon Sep 17 00:00:00 2001 From: Gustavo Stingelin Date: Fri, 17 Jul 2026 17:41:17 -0300 Subject: [PATCH 5/9] looprpc: expose static address labels Add a label to NewStaticAddress, a new UpdateStaticAddressLabel RPC, and labels on unspent deposits and deposit listings. --- ..._loop-static-listdeposits-withdrawing.json | 2 + ...03_loop-static-listdeposits-withdrawn.json | 8 + ...05_loop-static-listdeposits-looped_in.json | 2 + .../11_loop-static-listdeposits-failed.json | 12 + ...stdeposits-channel_published-nonempty.json | 4 + .../static-loop-in/01_loop-static-new.json | 9 +- .../05_loop-static-listunspent.json | 4 +- .../static-loop-in/06_loop-static-l.json | 4 +- .../08_loop-static-listunspent.json | 4 +- .../09_loop-static-listunspent.json | 4 +- .../10_loop-static-listdeposits.json | 2 + .../static-loop-in/15_loop-static-in.json | 2 + ...-static-in-positional-payment-timeout.json | 2 + .../23_loop-static-in-max-swap-fee-both.json | 2 + ...op-static-in-max-swap-fee-sat-success.json | 2 + .../25_loop-static-in-low-conf-utxo.json | 2 + .../26_loop-static-in-auto-unconfirmed.json | 2 + .../02_loop-static-listwithdrawals.json | 2 + looprpc/client.pb.go | 667 +++++++++++------- looprpc/client.pb.gw.go | 66 ++ looprpc/client.proto | 58 ++ looprpc/client.swagger.json | 79 +++ looprpc/client.yaml | 3 + looprpc/client_grpc.pb.go | 40 ++ looprpc/client_test.go | 38 + looprpc/perms.go | 7 + looprpc/swapclient.pb.json.go | 25 + 27 files changed, 798 insertions(+), 254 deletions(-) diff --git a/cmd/loop/testdata/sessions/static-filters/02_loop-static-listdeposits-withdrawing.json b/cmd/loop/testdata/sessions/static-filters/02_loop-static-listdeposits-withdrawing.json index 5876bff6d..7c48af0d3 100644 --- a/cmd/loop/testdata/sessions/static-filters/02_loop-static-listdeposits-withdrawing.json +++ b/cmd/loop/testdata/sessions/static-filters/02_loop-static-listdeposits-withdrawing.json @@ -60,8 +60,10 @@ "{\n", " \"filtered_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14395\",\n", " \"confirmation_height\": \"160\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"bb7f050df0b7c3e1fe61010e10ad45e30ddf7acd301fa6e05a2ddb825b5c2efb\",\n", " \"outpoint\": \"56cd081a3a6eadf25b7d3fe0b61207389352ed69a622d2ec28c5d669bf6a5313:0\",\n", " \"state\": \"WITHDRAWING\",\n", diff --git a/cmd/loop/testdata/sessions/static-filters/03_loop-static-listdeposits-withdrawn.json b/cmd/loop/testdata/sessions/static-filters/03_loop-static-listdeposits-withdrawn.json index ab221508b..03cb3402f 100644 --- a/cmd/loop/testdata/sessions/static-filters/03_loop-static-listdeposits-withdrawn.json +++ b/cmd/loop/testdata/sessions/static-filters/03_loop-static-listdeposits-withdrawn.json @@ -87,8 +87,10 @@ "{\n", " \"filtered_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14360\",\n", " \"confirmation_height\": \"125\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"68262a104c9ec325de6bec37b8e31bd875bbd2f5f0b9ce2da20cf0bd636fc448\",\n", " \"outpoint\": \"edcdab8f0b1138d853a453b8b7a5ac3c694bd53ad38b7ccf062e45f99440e6e6:0\",\n", " \"state\": \"WITHDRAWN\",\n", @@ -97,8 +99,10 @@ " \"value\": \"500000\"\n", " },\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14362\",\n", " \"confirmation_height\": \"127\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"86b5e2cdf9694c8e7398e42afde109766d7cd2142203905ba63fbd0eb1370ef3\",\n", " \"outpoint\": \"bb358e4f73ae97c4e2d99c6d64e852bba7cf56e13105b05d1200b8ae1796665e:0\",\n", " \"state\": \"WITHDRAWN\",\n", @@ -107,8 +111,10 @@ " \"value\": \"500000\"\n", " },\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14363\",\n", " \"confirmation_height\": \"128\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"6c290f7536ea5097946afffac6a69906a26d775823ebbacedfe6f2d69c0745e4\",\n", " \"outpoint\": \"5eaa7dd7a291665393eddf5dece91feef901f22665933cce7a0732a9b81c3001:0\",\n", " \"state\": \"WITHDRAWN\",\n", @@ -117,8 +123,10 @@ " \"value\": \"500000\"\n", " },\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14377\",\n", " \"confirmation_height\": \"142\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"0182b4d895b1c467290ae7b5c6c42ff76b2a4225807a94211c973170d5a883eb\",\n", " \"outpoint\": \"7e6360d6e6a394cfd096adf0bfe1275c5a83541eb573e90e463a78dc715f8894:0\",\n", " \"state\": \"WITHDRAWN\",\n", diff --git a/cmd/loop/testdata/sessions/static-filters/05_loop-static-listdeposits-looped_in.json b/cmd/loop/testdata/sessions/static-filters/05_loop-static-listdeposits-looped_in.json index 92d14aa1a..83746c68b 100644 --- a/cmd/loop/testdata/sessions/static-filters/05_loop-static-listdeposits-looped_in.json +++ b/cmd/loop/testdata/sessions/static-filters/05_loop-static-listdeposits-looped_in.json @@ -60,8 +60,10 @@ "{\n", " \"filtered_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14383\",\n", " \"confirmation_height\": \"148\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"8fbd6da2f945de2905aa7fa93860744d9387d3464484360e96e467a51de3bc9d\",\n", " \"outpoint\": \"9fa0d5dd5348794aa0541dd2729497f0907890606d044e1c4757bdc848f38df8:0\",\n", " \"state\": \"LOOPED_IN\",\n", diff --git a/cmd/loop/testdata/sessions/static-filters/11_loop-static-listdeposits-failed.json b/cmd/loop/testdata/sessions/static-filters/11_loop-static-listdeposits-failed.json index 6dbf9009d..1da168f03 100644 --- a/cmd/loop/testdata/sessions/static-filters/11_loop-static-listdeposits-failed.json +++ b/cmd/loop/testdata/sessions/static-filters/11_loop-static-listdeposits-failed.json @@ -105,8 +105,10 @@ "{\n", " \"filtered_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14360\",\n", " \"confirmation_height\": \"125\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"68262a104c9ec325de6bec37b8e31bd875bbd2f5f0b9ce2da20cf0bd636fc448\",\n", " \"outpoint\": \"edcdab8f0b1138d853a453b8b7a5ac3c694bd53ad38b7ccf062e45f99440e6e6:0\",\n", " \"state\": \"WITHDRAWN\",\n", @@ -115,8 +117,10 @@ " \"value\": \"500000\"\n", " },\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14362\",\n", " \"confirmation_height\": \"127\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"86b5e2cdf9694c8e7398e42afde109766d7cd2142203905ba63fbd0eb1370ef3\",\n", " \"outpoint\": \"bb358e4f73ae97c4e2d99c6d64e852bba7cf56e13105b05d1200b8ae1796665e:0\",\n", " \"state\": \"WITHDRAWN\",\n", @@ -125,8 +129,10 @@ " \"value\": \"500000\"\n", " },\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14363\",\n", " \"confirmation_height\": \"128\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"6c290f7536ea5097946afffac6a69906a26d775823ebbacedfe6f2d69c0745e4\",\n", " \"outpoint\": \"5eaa7dd7a291665393eddf5dece91feef901f22665933cce7a0732a9b81c3001:0\",\n", " \"state\": \"WITHDRAWN\",\n", @@ -135,8 +141,10 @@ " \"value\": \"500000\"\n", " },\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14377\",\n", " \"confirmation_height\": \"142\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"0182b4d895b1c467290ae7b5c6c42ff76b2a4225807a94211c973170d5a883eb\",\n", " \"outpoint\": \"7e6360d6e6a394cfd096adf0bfe1275c5a83541eb573e90e463a78dc715f8894:0\",\n", " \"state\": \"WITHDRAWN\",\n", @@ -145,8 +153,10 @@ " \"value\": \"500000\"\n", " },\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14383\",\n", " \"confirmation_height\": \"148\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"8fbd6da2f945de2905aa7fa93860744d9387d3464484360e96e467a51de3bc9d\",\n", " \"outpoint\": \"9fa0d5dd5348794aa0541dd2729497f0907890606d044e1c4757bdc848f38df8:0\",\n", " \"state\": \"LOOPED_IN\",\n", @@ -155,8 +165,10 @@ " \"value\": \"500000\"\n", " },\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14395\",\n", " \"confirmation_height\": \"160\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"bb7f050df0b7c3e1fe61010e10ad45e30ddf7acd301fa6e05a2ddb825b5c2efb\",\n", " \"outpoint\": \"56cd081a3a6eadf25b7d3fe0b61207389352ed69a622d2ec28c5d669bf6a5313:0\",\n", " \"state\": \"WITHDRAWING\",\n", diff --git a/cmd/loop/testdata/sessions/static-filters/14_loop-static-listdeposits-channel_published-nonempty.json b/cmd/loop/testdata/sessions/static-filters/14_loop-static-listdeposits-channel_published-nonempty.json index 12689a556..7a96fb1bc 100644 --- a/cmd/loop/testdata/sessions/static-filters/14_loop-static-listdeposits-channel_published-nonempty.json +++ b/cmd/loop/testdata/sessions/static-filters/14_loop-static-listdeposits-channel_published-nonempty.json @@ -72,8 +72,10 @@ "{\n", " \"filtered_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14395\",\n", " \"confirmation_height\": \"127\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"7a7cbe9b90f23d47aa92eb10a9d323f7ace6e9eaab5b77379c63422c15da19c8\",\n", " \"outpoint\": \"0e70673c1da3343648c26f779555346f30d235314838b1160826d0d5c29b4fba:1\",\n", " \"state\": \"CHANNEL_PUBLISHED\",\n", @@ -82,8 +84,10 @@ " \"value\": \"500000\"\n", " },\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14395\",\n", " \"confirmation_height\": \"127\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"ff9a43b2082f906a2e2758934220c4ce32393eb2823b292517ae081e16daded9\",\n", " \"outpoint\": \"d2d6e50f157f0d31b8688a4af4f064edf3454714e92369b2c8c4d82477edbaca:0\",\n", " \"state\": \"CHANNEL_PUBLISHED\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/01_loop-static-new.json b/cmd/loop/testdata/sessions/static-loop-in/01_loop-static-new.json index 69a7ab554..54c9d44bb 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/01_loop-static-new.json +++ b/cmd/loop/testdata/sessions/static-loop-in/01_loop-static-new.json @@ -40,7 +40,8 @@ "event": "request", "message_type": "looprpc.NewStaticAddressRequest", "payload": { - "client_key": "" + "client_key": "", + "label": "" } } }, @@ -53,7 +54,8 @@ "message_type": "looprpc.NewStaticAddressResponse", "payload": { "address": "bcrt1pfu9g59aqtxd39653f76y4c8z7r3t9tmcvrvhl57a3dgj3epdwxdqcd9fpw", - "expiry": 14400 + "expiry": 14400, + "label": "" } } }, @@ -64,7 +66,8 @@ "lines": [ "{\n", " \"address\": \"bcrt1pfu9g59aqtxd39653f76y4c8z7r3t9tmcvrvhl57a3dgj3epdwxdqcd9fpw\",\n", - " \"expiry\": 14400\n", + " \"expiry\": 14400,\n", + " \"label\": \"\"\n", "}\n" ] } diff --git a/cmd/loop/testdata/sessions/static-loop-in/05_loop-static-listunspent.json b/cmd/loop/testdata/sessions/static-loop-in/05_loop-static-listunspent.json index a9ab34a43..07cb777e8 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/05_loop-static-listunspent.json +++ b/cmd/loop/testdata/sessions/static-loop-in/05_loop-static-listunspent.json @@ -39,7 +39,8 @@ "static_address": "bcrt1pfu9g59aqtxd39653f76y4c8z7r3t9tmcvrvhl57a3dgj3epdwxdqcd9fpw", "amount_sat": "2500000", "outpoint": "188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0", - "confirmations": "0" + "confirmations": "0", + "address_label": "" } ] } @@ -53,6 +54,7 @@ "{\n", " \"utxos\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"amount_sat\": \"2500000\",\n", " \"confirmations\": \"0\",\n", " \"outpoint\": \"188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/06_loop-static-l.json b/cmd/loop/testdata/sessions/static-loop-in/06_loop-static-l.json index 4df67c2df..16756caeb 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/06_loop-static-l.json +++ b/cmd/loop/testdata/sessions/static-loop-in/06_loop-static-l.json @@ -39,7 +39,8 @@ "static_address": "bcrt1pfu9g59aqtxd39653f76y4c8z7r3t9tmcvrvhl57a3dgj3epdwxdqcd9fpw", "amount_sat": "2500000", "outpoint": "188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0", - "confirmations": "0" + "confirmations": "0", + "address_label": "" } ] } @@ -53,6 +54,7 @@ "{\n", " \"utxos\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"amount_sat\": \"2500000\",\n", " \"confirmations\": \"0\",\n", " \"outpoint\": \"188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/08_loop-static-listunspent.json b/cmd/loop/testdata/sessions/static-loop-in/08_loop-static-listunspent.json index 465c98349..43589fc98 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/08_loop-static-listunspent.json +++ b/cmd/loop/testdata/sessions/static-loop-in/08_loop-static-listunspent.json @@ -39,7 +39,8 @@ "static_address": "bcrt1pfu9g59aqtxd39653f76y4c8z7r3t9tmcvrvhl57a3dgj3epdwxdqcd9fpw", "amount_sat": "2500000", "outpoint": "188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0", - "confirmations": "1" + "confirmations": "1", + "address_label": "" } ] } @@ -53,6 +54,7 @@ "{\n", " \"utxos\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"amount_sat\": \"2500000\",\n", " \"confirmations\": \"1\",\n", " \"outpoint\": \"188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/09_loop-static-listunspent.json b/cmd/loop/testdata/sessions/static-loop-in/09_loop-static-listunspent.json index 8cb05ac6d..d09116818 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/09_loop-static-listunspent.json +++ b/cmd/loop/testdata/sessions/static-loop-in/09_loop-static-listunspent.json @@ -39,7 +39,8 @@ "static_address": "bcrt1pfu9g59aqtxd39653f76y4c8z7r3t9tmcvrvhl57a3dgj3epdwxdqcd9fpw", "amount_sat": "2500000", "outpoint": "188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0", - "confirmations": "6" + "confirmations": "6", + "address_label": "" } ] } @@ -53,6 +54,7 @@ "{\n", " \"utxos\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"amount_sat\": \"2500000\",\n", " \"confirmations\": \"6\",\n", " \"outpoint\": \"188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/10_loop-static-listdeposits.json b/cmd/loop/testdata/sessions/static-loop-in/10_loop-static-listdeposits.json index e22efed83..2aaf3f9da 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/10_loop-static-listdeposits.json +++ b/cmd/loop/testdata/sessions/static-loop-in/10_loop-static-listdeposits.json @@ -56,8 +56,10 @@ "{\n", " \"filtered_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14395\",\n", " \"confirmation_height\": \"131\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"ea6abbf0571c0ba82117ae9f2086614eacea8b2913dc0544b70c00de78353e71\",\n", " \"outpoint\": \"188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0\",\n", " \"state\": \"DEPOSITED\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/15_loop-static-in.json b/cmd/loop/testdata/sessions/static-loop-in/15_loop-static-in.json index 49c6a9ef1..6dec2b5de 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/15_loop-static-in.json +++ b/cmd/loop/testdata/sessions/static-loop-in/15_loop-static-in.json @@ -223,8 +223,10 @@ " \"swap_hash\": \"9f19fb5042a5de6da2f1ce183c5e224fd7802db408e9afdd598ee8174b2bce3f\",\n", " \"used_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14395\",\n", " \"confirmation_height\": \"131\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"ea6abbf0571c0ba82117ae9f2086614eacea8b2913dc0544b70c00de78353e71\",\n", " \"outpoint\": \"188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0\",\n", " \"state\": \"LOOPING_IN\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/18_loop-static-in-positional-payment-timeout.json b/cmd/loop/testdata/sessions/static-loop-in/18_loop-static-in-positional-payment-timeout.json index 666c2a7ea..fe47b4dea 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/18_loop-static-in-positional-payment-timeout.json +++ b/cmd/loop/testdata/sessions/static-loop-in/18_loop-static-in-positional-payment-timeout.json @@ -204,8 +204,10 @@ " \"swap_hash\": \"84302337424036419396ab7964dd78b85b1a481a9f1db73db5cddee57c2443e7\",\n", " \"used_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14383\",\n", " \"confirmation_height\": \"148\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"8fbd6da2f945de2905aa7fa93860744d9387d3464484360e96e467a51de3bc9d\",\n", " \"outpoint\": \"9fa0d5dd5348794aa0541dd2729497f0907890606d044e1c4757bdc848f38df8:0\",\n", " \"state\": \"LOOPING_IN\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/23_loop-static-in-max-swap-fee-both.json b/cmd/loop/testdata/sessions/static-loop-in/23_loop-static-in-max-swap-fee-both.json index 690c48d2f..6ed367dab 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/23_loop-static-in-max-swap-fee-both.json +++ b/cmd/loop/testdata/sessions/static-loop-in/23_loop-static-in-max-swap-fee-both.json @@ -239,8 +239,10 @@ " \"swap_hash\": \"3840a9ce4b1afff1311f085449ccd3db4eeecd07de1f0d02ad4f04dd1993ce2a\",\n", " \"used_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14395\",\n", " \"confirmation_height\": \"133\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"82771323e95dca403d966f70a88be39ef0a475ef6aa78694044ba9b87304ac63\",\n", " \"outpoint\": \"da52bf383c4fe5c684221c311fc5756ccaee211b6c6e6f5ccc159622a6039271:1\",\n", " \"state\": \"LOOPING_IN\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/24_loop-static-in-max-swap-fee-sat-success.json b/cmd/loop/testdata/sessions/static-loop-in/24_loop-static-in-max-swap-fee-sat-success.json index 69ff4b8ed..ef2159622 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/24_loop-static-in-max-swap-fee-sat-success.json +++ b/cmd/loop/testdata/sessions/static-loop-in/24_loop-static-in-max-swap-fee-sat-success.json @@ -230,8 +230,10 @@ " \"swap_hash\": \"6cf43eb817ef2a71bb205bb2445853fb59a97ae9695b4323293f4821a1ab2503\",\n", " \"used_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14395\",\n", " \"confirmation_height\": \"133\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"d8a58536d8472873b9e2e1657468328360fda0b94231cfc5e29900cab735da84\",\n", " \"outpoint\": \"f2280f0f086273be73bde92fd9b982208338a5ecebbe93b83b00c77c4d2f8d1b:0\",\n", " \"state\": \"LOOPING_IN\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/25_loop-static-in-low-conf-utxo.json b/cmd/loop/testdata/sessions/static-loop-in/25_loop-static-in-low-conf-utxo.json index 37aae5a7a..a75e451c9 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/25_loop-static-in-low-conf-utxo.json +++ b/cmd/loop/testdata/sessions/static-loop-in/25_loop-static-in-low-conf-utxo.json @@ -154,8 +154,10 @@ " \"swap_hash\": \"9f19fb5042a5de6da2f1ce183c5e224fd7802db408e9afdd598ee8174b2bce3f\",\n", " \"used_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14396\",\n", " \"confirmation_height\": \"131\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"ea6abbf0571c0ba82117ae9f2086614eacea8b2913dc0544b70c00de78353e71\",\n", " \"outpoint\": \"188f55042e49cfa9942cc1f8e216c5e8679a7036e9ee6449d0fcc6c6b81561be:0\",\n", " \"state\": \"LOOPING_IN\",\n", diff --git a/cmd/loop/testdata/sessions/static-loop-in/26_loop-static-in-auto-unconfirmed.json b/cmd/loop/testdata/sessions/static-loop-in/26_loop-static-in-auto-unconfirmed.json index d254a4508..505040ff3 100644 --- a/cmd/loop/testdata/sessions/static-loop-in/26_loop-static-in-auto-unconfirmed.json +++ b/cmd/loop/testdata/sessions/static-loop-in/26_loop-static-in-auto-unconfirmed.json @@ -209,8 +209,10 @@ " \"swap_hash\": \"84302337424036419396ab7964dd78b85b1a481a9f1db73db5cddee57c2443e7\",\n", " \"used_deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"14400\",\n", " \"confirmation_height\": \"0\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"8fbd6da2f945de2905aa7fa93860744d9387d3464484360e96e467a51de3bc9d\",\n", " \"outpoint\": \"9fa0d5dd5348794aa0541dd2729497f0907890606d044e1c4757bdc848f38df8:0\",\n", " \"state\": \"LOOPING_IN\",\n", diff --git a/cmd/loop/testdata/sessions/static/02_loop-static-listwithdrawals.json b/cmd/loop/testdata/sessions/static/02_loop-static-listwithdrawals.json index 211fc7a8f..5da62fca2 100644 --- a/cmd/loop/testdata/sessions/static/02_loop-static-listwithdrawals.json +++ b/cmd/loop/testdata/sessions/static/02_loop-static-listwithdrawals.json @@ -68,8 +68,10 @@ " \"confirmation_height\": 0,\n", " \"deposits\": [\n", " {\n", + " \"address_label\": \"\",\n", " \"blocks_until_expiry\": \"0\",\n", " \"confirmation_height\": \"125\",\n", + " \"funding_tx_label\": \"\",\n", " \"id\": \"68262a104c9ec325de6bec37b8e31bd875bbd2f5f0b9ce2da20cf0bd636fc448\",\n", " \"outpoint\": \"edcdab8f0b1138d853a453b8b7a5ac3c694bd53ad38b7ccf062e45f99440e6e6:0\",\n", " \"state\": \"WITHDRAWING\",\n", diff --git a/looprpc/client.pb.go b/looprpc/client.pb.go index 33e545c55..64f6d7dea 100644 --- a/looprpc/client.pb.go +++ b/looprpc/client.pb.go @@ -4927,7 +4927,9 @@ func (x *InstantOut) GetSweepTxId() string { type NewStaticAddressRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // The client's public key for the 2-of-2 MuSig2 taproot static address. - ClientKey []byte `protobuf:"bytes,1,opt,name=client_key,json=clientKey,proto3" json:"client_key,omitempty"` + ClientKey []byte `protobuf:"bytes,1,opt,name=client_key,json=clientKey,proto3" json:"client_key,omitempty"` + // An optional label for this static address. Empty string means no label. + Label string `protobuf:"bytes,3,opt,name=label,proto3" json:"label,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4969,12 +4971,21 @@ func (x *NewStaticAddressRequest) GetClientKey() []byte { return nil } +func (x *NewStaticAddressRequest) GetLabel() string { + if x != nil { + return x.Label + } + return "" +} + type NewStaticAddressResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // The newly derived taproot static address. Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` // The CSV expiry of the static address in blocks. - Expiry uint32 `protobuf:"varint,2,opt,name=expiry,proto3" json:"expiry,omitempty"` + Expiry uint32 `protobuf:"varint,2,opt,name=expiry,proto3" json:"expiry,omitempty"` + // The label for this static address. Empty string means no label. + Label string `protobuf:"bytes,4,opt,name=label,proto3" json:"label,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -5023,6 +5034,13 @@ func (x *NewStaticAddressResponse) GetExpiry() uint32 { return 0 } +func (x *NewStaticAddressResponse) GetLabel() string { + if x != nil { + return x.Label + } + return "" +} + type FundStaticAddressRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. The funding request passed to lnd's SendCoins API. If addr is @@ -5134,6 +5152,114 @@ func (x *FundStaticAddressResponse) GetSendCoinsResponse() *lnrpc.SendCoinsRespo return nil } +type UpdateStaticAddressLabelRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The static address whose label should be updated. + StaticAddress string `protobuf:"bytes,1,opt,name=static_address,json=staticAddress,proto3" json:"static_address,omitempty"` + // The updated label for the static address. Empty string means no label. + Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateStaticAddressLabelRequest) Reset() { + *x = UpdateStaticAddressLabelRequest{} + mi := &file_client_proto_msgTypes[59] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateStaticAddressLabelRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateStaticAddressLabelRequest) ProtoMessage() {} + +func (x *UpdateStaticAddressLabelRequest) ProtoReflect() protoreflect.Message { + mi := &file_client_proto_msgTypes[59] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateStaticAddressLabelRequest.ProtoReflect.Descriptor instead. +func (*UpdateStaticAddressLabelRequest) Descriptor() ([]byte, []int) { + return file_client_proto_rawDescGZIP(), []int{59} +} + +func (x *UpdateStaticAddressLabelRequest) GetStaticAddress() string { + if x != nil { + return x.StaticAddress + } + return "" +} + +func (x *UpdateStaticAddressLabelRequest) GetLabel() string { + if x != nil { + return x.Label + } + return "" +} + +type UpdateStaticAddressLabelResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The static address whose label was updated. + StaticAddress string `protobuf:"bytes,1,opt,name=static_address,json=staticAddress,proto3" json:"static_address,omitempty"` + // The updated label for the static address. Empty string means no label. + Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateStaticAddressLabelResponse) Reset() { + *x = UpdateStaticAddressLabelResponse{} + mi := &file_client_proto_msgTypes[60] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateStaticAddressLabelResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateStaticAddressLabelResponse) ProtoMessage() {} + +func (x *UpdateStaticAddressLabelResponse) ProtoReflect() protoreflect.Message { + mi := &file_client_proto_msgTypes[60] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateStaticAddressLabelResponse.ProtoReflect.Descriptor instead. +func (*UpdateStaticAddressLabelResponse) Descriptor() ([]byte, []int) { + return file_client_proto_rawDescGZIP(), []int{60} +} + +func (x *UpdateStaticAddressLabelResponse) GetStaticAddress() string { + if x != nil { + return x.StaticAddress + } + return "" +} + +func (x *UpdateStaticAddressLabelResponse) GetLabel() string { + if x != nil { + return x.Label + } + return "" +} + type ListUnspentDepositsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // The number of minimum confirmations a utxo must have to be listed. @@ -5147,7 +5273,7 @@ type ListUnspentDepositsRequest struct { func (x *ListUnspentDepositsRequest) Reset() { *x = ListUnspentDepositsRequest{} - mi := &file_client_proto_msgTypes[59] + mi := &file_client_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5159,7 +5285,7 @@ func (x *ListUnspentDepositsRequest) String() string { func (*ListUnspentDepositsRequest) ProtoMessage() {} func (x *ListUnspentDepositsRequest) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[59] + mi := &file_client_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5172,7 +5298,7 @@ func (x *ListUnspentDepositsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUnspentDepositsRequest.ProtoReflect.Descriptor instead. func (*ListUnspentDepositsRequest) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{59} + return file_client_proto_rawDescGZIP(), []int{61} } func (x *ListUnspentDepositsRequest) GetMinConfs() int32 { @@ -5199,7 +5325,7 @@ type ListUnspentDepositsResponse struct { func (x *ListUnspentDepositsResponse) Reset() { *x = ListUnspentDepositsResponse{} - mi := &file_client_proto_msgTypes[60] + mi := &file_client_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5211,7 +5337,7 @@ func (x *ListUnspentDepositsResponse) String() string { func (*ListUnspentDepositsResponse) ProtoMessage() {} func (x *ListUnspentDepositsResponse) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[60] + mi := &file_client_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5224,7 +5350,7 @@ func (x *ListUnspentDepositsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUnspentDepositsResponse.ProtoReflect.Descriptor instead. func (*ListUnspentDepositsResponse) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{60} + return file_client_proto_rawDescGZIP(), []int{62} } func (x *ListUnspentDepositsResponse) GetUtxos() []*Utxo { @@ -5244,13 +5370,16 @@ type Utxo struct { Outpoint string `protobuf:"bytes,3,opt,name=outpoint,proto3" json:"outpoint,omitempty"` // The number of confirmations for the Utxo. Confirmations int64 `protobuf:"varint,4,opt,name=confirmations,proto3" json:"confirmations,omitempty"` + // The local label of the static address that owns this Utxo. Empty string + // means no label. + AddressLabel string `protobuf:"bytes,5,opt,name=address_label,json=addressLabel,proto3" json:"address_label,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *Utxo) Reset() { *x = Utxo{} - mi := &file_client_proto_msgTypes[61] + mi := &file_client_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5262,7 +5391,7 @@ func (x *Utxo) String() string { func (*Utxo) ProtoMessage() {} func (x *Utxo) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[61] + mi := &file_client_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5275,7 +5404,7 @@ func (x *Utxo) ProtoReflect() protoreflect.Message { // Deprecated: Use Utxo.ProtoReflect.Descriptor instead. func (*Utxo) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{61} + return file_client_proto_rawDescGZIP(), []int{63} } func (x *Utxo) GetStaticAddress() string { @@ -5306,6 +5435,13 @@ func (x *Utxo) GetConfirmations() int64 { return 0 } +func (x *Utxo) GetAddressLabel() string { + if x != nil { + return x.AddressLabel + } + return "" +} + type WithdrawDepositsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // The outpoints of the deposits to withdraw. @@ -5328,7 +5464,7 @@ type WithdrawDepositsRequest struct { func (x *WithdrawDepositsRequest) Reset() { *x = WithdrawDepositsRequest{} - mi := &file_client_proto_msgTypes[62] + mi := &file_client_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5340,7 +5476,7 @@ func (x *WithdrawDepositsRequest) String() string { func (*WithdrawDepositsRequest) ProtoMessage() {} func (x *WithdrawDepositsRequest) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[62] + mi := &file_client_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5353,7 +5489,7 @@ func (x *WithdrawDepositsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WithdrawDepositsRequest.ProtoReflect.Descriptor instead. func (*WithdrawDepositsRequest) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{62} + return file_client_proto_rawDescGZIP(), []int{64} } func (x *WithdrawDepositsRequest) GetOutpoints() []*lnrpc.OutPoint { @@ -5403,7 +5539,7 @@ type WithdrawDepositsResponse struct { func (x *WithdrawDepositsResponse) Reset() { *x = WithdrawDepositsResponse{} - mi := &file_client_proto_msgTypes[63] + mi := &file_client_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5415,7 +5551,7 @@ func (x *WithdrawDepositsResponse) String() string { func (*WithdrawDepositsResponse) ProtoMessage() {} func (x *WithdrawDepositsResponse) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[63] + mi := &file_client_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5428,7 +5564,7 @@ func (x *WithdrawDepositsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use WithdrawDepositsResponse.ProtoReflect.Descriptor instead. func (*WithdrawDepositsResponse) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{63} + return file_client_proto_rawDescGZIP(), []int{65} } func (x *WithdrawDepositsResponse) GetWithdrawalTxHash() string { @@ -5457,7 +5593,7 @@ type ListStaticAddressDepositsRequest struct { func (x *ListStaticAddressDepositsRequest) Reset() { *x = ListStaticAddressDepositsRequest{} - mi := &file_client_proto_msgTypes[64] + mi := &file_client_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5469,7 +5605,7 @@ func (x *ListStaticAddressDepositsRequest) String() string { func (*ListStaticAddressDepositsRequest) ProtoMessage() {} func (x *ListStaticAddressDepositsRequest) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[64] + mi := &file_client_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5482,7 +5618,7 @@ func (x *ListStaticAddressDepositsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStaticAddressDepositsRequest.ProtoReflect.Descriptor instead. func (*ListStaticAddressDepositsRequest) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{64} + return file_client_proto_rawDescGZIP(), []int{66} } func (x *ListStaticAddressDepositsRequest) GetStateFilter() DepositState { @@ -5509,7 +5645,7 @@ type ListStaticAddressDepositsResponse struct { func (x *ListStaticAddressDepositsResponse) Reset() { *x = ListStaticAddressDepositsResponse{} - mi := &file_client_proto_msgTypes[65] + mi := &file_client_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5521,7 +5657,7 @@ func (x *ListStaticAddressDepositsResponse) String() string { func (*ListStaticAddressDepositsResponse) ProtoMessage() {} func (x *ListStaticAddressDepositsResponse) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[65] + mi := &file_client_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5534,7 +5670,7 @@ func (x *ListStaticAddressDepositsResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListStaticAddressDepositsResponse.ProtoReflect.Descriptor instead. func (*ListStaticAddressDepositsResponse) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{65} + return file_client_proto_rawDescGZIP(), []int{67} } func (x *ListStaticAddressDepositsResponse) GetFilteredDeposits() []*Deposit { @@ -5552,7 +5688,7 @@ type ListStaticAddressWithdrawalRequest struct { func (x *ListStaticAddressWithdrawalRequest) Reset() { *x = ListStaticAddressWithdrawalRequest{} - mi := &file_client_proto_msgTypes[66] + mi := &file_client_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5564,7 +5700,7 @@ func (x *ListStaticAddressWithdrawalRequest) String() string { func (*ListStaticAddressWithdrawalRequest) ProtoMessage() {} func (x *ListStaticAddressWithdrawalRequest) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[66] + mi := &file_client_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5577,7 +5713,7 @@ func (x *ListStaticAddressWithdrawalRequest) ProtoReflect() protoreflect.Message // Deprecated: Use ListStaticAddressWithdrawalRequest.ProtoReflect.Descriptor instead. func (*ListStaticAddressWithdrawalRequest) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{66} + return file_client_proto_rawDescGZIP(), []int{68} } type ListStaticAddressWithdrawalResponse struct { @@ -5590,7 +5726,7 @@ type ListStaticAddressWithdrawalResponse struct { func (x *ListStaticAddressWithdrawalResponse) Reset() { *x = ListStaticAddressWithdrawalResponse{} - mi := &file_client_proto_msgTypes[67] + mi := &file_client_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5602,7 +5738,7 @@ func (x *ListStaticAddressWithdrawalResponse) String() string { func (*ListStaticAddressWithdrawalResponse) ProtoMessage() {} func (x *ListStaticAddressWithdrawalResponse) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[67] + mi := &file_client_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5615,7 +5751,7 @@ func (x *ListStaticAddressWithdrawalResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use ListStaticAddressWithdrawalResponse.ProtoReflect.Descriptor instead. func (*ListStaticAddressWithdrawalResponse) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{67} + return file_client_proto_rawDescGZIP(), []int{69} } func (x *ListStaticAddressWithdrawalResponse) GetWithdrawals() []*StaticAddressWithdrawal { @@ -5633,7 +5769,7 @@ type ListStaticAddressSwapsRequest struct { func (x *ListStaticAddressSwapsRequest) Reset() { *x = ListStaticAddressSwapsRequest{} - mi := &file_client_proto_msgTypes[68] + mi := &file_client_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5645,7 +5781,7 @@ func (x *ListStaticAddressSwapsRequest) String() string { func (*ListStaticAddressSwapsRequest) ProtoMessage() {} func (x *ListStaticAddressSwapsRequest) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[68] + mi := &file_client_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5658,7 +5794,7 @@ func (x *ListStaticAddressSwapsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStaticAddressSwapsRequest.ProtoReflect.Descriptor instead. func (*ListStaticAddressSwapsRequest) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{68} + return file_client_proto_rawDescGZIP(), []int{70} } type ListStaticAddressSwapsResponse struct { @@ -5671,7 +5807,7 @@ type ListStaticAddressSwapsResponse struct { func (x *ListStaticAddressSwapsResponse) Reset() { *x = ListStaticAddressSwapsResponse{} - mi := &file_client_proto_msgTypes[69] + mi := &file_client_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5683,7 +5819,7 @@ func (x *ListStaticAddressSwapsResponse) String() string { func (*ListStaticAddressSwapsResponse) ProtoMessage() {} func (x *ListStaticAddressSwapsResponse) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[69] + mi := &file_client_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5696,7 +5832,7 @@ func (x *ListStaticAddressSwapsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStaticAddressSwapsResponse.ProtoReflect.Descriptor instead. func (*ListStaticAddressSwapsResponse) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{69} + return file_client_proto_rawDescGZIP(), []int{71} } func (x *ListStaticAddressSwapsResponse) GetSwaps() []*StaticAddressLoopInSwap { @@ -5714,7 +5850,7 @@ type StaticAddressSummaryRequest struct { func (x *StaticAddressSummaryRequest) Reset() { *x = StaticAddressSummaryRequest{} - mi := &file_client_proto_msgTypes[70] + mi := &file_client_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5726,7 +5862,7 @@ func (x *StaticAddressSummaryRequest) String() string { func (*StaticAddressSummaryRequest) ProtoMessage() {} func (x *StaticAddressSummaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[70] + mi := &file_client_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5739,7 +5875,7 @@ func (x *StaticAddressSummaryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StaticAddressSummaryRequest.ProtoReflect.Descriptor instead. func (*StaticAddressSummaryRequest) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{70} + return file_client_proto_rawDescGZIP(), []int{72} } type StaticAddressSummaryResponse struct { @@ -5775,7 +5911,7 @@ type StaticAddressSummaryResponse struct { func (x *StaticAddressSummaryResponse) Reset() { *x = StaticAddressSummaryResponse{} - mi := &file_client_proto_msgTypes[71] + mi := &file_client_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5787,7 +5923,7 @@ func (x *StaticAddressSummaryResponse) String() string { func (*StaticAddressSummaryResponse) ProtoMessage() {} func (x *StaticAddressSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[71] + mi := &file_client_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5800,7 +5936,7 @@ func (x *StaticAddressSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StaticAddressSummaryResponse.ProtoReflect.Descriptor instead. func (*StaticAddressSummaryResponse) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{71} + return file_client_proto_rawDescGZIP(), []int{73} } // Deprecated: Marked as deprecated in client.proto. @@ -5894,13 +6030,19 @@ type Deposit struct { SwapHash []byte `protobuf:"bytes,7,opt,name=swap_hash,json=swapHash,proto3" json:"swap_hash,omitempty"` // The static address that the deposit was sent to. StaticAddress string `protobuf:"bytes,8,opt,name=static_address,json=staticAddress,proto3" json:"static_address,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // The local label of the static address that the deposit was sent to. Empty + // string means no label. + AddressLabel string `protobuf:"bytes,9,opt,name=address_label,json=addressLabel,proto3" json:"address_label,omitempty"` + // The lnd wallet label of the transaction that funded the deposit. Empty + // string means no label, or that the label could not be looked up in lnd. + FundingTxLabel string `protobuf:"bytes,10,opt,name=funding_tx_label,json=fundingTxLabel,proto3" json:"funding_tx_label,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Deposit) Reset() { *x = Deposit{} - mi := &file_client_proto_msgTypes[72] + mi := &file_client_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5912,7 +6054,7 @@ func (x *Deposit) String() string { func (*Deposit) ProtoMessage() {} func (x *Deposit) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[72] + mi := &file_client_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5925,7 +6067,7 @@ func (x *Deposit) ProtoReflect() protoreflect.Message { // Deprecated: Use Deposit.ProtoReflect.Descriptor instead. func (*Deposit) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{72} + return file_client_proto_rawDescGZIP(), []int{74} } func (x *Deposit) GetId() []byte { @@ -5984,6 +6126,20 @@ func (x *Deposit) GetStaticAddress() string { return "" } +func (x *Deposit) GetAddressLabel() string { + if x != nil { + return x.AddressLabel + } + return "" +} + +func (x *Deposit) GetFundingTxLabel() string { + if x != nil { + return x.FundingTxLabel + } + return "" +} + type StaticAddressWithdrawal struct { state protoimpl.MessageState `protogen:"open.v1"` // The transaction id of the withdrawal transaction. @@ -6006,7 +6162,7 @@ type StaticAddressWithdrawal struct { func (x *StaticAddressWithdrawal) Reset() { *x = StaticAddressWithdrawal{} - mi := &file_client_proto_msgTypes[73] + mi := &file_client_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6018,7 +6174,7 @@ func (x *StaticAddressWithdrawal) String() string { func (*StaticAddressWithdrawal) ProtoMessage() {} func (x *StaticAddressWithdrawal) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[73] + mi := &file_client_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6031,7 +6187,7 @@ func (x *StaticAddressWithdrawal) ProtoReflect() protoreflect.Message { // Deprecated: Use StaticAddressWithdrawal.ProtoReflect.Descriptor instead. func (*StaticAddressWithdrawal) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{73} + return file_client_proto_rawDescGZIP(), []int{75} } func (x *StaticAddressWithdrawal) GetTxId() string { @@ -6106,7 +6262,7 @@ type StaticAddressLoopInSwap struct { func (x *StaticAddressLoopInSwap) Reset() { *x = StaticAddressLoopInSwap{} - mi := &file_client_proto_msgTypes[74] + mi := &file_client_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6118,7 +6274,7 @@ func (x *StaticAddressLoopInSwap) String() string { func (*StaticAddressLoopInSwap) ProtoMessage() {} func (x *StaticAddressLoopInSwap) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[74] + mi := &file_client_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6131,7 +6287,7 @@ func (x *StaticAddressLoopInSwap) ProtoReflect() protoreflect.Message { // Deprecated: Use StaticAddressLoopInSwap.ProtoReflect.Descriptor instead. func (*StaticAddressLoopInSwap) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{74} + return file_client_proto_rawDescGZIP(), []int{76} } func (x *StaticAddressLoopInSwap) GetSwapHash() []byte { @@ -6264,7 +6420,7 @@ type StaticAddressLoopInRequest struct { func (x *StaticAddressLoopInRequest) Reset() { *x = StaticAddressLoopInRequest{} - mi := &file_client_proto_msgTypes[75] + mi := &file_client_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6276,7 +6432,7 @@ func (x *StaticAddressLoopInRequest) String() string { func (*StaticAddressLoopInRequest) ProtoMessage() {} func (x *StaticAddressLoopInRequest) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[75] + mi := &file_client_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6289,7 +6445,7 @@ func (x *StaticAddressLoopInRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StaticAddressLoopInRequest.ProtoReflect.Descriptor instead. func (*StaticAddressLoopInRequest) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{75} + return file_client_proto_rawDescGZIP(), []int{77} } func (x *StaticAddressLoopInRequest) GetOutpoints() []string { @@ -6409,7 +6565,7 @@ type StaticAddressLoopInResponse struct { func (x *StaticAddressLoopInResponse) Reset() { *x = StaticAddressLoopInResponse{} - mi := &file_client_proto_msgTypes[76] + mi := &file_client_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6421,7 +6577,7 @@ func (x *StaticAddressLoopInResponse) String() string { func (*StaticAddressLoopInResponse) ProtoMessage() {} func (x *StaticAddressLoopInResponse) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[76] + mi := &file_client_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6434,7 +6590,7 @@ func (x *StaticAddressLoopInResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StaticAddressLoopInResponse.ProtoReflect.Descriptor instead. func (*StaticAddressLoopInResponse) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{76} + return file_client_proto_rawDescGZIP(), []int{78} } func (x *StaticAddressLoopInResponse) GetSwapHash() []byte { @@ -6563,7 +6719,7 @@ type AssetLoopOutRequest struct { func (x *AssetLoopOutRequest) Reset() { *x = AssetLoopOutRequest{} - mi := &file_client_proto_msgTypes[77] + mi := &file_client_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6575,7 +6731,7 @@ func (x *AssetLoopOutRequest) String() string { func (*AssetLoopOutRequest) ProtoMessage() {} func (x *AssetLoopOutRequest) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[77] + mi := &file_client_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6588,7 +6744,7 @@ func (x *AssetLoopOutRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AssetLoopOutRequest.ProtoReflect.Descriptor instead. func (*AssetLoopOutRequest) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{77} + return file_client_proto_rawDescGZIP(), []int{79} } func (x *AssetLoopOutRequest) GetAssetId() []byte { @@ -6643,7 +6799,7 @@ type AssetRfqInfo struct { func (x *AssetRfqInfo) Reset() { *x = AssetRfqInfo{} - mi := &file_client_proto_msgTypes[78] + mi := &file_client_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6655,7 +6811,7 @@ func (x *AssetRfqInfo) String() string { func (*AssetRfqInfo) ProtoMessage() {} func (x *AssetRfqInfo) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[78] + mi := &file_client_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6668,7 +6824,7 @@ func (x *AssetRfqInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use AssetRfqInfo.ProtoReflect.Descriptor instead. func (*AssetRfqInfo) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{78} + return file_client_proto_rawDescGZIP(), []int{80} } func (x *AssetRfqInfo) GetPrepayRfqId() []byte { @@ -6757,7 +6913,7 @@ type FixedPoint struct { func (x *FixedPoint) Reset() { *x = FixedPoint{} - mi := &file_client_proto_msgTypes[79] + mi := &file_client_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6769,7 +6925,7 @@ func (x *FixedPoint) String() string { func (*FixedPoint) ProtoMessage() {} func (x *FixedPoint) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[79] + mi := &file_client_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6782,7 +6938,7 @@ func (x *FixedPoint) ProtoReflect() protoreflect.Message { // Deprecated: Use FixedPoint.ProtoReflect.Descriptor instead. func (*FixedPoint) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{79} + return file_client_proto_rawDescGZIP(), []int{81} } func (x *FixedPoint) GetCoefficient() string { @@ -6813,7 +6969,7 @@ type AssetLoopOutInfo struct { func (x *AssetLoopOutInfo) Reset() { *x = AssetLoopOutInfo{} - mi := &file_client_proto_msgTypes[80] + mi := &file_client_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6825,7 +6981,7 @@ func (x *AssetLoopOutInfo) String() string { func (*AssetLoopOutInfo) ProtoMessage() {} func (x *AssetLoopOutInfo) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[80] + mi := &file_client_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6838,7 +6994,7 @@ func (x *AssetLoopOutInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use AssetLoopOutInfo.ProtoReflect.Descriptor instead. func (*AssetLoopOutInfo) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{80} + return file_client_proto_rawDescGZIP(), []int{82} } func (x *AssetLoopOutInfo) GetAssetId() string { @@ -6886,7 +7042,7 @@ type StatelessRecovery struct { func (x *StatelessRecovery) Reset() { *x = StatelessRecovery{} - mi := &file_client_proto_msgTypes[81] + mi := &file_client_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6898,7 +7054,7 @@ func (x *StatelessRecovery) String() string { func (*StatelessRecovery) ProtoMessage() {} func (x *StatelessRecovery) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[81] + mi := &file_client_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6911,7 +7067,7 @@ func (x *StatelessRecovery) ProtoReflect() protoreflect.Message { // Deprecated: Use StatelessRecovery.ProtoReflect.Descriptor instead. func (*StatelessRecovery) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{81} + return file_client_proto_rawDescGZIP(), []int{83} } func (x *StatelessRecovery) GetServerPubkey() []byte { @@ -6962,7 +7118,7 @@ type CooperativeSweep struct { func (x *CooperativeSweep) Reset() { *x = CooperativeSweep{} - mi := &file_client_proto_msgTypes[82] + mi := &file_client_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6974,7 +7130,7 @@ func (x *CooperativeSweep) String() string { func (*CooperativeSweep) ProtoMessage() {} func (x *CooperativeSweep) ProtoReflect() protoreflect.Message { - mi := &file_client_proto_msgTypes[82] + mi := &file_client_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6987,7 +7143,7 @@ func (x *CooperativeSweep) ProtoReflect() protoreflect.Message { // Deprecated: Use CooperativeSweep.ProtoReflect.Descriptor instead. func (*CooperativeSweep) Descriptor() ([]byte, []int) { - return file_client_proto_rawDescGZIP(), []int{82} + return file_client_proto_rawDescGZIP(), []int{84} } func (x *CooperativeSweep) GetPaymentAddress() []byte { @@ -7308,30 +7464,39 @@ const file_client_proto_rawDesc = "" + "\x05state\x18\x02 \x01(\tR\x05state\x12\x16\n" + "\x06amount\x18\x03 \x01(\x04R\x06amount\x12'\n" + "\x0freservation_ids\x18\x04 \x03(\fR\x0ereservationIds\x12\x1e\n" + - "\vsweep_tx_id\x18\x05 \x01(\tR\tsweepTxId\"R\n" + + "\vsweep_tx_id\x18\x05 \x01(\tR\tsweepTxId\"h\n" + "\x17NewStaticAddressRequest\x12\x1d\n" + "\n" + - "client_key\x18\x01 \x01(\fR\tclientKeyJ\x04\b\x02\x10\x03R\x12send_coins_request\"g\n" + + "client_key\x18\x01 \x01(\fR\tclientKey\x12\x14\n" + + "\x05label\x18\x03 \x01(\tR\x05labelJ\x04\b\x02\x10\x03R\x12send_coins_request\"}\n" + "\x18NewStaticAddressResponse\x12\x18\n" + "\aaddress\x18\x01 \x01(\tR\aaddress\x12\x16\n" + - "\x06expiry\x18\x02 \x01(\rR\x06expiryJ\x04\b\x03\x10\x04R\x13send_coins_response\"a\n" + + "\x06expiry\x18\x02 \x01(\rR\x06expiry\x12\x14\n" + + "\x05label\x18\x04 \x01(\tR\x05labelJ\x04\b\x03\x10\x04R\x13send_coins_response\"a\n" + "\x18FundStaticAddressRequest\x12E\n" + "\x12send_coins_request\x18\x01 \x01(\v2\x17.lnrpc.SendCoinsRequestR\x10sendCoinsRequest\"\x97\x01\n" + "\x19FundStaticAddressResponse\x12\x18\n" + "\aaddress\x18\x01 \x01(\tR\aaddress\x12\x16\n" + "\x06expiry\x18\x02 \x01(\rR\x06expiry\x12H\n" + - "\x13send_coins_response\x18\x03 \x01(\v2\x18.lnrpc.SendCoinsResponseR\x11sendCoinsResponse\"V\n" + + "\x13send_coins_response\x18\x03 \x01(\v2\x18.lnrpc.SendCoinsResponseR\x11sendCoinsResponse\"^\n" + + "\x1fUpdateStaticAddressLabelRequest\x12%\n" + + "\x0estatic_address\x18\x01 \x01(\tR\rstaticAddress\x12\x14\n" + + "\x05label\x18\x02 \x01(\tR\x05label\"_\n" + + " UpdateStaticAddressLabelResponse\x12%\n" + + "\x0estatic_address\x18\x01 \x01(\tR\rstaticAddress\x12\x14\n" + + "\x05label\x18\x02 \x01(\tR\x05label\"V\n" + "\x1aListUnspentDepositsRequest\x12\x1b\n" + "\tmin_confs\x18\x01 \x01(\x05R\bminConfs\x12\x1b\n" + "\tmax_confs\x18\x02 \x01(\x05R\bmaxConfs\"B\n" + "\x1bListUnspentDepositsResponse\x12#\n" + - "\x05utxos\x18\x01 \x03(\v2\r.looprpc.UtxoR\x05utxos\"\x8e\x01\n" + + "\x05utxos\x18\x01 \x03(\v2\r.looprpc.UtxoR\x05utxos\"\xb3\x01\n" + "\x04Utxo\x12%\n" + "\x0estatic_address\x18\x01 \x01(\tR\rstaticAddress\x12\x1d\n" + "\n" + "amount_sat\x18\x02 \x01(\x03R\tamountSat\x12\x1a\n" + "\boutpoint\x18\x03 \x01(\tR\boutpoint\x12$\n" + - "\rconfirmations\x18\x04 \x01(\x03R\rconfirmations\"\xb3\x01\n" + + "\rconfirmations\x18\x04 \x01(\x03R\rconfirmations\x12#\n" + + "\raddress_label\x18\x05 \x01(\tR\faddressLabel\"\xb3\x01\n" + "\x17WithdrawDepositsRequest\x12-\n" + "\toutpoints\x18\x01 \x03(\v2\x0f.lnrpc.OutPointR\toutpoints\x12\x10\n" + "\x03all\x18\x02 \x01(\bR\x03all\x12\x1b\n" + @@ -7364,7 +7529,7 @@ const file_client_proto_rawDesc = "" + "\x18value_looped_in_satoshis\x18\b \x01(\x03R\x15valueLoopedInSatoshis\x12J\n" + "\"value_htlc_timeout_sweeps_satoshis\x18\t \x01(\x03R\x1evalueHtlcTimeoutSweepsSatoshis\x122\n" + "\x15value_channels_opened\x18\n" + - " \x01(\x03R\x13valueChannelsOpened\"\x9d\x02\n" + + " \x01(\x03R\x13valueChannelsOpened\"\xec\x02\n" + "\aDeposit\x12\x0e\n" + "\x02id\x18\x01 \x01(\fR\x02id\x12+\n" + "\x05state\x18\x02 \x01(\x0e2\x15.looprpc.DepositStateR\x05state\x12\x1a\n" + @@ -7373,7 +7538,10 @@ const file_client_proto_rawDesc = "" + "\x13confirmation_height\x18\x05 \x01(\x03R\x12confirmationHeight\x12.\n" + "\x13blocks_until_expiry\x18\x06 \x01(\x03R\x11blocksUntilExpiry\x12\x1b\n" + "\tswap_hash\x18\a \x01(\fR\bswapHash\x12%\n" + - "\x0estatic_address\x18\b \x01(\tR\rstaticAddress\"\xc2\x02\n" + + "\x0estatic_address\x18\b \x01(\tR\rstaticAddress\x12#\n" + + "\raddress_label\x18\t \x01(\tR\faddressLabel\x12(\n" + + "\x10funding_tx_label\x18\n" + + " \x01(\tR\x0efundingTxLabel\"\xc2\x02\n" + "\x17StaticAddressWithdrawal\x12\x13\n" + "\x05tx_id\x18\x01 \x01(\tR\x04txId\x12,\n" + "\bdeposits\x18\x02 \x03(\v2\x10.looprpc.DepositR\bdeposits\x12A\n" + @@ -7538,7 +7706,7 @@ const file_client_proto_rawDesc = "" + "\x1eSUCCEEDED_TRANSITIONING_FAILED\x10\t\x12\x13\n" + "\x0fUNLOCK_DEPOSITS\x10\n" + "\x12\x1e\n" + - "\x1aFAILED_STATIC_ADDRESS_SWAP\x10\v2\xa6\x15\n" + + "\x1aFAILED_STATIC_ADDRESS_SWAP\x10\v2\x97\x16\n" + "\n" + "SwapClient\x129\n" + "\aLoopOut\x12\x17.looprpc.LoopOutRequest\x1a\x15.looprpc.SwapResponse\x127\n" + @@ -7568,7 +7736,8 @@ const file_client_proto_rawDesc = "" + "\x0fInstantOutQuote\x12\x1f.looprpc.InstantOutQuoteRequest\x1a .looprpc.InstantOutQuoteResponse\x12T\n" + "\x0fListInstantOuts\x12\x1f.looprpc.ListInstantOutsRequest\x1a .looprpc.ListInstantOutsResponse\x12W\n" + "\x10NewStaticAddress\x12 .looprpc.NewStaticAddressRequest\x1a!.looprpc.NewStaticAddressResponse\x12Z\n" + - "\x11FundStaticAddress\x12!.looprpc.FundStaticAddressRequest\x1a\".looprpc.FundStaticAddressResponse\x12`\n" + + "\x11FundStaticAddress\x12!.looprpc.FundStaticAddressRequest\x1a\".looprpc.FundStaticAddressResponse\x12o\n" + + "\x18UpdateStaticAddressLabel\x12(.looprpc.UpdateStaticAddressLabelRequest\x1a).looprpc.UpdateStaticAddressLabelResponse\x12`\n" + "\x13ListUnspentDeposits\x12#.looprpc.ListUnspentDepositsRequest\x1a$.looprpc.ListUnspentDepositsResponse\x12W\n" + "\x10WithdrawDeposits\x12 .looprpc.WithdrawDepositsRequest\x1a!.looprpc.WithdrawDepositsResponse\x12r\n" + "\x19ListStaticAddressDeposits\x12).looprpc.ListStaticAddressDepositsRequest\x1a*.looprpc.ListStaticAddressDepositsResponse\x12y\n" + @@ -7591,7 +7760,7 @@ func file_client_proto_rawDescGZIP() []byte { } var file_client_proto_enumTypes = make([]protoimpl.EnumInfo, 10) -var file_client_proto_msgTypes = make([]protoimpl.MessageInfo, 84) +var file_client_proto_msgTypes = make([]protoimpl.MessageInfo, 86) var file_client_proto_goTypes = []any{ (AddressType)(0), // 0: looprpc.AddressType (SwapType)(0), // 1: looprpc.SwapType @@ -7662,167 +7831,171 @@ var file_client_proto_goTypes = []any{ (*NewStaticAddressResponse)(nil), // 66: looprpc.NewStaticAddressResponse (*FundStaticAddressRequest)(nil), // 67: looprpc.FundStaticAddressRequest (*FundStaticAddressResponse)(nil), // 68: looprpc.FundStaticAddressResponse - (*ListUnspentDepositsRequest)(nil), // 69: looprpc.ListUnspentDepositsRequest - (*ListUnspentDepositsResponse)(nil), // 70: looprpc.ListUnspentDepositsResponse - (*Utxo)(nil), // 71: looprpc.Utxo - (*WithdrawDepositsRequest)(nil), // 72: looprpc.WithdrawDepositsRequest - (*WithdrawDepositsResponse)(nil), // 73: looprpc.WithdrawDepositsResponse - (*ListStaticAddressDepositsRequest)(nil), // 74: looprpc.ListStaticAddressDepositsRequest - (*ListStaticAddressDepositsResponse)(nil), // 75: looprpc.ListStaticAddressDepositsResponse - (*ListStaticAddressWithdrawalRequest)(nil), // 76: looprpc.ListStaticAddressWithdrawalRequest - (*ListStaticAddressWithdrawalResponse)(nil), // 77: looprpc.ListStaticAddressWithdrawalResponse - (*ListStaticAddressSwapsRequest)(nil), // 78: looprpc.ListStaticAddressSwapsRequest - (*ListStaticAddressSwapsResponse)(nil), // 79: looprpc.ListStaticAddressSwapsResponse - (*StaticAddressSummaryRequest)(nil), // 80: looprpc.StaticAddressSummaryRequest - (*StaticAddressSummaryResponse)(nil), // 81: looprpc.StaticAddressSummaryResponse - (*Deposit)(nil), // 82: looprpc.Deposit - (*StaticAddressWithdrawal)(nil), // 83: looprpc.StaticAddressWithdrawal - (*StaticAddressLoopInSwap)(nil), // 84: looprpc.StaticAddressLoopInSwap - (*StaticAddressLoopInRequest)(nil), // 85: looprpc.StaticAddressLoopInRequest - (*StaticAddressLoopInResponse)(nil), // 86: looprpc.StaticAddressLoopInResponse - (*AssetLoopOutRequest)(nil), // 87: looprpc.AssetLoopOutRequest - (*AssetRfqInfo)(nil), // 88: looprpc.AssetRfqInfo - (*FixedPoint)(nil), // 89: looprpc.FixedPoint - (*AssetLoopOutInfo)(nil), // 90: looprpc.AssetLoopOutInfo - (*StatelessRecovery)(nil), // 91: looprpc.StatelessRecovery - (*CooperativeSweep)(nil), // 92: looprpc.CooperativeSweep - nil, // 93: looprpc.LiquidityParameters.EasyAssetParamsEntry - (*lnrpc.OpenChannelRequest)(nil), // 94: lnrpc.OpenChannelRequest - (*swapserverrpc.RouteHint)(nil), // 95: looprpc.RouteHint - (*lnrpc.SendCoinsRequest)(nil), // 96: lnrpc.SendCoinsRequest - (*lnrpc.SendCoinsResponse)(nil), // 97: lnrpc.SendCoinsResponse - (*lnrpc.OutPoint)(nil), // 98: lnrpc.OutPoint + (*UpdateStaticAddressLabelRequest)(nil), // 69: looprpc.UpdateStaticAddressLabelRequest + (*UpdateStaticAddressLabelResponse)(nil), // 70: looprpc.UpdateStaticAddressLabelResponse + (*ListUnspentDepositsRequest)(nil), // 71: looprpc.ListUnspentDepositsRequest + (*ListUnspentDepositsResponse)(nil), // 72: looprpc.ListUnspentDepositsResponse + (*Utxo)(nil), // 73: looprpc.Utxo + (*WithdrawDepositsRequest)(nil), // 74: looprpc.WithdrawDepositsRequest + (*WithdrawDepositsResponse)(nil), // 75: looprpc.WithdrawDepositsResponse + (*ListStaticAddressDepositsRequest)(nil), // 76: looprpc.ListStaticAddressDepositsRequest + (*ListStaticAddressDepositsResponse)(nil), // 77: looprpc.ListStaticAddressDepositsResponse + (*ListStaticAddressWithdrawalRequest)(nil), // 78: looprpc.ListStaticAddressWithdrawalRequest + (*ListStaticAddressWithdrawalResponse)(nil), // 79: looprpc.ListStaticAddressWithdrawalResponse + (*ListStaticAddressSwapsRequest)(nil), // 80: looprpc.ListStaticAddressSwapsRequest + (*ListStaticAddressSwapsResponse)(nil), // 81: looprpc.ListStaticAddressSwapsResponse + (*StaticAddressSummaryRequest)(nil), // 82: looprpc.StaticAddressSummaryRequest + (*StaticAddressSummaryResponse)(nil), // 83: looprpc.StaticAddressSummaryResponse + (*Deposit)(nil), // 84: looprpc.Deposit + (*StaticAddressWithdrawal)(nil), // 85: looprpc.StaticAddressWithdrawal + (*StaticAddressLoopInSwap)(nil), // 86: looprpc.StaticAddressLoopInSwap + (*StaticAddressLoopInRequest)(nil), // 87: looprpc.StaticAddressLoopInRequest + (*StaticAddressLoopInResponse)(nil), // 88: looprpc.StaticAddressLoopInResponse + (*AssetLoopOutRequest)(nil), // 89: looprpc.AssetLoopOutRequest + (*AssetRfqInfo)(nil), // 90: looprpc.AssetRfqInfo + (*FixedPoint)(nil), // 91: looprpc.FixedPoint + (*AssetLoopOutInfo)(nil), // 92: looprpc.AssetLoopOutInfo + (*StatelessRecovery)(nil), // 93: looprpc.StatelessRecovery + (*CooperativeSweep)(nil), // 94: looprpc.CooperativeSweep + nil, // 95: looprpc.LiquidityParameters.EasyAssetParamsEntry + (*lnrpc.OpenChannelRequest)(nil), // 96: lnrpc.OpenChannelRequest + (*swapserverrpc.RouteHint)(nil), // 97: looprpc.RouteHint + (*lnrpc.SendCoinsRequest)(nil), // 98: lnrpc.SendCoinsRequest + (*lnrpc.SendCoinsResponse)(nil), // 99: lnrpc.SendCoinsResponse + (*lnrpc.OutPoint)(nil), // 100: lnrpc.OutPoint } var file_client_proto_depIdxs = []int32{ - 94, // 0: looprpc.StaticOpenChannelRequest.open_channel_request:type_name -> lnrpc.OpenChannelRequest - 0, // 1: looprpc.LoopOutRequest.account_addr_type:type_name -> looprpc.AddressType - 87, // 2: looprpc.LoopOutRequest.asset_info:type_name -> looprpc.AssetLoopOutRequest - 88, // 3: looprpc.LoopOutRequest.asset_rfq_info:type_name -> looprpc.AssetRfqInfo - 95, // 4: looprpc.LoopInRequest.route_hints:type_name -> looprpc.RouteHint - 1, // 5: looprpc.SwapStatus.type:type_name -> looprpc.SwapType - 2, // 6: looprpc.SwapStatus.state:type_name -> looprpc.SwapState - 8, // 7: looprpc.SwapStatus.static_loop_in_state:type_name -> looprpc.StaticAddressLoopInSwapState - 3, // 8: looprpc.SwapStatus.failure_reason:type_name -> looprpc.FailureReason - 90, // 9: looprpc.SwapStatus.asset_info:type_name -> looprpc.AssetLoopOutInfo - 20, // 10: looprpc.ListSwapsRequest.list_swap_filter:type_name -> looprpc.ListSwapsFilter - 9, // 11: looprpc.ListSwapsFilter.swap_type:type_name -> looprpc.ListSwapsFilter.SwapTypeFilter - 18, // 12: looprpc.ListSwapsResponse.swaps:type_name -> looprpc.SwapStatus - 91, // 13: looprpc.SweepHtlcRequest.stateless_recovery:type_name -> looprpc.StatelessRecovery - 92, // 14: looprpc.SweepHtlcRequest.cooperative:type_name -> looprpc.CooperativeSweep - 24, // 15: looprpc.SweepHtlcResponse.not_requested:type_name -> looprpc.PublishNotRequested - 25, // 16: looprpc.SweepHtlcResponse.published:type_name -> looprpc.PublishSucceeded - 26, // 17: looprpc.SweepHtlcResponse.failed:type_name -> looprpc.PublishFailed - 95, // 18: looprpc.QuoteRequest.loop_in_route_hints:type_name -> looprpc.RouteHint - 87, // 19: looprpc.QuoteRequest.asset_info:type_name -> looprpc.AssetLoopOutRequest - 88, // 20: looprpc.OutQuoteResponse.asset_rfq_info:type_name -> looprpc.AssetRfqInfo - 95, // 21: looprpc.ProbeRequest.route_hints:type_name -> looprpc.RouteHint - 40, // 22: looprpc.TokensResponse.tokens:type_name -> looprpc.L402Token - 41, // 23: looprpc.GetInfoResponse.loop_out_stats:type_name -> looprpc.LoopStats - 41, // 24: looprpc.GetInfoResponse.loop_in_stats:type_name -> looprpc.LoopStats - 47, // 25: looprpc.LiquidityParameters.rules:type_name -> looprpc.LiquidityRule - 0, // 26: looprpc.LiquidityParameters.account_addr_type:type_name -> looprpc.AddressType - 93, // 27: looprpc.LiquidityParameters.easy_asset_params:type_name -> looprpc.LiquidityParameters.EasyAssetParamsEntry - 4, // 28: looprpc.LiquidityParameters.loop_in_source:type_name -> looprpc.LoopInSource - 1, // 29: looprpc.LiquidityRule.swap_type:type_name -> looprpc.SwapType - 5, // 30: looprpc.LiquidityRule.type:type_name -> looprpc.LiquidityRuleType - 45, // 31: looprpc.SetLiquidityParamsRequest.parameters:type_name -> looprpc.LiquidityParameters - 6, // 32: looprpc.Disqualified.reason:type_name -> looprpc.AutoReason - 14, // 33: looprpc.SuggestSwapsResponse.loop_out:type_name -> looprpc.LoopOutRequest - 15, // 34: looprpc.SuggestSwapsResponse.loop_in:type_name -> looprpc.LoopInRequest - 85, // 35: looprpc.SuggestSwapsResponse.static_loop_in:type_name -> looprpc.StaticAddressLoopInRequest - 51, // 36: looprpc.SuggestSwapsResponse.disqualified:type_name -> looprpc.Disqualified - 57, // 37: looprpc.ListReservationsResponse.reservations:type_name -> looprpc.ClientReservation - 64, // 38: looprpc.ListInstantOutsResponse.swaps:type_name -> looprpc.InstantOut - 96, // 39: looprpc.FundStaticAddressRequest.send_coins_request:type_name -> lnrpc.SendCoinsRequest - 97, // 40: looprpc.FundStaticAddressResponse.send_coins_response:type_name -> lnrpc.SendCoinsResponse - 71, // 41: looprpc.ListUnspentDepositsResponse.utxos:type_name -> looprpc.Utxo - 98, // 42: looprpc.WithdrawDepositsRequest.outpoints:type_name -> lnrpc.OutPoint - 7, // 43: looprpc.ListStaticAddressDepositsRequest.state_filter:type_name -> looprpc.DepositState - 82, // 44: looprpc.ListStaticAddressDepositsResponse.filtered_deposits:type_name -> looprpc.Deposit - 83, // 45: looprpc.ListStaticAddressWithdrawalResponse.withdrawals:type_name -> looprpc.StaticAddressWithdrawal - 84, // 46: looprpc.ListStaticAddressSwapsResponse.swaps:type_name -> looprpc.StaticAddressLoopInSwap - 7, // 47: looprpc.Deposit.state:type_name -> looprpc.DepositState - 82, // 48: looprpc.StaticAddressWithdrawal.deposits:type_name -> looprpc.Deposit - 8, // 49: looprpc.StaticAddressLoopInSwap.state:type_name -> looprpc.StaticAddressLoopInSwapState - 82, // 50: looprpc.StaticAddressLoopInSwap.deposits:type_name -> looprpc.Deposit - 95, // 51: looprpc.StaticAddressLoopInRequest.route_hints:type_name -> looprpc.RouteHint - 82, // 52: looprpc.StaticAddressLoopInResponse.used_deposits:type_name -> looprpc.Deposit - 89, // 53: looprpc.AssetRfqInfo.prepay_asset_rate:type_name -> looprpc.FixedPoint - 89, // 54: looprpc.AssetRfqInfo.swap_asset_rate:type_name -> looprpc.FixedPoint - 46, // 55: looprpc.LiquidityParameters.EasyAssetParamsEntry.value:type_name -> looprpc.EasyAssetAutoloopParams - 14, // 56: looprpc.SwapClient.LoopOut:input_type -> looprpc.LoopOutRequest - 15, // 57: looprpc.SwapClient.LoopIn:input_type -> looprpc.LoopInRequest - 17, // 58: looprpc.SwapClient.Monitor:input_type -> looprpc.MonitorRequest - 19, // 59: looprpc.SwapClient.ListSwaps:input_type -> looprpc.ListSwapsRequest - 22, // 60: looprpc.SwapClient.SweepHtlc:input_type -> looprpc.SweepHtlcRequest - 27, // 61: looprpc.SwapClient.SwapInfo:input_type -> looprpc.SwapInfoRequest - 53, // 62: looprpc.SwapClient.AbandonSwap:input_type -> looprpc.AbandonSwapRequest - 28, // 63: looprpc.SwapClient.LoopOutTerms:input_type -> looprpc.TermsRequest - 31, // 64: looprpc.SwapClient.LoopOutQuote:input_type -> looprpc.QuoteRequest - 28, // 65: looprpc.SwapClient.GetLoopInTerms:input_type -> looprpc.TermsRequest - 31, // 66: looprpc.SwapClient.GetLoopInQuote:input_type -> looprpc.QuoteRequest - 34, // 67: looprpc.SwapClient.Probe:input_type -> looprpc.ProbeRequest - 36, // 68: looprpc.SwapClient.GetL402Tokens:input_type -> looprpc.TokensRequest - 36, // 69: looprpc.SwapClient.GetLsatTokens:input_type -> looprpc.TokensRequest - 38, // 70: looprpc.SwapClient.FetchL402Token:input_type -> looprpc.FetchL402TokenRequest - 42, // 71: looprpc.SwapClient.GetInfo:input_type -> looprpc.GetInfoRequest - 12, // 72: looprpc.SwapClient.StopDaemon:input_type -> looprpc.StopDaemonRequest - 44, // 73: looprpc.SwapClient.GetLiquidityParams:input_type -> looprpc.GetLiquidityParamsRequest - 48, // 74: looprpc.SwapClient.SetLiquidityParams:input_type -> looprpc.SetLiquidityParamsRequest - 50, // 75: looprpc.SwapClient.SuggestSwaps:input_type -> looprpc.SuggestSwapsRequest - 55, // 76: looprpc.SwapClient.ListReservations:input_type -> looprpc.ListReservationsRequest - 58, // 77: looprpc.SwapClient.InstantOut:input_type -> looprpc.InstantOutRequest - 60, // 78: looprpc.SwapClient.InstantOutQuote:input_type -> looprpc.InstantOutQuoteRequest - 62, // 79: looprpc.SwapClient.ListInstantOuts:input_type -> looprpc.ListInstantOutsRequest - 65, // 80: looprpc.SwapClient.NewStaticAddress:input_type -> looprpc.NewStaticAddressRequest - 67, // 81: looprpc.SwapClient.FundStaticAddress:input_type -> looprpc.FundStaticAddressRequest - 69, // 82: looprpc.SwapClient.ListUnspentDeposits:input_type -> looprpc.ListUnspentDepositsRequest - 72, // 83: looprpc.SwapClient.WithdrawDeposits:input_type -> looprpc.WithdrawDepositsRequest - 74, // 84: looprpc.SwapClient.ListStaticAddressDeposits:input_type -> looprpc.ListStaticAddressDepositsRequest - 76, // 85: looprpc.SwapClient.ListStaticAddressWithdrawals:input_type -> looprpc.ListStaticAddressWithdrawalRequest - 78, // 86: looprpc.SwapClient.ListStaticAddressSwaps:input_type -> looprpc.ListStaticAddressSwapsRequest - 80, // 87: looprpc.SwapClient.GetStaticAddressSummary:input_type -> looprpc.StaticAddressSummaryRequest - 85, // 88: looprpc.SwapClient.StaticAddressLoopIn:input_type -> looprpc.StaticAddressLoopInRequest - 10, // 89: looprpc.SwapClient.StaticOpenChannel:input_type -> looprpc.StaticOpenChannelRequest - 16, // 90: looprpc.SwapClient.LoopOut:output_type -> looprpc.SwapResponse - 16, // 91: looprpc.SwapClient.LoopIn:output_type -> looprpc.SwapResponse - 18, // 92: looprpc.SwapClient.Monitor:output_type -> looprpc.SwapStatus - 21, // 93: looprpc.SwapClient.ListSwaps:output_type -> looprpc.ListSwapsResponse - 23, // 94: looprpc.SwapClient.SweepHtlc:output_type -> looprpc.SweepHtlcResponse - 18, // 95: looprpc.SwapClient.SwapInfo:output_type -> looprpc.SwapStatus - 54, // 96: looprpc.SwapClient.AbandonSwap:output_type -> looprpc.AbandonSwapResponse - 30, // 97: looprpc.SwapClient.LoopOutTerms:output_type -> looprpc.OutTermsResponse - 33, // 98: looprpc.SwapClient.LoopOutQuote:output_type -> looprpc.OutQuoteResponse - 29, // 99: looprpc.SwapClient.GetLoopInTerms:output_type -> looprpc.InTermsResponse - 32, // 100: looprpc.SwapClient.GetLoopInQuote:output_type -> looprpc.InQuoteResponse - 35, // 101: looprpc.SwapClient.Probe:output_type -> looprpc.ProbeResponse - 37, // 102: looprpc.SwapClient.GetL402Tokens:output_type -> looprpc.TokensResponse - 37, // 103: looprpc.SwapClient.GetLsatTokens:output_type -> looprpc.TokensResponse - 39, // 104: looprpc.SwapClient.FetchL402Token:output_type -> looprpc.FetchL402TokenResponse - 43, // 105: looprpc.SwapClient.GetInfo:output_type -> looprpc.GetInfoResponse - 13, // 106: looprpc.SwapClient.StopDaemon:output_type -> looprpc.StopDaemonResponse - 45, // 107: looprpc.SwapClient.GetLiquidityParams:output_type -> looprpc.LiquidityParameters - 49, // 108: looprpc.SwapClient.SetLiquidityParams:output_type -> looprpc.SetLiquidityParamsResponse - 52, // 109: looprpc.SwapClient.SuggestSwaps:output_type -> looprpc.SuggestSwapsResponse - 56, // 110: looprpc.SwapClient.ListReservations:output_type -> looprpc.ListReservationsResponse - 59, // 111: looprpc.SwapClient.InstantOut:output_type -> looprpc.InstantOutResponse - 61, // 112: looprpc.SwapClient.InstantOutQuote:output_type -> looprpc.InstantOutQuoteResponse - 63, // 113: looprpc.SwapClient.ListInstantOuts:output_type -> looprpc.ListInstantOutsResponse - 66, // 114: looprpc.SwapClient.NewStaticAddress:output_type -> looprpc.NewStaticAddressResponse - 68, // 115: looprpc.SwapClient.FundStaticAddress:output_type -> looprpc.FundStaticAddressResponse - 70, // 116: looprpc.SwapClient.ListUnspentDeposits:output_type -> looprpc.ListUnspentDepositsResponse - 73, // 117: looprpc.SwapClient.WithdrawDeposits:output_type -> looprpc.WithdrawDepositsResponse - 75, // 118: looprpc.SwapClient.ListStaticAddressDeposits:output_type -> looprpc.ListStaticAddressDepositsResponse - 77, // 119: looprpc.SwapClient.ListStaticAddressWithdrawals:output_type -> looprpc.ListStaticAddressWithdrawalResponse - 79, // 120: looprpc.SwapClient.ListStaticAddressSwaps:output_type -> looprpc.ListStaticAddressSwapsResponse - 81, // 121: looprpc.SwapClient.GetStaticAddressSummary:output_type -> looprpc.StaticAddressSummaryResponse - 86, // 122: looprpc.SwapClient.StaticAddressLoopIn:output_type -> looprpc.StaticAddressLoopInResponse - 11, // 123: looprpc.SwapClient.StaticOpenChannel:output_type -> looprpc.StaticOpenChannelResponse - 90, // [90:124] is the sub-list for method output_type - 56, // [56:90] is the sub-list for method input_type - 56, // [56:56] is the sub-list for extension type_name - 56, // [56:56] is the sub-list for extension extendee - 0, // [0:56] is the sub-list for field type_name + 96, // 0: looprpc.StaticOpenChannelRequest.open_channel_request:type_name -> lnrpc.OpenChannelRequest + 0, // 1: looprpc.LoopOutRequest.account_addr_type:type_name -> looprpc.AddressType + 89, // 2: looprpc.LoopOutRequest.asset_info:type_name -> looprpc.AssetLoopOutRequest + 90, // 3: looprpc.LoopOutRequest.asset_rfq_info:type_name -> looprpc.AssetRfqInfo + 97, // 4: looprpc.LoopInRequest.route_hints:type_name -> looprpc.RouteHint + 1, // 5: looprpc.SwapStatus.type:type_name -> looprpc.SwapType + 2, // 6: looprpc.SwapStatus.state:type_name -> looprpc.SwapState + 8, // 7: looprpc.SwapStatus.static_loop_in_state:type_name -> looprpc.StaticAddressLoopInSwapState + 3, // 8: looprpc.SwapStatus.failure_reason:type_name -> looprpc.FailureReason + 92, // 9: looprpc.SwapStatus.asset_info:type_name -> looprpc.AssetLoopOutInfo + 20, // 10: looprpc.ListSwapsRequest.list_swap_filter:type_name -> looprpc.ListSwapsFilter + 9, // 11: looprpc.ListSwapsFilter.swap_type:type_name -> looprpc.ListSwapsFilter.SwapTypeFilter + 18, // 12: looprpc.ListSwapsResponse.swaps:type_name -> looprpc.SwapStatus + 93, // 13: looprpc.SweepHtlcRequest.stateless_recovery:type_name -> looprpc.StatelessRecovery + 94, // 14: looprpc.SweepHtlcRequest.cooperative:type_name -> looprpc.CooperativeSweep + 24, // 15: looprpc.SweepHtlcResponse.not_requested:type_name -> looprpc.PublishNotRequested + 25, // 16: looprpc.SweepHtlcResponse.published:type_name -> looprpc.PublishSucceeded + 26, // 17: looprpc.SweepHtlcResponse.failed:type_name -> looprpc.PublishFailed + 97, // 18: looprpc.QuoteRequest.loop_in_route_hints:type_name -> looprpc.RouteHint + 89, // 19: looprpc.QuoteRequest.asset_info:type_name -> looprpc.AssetLoopOutRequest + 90, // 20: looprpc.OutQuoteResponse.asset_rfq_info:type_name -> looprpc.AssetRfqInfo + 97, // 21: looprpc.ProbeRequest.route_hints:type_name -> looprpc.RouteHint + 40, // 22: looprpc.TokensResponse.tokens:type_name -> looprpc.L402Token + 41, // 23: looprpc.GetInfoResponse.loop_out_stats:type_name -> looprpc.LoopStats + 41, // 24: looprpc.GetInfoResponse.loop_in_stats:type_name -> looprpc.LoopStats + 47, // 25: looprpc.LiquidityParameters.rules:type_name -> looprpc.LiquidityRule + 0, // 26: looprpc.LiquidityParameters.account_addr_type:type_name -> looprpc.AddressType + 95, // 27: looprpc.LiquidityParameters.easy_asset_params:type_name -> looprpc.LiquidityParameters.EasyAssetParamsEntry + 4, // 28: looprpc.LiquidityParameters.loop_in_source:type_name -> looprpc.LoopInSource + 1, // 29: looprpc.LiquidityRule.swap_type:type_name -> looprpc.SwapType + 5, // 30: looprpc.LiquidityRule.type:type_name -> looprpc.LiquidityRuleType + 45, // 31: looprpc.SetLiquidityParamsRequest.parameters:type_name -> looprpc.LiquidityParameters + 6, // 32: looprpc.Disqualified.reason:type_name -> looprpc.AutoReason + 14, // 33: looprpc.SuggestSwapsResponse.loop_out:type_name -> looprpc.LoopOutRequest + 15, // 34: looprpc.SuggestSwapsResponse.loop_in:type_name -> looprpc.LoopInRequest + 87, // 35: looprpc.SuggestSwapsResponse.static_loop_in:type_name -> looprpc.StaticAddressLoopInRequest + 51, // 36: looprpc.SuggestSwapsResponse.disqualified:type_name -> looprpc.Disqualified + 57, // 37: looprpc.ListReservationsResponse.reservations:type_name -> looprpc.ClientReservation + 64, // 38: looprpc.ListInstantOutsResponse.swaps:type_name -> looprpc.InstantOut + 98, // 39: looprpc.FundStaticAddressRequest.send_coins_request:type_name -> lnrpc.SendCoinsRequest + 99, // 40: looprpc.FundStaticAddressResponse.send_coins_response:type_name -> lnrpc.SendCoinsResponse + 73, // 41: looprpc.ListUnspentDepositsResponse.utxos:type_name -> looprpc.Utxo + 100, // 42: looprpc.WithdrawDepositsRequest.outpoints:type_name -> lnrpc.OutPoint + 7, // 43: looprpc.ListStaticAddressDepositsRequest.state_filter:type_name -> looprpc.DepositState + 84, // 44: looprpc.ListStaticAddressDepositsResponse.filtered_deposits:type_name -> looprpc.Deposit + 85, // 45: looprpc.ListStaticAddressWithdrawalResponse.withdrawals:type_name -> looprpc.StaticAddressWithdrawal + 86, // 46: looprpc.ListStaticAddressSwapsResponse.swaps:type_name -> looprpc.StaticAddressLoopInSwap + 7, // 47: looprpc.Deposit.state:type_name -> looprpc.DepositState + 84, // 48: looprpc.StaticAddressWithdrawal.deposits:type_name -> looprpc.Deposit + 8, // 49: looprpc.StaticAddressLoopInSwap.state:type_name -> looprpc.StaticAddressLoopInSwapState + 84, // 50: looprpc.StaticAddressLoopInSwap.deposits:type_name -> looprpc.Deposit + 97, // 51: looprpc.StaticAddressLoopInRequest.route_hints:type_name -> looprpc.RouteHint + 84, // 52: looprpc.StaticAddressLoopInResponse.used_deposits:type_name -> looprpc.Deposit + 91, // 53: looprpc.AssetRfqInfo.prepay_asset_rate:type_name -> looprpc.FixedPoint + 91, // 54: looprpc.AssetRfqInfo.swap_asset_rate:type_name -> looprpc.FixedPoint + 46, // 55: looprpc.LiquidityParameters.EasyAssetParamsEntry.value:type_name -> looprpc.EasyAssetAutoloopParams + 14, // 56: looprpc.SwapClient.LoopOut:input_type -> looprpc.LoopOutRequest + 15, // 57: looprpc.SwapClient.LoopIn:input_type -> looprpc.LoopInRequest + 17, // 58: looprpc.SwapClient.Monitor:input_type -> looprpc.MonitorRequest + 19, // 59: looprpc.SwapClient.ListSwaps:input_type -> looprpc.ListSwapsRequest + 22, // 60: looprpc.SwapClient.SweepHtlc:input_type -> looprpc.SweepHtlcRequest + 27, // 61: looprpc.SwapClient.SwapInfo:input_type -> looprpc.SwapInfoRequest + 53, // 62: looprpc.SwapClient.AbandonSwap:input_type -> looprpc.AbandonSwapRequest + 28, // 63: looprpc.SwapClient.LoopOutTerms:input_type -> looprpc.TermsRequest + 31, // 64: looprpc.SwapClient.LoopOutQuote:input_type -> looprpc.QuoteRequest + 28, // 65: looprpc.SwapClient.GetLoopInTerms:input_type -> looprpc.TermsRequest + 31, // 66: looprpc.SwapClient.GetLoopInQuote:input_type -> looprpc.QuoteRequest + 34, // 67: looprpc.SwapClient.Probe:input_type -> looprpc.ProbeRequest + 36, // 68: looprpc.SwapClient.GetL402Tokens:input_type -> looprpc.TokensRequest + 36, // 69: looprpc.SwapClient.GetLsatTokens:input_type -> looprpc.TokensRequest + 38, // 70: looprpc.SwapClient.FetchL402Token:input_type -> looprpc.FetchL402TokenRequest + 42, // 71: looprpc.SwapClient.GetInfo:input_type -> looprpc.GetInfoRequest + 12, // 72: looprpc.SwapClient.StopDaemon:input_type -> looprpc.StopDaemonRequest + 44, // 73: looprpc.SwapClient.GetLiquidityParams:input_type -> looprpc.GetLiquidityParamsRequest + 48, // 74: looprpc.SwapClient.SetLiquidityParams:input_type -> looprpc.SetLiquidityParamsRequest + 50, // 75: looprpc.SwapClient.SuggestSwaps:input_type -> looprpc.SuggestSwapsRequest + 55, // 76: looprpc.SwapClient.ListReservations:input_type -> looprpc.ListReservationsRequest + 58, // 77: looprpc.SwapClient.InstantOut:input_type -> looprpc.InstantOutRequest + 60, // 78: looprpc.SwapClient.InstantOutQuote:input_type -> looprpc.InstantOutQuoteRequest + 62, // 79: looprpc.SwapClient.ListInstantOuts:input_type -> looprpc.ListInstantOutsRequest + 65, // 80: looprpc.SwapClient.NewStaticAddress:input_type -> looprpc.NewStaticAddressRequest + 67, // 81: looprpc.SwapClient.FundStaticAddress:input_type -> looprpc.FundStaticAddressRequest + 69, // 82: looprpc.SwapClient.UpdateStaticAddressLabel:input_type -> looprpc.UpdateStaticAddressLabelRequest + 71, // 83: looprpc.SwapClient.ListUnspentDeposits:input_type -> looprpc.ListUnspentDepositsRequest + 74, // 84: looprpc.SwapClient.WithdrawDeposits:input_type -> looprpc.WithdrawDepositsRequest + 76, // 85: looprpc.SwapClient.ListStaticAddressDeposits:input_type -> looprpc.ListStaticAddressDepositsRequest + 78, // 86: looprpc.SwapClient.ListStaticAddressWithdrawals:input_type -> looprpc.ListStaticAddressWithdrawalRequest + 80, // 87: looprpc.SwapClient.ListStaticAddressSwaps:input_type -> looprpc.ListStaticAddressSwapsRequest + 82, // 88: looprpc.SwapClient.GetStaticAddressSummary:input_type -> looprpc.StaticAddressSummaryRequest + 87, // 89: looprpc.SwapClient.StaticAddressLoopIn:input_type -> looprpc.StaticAddressLoopInRequest + 10, // 90: looprpc.SwapClient.StaticOpenChannel:input_type -> looprpc.StaticOpenChannelRequest + 16, // 91: looprpc.SwapClient.LoopOut:output_type -> looprpc.SwapResponse + 16, // 92: looprpc.SwapClient.LoopIn:output_type -> looprpc.SwapResponse + 18, // 93: looprpc.SwapClient.Monitor:output_type -> looprpc.SwapStatus + 21, // 94: looprpc.SwapClient.ListSwaps:output_type -> looprpc.ListSwapsResponse + 23, // 95: looprpc.SwapClient.SweepHtlc:output_type -> looprpc.SweepHtlcResponse + 18, // 96: looprpc.SwapClient.SwapInfo:output_type -> looprpc.SwapStatus + 54, // 97: looprpc.SwapClient.AbandonSwap:output_type -> looprpc.AbandonSwapResponse + 30, // 98: looprpc.SwapClient.LoopOutTerms:output_type -> looprpc.OutTermsResponse + 33, // 99: looprpc.SwapClient.LoopOutQuote:output_type -> looprpc.OutQuoteResponse + 29, // 100: looprpc.SwapClient.GetLoopInTerms:output_type -> looprpc.InTermsResponse + 32, // 101: looprpc.SwapClient.GetLoopInQuote:output_type -> looprpc.InQuoteResponse + 35, // 102: looprpc.SwapClient.Probe:output_type -> looprpc.ProbeResponse + 37, // 103: looprpc.SwapClient.GetL402Tokens:output_type -> looprpc.TokensResponse + 37, // 104: looprpc.SwapClient.GetLsatTokens:output_type -> looprpc.TokensResponse + 39, // 105: looprpc.SwapClient.FetchL402Token:output_type -> looprpc.FetchL402TokenResponse + 43, // 106: looprpc.SwapClient.GetInfo:output_type -> looprpc.GetInfoResponse + 13, // 107: looprpc.SwapClient.StopDaemon:output_type -> looprpc.StopDaemonResponse + 45, // 108: looprpc.SwapClient.GetLiquidityParams:output_type -> looprpc.LiquidityParameters + 49, // 109: looprpc.SwapClient.SetLiquidityParams:output_type -> looprpc.SetLiquidityParamsResponse + 52, // 110: looprpc.SwapClient.SuggestSwaps:output_type -> looprpc.SuggestSwapsResponse + 56, // 111: looprpc.SwapClient.ListReservations:output_type -> looprpc.ListReservationsResponse + 59, // 112: looprpc.SwapClient.InstantOut:output_type -> looprpc.InstantOutResponse + 61, // 113: looprpc.SwapClient.InstantOutQuote:output_type -> looprpc.InstantOutQuoteResponse + 63, // 114: looprpc.SwapClient.ListInstantOuts:output_type -> looprpc.ListInstantOutsResponse + 66, // 115: looprpc.SwapClient.NewStaticAddress:output_type -> looprpc.NewStaticAddressResponse + 68, // 116: looprpc.SwapClient.FundStaticAddress:output_type -> looprpc.FundStaticAddressResponse + 70, // 117: looprpc.SwapClient.UpdateStaticAddressLabel:output_type -> looprpc.UpdateStaticAddressLabelResponse + 72, // 118: looprpc.SwapClient.ListUnspentDeposits:output_type -> looprpc.ListUnspentDepositsResponse + 75, // 119: looprpc.SwapClient.WithdrawDeposits:output_type -> looprpc.WithdrawDepositsResponse + 77, // 120: looprpc.SwapClient.ListStaticAddressDeposits:output_type -> looprpc.ListStaticAddressDepositsResponse + 79, // 121: looprpc.SwapClient.ListStaticAddressWithdrawals:output_type -> looprpc.ListStaticAddressWithdrawalResponse + 81, // 122: looprpc.SwapClient.ListStaticAddressSwaps:output_type -> looprpc.ListStaticAddressSwapsResponse + 83, // 123: looprpc.SwapClient.GetStaticAddressSummary:output_type -> looprpc.StaticAddressSummaryResponse + 88, // 124: looprpc.SwapClient.StaticAddressLoopIn:output_type -> looprpc.StaticAddressLoopInResponse + 11, // 125: looprpc.SwapClient.StaticOpenChannel:output_type -> looprpc.StaticOpenChannelResponse + 91, // [91:126] is the sub-list for method output_type + 56, // [56:91] is the sub-list for method input_type + 56, // [56:56] is the sub-list for extension type_name + 56, // [56:56] is the sub-list for extension extendee + 0, // [0:56] is the sub-list for field type_name } func init() { file_client_proto_init() } @@ -7847,7 +8020,7 @@ func file_client_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_client_proto_rawDesc), len(file_client_proto_rawDesc)), NumEnums: 10, - NumMessages: 84, + NumMessages: 86, NumExtensions: 0, NumServices: 1, }, diff --git a/looprpc/client.pb.gw.go b/looprpc/client.pb.gw.go index 68783166c..c89bba864 100644 --- a/looprpc/client.pb.gw.go +++ b/looprpc/client.pb.gw.go @@ -694,6 +694,33 @@ func local_request_SwapClient_FundStaticAddress_0(ctx context.Context, marshaler return msg, metadata, err } +func request_SwapClient_UpdateStaticAddressLabel_0(ctx context.Context, marshaler runtime.Marshaler, client SwapClientClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq UpdateStaticAddressLabelRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.UpdateStaticAddressLabel(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_SwapClient_UpdateStaticAddressLabel_0(ctx context.Context, marshaler runtime.Marshaler, server SwapClientServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq UpdateStaticAddressLabelRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.UpdateStaticAddressLabel(ctx, &protoReq) + return msg, metadata, err +} + var filter_SwapClient_ListUnspentDeposits_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} func request_SwapClient_ListUnspentDeposits_0(ctx context.Context, marshaler runtime.Marshaler, client SwapClientClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { @@ -1347,6 +1374,26 @@ func RegisterSwapClientHandlerServer(ctx context.Context, mux *runtime.ServeMux, } forward_SwapClient_FundStaticAddress_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodPost, pattern_SwapClient_UpdateStaticAddressLabel_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/looprpc.SwapClient/UpdateStaticAddressLabel", runtime.WithHTTPPathPattern("/v1/staticaddr/label")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_SwapClient_UpdateStaticAddressLabel_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_SwapClient_UpdateStaticAddressLabel_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodGet, pattern_SwapClient_ListUnspentDeposits_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1918,6 +1965,23 @@ func RegisterSwapClientHandlerClient(ctx context.Context, mux *runtime.ServeMux, } forward_SwapClient_FundStaticAddress_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodPost, pattern_SwapClient_UpdateStaticAddressLabel_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/looprpc.SwapClient/UpdateStaticAddressLabel", runtime.WithHTTPPathPattern("/v1/staticaddr/label")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_SwapClient_UpdateStaticAddressLabel_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_SwapClient_UpdateStaticAddressLabel_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodGet, pattern_SwapClient_ListUnspentDeposits_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -2064,6 +2128,7 @@ var ( pattern_SwapClient_ListInstantOuts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "instantout", "swaps"}, "")) pattern_SwapClient_NewStaticAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "staticaddr"}, "")) pattern_SwapClient_FundStaticAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "staticaddr", "fund"}, "")) + pattern_SwapClient_UpdateStaticAddressLabel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "staticaddr", "label"}, "")) pattern_SwapClient_ListUnspentDeposits_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "staticaddr", "deposits", "unspent"}, "")) pattern_SwapClient_WithdrawDeposits_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "staticaddr", "withdraw"}, "")) pattern_SwapClient_ListStaticAddressDeposits_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "staticaddr", "deposits"}, "")) @@ -2097,6 +2162,7 @@ var ( forward_SwapClient_ListInstantOuts_0 = runtime.ForwardResponseMessage forward_SwapClient_NewStaticAddress_0 = runtime.ForwardResponseMessage forward_SwapClient_FundStaticAddress_0 = runtime.ForwardResponseMessage + forward_SwapClient_UpdateStaticAddressLabel_0 = runtime.ForwardResponseMessage forward_SwapClient_ListUnspentDeposits_0 = runtime.ForwardResponseMessage forward_SwapClient_WithdrawDeposits_0 = runtime.ForwardResponseMessage forward_SwapClient_ListStaticAddressDeposits_0 = runtime.ForwardResponseMessage diff --git a/looprpc/client.proto b/looprpc/client.proto index db6622846..41f087346 100644 --- a/looprpc/client.proto +++ b/looprpc/client.proto @@ -177,6 +177,12 @@ service SwapClient { rpc FundStaticAddress (FundStaticAddressRequest) returns (FundStaticAddressResponse); + /* loop: `static updatelabel` + UpdateStaticAddressLabel updates the local label for a static address. + */ + rpc UpdateStaticAddressLabel (UpdateStaticAddressLabelRequest) + returns (UpdateStaticAddressLabelResponse); + /* loop: `static listunspentdeposits` ListUnspentDeposits returns a list of utxos deposited at a static address. */ @@ -1808,6 +1814,11 @@ message NewStaticAddressRequest { // Reserved for the funding field from the unreleased combined RPC. reserved 2; reserved "send_coins_request"; + + /* + An optional label for this static address. Empty string means no label. + */ + string label = 3; } message NewStaticAddressResponse { @@ -1820,6 +1831,11 @@ message NewStaticAddressResponse { // Reserved for the funding field from the unreleased combined RPC. reserved 3; reserved "send_coins_response"; + + /* + The label for this static address. Empty string means no label. + */ + string label = 4; } message FundStaticAddressRequest { @@ -1843,6 +1859,30 @@ message FundStaticAddressResponse { lnrpc.SendCoinsResponse send_coins_response = 3; } +message UpdateStaticAddressLabelRequest { + /* + The static address whose label should be updated. + */ + string static_address = 1; + + /* + The updated label for the static address. Empty string means no label. + */ + string label = 2; +} + +message UpdateStaticAddressLabelResponse { + /* + The static address whose label was updated. + */ + string static_address = 1; + + /* + The updated label for the static address. Empty string means no label. + */ + string label = 2; +} + message ListUnspentDepositsRequest { /* The number of minimum confirmations a utxo must have to be listed. @@ -1883,6 +1923,12 @@ message Utxo { The number of confirmations for the Utxo. */ int64 confirmations = 4; + + /* + The local label of the static address that owns this Utxo. Empty string + means no label. + */ + string address_label = 5; } message WithdrawDepositsRequest { @@ -2147,6 +2193,18 @@ message Deposit { The static address that the deposit was sent to. */ string static_address = 8; + + /* + The local label of the static address that the deposit was sent to. Empty + string means no label. + */ + string address_label = 9; + + /* + The lnd wallet label of the transaction that funded the deposit. Empty + string means no label, or that the label could not be looked up in lnd. + */ + string funding_tx_label = 10; } message StaticAddressWithdrawal { diff --git a/looprpc/client.swagger.json b/looprpc/client.swagger.json index 63a429643..059c8d599 100644 --- a/looprpc/client.swagger.json +++ b/looprpc/client.swagger.json @@ -1034,6 +1034,39 @@ ] } }, + "/v1/staticaddr/label": { + "post": { + "summary": "loop: `static updatelabel`\nUpdateStaticAddressLabel updates the local label for a static address.", + "operationId": "SwapClient_UpdateStaticAddressLabel", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/looprpcUpdateStaticAddressLabelResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/looprpcUpdateStaticAddressLabelRequest" + } + } + ], + "tags": [ + "SwapClient" + ] + } + }, "/v1/staticaddr/loopin": { "post": { "summary": "loop:`static in`\nStaticAddressLoopIn initiates a static address loop-in swap.", @@ -1473,6 +1506,14 @@ "static_address": { "type": "string", "description": "The static address that the deposit was sent to." + }, + "address_label": { + "type": "string", + "description": "The local label of the static address that the deposit was sent to. Empty\nstring means no label." + }, + "funding_tx_label": { + "type": "string", + "description": "The lnd wallet label of the transaction that funded the deposit. Empty\nstring means no label, or that the label could not be looked up in lnd." } } }, @@ -2397,6 +2438,10 @@ "type": "string", "format": "byte", "description": "The client's public key for the 2-of-2 MuSig2 taproot static address." + }, + "label": { + "type": "string", + "description": "An optional label for this static address. Empty string means no label." } } }, @@ -2411,6 +2456,10 @@ "type": "integer", "format": "int64", "description": "The CSV expiry of the static address in blocks." + }, + "label": { + "type": "string", + "description": "The label for this static address. Empty string means no label." } } }, @@ -3123,6 +3172,32 @@ } } }, + "looprpcUpdateStaticAddressLabelRequest": { + "type": "object", + "properties": { + "static_address": { + "type": "string", + "description": "The static address whose label should be updated." + }, + "label": { + "type": "string", + "description": "The updated label for the static address. Empty string means no label." + } + } + }, + "looprpcUpdateStaticAddressLabelResponse": { + "type": "object", + "properties": { + "static_address": { + "type": "string", + "description": "The static address whose label was updated." + }, + "label": { + "type": "string", + "description": "The updated label for the static address. Empty string means no label." + } + } + }, "looprpcUtxo": { "type": "object", "properties": { @@ -3143,6 +3218,10 @@ "type": "string", "format": "int64", "description": "The number of confirmations for the Utxo." + }, + "address_label": { + "type": "string", + "description": "The local label of the static address that owns this Utxo. Empty string\nmeans no label." } } }, diff --git a/looprpc/client.yaml b/looprpc/client.yaml index 09132eabe..265f27732 100644 --- a/looprpc/client.yaml +++ b/looprpc/client.yaml @@ -56,6 +56,9 @@ http: - selector: looprpc.SwapClient.FundStaticAddress post: "/v1/staticaddr/fund" body: "*" + - selector: looprpc.SwapClient.UpdateStaticAddressLabel + post: "/v1/staticaddr/label" + body: "*" - selector: looprpc.SwapClient.ListUnspentDeposits get: "/v1/staticaddr/deposits/unspent" - selector: looprpc.SwapClient.WithdrawDeposits diff --git a/looprpc/client_grpc.pb.go b/looprpc/client_grpc.pb.go index 9df094f39..65b648b78 100644 --- a/looprpc/client_grpc.pb.go +++ b/looprpc/client_grpc.pb.go @@ -122,6 +122,9 @@ type SwapClientClient interface { // wallet. Requires wallet:fund in addition to swap:execute and loop:in, or an // explicit URI permission for this RPC. FundStaticAddress(ctx context.Context, in *FundStaticAddressRequest, opts ...grpc.CallOption) (*FundStaticAddressResponse, error) + // loop: `static updatelabel` + // UpdateStaticAddressLabel updates the local label for a static address. + UpdateStaticAddressLabel(ctx context.Context, in *UpdateStaticAddressLabelRequest, opts ...grpc.CallOption) (*UpdateStaticAddressLabelResponse, error) // loop: `static listunspentdeposits` // ListUnspentDeposits returns a list of utxos deposited at a static address. ListUnspentDeposits(ctx context.Context, in *ListUnspentDepositsRequest, opts ...grpc.CallOption) (*ListUnspentDepositsResponse, error) @@ -417,6 +420,15 @@ func (c *swapClientClient) FundStaticAddress(ctx context.Context, in *FundStatic return out, nil } +func (c *swapClientClient) UpdateStaticAddressLabel(ctx context.Context, in *UpdateStaticAddressLabelRequest, opts ...grpc.CallOption) (*UpdateStaticAddressLabelResponse, error) { + out := new(UpdateStaticAddressLabelResponse) + err := c.cc.Invoke(ctx, "/looprpc.SwapClient/UpdateStaticAddressLabel", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *swapClientClient) ListUnspentDeposits(ctx context.Context, in *ListUnspentDepositsRequest, opts ...grpc.CallOption) (*ListUnspentDepositsResponse, error) { out := new(ListUnspentDepositsResponse) err := c.cc.Invoke(ctx, "/looprpc.SwapClient/ListUnspentDeposits", in, out, opts...) @@ -597,6 +609,9 @@ type SwapClientServer interface { // wallet. Requires wallet:fund in addition to swap:execute and loop:in, or an // explicit URI permission for this RPC. FundStaticAddress(context.Context, *FundStaticAddressRequest) (*FundStaticAddressResponse, error) + // loop: `static updatelabel` + // UpdateStaticAddressLabel updates the local label for a static address. + UpdateStaticAddressLabel(context.Context, *UpdateStaticAddressLabelRequest) (*UpdateStaticAddressLabelResponse, error) // loop: `static listunspentdeposits` // ListUnspentDeposits returns a list of utxos deposited at a static address. ListUnspentDeposits(context.Context, *ListUnspentDepositsRequest) (*ListUnspentDepositsResponse, error) @@ -710,6 +725,9 @@ func (UnimplementedSwapClientServer) NewStaticAddress(context.Context, *NewStati func (UnimplementedSwapClientServer) FundStaticAddress(context.Context, *FundStaticAddressRequest) (*FundStaticAddressResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method FundStaticAddress not implemented") } +func (UnimplementedSwapClientServer) UpdateStaticAddressLabel(context.Context, *UpdateStaticAddressLabelRequest) (*UpdateStaticAddressLabelResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateStaticAddressLabel not implemented") +} func (UnimplementedSwapClientServer) ListUnspentDeposits(context.Context, *ListUnspentDepositsRequest) (*ListUnspentDepositsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListUnspentDeposits not implemented") } @@ -1218,6 +1236,24 @@ func _SwapClient_FundStaticAddress_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _SwapClient_UpdateStaticAddressLabel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateStaticAddressLabelRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SwapClientServer).UpdateStaticAddressLabel(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/looprpc.SwapClient/UpdateStaticAddressLabel", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SwapClientServer).UpdateStaticAddressLabel(ctx, req.(*UpdateStaticAddressLabelRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _SwapClient_ListUnspentDeposits_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListUnspentDepositsRequest) if err := dec(in); err != nil { @@ -1469,6 +1505,10 @@ var SwapClient_ServiceDesc = grpc.ServiceDesc{ MethodName: "FundStaticAddress", Handler: _SwapClient_FundStaticAddress_Handler, }, + { + MethodName: "UpdateStaticAddressLabel", + Handler: _SwapClient_UpdateStaticAddressLabel_Handler, + }, { MethodName: "ListUnspentDeposits", Handler: _SwapClient_ListUnspentDeposits_Handler, diff --git a/looprpc/client_test.go b/looprpc/client_test.go index 4a19c68ff..1539e3216 100644 --- a/looprpc/client_test.go +++ b/looprpc/client_test.go @@ -1,11 +1,49 @@ package looprpc import ( + "bytes" "testing" "google.golang.org/protobuf/proto" ) +// TestStaticAddressLabelWireFields keeps local labels separate from the +// reserved funding fields of the former combined address/funding RPC. +func TestStaticAddressLabelWireFields(t *testing.T) { + type labeledMessage interface { + proto.Message + GetLabel() string + } + for _, test := range []struct { + name string + message labeledMessage + field byte + retired byte + }{ + {"request", &NewStaticAddressRequest{Label: "x"}, 0x1a, 0x12}, + {"response", &NewStaticAddressResponse{Label: "x"}, 0x22, 0x1a}, + } { + t.Run(test.name, func(t *testing.T) { + encoded, err := proto.Marshal(test.message) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(encoded, []byte{test.field, 1, 'x'}) { + t.Fatalf("unexpected label encoding: %x", encoded) + } + + if err := proto.Unmarshal( + []byte{test.retired, 1, 'x'}, test.message, + ); err != nil { + t.Fatal(err) + } + if test.message.GetLabel() != "" { + t.Fatal("reserved funding field decoded as a label") + } + }) + } +} + // TestInstantOutMaxSwapFeePresence verifies that an omitted fee cap remains // distinguishable from an explicitly encoded zero while retaining the scalar // field's original wire representation. diff --git a/looprpc/perms.go b/looprpc/perms.go index 728f70a30..9c7ec3e6a 100644 --- a/looprpc/perms.go +++ b/looprpc/perms.go @@ -97,6 +97,13 @@ var RequiredPermissions = map[string][]bakery.Op{ Entity: "wallet", Action: "fund", }}, + "/looprpc.SwapClient/UpdateStaticAddressLabel": {{ + Entity: "swap", + Action: "execute", + }, { + Entity: "loop", + Action: "in", + }}, "/looprpc.SwapClient/ListUnspentDeposits": {{ Entity: "swap", Action: "read", diff --git a/looprpc/swapclient.pb.json.go b/looprpc/swapclient.pb.json.go index 75041d3e9..0b58c153a 100644 --- a/looprpc/swapclient.pb.json.go +++ b/looprpc/swapclient.pb.json.go @@ -688,6 +688,31 @@ func RegisterSwapClientJSONCallbacks(registry map[string]func(ctx context.Contex callback(string(respBytes), nil) } + registry["looprpc.SwapClient.UpdateStaticAddressLabel"] = func(ctx context.Context, + conn *grpc.ClientConn, reqJSON string, callback func(string, error)) { + + req := &UpdateStaticAddressLabelRequest{} + err := marshaler.Unmarshal([]byte(reqJSON), req) + if err != nil { + callback("", err) + return + } + + client := NewSwapClientClient(conn) + resp, err := client.UpdateStaticAddressLabel(ctx, req) + if err != nil { + callback("", err) + return + } + + respBytes, err := marshaler.Marshal(resp) + if err != nil { + callback("", err) + return + } + callback(string(respBytes), nil) + } + registry["looprpc.SwapClient.ListUnspentDeposits"] = func(ctx context.Context, conn *grpc.ClientConn, reqJSON string, callback func(string, error)) { From 321f399c54d7e2ee2158b7e9d038caa6382e4511 Mon Sep 17 00:00:00 2001 From: Gustavo Stingelin Date: Fri, 17 Jul 2026 17:43:38 -0300 Subject: [PATCH 6/9] staticaddr/loopd: wire static address labels Label new addresses, relabel them without mutating published address snapshots, and fill in address and funding transaction labels in deposit responses. --- loopd/swapclient_server.go | 113 ++++++- loopd/swapclient_server_staticaddr_test.go | 73 +++++ loopd/swapclient_server_test.go | 346 ++++++++++++++++++++- staticaddr/address/issuance_test.go | 4 +- staticaddr/address/manager.go | 72 ++++- staticaddr/address/manager_label_test.go | 215 +++++++++++++ staticaddr/address/manager_test.go | 10 +- test/walletkit_mock.go | 18 ++ 8 files changed, 824 insertions(+), 27 deletions(-) create mode 100644 staticaddr/address/manager_label_test.go diff --git a/loopd/swapclient_server.go b/loopd/swapclient_server.go index a8139122e..11a777c65 100644 --- a/loopd/swapclient_server.go +++ b/loopd/swapclient_server.go @@ -18,6 +18,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightninglabs/aperture/l402" @@ -1861,11 +1862,19 @@ func rpcInstantOut(instantOut *instantout.InstantOut) *looprpc.InstantOut { } // NewStaticAddress creates a fresh static receive address without funding it. +// Its label is local operator metadata and is validated before address creation. func (s *swapClientServer) NewStaticAddress(ctx context.Context, - _ *looprpc.NewStaticAddressRequest) (*looprpc.NewStaticAddressResponse, - error) { + req *looprpc.NewStaticAddressRequest) ( + *looprpc.NewStaticAddressResponse, error) { + + label := req.GetLabel() + if err := labels.Validate(label); err != nil { + return nil, fmt.Errorf("invalid static address label: %w", err) + } - staticAddress, expiry, err := s.staticAddressManager.NewAddress(ctx) + staticAddress, expiry, err := s.staticAddressManager.NewAddress( + ctx, label, + ) if err != nil { return nil, err } @@ -1873,6 +1882,48 @@ func (s *swapClientServer) NewStaticAddress(ctx context.Context, return &looprpc.NewStaticAddressResponse{ Address: staticAddress.String(), Expiry: uint32(expiry), + Label: label, + }, nil +} + +// UpdateStaticAddressLabel updates the local label for a static address so +// operators can rename it without changing the address script or contacting the +// Loop server. +func (s *swapClientServer) UpdateStaticAddressLabel(ctx context.Context, + req *looprpc.UpdateStaticAddressLabelRequest) ( + *looprpc.UpdateStaticAddressLabelResponse, error) { + + label := req.GetLabel() + if err := labels.Validate(label); err != nil { + return nil, fmt.Errorf("invalid static address label: %w", err) + } + + staticAddress, err := btcutil.DecodeAddress( + req.GetStaticAddress(), s.lnd.ChainParams, + ) + if err != nil { + return nil, fmt.Errorf("decode static address: %w", err) + } + + pkScript, err := txscript.PayToAddrScript(staticAddress) + if err != nil { + return nil, fmt.Errorf("static address pkScript: %w", err) + } + + err = s.staticAddressManager.UpdateStaticAddressLabel( + ctx, pkScript, label, + ) + if errors.Is(err, address.ErrStaticAddressNotFound) { + return nil, status.Errorf(codes.NotFound, "static address %v "+ + "not found", staticAddress) + } + if err != nil { + return nil, fmt.Errorf("update static address label: %w", err) + } + + return &looprpc.UpdateStaticAddressLabelResponse{ + StaticAddress: staticAddress.String(), + Label: label, }, nil } @@ -1891,7 +1942,7 @@ func (s *swapClientServer) FundStaticAddress(ctx context.Context, return s.fundExistingStaticAddress(ctx, sendCoinsReq) } - staticAddress, expiry, err := s.staticAddressManager.NewAddress(ctx) + staticAddress, expiry, err := s.staticAddressManager.NewAddress(ctx, "") if err != nil { return nil, err } @@ -2092,6 +2143,7 @@ func (s *swapClientServer) ListUnspentDeposits(ctx context.Context, AmountSat: int64(u.Value), Confirmations: u.Confirmations, Outpoint: u.OutPoint.String(), + AddressLabel: params.Label, } respUtxos = append(respUtxos, utxo) } @@ -2230,6 +2282,7 @@ func (s *swapClientServer) ListStaticAddressDeposits(ctx context.Context, if err != nil { infof("Failed to populate blocks until expiry: %v", err) } + s.populateFundingTxLabels(ctx, filteredDeposits) return &looprpc.ListStaticAddressDepositsResponse{ FilteredDeposits: filteredDeposits, @@ -2254,6 +2307,7 @@ func (s *swapClientServer) ListStaticAddressWithdrawals(ctx context.Context, clientWithdrawals := make( []*looprpc.StaticAddressWithdrawal, 0, len(withdrawals), ) + var deposits []*looprpc.Deposit for _, w := range withdrawals { withdrawal, err := s.rpcStaticAddressWithdrawal(w) if err != nil { @@ -2261,7 +2315,9 @@ func (s *swapClientServer) ListStaticAddressWithdrawals(ctx context.Context, } clientWithdrawals = append(clientWithdrawals, withdrawal) + deposits = append(deposits, withdrawal.Deposits...) } + s.populateFundingTxLabels(ctx, deposits) return &looprpc.ListStaticAddressWithdrawalResponse{ Withdrawals: clientWithdrawals, @@ -2331,7 +2387,10 @@ func (s *swapClientServer) ListStaticAddressSwaps(ctx context.Context, ) } - var clientSwaps []*looprpc.StaticAddressLoopInSwap + var ( + clientSwaps []*looprpc.StaticAddressLoopInSwap + deposits []*looprpc.Deposit + ) for _, swp := range swaps { if swp == nil { continue @@ -2395,7 +2454,9 @@ func (s *swapClientServer) ListStaticAddressSwaps(ctx context.Context, } clientSwaps = append(clientSwaps, swap) + deposits = append(deposits, protoDeposits...) } + s.populateFundingTxLabels(ctx, deposits) return &looprpc.ListStaticAddressSwapsResponse{ Swaps: clientSwaps, @@ -2713,6 +2774,7 @@ func (s *swapClientServer) rpcStaticAddressLoopInResponse(ctx context.Context, if err != nil { infof("Failed to populate blocks until expiry: %v", err) } + s.populateFundingTxLabels(ctx, usedDeposits) // Determine the actual swap amount and change based on the selected // amount and the total value of the selected deposits. @@ -2883,9 +2945,50 @@ func (s *swapClientServer) rpcDeposit(d *deposit.Deposit) ( } deposit.StaticAddress = staticAddress.String() + // Deposits read from the database carry the current label, but active + // deposits held in memory keep the label from when they were loaded. + // Prefer the address manager's copy, which relabeling updates. + deposit.AddressLabel = d.AddressParams.Label + params := s.staticAddressManager.GetParameters(d.AddressParams.PkScript) + if params != nil { + deposit.AddressLabel = params.Label + } + return deposit, nil } +// populateFundingTxLabels sets the lnd wallet label of each deposit's funding +// transaction. The lookup is best-effort: deposits whose transaction lnd can't +// return keep an empty label. +func (s *swapClientServer) populateFundingTxLabels(ctx context.Context, + deposits []*looprpc.Deposit) { + + labelByTxid := make(map[chainhash.Hash]string) + for _, d := range deposits { + outpoint, err := wire.NewOutPointFromString(d.Outpoint) + if err != nil { + warnf("Invalid deposit outpoint %v: %v", d.Outpoint, err) + continue + } + + txid := outpoint.Hash + if _, ok := labelByTxid[txid]; !ok { + tx, err := s.lnd.WalletKit.GetTransaction(ctx, txid) + if err != nil { + debugf("Unable to look up funding transaction "+ + "%v: %v", txid, err) + } + + // Several deposits can share a funding transaction. + // On error tx is empty, so we cache an empty label and + // don't query lnd again for the same txid. + labelByTxid[txid] = tx.Label + } + + d.FundingTxLabel = labelByTxid[txid] + } +} + func toClientDepositState(state fsm.StateType) looprpc.DepositState { switch state { case deposit.Deposited: diff --git a/loopd/swapclient_server_staticaddr_test.go b/loopd/swapclient_server_staticaddr_test.go index 580d42c1f..899aa667a 100644 --- a/loopd/swapclient_server_staticaddr_test.go +++ b/loopd/swapclient_server_staticaddr_test.go @@ -650,6 +650,79 @@ func TestListStaticAddressDepositsReturnsVisibleDeposits(t *testing.T) { ) } +// TestListStaticAddressDepositsIncludesLabels verifies deposit listings carry +// the current address label and the lnd label of the funding transaction. +func TestListStaticAddressDepositsIncludesLabels(t *testing.T) { + t.Parallel() + setLogger(btclog.Disabled) + + ctx := context.Background() + addrMgr, lnd := newTestStaticAddressContext(t, 10) + addresses, err := addrMgr.GetAllAddresses(ctx) + require.NoError(t, err) + require.Len(t, addresses, 1) + + // Relabel after the deposit captured its address parameters, so the + // listing must read the label from the manager's active snapshot. + params := addresses[0] + err = addrMgr.UpdateStaticAddressLabel(ctx, params.PkScript, "treasury") + require.NoError(t, err) + + fundingTx := wire.NewMsgTx(2) + fundingTx.AddTxOut(wire.NewTxOut(100_000, params.PkScript)) + lnd.Transactions = append(lnd.Transactions, lndclient.Transaction{ + Tx: fundingTx, + Label: "September top-up", + }) + + labeled := &deposit.Deposit{ + OutPoint: wire.OutPoint{ + Hash: fundingTx.TxHash(), + Index: 0, + }, + AddressParams: params, + } + labeled.SetState(deposit.Deposited) + + // lnd doesn't know this deposit's transaction, so its funding label + // stays empty without failing the listing. + unknown := &deposit.Deposit{ + OutPoint: wire.OutPoint{ + Hash: chainhash.Hash{4}, + Index: 1, + }, + AddressParams: params, + } + unknown.SetState(deposit.Deposited) + + server := &swapClientServer{ + depositManager: newTestDepositManager(labeled, unknown), + staticAddressManager: addrMgr, + lnd: &lnd.LndServices, + } + + resp, err := server.ListStaticAddressDeposits( + ctx, &looprpc.ListStaticAddressDepositsRequest{}, + ) + require.NoError(t, err) + require.Len(t, resp.FilteredDeposits, 2) + + byOutpoint := make(map[string]*looprpc.Deposit) + for _, d := range resp.FilteredDeposits { + byOutpoint[d.Outpoint] = d + } + + got := byOutpoint[labeled.OutPoint.String()] + require.NotNil(t, got) + require.Equal(t, "treasury", got.AddressLabel) + require.Equal(t, "September top-up", got.FundingTxLabel) + + got = byOutpoint[unknown.OutPoint.String()] + require.NotNil(t, got) + require.Equal(t, "treasury", got.AddressLabel) + require.Empty(t, got.FundingTxLabel) +} + // TestStaticAddressWithdrawalIncludesDepositAddress verifies withdrawal // listings use the common deposit conversion path, including the address that // received each deposit. diff --git a/loopd/swapclient_server_test.go b/loopd/swapclient_server_test.go index bd53c0707..7c1b7fee5 100644 --- a/loopd/swapclient_server_test.go +++ b/loopd/swapclient_server_test.go @@ -2008,6 +2008,218 @@ func (s *mockAddressStore) UpdateStaticAddressLabel(_ context.Context, return address.ErrStaticAddressNotFound } +// newStaticAddressLabelTestServer builds the smallest real RPC handler stack +// needed to prove labels round-trip as local static-address metadata. +func newStaticAddressLabelTestServer(t *testing.T, label string) ( + *swapClientServer, *mockAddressStore, string) { + + t.Helper() + + lnd := mock_lnd.NewMockLnd() + _, clientPubkey := mock_lnd.CreateKey(1) + _, serverPubkey := mock_lnd.CreateKey(2) + + addrMgr, err := address.NewManager(&address.ManagerConfig{ + ChainParams: lnd.ChainParams, + }, 1) + require.NoError(t, err) + + staticAddress, err := addrMgr.GetTaprootAddress( + clientPubkey, serverPubkey, 10, + ) + require.NoError(t, err) + + pkScript, err := txscript.PayToAddrScript(staticAddress) + require.NoError(t, err) + + addrStore := &mockAddressStore{} + err = addrStore.CreateStaticAddress( + context.Background(), &script.Parameters{ + ClientPubkey: clientPubkey, + ServerPubkey: serverPubkey, + Expiry: 10, + PkScript: pkScript, + Label: label, + }, + ) + require.NoError(t, err) + + addrMgr, err = address.NewManager(&address.ManagerConfig{ + Store: addrStore, + WalletKit: lnd.WalletKit, + ChainParams: lnd.ChainParams, + }, 1) + require.NoError(t, err) + _, err = addrMgr.EnsureStaticAddressRoot(t.Context()) + require.NoError(t, err) + + depositMgr := deposit.NewManager(&deposit.ManagerConfig{ + Store: &mockDepositStore{ + byOutpoint: make(map[string]*deposit.Deposit), + }, + }) + + return &swapClientServer{ + lnd: &lnd.LndServices, + staticAddressManager: addrMgr, + depositManager: depositMgr, + }, addrStore, staticAddress.String() +} + +// TestStaticAddressLabels covers the RPC boundary for local operator metadata: +// creation returns stored labels, updates mutate only local storage, and invalid +// labels are rejected before persistence changes. +func TestStaticAddressLabels(t *testing.T) { + ctx := context.Background() + + t.Run("new static address stores its own label", func(t *testing.T) { + server, store, _ := newStaticAddressLabelTestServer( + t, "stored label", + ) + + resp, err := server.NewStaticAddress( + ctx, &looprpc.NewStaticAddressRequest{Label: "requested"}, + ) + + require.NoError(t, err) + require.Equal(t, "requested", resp.Label) + require.Len(t, store.params, 2) + require.Equal(t, "stored label", store.params[0].Label) + require.Equal(t, "requested", store.params[1].Label) + require.NotEqual(t, store.params[0].PkScript, + store.params[1].PkScript) + }) + + t.Run("new static address rejects invalid label", func(t *testing.T) { + server, store, _ := newStaticAddressLabelTestServer( + t, "stored label", + ) + + _, err := server.NewStaticAddress( + ctx, &looprpc.NewStaticAddressRequest{ + Label: labels.Reserved + " static", + }, + ) + + require.Error(t, err) + require.ErrorContains(t, err, "invalid static address label") + require.Len(t, store.params, 1) + require.Equal(t, "stored label", store.params[0].Label) + }) + + t.Run("summary reports legacy address", func(t *testing.T) { + server, _, legacyAddress := newStaticAddressLabelTestServer( + t, "legacy label", + ) + _, err := server.NewStaticAddress(ctx, + &looprpc.NewStaticAddressRequest{Label: "receive label"}) + require.NoError(t, err) + + resp, err := server.GetStaticAddressSummary( + ctx, &looprpc.StaticAddressSummaryRequest{}, + ) + + require.NoError(t, err) + // Field 1 retains the legacy address for wire compatibility. + summary := resp.ProtoReflect() + legacyField := summary.Descriptor().Fields().ByNumber(1) + require.Equal(t, legacyAddress, summary.Get(legacyField).String()) + }) + + t.Run("update changes stored label", func(t *testing.T) { + server, store, staticAddress := newStaticAddressLabelTestServer( + t, "old label", + ) + + resp, err := server.UpdateStaticAddressLabel( + ctx, &looprpc.UpdateStaticAddressLabelRequest{ + StaticAddress: staticAddress, + Label: "new label", + }, + ) + + require.NoError(t, err) + require.Equal(t, staticAddress, resp.StaticAddress) + require.Equal(t, "new label", resp.Label) + require.Len(t, store.params, 1) + require.Equal(t, "new label", store.params[0].Label) + require.Equal(t, "new label", + server.staticAddressManager.GetParameters( + store.params[0].PkScript).Label) + }) + + t.Run("update clears stored label", func(t *testing.T) { + server, store, staticAddress := newStaticAddressLabelTestServer( + t, "old label", + ) + + resp, err := server.UpdateStaticAddressLabel( + ctx, &looprpc.UpdateStaticAddressLabelRequest{ + StaticAddress: staticAddress, + Label: "", + }, + ) + + require.NoError(t, err) + require.Equal(t, staticAddress, resp.StaticAddress) + require.Empty(t, resp.Label) + require.Len(t, store.params, 1) + require.Empty(t, store.params[0].Label) + require.Empty(t, server.staticAddressManager.GetParameters( + store.params[0].PkScript).Label) + }) + + t.Run("update unknown static address fails", func(t *testing.T) { + server, _, _ := newStaticAddressLabelTestServer(t, "old label") + + unknownAddress, err := btcutil.NewAddressScriptHash( + []byte{1}, server.lnd.ChainParams, + ) + require.NoError(t, err) + + _, err = server.UpdateStaticAddressLabel( + ctx, &looprpc.UpdateStaticAddressLabelRequest{ + StaticAddress: unknownAddress.String(), + Label: "new label", + }, + ) + + require.Equal(t, codes.NotFound, status.Code(err)) + }) + + t.Run("update foreign static address fails", func(t *testing.T) { + server, _, _ := newStaticAddressLabelTestServer(t, "old label") + + _, err := server.UpdateStaticAddressLabel( + ctx, &looprpc.UpdateStaticAddressLabelRequest{ + StaticAddress: mainnetAddr.String(), + Label: "new label", + }, + ) + + require.Error(t, err) + require.ErrorContains(t, err, "decode static address") + }) + + t.Run("update rejects invalid label", func(t *testing.T) { + server, store, staticAddress := newStaticAddressLabelTestServer( + t, "old label", + ) + + _, err := server.UpdateStaticAddressLabel( + ctx, &looprpc.UpdateStaticAddressLabelRequest{ + StaticAddress: staticAddress, + Label: labels.Reserved + " static", + }, + ) + + require.Error(t, err) + require.ErrorContains(t, err, "invalid static address label") + require.Len(t, store.params, 1) + require.Equal(t, "old label", store.params[0].Label) + }) +} + // mockDepositStore implements deposit.Store minimally for DepositsForOutpoints. type mockDepositStore struct { byOutpoint map[string]*deposit.Deposit @@ -2183,6 +2395,12 @@ func TestListUnspentDeposits(t *testing.T) { require.NoError(t, err) pkScript, err := staticAddress.StaticAddressScript() require.NoError(t, err) + addrMgr, err := address.NewManager(&address.ManagerConfig{ + ChainParams: mock.ChainParams, + }, 1) + require.NoError(t, err) + encodedAddress, err := addrMgr.GetTaprootAddress(client, server, 10) + require.NoError(t, err) addrParams := &script.Parameters{ ClientPubkey: client, ServerPubkey: server, @@ -2190,10 +2408,13 @@ func TestListUnspentDeposits(t *testing.T) { PkScript: pkScript, } - addrStore := &mockAddressStore{params: []*script.Parameters{addrParams}} + addrStore := &mockAddressStore{ + params: []*script.Parameters{addrParams}, + } + addrParams.Label = "list label" // Build an address manager using our mock lnd and fake address store. - addrMgr, err := address.NewManager(&address.ManagerConfig{ + addrMgr, err = address.NewManager(&address.ManagerConfig{ Store: addrStore, WalletKit: mock.WalletKit, ChainParams: mock.ChainParams, @@ -2273,6 +2494,7 @@ func TestListUnspentDeposits(t *testing.T) { // Confirm address string is non-empty and the // same across utxos. require.NotEmpty(t, u.StaticAddress) + require.Equal(t, "list label", u.AddressLabel) } _, ok := got[utxoDeposited.OutPoint.String()] require.True(t, ok) @@ -2308,6 +2530,7 @@ func TestListUnspentDeposits(t *testing.T) { got := map[string]struct{}{} for _, u := range resp.Utxos { got[u.Outpoint] = struct{}{} + require.Equal(t, "list label", u.AddressLabel) } _, ok := got[utxoDeposited.OutPoint.String()] require.True(t, ok) @@ -2393,5 +2616,124 @@ func TestListUnspentDeposits(t *testing.T) { t, utxoConfirmedUnknown.OutPoint.String(), resp.Utxos[0].Outpoint, ) + require.NotEmpty(t, resp.Utxos[0].StaticAddress) + require.Equal(t, "list label", resp.Utxos[0].AddressLabel) + }) + + t.Run("responses retain per address metadata", func(t *testing.T) { + secondAddress, _, err := addrMgr.NewAddress(ctx, "second label") + require.NoError(t, err) + + secondPkScript, err := txscript.PayToAddrScript(secondAddress) + require.NoError(t, err) + + secondUtxo := &lnwallet.Utxo{ + AddressType: lnwallet.TaprootPubkey, + Value: 250_001, + Confirmations: 1, + PkScript: secondPkScript, + OutPoint: wire.OutPoint{ + Hash: chainhash.Hash{9}, + Index: 9, + }, + } + mock.SetListUnspent([]*lnwallet.Utxo{ + utxoDeposited, secondUtxo, + }) + + depMgr := buildDepositMgr(map[wire.OutPoint]fsm.StateType{ + utxoDeposited.OutPoint: deposit.Deposited, + secondUtxo.OutPoint: deposit.Deposited, + }) + server := &swapClientServer{ + staticAddressManager: addrMgr, + depositManager: depMgr, + } + + resp, err := server.ListUnspentDeposits( + ctx, &looprpc.ListUnspentDepositsRequest{}, + ) + require.NoError(t, err) + require.Len(t, resp.Utxos, 2) + + got := make(map[string]*looprpc.Utxo, len(resp.Utxos)) + for _, utxo := range resp.Utxos { + got[utxo.Outpoint] = utxo + } + require.Equal( + t, encodedAddress.String(), + got[utxoDeposited.OutPoint.String()].StaticAddress, + ) + require.Equal( + t, "list label", got[utxoDeposited.OutPoint.String()].AddressLabel, + ) + require.Equal( + t, secondAddress.String(), + got[secondUtxo.OutPoint.String()].StaticAddress, + ) + require.Equal( + t, "second label", got[secondUtxo.OutPoint.String()].AddressLabel, + ) + }) + + for _, tc := range []struct { + name string + label string + }{ + {name: "updated label is visible", label: "renamed"}, + {name: "cleared label is visible", label: ""}, + } { + t.Run(tc.name, func(t *testing.T) { + mock.SetListUnspent([]*lnwallet.Utxo{utxoDeposited}) + depMgr := buildDepositMgr( + map[wire.OutPoint]fsm.StateType{ + utxoDeposited.OutPoint: deposit.Deposited, + }, + ) + server := &swapClientServer{ + staticAddressManager: addrMgr, + depositManager: depMgr, + lnd: &mock.LndServices, + } + + _, err := server.UpdateStaticAddressLabel( + ctx, &looprpc.UpdateStaticAddressLabelRequest{ + StaticAddress: encodedAddress.String(), + Label: tc.label, + }, + ) + require.NoError(t, err) + + resp, err := server.ListUnspentDeposits( + ctx, &looprpc.ListUnspentDepositsRequest{}, + ) + require.NoError(t, err) + require.Len(t, resp.Utxos, 1) + require.Equal(t, tc.label, resp.Utxos[0].AddressLabel) + }) + } + + t.Run("no static address returns an empty result", func(t *testing.T) { + addrStore := &mockAddressStore{} + addrMgr, err := address.NewManager(&address.ManagerConfig{ + Store: addrStore, + WalletKit: mock.WalletKit, + ChainParams: mock.ChainParams, + }, 1) + require.NoError(t, err) + + depMgr := &listUnspentDepositManager{} + server := &swapClientServer{ + staticAddressManager: addrMgr, + depositManager: depMgr, + } + + resp, err := server.ListUnspentDeposits( + ctx, &looprpc.ListUnspentDepositsRequest{}, + ) + + require.NoError(t, err) + require.Empty(t, resp.Utxos) + require.Equal(t, 1, depMgr.ensureDepositsFreshCalls) }) } diff --git a/staticaddr/address/issuance_test.go b/staticaddr/address/issuance_test.go index a65b4d9fc..1b0f86428 100644 --- a/staticaddr/address/issuance_test.go +++ b/staticaddr/address/issuance_test.go @@ -23,7 +23,9 @@ func TestIssuanceWaiterCancellation(t *testing.T) { if derived { _, err := issue(t.Context()) require.NoError(t, err) - issue = manager.NewReceiveAddress + issue = func(ctx context.Context) (*AddressParameters, error) { + return manager.NewReceiveAddress(ctx, "") + } } started, release := make(chan struct{}), make(chan struct{}) manager.cfg.WalletKit = &blockingImportWallet{ diff --git a/staticaddr/address/manager.go b/staticaddr/address/manager.go index fb7404aad..0840213b5 100644 --- a/staticaddr/address/manager.go +++ b/staticaddr/address/manager.go @@ -294,15 +294,17 @@ func (m *Manager) walletAddressScripts(ctx context.Context) ( return scriptKeys, nil } -// NewAddress creates the next externally visible receive static address. +// NewAddress creates the next externally visible receive static address with +// local label metadata. The label is never sent to the Loop server or included +// in the address script. // // The first call also makes sure the legacy/root static address exists, // because receive and change addresses are derived from the server pubkey and // expiry returned for that root. -func (m *Manager) NewAddress(ctx context.Context) (*btcutil.AddressTaproot, - int64, error) { +func (m *Manager) NewAddress(ctx context.Context, label string) ( + *btcutil.AddressTaproot, int64, error) { - addrParams, err := m.NewReceiveAddress(ctx) + addrParams, err := m.NewReceiveAddress(ctx, label) if err != nil { return nil, 0, err } @@ -424,21 +426,23 @@ func (m *Manager) EnsureStaticAddressRoot(ctx context.Context) (*AddressParamete return m.createAddressFromKey( ctx, clientPubKey, serverPubKey, serverParams.Expiry, - version.AddressProtocolVersion(protocolVersion), + version.AddressProtocolVersion(protocolVersion), "", ) } // NewReceiveAddress derives, stores, imports and activates the next receive // family static address. It is used by `loop static new`. -func (m *Manager) NewReceiveAddress(ctx context.Context) (*AddressParameters, - error) { +func (m *Manager) NewReceiveAddress(ctx context.Context, label string) ( + *AddressParameters, error) { root, err := m.EnsureStaticAddressRoot(ctx) if err != nil { return nil, err } - return m.newDerivedAddress(ctx, root, swap.StaticMultiAddressKeyFamily) + return m.newDerivedAddress( + ctx, root, swap.StaticMultiAddressKeyFamily, label, + ) } // NewChangeAddress derives, stores, imports and activates the next change @@ -452,13 +456,15 @@ func (m *Manager) NewChangeAddress(ctx context.Context) (*AddressParameters, return nil, err } - return m.newDerivedAddress(ctx, root, swap.StaticAddressChangeKeyFamily) + return m.newDerivedAddress( + ctx, root, swap.StaticAddressChangeKeyFamily, "", + ) } // newDerivedAddress derives a client key in the requested family and creates // an address using the root address's server key, expiry and protocol version. func (m *Manager) newDerivedAddress(ctx context.Context, root *AddressParameters, - keyFamily int32) (*AddressParameters, error) { + keyFamily int32, label string) (*AddressParameters, error) { if err := m.lockIssuance(ctx); err != nil { return nil, err @@ -472,7 +478,7 @@ func (m *Manager) newDerivedAddress(ctx context.Context, root *AddressParameters return m.createAddressFromKey( ctx, clientPubKey, root.ServerPubkey, root.Expiry, - root.ProtocolVersion, + root.ProtocolVersion, label, ) } @@ -480,8 +486,8 @@ func (m *Manager) newDerivedAddress(ctx context.Context, root *AddressParameters // and adding it to the active script index. func (m *Manager) createAddressFromKey(ctx context.Context, clientPubKey *keychain.KeyDescriptor, serverPubKey *btcec.PublicKey, - expiry uint32, protocolVersion version.AddressProtocolVersion) ( - *AddressParameters, error) { + expiry uint32, protocolVersion version.AddressProtocolVersion, + label string) (*AddressParameters, error) { staticAddress, err := script.NewStaticAddress( input.MuSig2Version100RC2, int64(expiry), clientPubKey.PubKey, @@ -507,6 +513,7 @@ func (m *Manager) createAddressFromKey(ctx context.Context, }, ProtocolVersion: protocolVersion, InitiationHeight: m.currentHeight.Load(), + Label: label, } // Persist the address before importing it into lnd. In particular, the @@ -738,7 +745,44 @@ func (m *Manager) GetLegacyParameters(ctx context.Context) (*AddressParameters, return addrParams, nil } -// GetParameters returns active static address parameters for a pkScript. +// UpdateStaticAddressLabel persists local metadata and publishes a new snapshot +// for active readers. Existing snapshots remain immutable. +func (m *Manager) UpdateStaticAddressLabel(ctx context.Context, + pkScript []byte, label string) error { + + // Serialize with issuance, which can rebuild the active index from the + // database. Otherwise a rebuild that read the old label could publish + // it after this update. The startup load runs without the lock, but + // finishes before the RPC server accepts relabel requests. + if err := m.lockIssuance(ctx); err != nil { + return err + } + defer m.unlockIssuance() + + if err := m.cfg.Store.UpdateStaticAddressLabel( + ctx, pkScript, label, + ); err != nil { + return err + } + + m.activeMu.Lock() + defer m.activeMu.Unlock() + + key := string(pkScript) + if params := m.activeStaticAddresses[key]; params != nil { + updated := *params + updated.Label = label + m.activeStaticAddresses[key] = &updated + if m.rootAddress == params { + m.rootAddress = &updated + } + } + + return nil +} + +// GetParameters returns an immutable snapshot of active static address +// parameters for a pkScript. func (m *Manager) GetParameters(pkScript []byte) *AddressParameters { m.activeMu.Lock() defer m.activeMu.Unlock() diff --git a/staticaddr/address/manager_label_test.go b/staticaddr/address/manager_label_test.go new file mode 100644 index 000000000..88ea63c0d --- /dev/null +++ b/staticaddr/address/manager_label_test.go @@ -0,0 +1,215 @@ +package address + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/btcsuite/btcd/txscript" + "github.com/stretchr/testify/require" +) + +// TestNewAddressLabels verifies that labels belong to individual receive +// addresses, not the shared root or automatically generated change. +func TestNewAddressLabels(t *testing.T) { + fixture := NewAddressManagerTestContext(t) + manager := fixture.manager + ctx := t.Context() + var received []*AddressParameters + + for _, label := range []string{"treasury", "treasury", ""} { + addr, _, err := manager.NewAddress(ctx, label) + require.NoError(t, err) + pkScript, err := txscript.PayToAddrScript(addr) + require.NoError(t, err) + params := manager.GetParameters(pkScript) + require.NotNil(t, params) + require.Equal(t, label, params.Label) + for _, previous := range received { + require.NotEqual(t, previous.ID, params.ID) + require.NotEqual(t, previous.PkScript, params.PkScript) + } + received = append(received, params) + } + + root, err := manager.EnsureStaticAddressRoot(ctx) + require.NoError(t, err) + require.Empty(t, root.Label) + require.NoError(t, manager.UpdateStaticAddressLabel( + ctx, root.PkScript, "legacy", + )) + updatedRoot, err := manager.EnsureStaticAddressRoot(ctx) + require.NoError(t, err) + require.Equal(t, "legacy", updatedRoot.Label) + require.Empty(t, root.Label) + + change, err := manager.NewChangeAddress(ctx) + require.NoError(t, err) + require.Empty(t, change.Label) + + for _, label := range []string{"operations", ""} { + require.NoError(t, manager.UpdateStaticAddressLabel( + ctx, received[0].PkScript, label, + )) + require.Equal(t, label, + manager.GetParameters(received[0].PkScript).Label) + require.Equal(t, "treasury", + manager.GetParameters(received[1].PkScript).Label) + require.Equal(t, "treasury", received[0].Label) + } + + // Rebuilding the index from SQL must restore each label independently. + restarted, err := NewManager(manager.cfg, manager.currentHeight.Load()) + require.NoError(t, err) + require.NoError(t, restarted.loadActiveAddresses(ctx)) + for _, params := range append(received, updatedRoot, change) { + require.Equal(t, manager.GetParameters(params.PkScript).Label, + restarted.GetParameters(params.PkScript).Label) + } + fixture.mockStaticAddressClient.AssertNumberOfCalls( + t, "ServerNewAddress", 1, + ) +} + +type failingLabelStore struct { + Store + + err error +} + +func (s *failingLabelStore) UpdateStaticAddressLabel(context.Context, + []byte, string) error { + + return s.err +} + +// TestUpdateLabelStoreFailure verifies that failed writes do not publish new +// metadata to the active index. +func TestUpdateLabelStoreFailure(t *testing.T) { + fixture := NewAddressManagerTestContext(t) + manager := fixture.manager + params, err := manager.NewReceiveAddress(t.Context(), "original") + require.NoError(t, err) + store := manager.cfg.Store + writeErr := errors.New("label write failed") + manager.cfg.Store = &failingLabelStore{Store: store, err: writeErr} + + err = manager.UpdateStaticAddressLabel( + t.Context(), params.PkScript, "replacement", + ) + require.ErrorIs(t, err, writeErr) + require.Same(t, params, manager.GetParameters(params.PkScript)) + require.Equal(t, "original", params.Label) + stored, err := store.GetAllStaticAddresses(t.Context()) + require.NoError(t, err) + require.Equal(t, "original", stored[1].Label) +} + +type blockingLabelStore struct { + Store + + started chan struct{} + release chan struct{} +} + +func (s *blockingLabelStore) UpdateStaticAddressLabel(ctx context.Context, + pkScript []byte, label string) error { + + close(s.started) + select { + case <-s.release: + return s.Store.UpdateStaticAddressLabel(ctx, pkScript, label) + case <-ctx.Done(): + return ctx.Err() + } +} + +// TestLabelUpdateDoesNotBlockReads verifies that a pending SQL write does not +// block index lookups, and that publication leaves readers' snapshots intact. +func TestLabelUpdateDoesNotBlockReads(t *testing.T) { + fixture := NewAddressManagerTestContext(t) + manager := fixture.manager + params, err := manager.NewReceiveAddress(t.Context(), "original") + require.NoError(t, err) + ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) + defer cancel() + store := &blockingLabelStore{ + Store: manager.cfg.Store, started: make(chan struct{}), + release: make(chan struct{}), + } + manager.cfg.Store = store + done := make(chan error, 1) + go func() { + done <- manager.UpdateStaticAddressLabel( + ctx, params.PkScript, "replacement", + ) + }() + select { + case <-store.started: + case <-ctx.Done(): + t.Fatal("label write did not start") + } + + read := make(chan *AddressParameters, 1) + go func() { + read <- manager.GetParameters(params.PkScript) + }() + select { + case snapshot := <-read: + require.Same(t, params, snapshot) + require.Equal(t, "original", snapshot.Label) + case <-ctx.Done(): + t.Fatal("index read blocked on label write") + } + + close(store.release) + select { + case err := <-done: + require.NoError(t, err) + case <-ctx.Done(): + t.Fatal("label write did not finish") + } + require.Equal(t, "original", params.Label) + require.Equal(t, "replacement", + manager.GetParameters(params.PkScript).Label) +} + +// TestConcurrentLabelUpdates verifies that concurrent writers leave the SQL +// record, active index and cached root on the same committed label. +func TestConcurrentLabelUpdates(t *testing.T) { + fixture := NewAddressManagerTestContext(t) + manager := fixture.manager + ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) + defer cancel() + root, err := manager.EnsureStaticAddressRoot(ctx) + require.NoError(t, err) + start := make(chan struct{}) + results := make(chan error, 3) + for _, label := range []string{"treasury", "operations", ""} { + go func() { + <-start + results <- manager.UpdateStaticAddressLabel( + ctx, root.PkScript, label, + ) + }() + } + close(start) + for range cap(results) { + select { + case err := <-results: + require.NoError(t, err) + case <-ctx.Done(): + t.Fatal("concurrent updates did not finish") + } + } + + stored, err := manager.GetLegacyParameters(ctx) + require.NoError(t, err) + active := manager.GetParameters(root.PkScript) + cachedRoot, err := manager.EnsureStaticAddressRoot(ctx) + require.NoError(t, err) + require.Equal(t, stored.Label, active.Label) + require.Same(t, active, cachedRoot) + require.Empty(t, root.Label) +} diff --git a/staticaddr/address/manager_test.go b/staticaddr/address/manager_test.go index 7ae9bf0a7..be089698d 100644 --- a/staticaddr/address/manager_test.go +++ b/staticaddr/address/manager_test.go @@ -258,7 +258,7 @@ func TestManager(t *testing.T) { require.NoError(t, err) // Create a new static address. - taprootAddress, expiry, err := testContext.manager.NewAddress(ctxb) + taprootAddress, expiry, err := testContext.manager.NewAddress(ctxb, "") require.NoError(t, err) // The addresses have to match. @@ -300,7 +300,7 @@ func TestAddressIssuanceDoesNotBlockAddressReads(t *testing.T) { issuanceDone := make(chan error, 1) go func() { - _, err := testContext.manager.NewReceiveAddress(t.Context()) + _, err := testContext.manager.NewReceiveAddress(t.Context(), "") issuanceDone <- err }() @@ -537,7 +537,7 @@ func TestLoadActiveAddressesImportsOnlyMissing(t *testing.T) { func TestMultiAddressRestartRecovery(t *testing.T) { testContext := NewAddressManagerTestContext(t) - _, _, err := testContext.manager.NewAddress(t.Context()) + _, _, err := testContext.manager.NewAddress(t.Context(), "") require.NoError(t, err) changeParams, err := testContext.manager.NewChangeAddress(t.Context()) require.NoError(t, err) @@ -742,7 +742,7 @@ func TestNewAddressValidatesServerResponse(t *testing.T) { t, test.resp, ) - _, _, err := testContext.manager.NewAddress(t.Context()) + _, _, err := testContext.manager.NewAddress(t.Context(), "") require.ErrorContains(t, err, test.expected) }) } @@ -754,7 +754,7 @@ func TestNewAddressAcceptsMaxCSVExpiry(t *testing.T) { t, newServerNewAddressResponse(maxStaticAddressCSVExpiry), ) - _, expiry, err := testContext.manager.NewAddress(t.Context()) + _, expiry, err := testContext.manager.NewAddress(t.Context(), "") require.NoError(t, err) require.EqualValues(t, maxStaticAddressCSVExpiry, expiry) } diff --git a/test/walletkit_mock.go b/test/walletkit_mock.go index e35d5fbaf..9839db576 100644 --- a/test/walletkit_mock.go +++ b/test/walletkit_mock.go @@ -259,6 +259,24 @@ func (m *mockWalletKit) ListSweeps(_ context.Context, _ int32) ( return m.lnd.Sweeps, nil } +// GetTransaction returns the wallet transaction with the given txid from the +// mock's transaction list. +func (m *mockWalletKit) GetTransaction(_ context.Context, + txid chainhash.Hash) (lndclient.Transaction, error) { + + m.lnd.lock.Lock() + defer m.lnd.lock.Unlock() + + for _, tx := range m.lnd.Transactions { + if tx.Tx != nil && tx.Tx.TxHash() == txid { + return tx, nil + } + } + + return lndclient.Transaction{}, fmt.Errorf("transaction %v not found", + txid) +} + // ListSweepsVerbose returns a list of sweep transactions known to our node // with verbose information about each sweep. func (m *mockWalletKit) ListSweepsVerbose(ctx context.Context, _ int32) ( From c11039f55726de389420020037e160d0ad143ada Mon Sep 17 00:00:00 2001 From: Gustavo Stingelin Date: Fri, 17 Jul 2026 17:46:36 -0300 Subject: [PATCH 7/9] cmd/loop: support static address labels Add --label to static new and a static updatelabel command. Also run the static deposit CLI tests serially and cover its funding --label. --- cmd/loop/staticaddr.go | 102 ++++++- cmd/loop/staticaddr_test.go | 275 +++++++++++++++++- cmd/loop/testdata/sessions/AGENTS.md | 1 + .../01_loop-static-new-label-treasury.json | 82 ++++++ .../03_loop-static-updatelabel-ops.json | 61 ++++ .../04_loop-static-updatelabel-ops-again.json | 61 ++++ .../05_loop-static-updatelabel-clear.json | 61 ++++ .../06_loop-static-updatelabel-treasury.json | 61 ++++ ...oop-static-listunspent-label-treasury.json | 73 +++++ .../09_loop-static-l-label-treasury.json | 73 +++++ .../static-loop-in/04_loop-static.json | 1 + docs/loop.1 | 12 + docs/loop.md | 28 +- 13 files changed, 877 insertions(+), 14 deletions(-) create mode 100644 cmd/loop/testdata/sessions/static-labels/01_loop-static-new-label-treasury.json create mode 100644 cmd/loop/testdata/sessions/static-labels/03_loop-static-updatelabel-ops.json create mode 100644 cmd/loop/testdata/sessions/static-labels/04_loop-static-updatelabel-ops-again.json create mode 100644 cmd/loop/testdata/sessions/static-labels/05_loop-static-updatelabel-clear.json create mode 100644 cmd/loop/testdata/sessions/static-labels/06_loop-static-updatelabel-treasury.json create mode 100644 cmd/loop/testdata/sessions/static-labels/08_loop-static-listunspent-label-treasury.json create mode 100644 cmd/loop/testdata/sessions/static-labels/09_loop-static-l-label-treasury.json diff --git a/cmd/loop/staticaddr.go b/cmd/loop/staticaddr.go index 5b76551fa..ebca8521e 100644 --- a/cmd/loop/staticaddr.go +++ b/cmd/loop/staticaddr.go @@ -37,6 +37,7 @@ var staticAddressCommands = &cli.Command{ Commands: []*cli.Command{ newStaticAddressCommand, depositStaticAddressCommand, + updateStaticAddressLabelCommand, listUnspentCommand, listDepositsCommand, listWithdrawalsCommand, @@ -48,18 +49,27 @@ var staticAddressCommands = &cli.Command{ }, } +// newStaticAddressCommand creates a static address and lets operators +// optionally set a local label at creation time. var newStaticAddressCommand = &cli.Command{ Name: "new", Aliases: []string{"n"}, Usage: "Create a new static loop in address.", Description: ` - Creates a new static loop in address. On a fresh installation, loopd creates - the static-address root lazily when the first address is requested; startup - alone does not create an address. Funds sent to the address will be locked by - a 2:2 multisig between us and the loop server, or a timeout path that we can - sweep once it opens up. The funds can either be cooperatively spent with a - signature from the server or looped in. + Creates a fresh static loop in address every time. --label sets local + address metadata, not the funding transaction label. On a fresh installation, + loopd creates the static-address root lazily when the first address is + requested; startup alone does not create an address. Funds sent to the address + will be locked by a 2:2 multisig between us and the loop server, or a timeout + path that we can sweep once it opens up. The funds can either be cooperatively + spent with a signature from the server or looped in. `, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: labelFlag.Name, + Usage: "an optional local label for this static address", + }, + }, Action: newStaticAddress, } @@ -148,11 +158,18 @@ var ( } ) +// newStaticAddress requests a new static address while keeping the label as +// local operator metadata. func newStaticAddress(ctx context.Context, cmd *cli.Command) error { if cmd.NArg() > 0 { return showCommandHelp(ctx, cmd) } + label := cmd.String(labelFlag.Name) + if err := labels.Validate(label); err != nil { + return err + } + err := displayNewAddressWarning() if err != nil { return err @@ -165,7 +182,78 @@ func newStaticAddress(ctx context.Context, cmd *cli.Command) error { defer cleanup() resp, err := client.NewStaticAddress( - ctx, &looprpc.NewStaticAddressRequest{}, + ctx, &looprpc.NewStaticAddressRequest{ + Label: label, + }, + ) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +// updateStaticAddressLabelCommand updates local metadata for an existing static +// address so operators can relabel it without affecting the address script or +// Loop server protocol state. +var updateStaticAddressLabelCommand = &cli.Command{ + Name: "updatelabel", + Usage: "Update the label for a static address.", + ArgsUsage: "