2026-07-08 13:51:46 +02:00
|
|
|
package loopd
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"testing"
|
|
|
|
|
|
2026-07-08 13:55:04 +02:00
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
2026-07-08 13:51:46 +02:00
|
|
|
"github.com/btcsuite/btcd/btcutil"
|
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
|
|
|
"github.com/btcsuite/btclog/v2"
|
|
|
|
|
"github.com/lightninglabs/loop/looprpc"
|
|
|
|
|
"github.com/lightninglabs/loop/staticaddr/address"
|
|
|
|
|
"github.com/lightninglabs/loop/staticaddr/deposit"
|
|
|
|
|
"github.com/lightninglabs/loop/staticaddr/script"
|
|
|
|
|
mock_lnd "github.com/lightninglabs/loop/test"
|
2026-07-08 13:55:04 +02:00
|
|
|
"github.com/lightningnetwork/lnd/lnwallet"
|
2026-07-08 13:51:46 +02:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type staticAddrDepositStore struct {
|
|
|
|
|
allDeposits []*deposit.Deposit
|
|
|
|
|
byOutpoint map[string]*deposit.Deposit
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CreateDeposit implements deposit.Store for static address server tests.
|
|
|
|
|
func (s *staticAddrDepositStore) CreateDeposit(context.Context,
|
|
|
|
|
*deposit.Deposit) error {
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// UpdateDeposit implements deposit.Store for static address server tests.
|
|
|
|
|
func (s *staticAddrDepositStore) UpdateDeposit(context.Context,
|
|
|
|
|
*deposit.Deposit) error {
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetDeposit implements deposit.Store for static address server tests.
|
|
|
|
|
func (s *staticAddrDepositStore) GetDeposit(context.Context,
|
|
|
|
|
deposit.ID) (*deposit.Deposit, error) {
|
|
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DepositForOutpoint returns the deposit for the requested outpoint.
|
|
|
|
|
func (s *staticAddrDepositStore) DepositForOutpoint(_ context.Context,
|
|
|
|
|
outpoint string) (*deposit.Deposit, error) {
|
|
|
|
|
|
|
|
|
|
if deposit, ok := s.byOutpoint[outpoint]; ok {
|
|
|
|
|
return deposit, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil, deposit.ErrDepositNotFound
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AllDeposits returns all deposits seeded into the test store.
|
|
|
|
|
func (s *staticAddrDepositStore) AllDeposits(context.Context) (
|
|
|
|
|
[]*deposit.Deposit, error) {
|
|
|
|
|
|
|
|
|
|
return s.allDeposits, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-08 13:55:04 +02:00
|
|
|
type staticAddrTestAddressManager struct{}
|
|
|
|
|
|
|
|
|
|
func (s *staticAddrTestAddressManager) GetStaticAddressParameters(
|
|
|
|
|
context.Context) (*script.Parameters, error) {
|
|
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *staticAddrTestAddressManager) GetStaticAddress(
|
|
|
|
|
context.Context) (*script.StaticAddress, error) {
|
|
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *staticAddrTestAddressManager) ListUnspent(context.Context,
|
|
|
|
|
int32, int32) ([]*lnwallet.Utxo, error) {
|
|
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *staticAddrTestAddressManager) GetTaprootAddress(
|
|
|
|
|
*btcec.PublicKey, *btcec.PublicKey, int64) (*btcutil.AddressTaproot,
|
|
|
|
|
error) {
|
|
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-08 13:51:46 +02:00
|
|
|
// newTestDepositManager creates a deposit manager backed by seeded deposits.
|
|
|
|
|
func newTestDepositManager(
|
|
|
|
|
deposits ...*deposit.Deposit) *deposit.Manager {
|
|
|
|
|
|
|
|
|
|
byOutpoint := make(map[string]*deposit.Deposit, len(deposits))
|
|
|
|
|
for _, deposit := range deposits {
|
|
|
|
|
byOutpoint[deposit.OutPoint.String()] = deposit
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return deposit.NewManager(&deposit.ManagerConfig{
|
2026-07-08 13:55:04 +02:00
|
|
|
AddressManager: &staticAddrTestAddressManager{},
|
2026-07-08 13:51:46 +02:00
|
|
|
Store: &staticAddrDepositStore{
|
|
|
|
|
allDeposits: deposits,
|
|
|
|
|
byOutpoint: byOutpoint,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// newTestStaticAddressContext creates static address test dependencies.
|
|
|
|
|
func newTestStaticAddressContext(t *testing.T) (*address.Manager,
|
|
|
|
|
*mock_lnd.LndMockServices) {
|
|
|
|
|
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
mock := mock_lnd.NewMockLnd()
|
|
|
|
|
_, client := mock_lnd.CreateKey(1)
|
|
|
|
|
_, server := mock_lnd.CreateKey(2)
|
|
|
|
|
|
|
|
|
|
addrStore := &mockAddressStore{
|
|
|
|
|
params: []*script.Parameters{{
|
|
|
|
|
ClientPubkey: client,
|
|
|
|
|
ServerPubkey: server,
|
|
|
|
|
Expiry: 10,
|
|
|
|
|
PkScript: []byte("pkscript"),
|
|
|
|
|
}},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addrMgr, err := address.NewManager(&address.ManagerConfig{
|
|
|
|
|
Store: addrStore,
|
|
|
|
|
WalletKit: mock.WalletKit,
|
|
|
|
|
ChainParams: mock.ChainParams,
|
|
|
|
|
}, 1)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
return addrMgr, mock
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-08 13:55:32 +02:00
|
|
|
// TestListStaticAddressDepositsReturnsVisibleDeposits verifies normal deposit
|
|
|
|
|
// listings include visible deposit records.
|
|
|
|
|
func TestListStaticAddressDepositsReturnsVisibleDeposits(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
available := &deposit.Deposit{
|
|
|
|
|
OutPoint: wire.OutPoint{
|
|
|
|
|
Hash: chainhash.Hash{2},
|
|
|
|
|
Index: 2,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
available.SetState(deposit.Deposited)
|
|
|
|
|
|
|
|
|
|
addrMgr, lnd := newTestStaticAddressContext(t)
|
|
|
|
|
server := &swapClientServer{
|
|
|
|
|
depositManager: newTestDepositManager(available),
|
|
|
|
|
staticAddressManager: addrMgr,
|
|
|
|
|
lnd: &lnd.LndServices,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp, err := server.ListStaticAddressDeposits(
|
|
|
|
|
context.Background(), &looprpc.ListStaticAddressDepositsRequest{},
|
|
|
|
|
)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Len(t, resp.FilteredDeposits, 1)
|
|
|
|
|
require.Equal(
|
|
|
|
|
t, available.OutPoint.String(),
|
|
|
|
|
resp.FilteredDeposits[0].Outpoint,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestGetStaticAddressSummaryTotalsDeposits verifies visible deposits are
|
|
|
|
|
// included in static address summary totals.
|
|
|
|
|
func TestGetStaticAddressSummaryTotalsDeposits(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
unconfirmed := &deposit.Deposit{
|
|
|
|
|
OutPoint: wire.OutPoint{
|
|
|
|
|
Hash: chainhash.Hash{4},
|
|
|
|
|
Index: 4,
|
|
|
|
|
},
|
|
|
|
|
Value: btcutil.Amount(2_000),
|
|
|
|
|
ConfirmationHeight: 0,
|
|
|
|
|
}
|
|
|
|
|
unconfirmed.SetState(deposit.Deposited)
|
|
|
|
|
|
|
|
|
|
confirmed := &deposit.Deposit{
|
|
|
|
|
OutPoint: wire.OutPoint{
|
|
|
|
|
Hash: chainhash.Hash{5},
|
|
|
|
|
Index: 5,
|
|
|
|
|
},
|
|
|
|
|
Value: btcutil.Amount(3_000),
|
|
|
|
|
ConfirmationHeight: 123,
|
|
|
|
|
}
|
|
|
|
|
confirmed.SetState(deposit.Deposited)
|
|
|
|
|
|
|
|
|
|
addrMgr, _ := newTestStaticAddressContext(t)
|
|
|
|
|
server := &swapClientServer{
|
|
|
|
|
depositManager: newTestDepositManager(
|
|
|
|
|
unconfirmed, confirmed,
|
|
|
|
|
),
|
|
|
|
|
staticAddressManager: addrMgr,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp, err := server.GetStaticAddressSummary(
|
|
|
|
|
context.Background(), &looprpc.StaticAddressSummaryRequest{},
|
|
|
|
|
)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.EqualValues(t, 2, resp.TotalNumDeposits)
|
|
|
|
|
require.EqualValues(t, 2_000, resp.ValueUnconfirmedSatoshis)
|
|
|
|
|
require.EqualValues(t, 3_000, resp.ValueDepositedSatoshis)
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-08 13:51:46 +02:00
|
|
|
// TestGetLoopInQuoteRejectsUnavailableSelectedDeposit verifies manual quote
|
|
|
|
|
// requests fail for selected deposits that are no longer available.
|
|
|
|
|
func TestGetLoopInQuoteRejectsUnavailableSelectedDeposit(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
setLogger(btclog.Disabled)
|
|
|
|
|
|
|
|
|
|
locked := &deposit.Deposit{
|
|
|
|
|
OutPoint: wire.OutPoint{
|
|
|
|
|
Hash: chainhash.Hash{6},
|
|
|
|
|
Index: 6,
|
|
|
|
|
},
|
|
|
|
|
Value: btcutil.Amount(5_000),
|
|
|
|
|
}
|
|
|
|
|
locked.SetState(deposit.LoopingIn)
|
|
|
|
|
|
|
|
|
|
addrMgr, lnd := newTestStaticAddressContext(t)
|
|
|
|
|
server := &swapClientServer{
|
|
|
|
|
depositManager: newTestDepositManager(locked),
|
|
|
|
|
staticAddressManager: addrMgr,
|
|
|
|
|
lnd: &lnd.LndServices,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err := server.GetLoopInQuote(context.Background(), &looprpc.QuoteRequest{
|
|
|
|
|
DepositOutpoints: []string{locked.OutPoint.String()},
|
|
|
|
|
})
|
|
|
|
|
require.ErrorContains(t, err, "is not currently available")
|
|
|
|
|
}
|