mirror of https://github.com/lightninglabs/loop
staticaddr: interfaces
parent
d653753ecf
commit
ca51271bdb
@ -0,0 +1,44 @@
|
||||
package deposit
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/lightninglabs/loop/staticaddr/address"
|
||||
"github.com/lightninglabs/loop/staticaddr/script"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
)
|
||||
|
||||
const (
|
||||
IdLength = 32
|
||||
)
|
||||
|
||||
// Store is the database interface that is used to store and retrieve
|
||||
// static address deposits.
|
||||
type Store interface {
|
||||
// CreateDeposit inserts a new deposit into the store.
|
||||
CreateDeposit(ctx context.Context, deposit *Deposit) error
|
||||
|
||||
// UpdateDeposit updates the deposit in the database.
|
||||
UpdateDeposit(ctx context.Context, deposit *Deposit) error
|
||||
|
||||
// GetDeposit retrieves a deposit with depositID from the database.
|
||||
GetDeposit(ctx context.Context, depositID ID) (*Deposit, error)
|
||||
|
||||
// AllDeposits retrieves all deposits from the store.
|
||||
AllDeposits(ctx context.Context) ([]*Deposit, error)
|
||||
}
|
||||
|
||||
// AddressManager handles fetching of address parameters.
|
||||
type AddressManager interface {
|
||||
// GetStaticAddressParameters returns the static address parameters.
|
||||
GetStaticAddressParameters(ctx context.Context) (*address.Parameters,
|
||||
error)
|
||||
|
||||
// GetStaticAddress returns the deposit address for the given
|
||||
// client and server public keys.
|
||||
GetStaticAddress(ctx context.Context) (*script.StaticAddress, error)
|
||||
|
||||
// ListUnspent returns a list of utxos at the static address.
|
||||
ListUnspent(ctx context.Context, minConfs,
|
||||
maxConfs int32) ([]*lnwallet.Utxo, error)
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
package deposit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
"github.com/lightninglabs/loop/loopdb"
|
||||
"github.com/lightninglabs/loop/loopdb/sqlc"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
)
|
||||
|
||||
// SqlStore is the backing store for static addresses.
|
||||
type SqlStore struct {
|
||||
baseDB *loopdb.BaseDB
|
||||
|
||||
clock clock.Clock
|
||||
}
|
||||
|
||||
// NewSqlStore constructs a new SQLStore from a BaseDB. The BaseDB is agnostic
|
||||
// to the underlying driver which can be postgres or sqlite.
|
||||
func NewSqlStore(db *loopdb.BaseDB) *SqlStore {
|
||||
return &SqlStore{
|
||||
baseDB: db,
|
||||
|
||||
clock: clock.NewDefaultClock(),
|
||||
}
|
||||
}
|
||||
|
||||
// CreateDeposit creates a static address record in the database.
|
||||
func (s *SqlStore) CreateDeposit(ctx context.Context, deposit *Deposit) error {
|
||||
createArgs := sqlc.CreateDepositParams{
|
||||
DepositID: deposit.ID[:],
|
||||
TxHash: deposit.Hash[:],
|
||||
OutIndex: int32(deposit.Index),
|
||||
Amount: int64(deposit.Value),
|
||||
ConfirmationHeight: deposit.ConfirmationHeight,
|
||||
TimeoutSweepPkScript: deposit.TimeOutSweepPkScript,
|
||||
}
|
||||
|
||||
updateArgs := sqlc.InsertDepositUpdateParams{
|
||||
DepositID: deposit.ID[:],
|
||||
UpdateTimestamp: s.clock.Now().UTC(),
|
||||
UpdateState: string(deposit.State),
|
||||
}
|
||||
|
||||
return s.baseDB.ExecTx(ctx, &loopdb.SqliteTxOptions{},
|
||||
func(q *sqlc.Queries) error {
|
||||
err := q.CreateDeposit(ctx, createArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return q.InsertDepositUpdate(ctx, updateArgs)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateDeposit updates the deposit in the database.
|
||||
func (s *SqlStore) UpdateDeposit(ctx context.Context, deposit *Deposit) error {
|
||||
insertUpdateArgs := sqlc.InsertDepositUpdateParams{
|
||||
DepositID: deposit.ID[:],
|
||||
UpdateTimestamp: s.clock.Now().UTC(),
|
||||
UpdateState: string(deposit.State),
|
||||
}
|
||||
|
||||
var (
|
||||
txHash = deposit.Hash[:]
|
||||
outIndex = sql.NullInt32{
|
||||
Int32: int32(deposit.Index),
|
||||
Valid: true,
|
||||
}
|
||||
)
|
||||
|
||||
updateArgs := sqlc.UpdateDepositParams{
|
||||
DepositID: deposit.ID[:],
|
||||
TxHash: txHash,
|
||||
OutIndex: outIndex.Int32,
|
||||
ConfirmationHeight: marshalSqlNullInt64(
|
||||
deposit.ConfirmationHeight,
|
||||
).Int64,
|
||||
}
|
||||
|
||||
return s.baseDB.ExecTx(ctx, &loopdb.SqliteTxOptions{},
|
||||
func(q *sqlc.Queries) error {
|
||||
err := q.UpdateDeposit(ctx, updateArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return q.InsertDepositUpdate(ctx, insertUpdateArgs)
|
||||
})
|
||||
}
|
||||
|
||||
// GetDeposit retrieves the deposit from the database.
|
||||
func (s *SqlStore) GetDeposit(ctx context.Context, id ID) (*Deposit, error) {
|
||||
var deposit *Deposit
|
||||
err := s.baseDB.ExecTx(ctx, loopdb.NewSqlReadOpts(),
|
||||
func(q *sqlc.Queries) error {
|
||||
row, err := q.GetDeposit(ctx, id[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
latestUpdate, err := q.GetLatestDepositUpdate(
|
||||
ctx, id[:],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deposit, err = s.toDeposit(row, latestUpdate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return deposit, nil
|
||||
}
|
||||
|
||||
// AllDeposits retrieves all known deposits to our static address.
|
||||
func (s *SqlStore) AllDeposits(ctx context.Context) ([]*Deposit, error) {
|
||||
var allDeposits []*Deposit
|
||||
|
||||
err := s.baseDB.ExecTx(ctx, loopdb.NewSqlReadOpts(),
|
||||
func(q *sqlc.Queries) error {
|
||||
var err error
|
||||
|
||||
deposits, err := q.AllDeposits(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, deposit := range deposits {
|
||||
latestUpdate, err := q.GetLatestDepositUpdate(
|
||||
ctx, deposit.DepositID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d, err := s.toDeposit(deposit, latestUpdate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allDeposits = append(allDeposits, d)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return allDeposits, nil
|
||||
}
|
||||
|
||||
// toDeposit converts an sql deposit to a deposit.
|
||||
func (s *SqlStore) toDeposit(row sqlc.Deposit,
|
||||
lastUpdate sqlc.DepositUpdate) (*Deposit, error) {
|
||||
|
||||
id := ID{}
|
||||
err := id.FromByteSlice(row.DepositID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var txHash *chainhash.Hash
|
||||
if row.TxHash != nil {
|
||||
txHash, err = chainhash.NewHash(row.TxHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &Deposit{
|
||||
ID: id,
|
||||
State: fsm.StateType(lastUpdate.UpdateState),
|
||||
OutPoint: wire.OutPoint{
|
||||
Hash: *txHash,
|
||||
Index: uint32(row.OutIndex),
|
||||
},
|
||||
Value: btcutil.Amount(row.Amount),
|
||||
ConfirmationHeight: row.ConfirmationHeight,
|
||||
TimeOutSweepPkScript: row.TimeoutSweepPkScript,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Close closes the database connection.
|
||||
func (s *SqlStore) Close() {
|
||||
s.baseDB.DB.Close()
|
||||
}
|
||||
|
||||
// marshalSqlNullInt64 converts an int64 to a sql.NullInt64.
|
||||
func marshalSqlNullInt64(i int64) sql.NullInt64 {
|
||||
return sql.NullInt64{
|
||||
Int64: i,
|
||||
Valid: i != 0,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue