github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/ledger/ledger.go (about) 1 package ledger 2 3 import ( 4 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base" 5 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/names" 6 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/rpc" 7 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types" 8 ) 9 10 // TODO: Two things to note. (1) if balances were part of this structure, we could fill those 11 // TODO: balances in a concurrent way before spinning through the appearances. And (2) if we did that 12 // TODO: prior to doing the accounting, we could easily travers in reverse order. 13 14 // Ledger is a structure that carries enough information to complate a reconciliation 15 type Ledger struct { 16 Chain string 17 AccountFor base.Address 18 FirstBlock base.Blknum 19 LastBlock base.Blknum 20 Names map[base.Address]types.Name 21 TestMode bool 22 Contexts map[ledgerContextKey]*ledgerContext 23 AsEther bool 24 NoZero bool 25 Reversed bool 26 UseTraces bool 27 Conn *rpc.Connection 28 assetFilter []base.Address 29 theTx *types.Transaction 30 } 31 32 // NewLedger returns a new empty Ledger struct 33 func NewLedger(conn *rpc.Connection, acctFor base.Address, fb, lb base.Blknum, asEther, testMode, noZero, useTraces, reversed bool, assetFilters *[]string) *Ledger { 34 l := &Ledger{ 35 Conn: conn, 36 AccountFor: acctFor, 37 FirstBlock: fb, 38 LastBlock: lb, 39 Contexts: make(map[ledgerContextKey]*ledgerContext), 40 AsEther: asEther, 41 TestMode: testMode, 42 NoZero: noZero, 43 Reversed: reversed, 44 UseTraces: useTraces, 45 } 46 47 if assetFilters != nil { 48 l.assetFilter = make([]base.Address, len(*assetFilters)) 49 for i, addr := range *assetFilters { 50 l.assetFilter[i] = base.HexToAddress(addr) 51 } 52 } else { 53 l.assetFilter = []base.Address{} 54 } 55 56 parts := types.Custom | types.Prefund | types.Regular 57 l.Names, _ = names.LoadNamesMap(conn.Chain, parts, []string{}) 58 59 return l 60 } 61 62 // assetOfInterest returns true if the asset filter is empty or the asset matches 63 func (l *Ledger) assetOfInterest(needle base.Address) bool { 64 if len(l.assetFilter) == 0 { 65 return true 66 } 67 68 for _, asset := range l.assetFilter { 69 if asset.Hex() == needle.Hex() { 70 return true 71 } 72 } 73 74 return false 75 } 76 77 // See issue #2791 - This is the code that used to generate extra traces to make reconcilation work 78 // (or, at least, similar code in `chifra export` generated these traces. 79 // bool isSuicide = trace.action.selfDestructed != ""; 80 // bool isCreation = trace.result.address != ""; 81 // // do not colapse 82 // if (isCreation) { 83 // displayAsTrace(opt, trace); 84 // displayAsCreation(opt, trace); 85 // } 86 // // do not colapse 87 // if (isSuicide) { 88 // displayAsSuicide(opt, trace); 89 // } 90 // // do not colapse 91 // if (!isCreation && !isSuicide) { 92 // displayAsTrace(opt, trace); 93 // } 94 //-------------------------------------------------------------- 95 // bool displayAsCreation(COptions* opt, const CTrace& trace) { 96 // if (trace.result.address == "") 97 // return false; 98 // CTrace copy = trace; 99 // copy.action.from = "0x0"; 100 // copy.action.to = trace.result.address; 101 // copy.action.callType = "creation"; 102 // copy.action.value = trace.action.value; 103 // if (copy.traceAddress.size() == 0) 104 // copy.traceAddress.push_back("null"); 105 // copy.traceAddress.push_back("s"); 106 // copy.transactionHash = uint_2_Hex(trace.blockNumber * 100000 + trace.transactionIndex); 107 // copy.action.input = trace.action.input; 108 // return displayAsTrace(opt, copy); 109 // } 110 // //-------------------------------------------------------------- 111 // bool displayAsSuicide(COptions* opt, const CTrace& trace) { 112 // if (trace.action.refundAddress == "") 113 // return false; 114 // CTrace copy = trace; 115 // copy.action.from = trace.action.selfDestructed; 116 // copy.action.to = trace.action.refundAddress; 117 // copy.action.callType = "suicide"; 118 // copy.action.value = trace.action.balance; 119 // copy.traceAddress.push_back("s"); 120 // copy.transactionHash = uint_2_Hex(trace.blockNumber * 100000 + trace.transactionIndex); 121 // copy.action.input = "0x"; 122 // return displayAsTrace(opt, copy); 123 // } 124 // //-------------------------------------------------------------- 125 // bool displayAsTrace(COptions* opt, const CTrace& trace) { 126 // bool isText = (expContext().exportFmt & (TXT1 | CSV1)); 127 // if (isText) { 128 // cout << trim(trace.Format(expContext().fmtMap["format"]), '\t') << endl; 129 // } else { 130 // if (!opt->firstOut) 131 // cout << ","; 132 // cout << " "; 133 // indent(); 134 // trace.toJson(cout); 135 // unindent(); 136 // opt->firstOut = false; 137 // } 138 // return true; 139 // }