First pass at GetBalance
This commit is contained in:
parent
272db602e4
commit
2200f52687
5 changed files with 99 additions and 26 deletions
|
@ -84,11 +84,12 @@ type Indexer struct {
|
||||||
|
|
||||||
client Client
|
client Client
|
||||||
|
|
||||||
asserter *asserter.Asserter
|
asserter *asserter.Asserter
|
||||||
database storage.Database
|
database storage.Database
|
||||||
blockStorage *storage.BlockStorage
|
blockStorage *storage.BlockStorage
|
||||||
coinStorage *storage.CoinStorage
|
balanceStorage *storage.BalanceStorage
|
||||||
workers []storage.BlockWorker
|
coinStorage *storage.CoinStorage
|
||||||
|
workers []storage.BlockWorker
|
||||||
|
|
||||||
waiter *waitTable
|
waiter *waitTable
|
||||||
}
|
}
|
||||||
|
@ -208,6 +209,7 @@ func Initialize(
|
||||||
&BalanceStorageHelper{asserter},
|
&BalanceStorageHelper{asserter},
|
||||||
&BalanceStorageHandler{},
|
&BalanceStorageHandler{},
|
||||||
)
|
)
|
||||||
|
i.balanceStorage = balanceStorage
|
||||||
|
|
||||||
i.workers = []storage.BlockWorker{coinStorage, balanceStorage}
|
i.workers = []storage.BlockWorker{coinStorage, balanceStorage}
|
||||||
|
|
||||||
|
@ -758,7 +760,11 @@ func (i *Indexer) GetBlockTransaction(
|
||||||
blockIdentifier *types.BlockIdentifier,
|
blockIdentifier *types.BlockIdentifier,
|
||||||
transactionIdentifier *types.TransactionIdentifier,
|
transactionIdentifier *types.TransactionIdentifier,
|
||||||
) (*types.Transaction, error) {
|
) (*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.
|
// GetCoins returns all unspent coins for a particular *types.AccountIdentifier.
|
||||||
|
@ -768,3 +774,27 @@ func (i *Indexer) GetCoins(
|
||||||
) ([]*types.Coin, *types.BlockIdentifier, error) {
|
) ([]*types.Coin, *types.BlockIdentifier, error) {
|
||||||
return i.coinStorage.GetCoins(ctx, accountIdentifier)
|
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
|
||||||
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -154,7 +154,7 @@ func main() {
|
||||||
// requests.
|
// requests.
|
||||||
asserter, err := asserter.NewServer(
|
asserter, err := asserter.NewServer(
|
||||||
bitcoin.OperationTypes,
|
bitcoin.OperationTypes,
|
||||||
false,
|
true,
|
||||||
[]*types.NetworkIdentifier{cfg.Network},
|
[]*types.NetworkIdentifier{cfg.Network},
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
|
|
|
@ -49,27 +49,51 @@ func (s *AccountAPIService) AccountBalance(
|
||||||
return nil, wrapErr(ErrUnavailableOffline, nil)
|
return nil, wrapErr(ErrUnavailableOffline, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
coins, block, err := s.i.GetCoins(ctx, request.AccountIdentifier)
|
// If we are fetching the current balance,
|
||||||
if err != nil {
|
// return all coins for an address and calculate
|
||||||
return nil, wrapErr(ErrUnableToGetCoins, err)
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
balance := "0"
|
||||||
|
for _, coin := range coins {
|
||||||
|
balance, err = types.AddValues(balance, coin.Amount.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, wrapErr(ErrUnableToParseIntermediateResult, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.AccountBalanceResponse{
|
||||||
|
BlockIdentifier: block,
|
||||||
|
Coins: coins,
|
||||||
|
Balances: []*types.Amount{
|
||||||
|
{
|
||||||
|
Value: balance,
|
||||||
|
Currency: s.config.Currency,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
balance := "0"
|
// If we are fetching a historical balance,
|
||||||
for _, coin := range coins {
|
// use balance storage and don't return coins.
|
||||||
balance, err = types.AddValues(balance, coin.Amount.Value)
|
amount, block, err := s.i.GetBalance(
|
||||||
if err != nil {
|
ctx,
|
||||||
return nil, wrapErr(ErrUnableToParseIntermediateResult, err)
|
request.AccountIdentifier,
|
||||||
}
|
s.config.Currency,
|
||||||
|
request.BlockIdentifier,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, wrapErr(ErrUnableToGetBalance, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.AccountBalanceResponse{
|
return &types.AccountBalanceResponse{
|
||||||
BlockIdentifier: block,
|
BlockIdentifier: block,
|
||||||
Coins: coins,
|
|
||||||
Balances: []*types.Amount{
|
Balances: []*types.Amount{
|
||||||
{
|
amount,
|
||||||
Value: balance,
|
|
||||||
Currency: s.config.Currency,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ var (
|
||||||
ErrUnableToGetCoins,
|
ErrUnableToGetCoins,
|
||||||
ErrTransactionNotFound,
|
ErrTransactionNotFound,
|
||||||
ErrCouldNotGetFeeRate,
|
ErrCouldNotGetFeeRate,
|
||||||
|
ErrUnableToGetBalance,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrUnimplemented is returned when an endpoint
|
// ErrUnimplemented is returned when an endpoint
|
||||||
|
@ -59,8 +60,9 @@ var (
|
||||||
// ErrNotReady is returned when bitcoind is not
|
// ErrNotReady is returned when bitcoind is not
|
||||||
// yet ready to serve queries.
|
// yet ready to serve queries.
|
||||||
ErrNotReady = &types.Error{
|
ErrNotReady = &types.Error{
|
||||||
Code: 2, //nolint
|
Code: 2, //nolint
|
||||||
Message: "Bitcoind is not ready",
|
Message: "Bitcoind is not ready",
|
||||||
|
Retriable: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrBitcoind is returned when bitcoind
|
// ErrBitcoind is returned when bitcoind
|
||||||
|
@ -173,6 +175,14 @@ var (
|
||||||
Code: 17, // nolint
|
Code: 17, // nolint
|
||||||
Message: "Could not get suggested fee rate",
|
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
|
// wrapErr adds details to the types.Error provided. We use a function
|
||||||
|
@ -180,8 +190,8 @@ var (
|
||||||
// errors.
|
// errors.
|
||||||
func wrapErr(rErr *types.Error, err error) *types.Error {
|
func wrapErr(rErr *types.Error, err error) *types.Error {
|
||||||
newErr := &types.Error{
|
newErr := &types.Error{
|
||||||
Code: rErr.Code,
|
Code: rErr.Code,
|
||||||
Message: rErr.Message,
|
Message: rErr.Message,
|
||||||
Retriable: rErr.Retriable,
|
Retriable: rErr.Retriable,
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -48,7 +48,10 @@ type Client interface {
|
||||||
|
|
||||||
// Indexer is used by the servicers to get block and account data.
|
// Indexer is used by the servicers to get block and account data.
|
||||||
type Indexer interface {
|
type Indexer interface {
|
||||||
GetBlockLazy(context.Context, *types.PartialBlockIdentifier) (*types.BlockResponse, error)
|
GetBlockLazy(
|
||||||
|
context.Context,
|
||||||
|
*types.PartialBlockIdentifier,
|
||||||
|
) (*types.BlockResponse, error)
|
||||||
GetBlockTransaction(
|
GetBlockTransaction(
|
||||||
context.Context,
|
context.Context,
|
||||||
*types.BlockIdentifier,
|
*types.BlockIdentifier,
|
||||||
|
@ -62,6 +65,12 @@ type Indexer interface {
|
||||||
context.Context,
|
context.Context,
|
||||||
[]*types.Coin,
|
[]*types.Coin,
|
||||||
) ([]*bitcoin.ScriptPubKey, error)
|
) ([]*bitcoin.ScriptPubKey, error)
|
||||||
|
GetBalance(
|
||||||
|
context.Context,
|
||||||
|
*types.AccountIdentifier,
|
||||||
|
*types.Currency,
|
||||||
|
*types.PartialBlockIdentifier,
|
||||||
|
) (*types.Amount, *types.BlockIdentifier, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type unsignedTransaction struct {
|
type unsignedTransaction struct {
|
||||||
|
|
Loading…
Reference in a new issue