Skip to content

Commit 064e45b

Browse files
committed
assets+loopdb: implement functionality to list asset deposits
This commit adds the necessary changes to the asset deposit manager, the underlying sql store and the asset deposit subserver to be able to list asset deposits.
1 parent e28623e commit 064e45b

File tree

7 files changed

+293
-1
lines changed

7 files changed

+293
-1
lines changed

assets/deposit/manager.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,3 +598,40 @@ func (m *Manager) markDepositConfirmed(ctx context.Context, d *Deposit,
598598

599599
return nil
600600
}
601+
602+
// ListDeposits returns all deposits that are in the given range of
603+
// confirmations.
604+
func (m *Manager) ListDeposits(ctx context.Context, minConfs, maxConfs uint32) (
605+
[]Deposit, error) {
606+
607+
bestBlock, err := m.GetBestBlock()
608+
if err != nil {
609+
return nil, err
610+
}
611+
612+
deposits, err := m.store.GetAllDeposits(ctx)
613+
if err != nil {
614+
return nil, err
615+
}
616+
617+
// Only filter based on confirmations if the user has set a min or max
618+
// confs.
619+
filterConfs := minConfs != 0 || maxConfs != 0
620+
621+
// Prefilter deposits based on the min/max confs.
622+
filteredDeposits := make([]Deposit, 0, len(deposits))
623+
for _, deposit := range deposits {
624+
if filterConfs {
625+
// Check that the deposit suits our min/max confs
626+
// criteria.
627+
confs := bestBlock - deposit.ConfirmationHeight
628+
if confs < minConfs || confs > maxConfs {
629+
continue
630+
}
631+
}
632+
633+
filteredDeposits = append(filteredDeposits, deposit)
634+
}
635+
636+
return filteredDeposits, nil
637+
}

assets/deposit/server.go

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,44 @@ func (s *Server) ListAssetDeposits(ctx context.Context,
8383
in *looprpc.ListAssetDepositsRequest) (
8484
*looprpc.ListAssetDepositsResponse, error) {
8585

86-
return nil, status.Error(codes.Unimplemented, "unimplemented")
86+
if s.manager == nil {
87+
return nil, ErrAssetDepositsUnavailable
88+
}
89+
90+
if in.MinConfs < in.MaxConfs {
91+
return nil, status.Error(codes.InvalidArgument,
92+
"max_confs must be greater than or equal to min_confs")
93+
}
94+
95+
deposits, err := s.manager.ListDeposits(ctx, in.MinConfs, in.MaxConfs)
96+
if err != nil {
97+
return nil, status.Error(codes.Internal, err.Error())
98+
}
99+
100+
filteredDeposits := make([]*looprpc.AssetDeposit, 0, len(deposits))
101+
for _, d := range deposits {
102+
rpcDeposit := &looprpc.AssetDeposit{
103+
DepositId: d.ID,
104+
CreatedAt: d.CreatedAt.Unix(),
105+
AssetId: d.AssetID.String(),
106+
Amount: d.Amount,
107+
DepositAddr: d.Addr,
108+
State: d.State.String(),
109+
ConfirmationHeight: d.ConfirmationHeight,
110+
Expiry: d.ConfirmationHeight + d.CsvExpiry,
111+
SweepAddr: d.SweepAddr,
112+
}
113+
114+
if d.Outpoint != nil {
115+
rpcDeposit.AnchorOutpoint = d.Outpoint.String()
116+
}
117+
118+
filteredDeposits = append(filteredDeposits, rpcDeposit)
119+
}
120+
121+
return &looprpc.ListAssetDepositsResponse{
122+
FilteredDeposits: filteredDeposits,
123+
}, nil
87124
}
88125

89126
// RevealAssetDepositKey is the rpc endpoint for loop clients to reveal the

assets/deposit/sql_store.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ import (
55
"database/sql"
66
"fmt"
77

8+
"github.com/btcsuite/btcd/btcec/v2"
89
"github.com/btcsuite/btcd/chaincfg"
10+
"github.com/btcsuite/btcd/wire"
911
"github.com/lightninglabs/loop/loopdb"
1012
"github.com/lightninglabs/loop/loopdb/sqlc"
1113
"github.com/lightninglabs/taproot-assets/address"
14+
"github.com/lightninglabs/taproot-assets/asset"
1215
"github.com/lightningnetwork/lnd/clock"
16+
"github.com/lightningnetwork/lnd/keychain"
1317
)
1418

1519
// Querier is a subset of the methods we need from the postgres.querier
@@ -22,6 +26,9 @@ type Querier interface {
2226

2327
MarkDepositConfirmed(ctx context.Context,
2428
arg sqlc.MarkDepositConfirmedParams) error
29+
30+
GetAssetDeposits(ctx context.Context) ([]sqlc.GetAssetDepositsRow,
31+
error)
2532
}
2633

2734
// DepositBaseDB is the interface that contains all the queries generated
@@ -135,3 +142,115 @@ func (s *SQLStore) UpdateDeposit(ctx context.Context, d *Deposit) error {
135142
)
136143
})
137144
}
145+
146+
func (s *SQLStore) GetAllDeposits(ctx context.Context) ([]Deposit, error) {
147+
sqlDeposits, err := s.db.GetAssetDeposits(ctx)
148+
if err != nil {
149+
return nil, err
150+
}
151+
152+
deposits := make([]Deposit, 0, len(sqlDeposits))
153+
for _, sqlDeposit := range sqlDeposits {
154+
deposit, err := sqlcDepositToDeposit(
155+
sqlDeposit, &s.addressParams,
156+
)
157+
if err != nil {
158+
return nil, err
159+
}
160+
161+
deposits = append(deposits, deposit)
162+
}
163+
164+
return deposits, nil
165+
}
166+
167+
func sqlcDepositToDeposit(sqlDeposit sqlc.GetAssetDepositsRow,
168+
addressParams *address.ChainParams) (Deposit, error) {
169+
170+
clientScriptPubKey, err := btcec.ParsePubKey(
171+
sqlDeposit.ClientScriptPubkey,
172+
)
173+
if err != nil {
174+
return Deposit{}, err
175+
}
176+
177+
serverScriptPubKey, err := btcec.ParsePubKey(
178+
sqlDeposit.ServerScriptPubkey,
179+
)
180+
if err != nil {
181+
return Deposit{}, err
182+
}
183+
184+
clientInteralPubKey, err := btcec.ParsePubKey(
185+
sqlDeposit.ClientInternalPubkey,
186+
)
187+
if err != nil {
188+
return Deposit{}, err
189+
}
190+
191+
serverInternalPubKey, err := btcec.ParsePubKey(
192+
sqlDeposit.ServerInternalPubkey,
193+
)
194+
if err != nil {
195+
return Deposit{}, err
196+
}
197+
198+
clientKeyLocator := keychain.KeyLocator{
199+
Family: keychain.KeyFamily(
200+
sqlDeposit.ClientKeyFamily,
201+
),
202+
Index: uint32(sqlDeposit.ClientKeyIndex),
203+
}
204+
205+
if len(sqlDeposit.AssetID) != len(asset.ID{}) {
206+
return Deposit{}, fmt.Errorf("malformed asset ID for deposit: "+
207+
"%v", sqlDeposit.DepositID)
208+
}
209+
210+
depositInfo := &DepositInfo{
211+
ID: sqlDeposit.DepositID,
212+
Version: AssetDepositProtocolVersion(
213+
sqlDeposit.ProtocolVersion,
214+
),
215+
CreatedAt: sqlDeposit.CreatedAt.Local(),
216+
Amount: uint64(sqlDeposit.Amount),
217+
Addr: sqlDeposit.Addr,
218+
State: State(sqlDeposit.UpdateState),
219+
}
220+
221+
if sqlDeposit.ConfirmationHeight.Valid {
222+
depositInfo.ConfirmationHeight = uint32(
223+
sqlDeposit.ConfirmationHeight.Int32,
224+
)
225+
}
226+
227+
if sqlDeposit.Outpoint.Valid {
228+
outpoint, err := wire.NewOutPointFromString(
229+
sqlDeposit.Outpoint.String,
230+
)
231+
if err != nil {
232+
return Deposit{}, err
233+
}
234+
235+
depositInfo.Outpoint = outpoint
236+
}
237+
238+
if sqlDeposit.SweepAddr.Valid {
239+
depositInfo.SweepAddr = sqlDeposit.SweepAddr.String
240+
}
241+
242+
kit, err := NewKit(
243+
clientScriptPubKey, clientInteralPubKey, serverScriptPubKey,
244+
serverInternalPubKey, clientKeyLocator,
245+
asset.ID(sqlDeposit.AssetID), uint32(sqlDeposit.Expiry),
246+
addressParams,
247+
)
248+
if err != nil {
249+
return Deposit{}, err
250+
}
251+
252+
return Deposit{
253+
Kit: kit,
254+
DepositInfo: depositInfo,
255+
}, nil
256+
}

loopdb/sqlc/asset_deposits.sql.go

Lines changed: 80 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

loopdb/sqlc/models.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

loopdb/sqlc/querier.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

loopdb/sqlc/queries/asset_deposits.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,15 @@ INSERT INTO asset_deposit_updates (
2727
UPDATE asset_deposits
2828
SET confirmation_height = $2, outpoint = $3, pk_script = $4
2929
WHERE deposit_id = $1;
30+
31+
-- name: GetAssetDeposits :many
32+
SELECT d.*, u.update_state, u.update_timestamp
33+
FROM asset_deposits d
34+
JOIN asset_deposit_updates u ON u.id = (
35+
SELECT id
36+
FROM asset_deposit_updates
37+
WHERE deposit_id = d.deposit_id
38+
ORDER BY update_timestamp DESC
39+
LIMIT 1
40+
)
41+
ORDER BY d.created_at ASC;

0 commit comments

Comments
 (0)