@@ -17,6 +17,14 @@ import (
1717 timelock_token "github.com/code-payments/code-server/pkg/solana/timelock/v1"
1818)
1919
20+ type Source uint8
21+
22+ const (
23+ UnknownSource Source = iota
24+ CacheSource
25+ BlockchainSource
26+ )
27+
2028const (
2129 metricsPackageName = "balance"
2230)
@@ -51,6 +59,9 @@ type State struct {
5159
5260// CalculateFromCache is the default and recommended strategy for reliably estimating
5361// a token account's balance using cached values.
62+ //
63+ // Note: Use this method when calculating balances for accounts that are managed by
64+ // Code (ie. Timelock account) and operate within the L2 system.
5465func CalculateFromCache (ctx context.Context , data code_data.Provider , tokenAccount * common.Account ) (uint64 , error ) {
5566 tracer := metrics .TraceMethodCall (ctx , metricsPackageName , "CalculateFromCache" )
5667 tracer .AddAttribute ("account" , tokenAccount .PublicKey ().ToBase58 ())
@@ -106,32 +117,37 @@ func CalculateFromCache(ctx context.Context, data code_data.Provider, tokenAccou
106117}
107118
108119// CalculateFromBlockchain is the default and recommended strategy for reliably
109- // estimating a token account's balance from the blockchain.
120+ // estimating a token account's balance from the blockchain. This strategy is
121+ // resistant to various RPC failure nodes, and may return a cached value. The
122+ // source of the balance calculation is returned.
123+ //
124+ // Note: Use this method when calculating token account balances that are external
125+ // and not managed by Code and outside the L2 system.
110126//
111127// todo: add a batching variant
112- func CalculateFromBlockchain (ctx context.Context , data code_data.Provider , tokenAccount * common.Account ) (uint64 , error ) {
128+ func CalculateFromBlockchain (ctx context.Context , data code_data.Provider , tokenAccount * common.Account ) (uint64 , Source , error ) {
113129 var cachedQuarks uint64
114130 var cachedSlot uint64
115131 checkpointRecord , err := data .GetBalanceCheckpoint (ctx , tokenAccount .PublicKey ().ToBase58 ())
116132 if err == nil {
117133 cachedQuarks = checkpointRecord .Quarks
118134 cachedSlot = checkpointRecord .SlotCheckpoint
119135 } else if err != balance .ErrCheckpointNotFound {
120- return 0 , err
136+ return 0 , UnknownSource , err
121137 }
122138
123139 // todo: we may need something that's more resistant to RPC nodes with stale account state
124140 quarks , slot , err := data .GetBlockchainBalance (ctx , tokenAccount .PublicKey ().ToBase58 ())
125141 if err == solana .ErrNoBalance {
126- return 0 , nil
142+ return 0 , BlockchainSource , nil
127143 } else if err != nil {
128144 // RPC node threw an error. Return the cached balance
129- return cachedQuarks , nil
145+ return cachedQuarks , CacheSource , nil
130146 }
131147
132148 // RPC node is behind, use cached balance
133149 if cachedSlot > slot {
134- return cachedQuarks , nil
150+ return cachedQuarks , CacheSource , nil
135151 }
136152
137153 // Observed a balance that's more recent. Best-effort update the checkpoint.
@@ -144,7 +160,7 @@ func CalculateFromBlockchain(ctx context.Context, data code_data.Provider, token
144160 data .SaveBalanceCheckpoint (ctx , newCheckpointRecord )
145161 }
146162
147- return quarks , nil
163+ return quarks , BlockchainSource , nil
148164}
149165
150166// Calculate calculates a token account's balance using a starting point and a set
@@ -262,6 +278,9 @@ type BatchState struct {
262278// or reliably estimating a set of token accounts' balance when common.AccountRecords are
263279// available.
264280//
281+ // Note: Use this method when calculating balances for accounts that are managed by
282+ // Code (ie. Timelock account) and operate within the L2 system.
283+ //
265284// Note: This only supports post-privacy accounts. Use CalculateFromCache instead.
266285func BatchCalculateFromCacheWithAccountRecords (ctx context.Context , data code_data.Provider , accountRecordsBatch ... * common.AccountRecords ) (map [string ]uint64 , error ) {
267286 tracer := metrics .TraceMethodCall (ctx , metricsPackageName , "BatchCalculateFromCacheWithAccountRecords" )
@@ -289,6 +308,9 @@ func BatchCalculateFromCacheWithAccountRecords(ctx context.Context, data code_da
289308// or reliably estimating a set of token accounts' balance when common.Account are
290309// available.
291310//
311+ // Note: Use this method when calculating balances for accounts that are managed by
312+ // Code (ie. Timelock account) and operate within the L2 system.
313+ //
292314// Note: This only supports post-privacy accounts. Use CalculateFromCache instead.
293315func BatchCalculateFromCacheWithTokenAccounts (ctx context.Context , data code_data.Provider , tokenAccounts ... * common.Account ) (map [string ]uint64 , error ) {
294316 tracer := metrics .TraceMethodCall (ctx , metricsPackageName , "BatchCalculateFromCacheWithTokenAccounts" )
@@ -469,3 +491,15 @@ func GetPrivateBalance(ctx context.Context, data code_data.Provider, owner *comm
469491 }
470492 return total , nil
471493}
494+
495+ func (s Source ) String () string {
496+ switch s {
497+ case UnknownSource :
498+ return "unknown"
499+ case CacheSource :
500+ return "cache"
501+ case BlockchainSource :
502+ return "blockchain"
503+ }
504+ return "unknown"
505+ }
0 commit comments