Skip to content

Commit 8371808

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 e2872fc commit 8371808

File tree

6 files changed

+317
-1
lines changed

6 files changed

+317
-1
lines changed

assets/deposit/manager.go

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

663663
return nil
664664
}
665+
666+
// ListDeposits returns all deposits that are in the given range of
667+
// confirmations.
668+
func (m *Manager) ListDeposits(ctx context.Context, minConfs, maxConfs uint32) (
669+
[]Deposit, error) {
670+
671+
bestBlock, err := m.GetBestBlock()
672+
if err != nil {
673+
return nil, err
674+
}
675+
676+
deposits, err := m.store.GetAllDeposits(ctx)
677+
if err != nil {
678+
return nil, err
679+
}
680+
681+
// Only filter based on confirmations if the user has set a min or max
682+
// confs.
683+
filterConfs := minConfs != 0 || maxConfs != 0
684+
685+
// Prefilter deposits based on the min/max confs.
686+
filteredDeposits := make([]Deposit, 0, len(deposits))
687+
for _, deposit := range deposits {
688+
if filterConfs {
689+
// Check that the deposit suits our min/max confs
690+
// criteria.
691+
confs := bestBlock - deposit.ConfirmationHeight
692+
if confs < minConfs || confs > maxConfs {
693+
continue
694+
}
695+
}
696+
697+
filteredDeposits = append(filteredDeposits, deposit)
698+
}
699+
700+
return filteredDeposits, nil
701+
}

assets/deposit/server.go

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,55 @@ 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+
}
112+
113+
if d.Outpoint != nil {
114+
rpcDeposit.AnchorOutpoint = d.Outpoint.String()
115+
}
116+
117+
if d.SweepScriptKey != nil {
118+
rpcDeposit.SweepScriptKey = hex.EncodeToString(
119+
d.SweepScriptKey.SerializeCompressed(),
120+
)
121+
}
122+
123+
if d.SweepInternalKey != nil {
124+
rpcDeposit.SweepInternalKey = hex.EncodeToString(
125+
d.SweepInternalKey.SerializeCompressed(),
126+
)
127+
}
128+
129+
filteredDeposits = append(filteredDeposits, rpcDeposit)
130+
}
131+
132+
return &looprpc.ListAssetDepositsResponse{
133+
FilteredDeposits: filteredDeposits,
134+
}, nil
87135
}
88136

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

assets/deposit/sql_store.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@ package deposit
33
import (
44
"context"
55
"database/sql"
6+
"fmt"
67

8+
"github.com/btcsuite/btcd/btcec/v2"
79
"github.com/btcsuite/btcd/chaincfg"
10+
"github.com/btcsuite/btcd/wire"
811
"github.com/lightninglabs/loop/loopdb"
912
"github.com/lightninglabs/loop/loopdb/sqlc"
1013
"github.com/lightninglabs/taproot-assets/address"
14+
"github.com/lightninglabs/taproot-assets/asset"
1115
"github.com/lightningnetwork/lnd/clock"
16+
"github.com/lightningnetwork/lnd/keychain"
1217
)
1318

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

2227
MarkDepositConfirmed(ctx context.Context,
2328
arg sqlc.MarkDepositConfirmedParams) error
29+
30+
GetAssetDeposits(ctx context.Context) ([]sqlc.GetAssetDepositsRow,
31+
error)
2432
}
2533

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

loopdb/sqlc/asset_deposits.sql.go

Lines changed: 82 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)