mirror of
https://github.com/hanzo-fi/numscript.git
synced 2026-10-30 20:54:52 +00:00
102 lines
2.7 KiB
Go
102 lines
2.7 KiB
Go
package interpreter
|
|
|
|
import (
|
|
"context"
|
|
"math/big"
|
|
"strings"
|
|
)
|
|
|
|
// For each account, list of the needed assets
|
|
type BalanceQueryItem struct {
|
|
Account string
|
|
Asset string
|
|
Color string
|
|
Scope string
|
|
}
|
|
|
|
type MetadataQueryItem = struct {
|
|
Account string
|
|
Scope string
|
|
Keys []string
|
|
}
|
|
|
|
type BalanceQuery []BalanceQueryItem
|
|
|
|
type MetadataQuery []MetadataQueryItem
|
|
|
|
type Store interface {
|
|
// Returns the batched balances for a given batched query.
|
|
//
|
|
// Note: the "Balances" result is expected not to have duplicate entries.
|
|
// Malformed Balances will result it undefined behaviour, and the implementation doesn't guarantee keys are deduped.
|
|
GetBalances(context.Context, BalanceQuery) (Balances, error)
|
|
GetAccountsMetadata(context.Context, MetadataQuery) (AccountsMetadata, error)
|
|
}
|
|
|
|
type StaticStore struct {
|
|
Balances Balances
|
|
Meta AccountsMetadata
|
|
}
|
|
|
|
func (s StaticStore) GetBalances(_ context.Context, q BalanceQuery) (Balances, error) {
|
|
var output Balances
|
|
for _, item := range q {
|
|
baseAsset, isCatchAll := strings.CutSuffix(item.Asset, "/*")
|
|
|
|
if isCatchAll {
|
|
// return every stored asset (of the queried color) under the base asset
|
|
for _, row := range s.Balances {
|
|
if row.Account != item.Account || row.Color != item.Color || row.Scope != item.Scope {
|
|
continue
|
|
}
|
|
if row.Asset == baseAsset || strings.HasPrefix(row.Asset, baseAsset+"/") {
|
|
output = append(output, BalanceRow{
|
|
Account: row.Account,
|
|
Asset: row.Asset,
|
|
Color: row.Color,
|
|
Scope: row.Scope,
|
|
Amount: new(big.Int).Set(row.Amount),
|
|
})
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
|
|
// materialize the queried (account, asset, color, scope), defaulting to a zero balance
|
|
amount := new(big.Int)
|
|
for _, row := range s.Balances {
|
|
if row.Account == item.Account && row.Asset == item.Asset && row.Color == item.Color && row.Scope == item.Scope {
|
|
amount.Set(row.Amount)
|
|
break
|
|
}
|
|
}
|
|
output = append(output, BalanceRow{
|
|
Account: item.Account,
|
|
Asset: item.Asset,
|
|
Color: item.Color,
|
|
Scope: item.Scope,
|
|
Amount: amount,
|
|
})
|
|
}
|
|
|
|
return output, nil
|
|
}
|
|
|
|
func (s StaticStore) GetAccountsMetadata(_ context.Context, q MetadataQuery) (AccountsMetadata, error) {
|
|
// mirror GetBalances: return only the queried (account, scope, key) rows,
|
|
// never the whole store. Callers cache what they query, so over-fetching
|
|
// here would cache keys that were never asked for.
|
|
var output AccountsMetadata
|
|
for _, item := range q {
|
|
for _, key := range item.Keys {
|
|
for _, row := range s.Meta {
|
|
if row.Account == item.Account && row.Scope == item.Scope && row.Key == key {
|
|
output = append(output, row)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return output, nil
|
|
}
|