github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/tokens/handle_show.go (about) 1 package tokensPkg 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base" 8 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/output" 9 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/tslib" 10 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types" 11 "github.com/ethereum/go-ethereum" 12 ) 13 14 func (opts *TokensOptions) HandleShow(rCtx *output.RenderCtx) error { 15 chain := opts.Globals.Chain 16 tokenAddr := base.HexToAddress(opts.Addrs[0]) 17 18 fetchData := func(modelChan chan types.Modeler, errorChan chan error) { 19 for _, address := range opts.Addrs[1:] { 20 addr := base.HexToAddress(address) 21 currentBn := base.Blknum(0) 22 currentTs := base.Timestamp(0) 23 for _, br := range opts.BlockIds { 24 blockNums, err := br.ResolveBlocks(chain) 25 if err != nil { 26 errorChan <- err 27 if errors.Is(err, ethereum.NotFound) { 28 continue 29 } 30 rCtx.Cancel() 31 return 32 } 33 34 for _, bn := range blockNums { 35 if balance, err := opts.Conn.GetBalanceAtToken(tokenAddr, addr, fmt.Sprintf("0x%x", bn)); balance == nil { 36 errorChan <- err 37 } else { 38 if opts.Globals.Verbose { 39 if bn == 0 || bn != currentBn { 40 currentTs, _ = tslib.FromBnToTs(chain, bn) 41 } 42 currentBn = bn 43 } 44 s := &types.Token{ 45 Holder: addr, 46 Address: tokenAddr, 47 Balance: *balance, 48 BlockNumber: bn, 49 Timestamp: currentTs, 50 TokenType: types.TokenErc20, 51 } 52 modelChan <- s 53 } 54 } 55 } 56 } 57 } 58 59 extraOpts := map[string]any{ 60 "parts": []string{"all_held"}, 61 "loadNames": true, 62 } 63 64 return output.StreamMany(rCtx, fetchData, opts.Globals.OutputOptsWithExtra(extraOpts)) 65 } 66 67 // TODO: NOTE THIS - DOES IT STILL WORK THIS WAY? 68 // } else if (by_acct) { 69 // // All user-provided addresses are assumed to be tokens, except the last one which is the holder 70 // holders.push_back(addrs[addrs.size() - 1]); 71 // CAddressArray::iterator it; 72 // it = prev(addrs.end()); 73 // addrs.erase(it); 74 // for (auto addr : addrs) { 75 // if (!isContractAt(addr, latestBlock)) 76 // errors.push_back("Address '" + addr + "' is not a token contract."); 77 // else 78 // tokens.push_back(addr); 79 // }