First pass at GetBalance

This commit is contained in:
Patrick O'Grady 2020-10-27 10:25:02 -07:00
parent 272db602e4
commit 2200f52687
No known key found for this signature in database
GPG key ID: 8DE11C985C0C8D85
5 changed files with 99 additions and 26 deletions

View file

@ -87,6 +87,7 @@ type Indexer struct {
asserter *asserter.Asserter
database storage.Database
blockStorage *storage.BlockStorage
balanceStorage *storage.BalanceStorage
coinStorage *storage.CoinStorage
workers []storage.BlockWorker
@ -208,6 +209,7 @@ func Initialize(
&BalanceStorageHelper{asserter},
&BalanceStorageHandler{},
)
i.balanceStorage = balanceStorage
i.workers = []storage.BlockWorker{coinStorage, balanceStorage}
@ -758,7 +760,11 @@ func (i *Indexer) GetBlockTransaction(
blockIdentifier *types.BlockIdentifier,
transactionIdentifier *types.TransactionIdentifier,
) (*types.Transaction, error) {
return i.blockStorage.GetBlockTransaction(ctx, blockIdentifier, transactionIdentifier)
return i.blockStorage.GetBlockTransaction(
ctx,
blockIdentifier,
transactionIdentifier,
)
}
// GetCoins returns all unspent coins for a particular *types.AccountIdentifier.
@ -768,3 +774,27 @@ func (i *Indexer) GetCoins(
) ([]*types.Coin, *types.BlockIdentifier, error) {
return i.coinStorage.GetCoins(ctx, accountIdentifier)
}
func (i *Indexer) GetBalance(
ctx context.Context,
accountIdentifier *types.AccountIdentifier,
currency *types.Currency,
blockIdentifier *types.PartialBlockIdentifier,
) (*types.Amount, *types.BlockIdentifier, error) {
blockResponse, err := i.GetBlockLazy(ctx, blockIdentifier)
if err != nil {
return nil, nil, err
}
amount, err := i.balanceStorage.GetBalance(
ctx,
accountIdentifier,
currency,
blockResponse.Block.BlockIdentifier,
)
if err != nil {
return nil, nil, err
}
return amount, blockResponse.Block.BlockIdentifier, nil
}

View file

@ -154,7 +154,7 @@ func main() {
// requests.
asserter, err := asserter.NewServer(
bitcoin.OperationTypes,
false,
true,
[]*types.NetworkIdentifier{cfg.Network},
nil,
)

View file

@ -49,6 +49,10 @@ func (s *AccountAPIService) AccountBalance(
return nil, wrapErr(ErrUnavailableOffline, nil)
}
// If we are fetching the current balance,
// return all coins for an address and calculate
// the balance from those coins.
if request.BlockIdentifier == nil {
coins, block, err := s.i.GetCoins(ctx, request.AccountIdentifier)
if err != nil {
return nil, wrapErr(ErrUnableToGetCoins, err)
@ -72,4 +76,24 @@ func (s *AccountAPIService) AccountBalance(
},
},
}, nil
}
// If we are fetching a historical balance,
// use balance storage and don't return coins.
amount, block, err := s.i.GetBalance(
ctx,
request.AccountIdentifier,
s.config.Currency,
request.BlockIdentifier,
)
if err != nil {
return nil, wrapErr(ErrUnableToGetBalance, err)
}
return &types.AccountBalanceResponse{
BlockIdentifier: block,
Balances: []*types.Amount{
amount,
},
}, nil
}

View file

@ -40,6 +40,7 @@ var (
ErrUnableToGetCoins,
ErrTransactionNotFound,
ErrCouldNotGetFeeRate,
ErrUnableToGetBalance,
}
// ErrUnimplemented is returned when an endpoint
@ -61,6 +62,7 @@ var (
ErrNotReady = &types.Error{
Code: 2, //nolint
Message: "Bitcoind is not ready",
Retriable: true,
}
// ErrBitcoind is returned when bitcoind
@ -173,6 +175,14 @@ var (
Code: 17, // nolint
Message: "Could not get suggested fee rate",
}
// ErrUnableToGetBalance is returned by the indexer
// when it is not possible to get the balance
// of a *types.AccountIdentifier.
ErrUnableToGetBalance = &types.Error{
Code: 18, //nolint
Message: "Unable to get balance",
}
)
// wrapErr adds details to the types.Error provided. We use a function

View file

@ -48,7 +48,10 @@ type Client interface {
// Indexer is used by the servicers to get block and account data.
type Indexer interface {
GetBlockLazy(context.Context, *types.PartialBlockIdentifier) (*types.BlockResponse, error)
GetBlockLazy(
context.Context,
*types.PartialBlockIdentifier,
) (*types.BlockResponse, error)
GetBlockTransaction(
context.Context,
*types.BlockIdentifier,
@ -62,6 +65,12 @@ type Indexer interface {
context.Context,
[]*types.Coin,
) ([]*bitcoin.ScriptPubKey, error)
GetBalance(
context.Context,
*types.AccountIdentifier,
*types.Currency,
*types.PartialBlockIdentifier,
) (*types.Amount, *types.BlockIdentifier, error)
}
type unsignedTransaction struct {