Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -238,4 +238,8 @@ replace gonum.org/v1/gonum => github.com/gonum/gonum v0.11.0

replace gonum.org/v1/plot => github.com/gonum/plot v0.10.1

// the replaced domain disappeared and package moved to new location. Worth
// checking later if the domain reappears and replace can be removed.
replace dario.cat/mergo => github.com/darccio/mergo v1.0.1

go 1.25.5
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -592,8 +592,6 @@ cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoIS
cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M=
cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
Expand Down Expand Up @@ -747,6 +745,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/darccio/mergo v1.0.1 h1:xYD7+aWQRjjQuN2qd0DjhRavXPuEnm8pMIRJMY1AAiU=
github.com/darccio/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand Down
35 changes: 35 additions & 0 deletions loopd/swapclient_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -1966,6 +1966,10 @@ func (s *swapClientServer) ListStaticAddressSwaps(ctx context.Context,

var clientSwaps []*looprpc.StaticAddressLoopInSwap
for _, swp := range swaps {
if swp == nil {
continue
}

chainParams, err := s.network.ChainParams()
if err != nil {
return nil, fmt.Errorf("error getting chain params")
Expand Down Expand Up @@ -2005,13 +2009,19 @@ func (s *swapClientServer) ListStaticAddressSwaps(ctx context.Context,
if swp.SelectedAmount > 0 {
swapAmount = swp.SelectedAmount
}
costServer := staticAddressLoopInSwapServerCost(swp)
initiationTime := staticAddressLoopInTimestamp(swp.InitiationTime)
lastUpdateTime := staticAddressLoopInTimestamp(swp.LastUpdateTime)
swap := &looprpc.StaticAddressLoopInSwap{
SwapHash: swp.SwapHash[:],
DepositOutpoints: swp.DepositOutpoints,
State: state,
SwapAmountSatoshis: int64(swapAmount),
PaymentRequestAmountSatoshis: payReqAmount,
Deposits: protoDeposits,
InitiationTime: initiationTime,
LastUpdateTime: lastUpdateTime,
CostServer: costServer,
}

clientSwaps = append(clientSwaps, swap)
Expand All @@ -2022,6 +2032,31 @@ func (s *swapClientServer) ListStaticAddressSwaps(ctx context.Context,
}, nil
}

func staticAddressLoopInTimestamp(t time.Time) int64 {
if t.IsZero() {
return 0
}

return t.UnixNano()
}

// staticAddressLoopInSwapServerCost returns the paid server cost using the
// legacy ListSwaps cost semantics. Static loop-ins currently only persist the
// accepted quote fee, and that fee is paid once the swap invoice settles.
// Timeout-path miner fees are not persisted, so cost_onchain and cost_offchain
// remain zero instead of returning an estimate as an actual cost.
func staticAddressLoopInSwapServerCost(swp *loopin.StaticAddressLoopIn) int64 {
switch swp.GetState() {
case loopin.PaymentReceived, loopin.Succeeded,
loopin.SucceededTransitioningFailed:

return int64(swp.QuotedSwapFee)

default:
return 0
}
}

// GetStaticAddressSummary returns a summary of static address-related
// information. Amongst deposits and withdrawals and their total values, it also
// includes a list of detailed deposit information filtered by their state.
Expand Down
67 changes: 67 additions & 0 deletions loopd/swapclient_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/lightninglabs/loop/looprpc"
"github.com/lightninglabs/loop/staticaddr/address"
"github.com/lightninglabs/loop/staticaddr/deposit"
"github.com/lightninglabs/loop/staticaddr/loopin"
"github.com/lightninglabs/loop/staticaddr/script"
"github.com/lightninglabs/loop/swap"
mock_lnd "github.com/lightninglabs/loop/test"
Expand Down Expand Up @@ -306,6 +307,72 @@ func TestSetLiquidityParamsRejectsStaticAutoloopWithoutExperimental(
require.ErrorContains(t, err, "--experimental")
}

// TestStaticAddressLoopInTimestamp verifies that zero timestamps are omitted
// from static loop-in responses instead of passing a zero time to UnixNano.
func TestStaticAddressLoopInTimestamp(t *testing.T) {
require.Zero(t, staticAddressLoopInTimestamp(time.Time{}))

timestamp := time.Unix(1_234, 567).UTC()
require.Equal(
t, timestamp.UnixNano(),
staticAddressLoopInTimestamp(timestamp),
)
}

// TestStaticAddressLoopInSwapServerCost verifies that static loop-in server
// costs are only reported once the invoice payment was received. Timeout path
// costs are not persisted today, so they are intentionally not estimated here.
func TestStaticAddressLoopInSwapServerCost(t *testing.T) {
const quoteFee = btcutil.Amount(1_234)

tests := []struct {
name string
state fsm.StateType
wantServer int64
}{
{
name: "pending before payment",
state: loopin.SignHtlcTx,
},
{
name: "payment received",
state: loopin.PaymentReceived,
wantServer: int64(quoteFee),
},
{
name: "succeeded",
state: loopin.Succeeded,
wantServer: int64(quoteFee),
},
{
name: "succeeded transition failed",
state: loopin.SucceededTransitioningFailed,
wantServer: int64(quoteFee),
},
{
name: "timeout swept",
state: loopin.HtlcTimeoutSwept,
},
{
name: "failed",
state: loopin.Failed,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
swap := &loopin.StaticAddressLoopIn{
QuotedSwapFee: quoteFee,
}
swap.SetState(test.state)

costServer := staticAddressLoopInSwapServerCost(swap)

require.Equal(t, test.wantServer, costServer)
})
}
}

// TestRPCAutoloopReasonStaticLoopInNoCandidate verifies that the new planner
// reason is exposed over rpc.
func TestRPCAutoloopReasonStaticLoopInNoCandidate(t *testing.T) {
Expand Down
58 changes: 55 additions & 3 deletions looprpc/client.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions looprpc/client.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2143,6 +2143,31 @@ message StaticAddressLoopInSwap {
The deposits that were used for this swap.
*/
repeated Deposit deposits = 6;

/*
Initiation time of the swap.
*/
int64 initiation_time = 7;

/*
Last update time of the swap.
*/
int64 last_update_time = 8;

/*
Swap server cost.
*/
int64 cost_server = 9;

/*
On-chain transaction cost.
*/
int64 cost_onchain = 10;

/*
Off-chain routing fees.
*/
int64 cost_offchain = 11;
}

enum StaticAddressLoopInSwapState {
Expand Down
25 changes: 25 additions & 0 deletions looprpc/client.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -2807,6 +2807,31 @@
"$ref": "#/definitions/looprpcDeposit"
},
"description": "The deposits that were used for this swap."
},
"initiation_time": {
"type": "string",
"format": "int64",
"description": "Initiation time of the swap."
},
"last_update_time": {
"type": "string",
"format": "int64",
"description": "Last update time of the swap."
},
"cost_server": {
"type": "string",
"format": "int64",
"description": "Swap server cost."
},
"cost_onchain": {
"type": "string",
"format": "int64",
"description": "On-chain transaction cost."
},
"cost_offchain": {
"type": "string",
"format": "int64",
"description": "Off-chain routing fees."
}
}
},
Expand Down
4 changes: 4 additions & 0 deletions looprpc/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,7 @@ replace gonum.org/v1/gonum => github.com/gonum/gonum v0.11.0
replace github.com/golang-migrate/migrate/v4 => github.com/lightninglabs/migrate/v4 v4.18.2-9023d66a-fork-pr-2

replace lukechampine.com/uint128 => github.com/lukechampine/uint128 v1.2.0

// the replaced domain disappeared and package moved to new location. Worth
// checking later if the domain reappears and replace can be removed.
replace dario.cat/mergo => github.com/darccio/mergo v1.0.1
1 change: 1 addition & 0 deletions looprpc/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/darccio/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand Down
Loading