github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/articulate/log.go (about) 1 package articulate 2 3 import ( 4 "encoding/hex" 5 "errors" 6 7 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/abi" 8 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/rpc" 9 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types" 10 ) 11 12 // ArticulateLog articulates a log by attaching the Articulated log structure if the ABI is found. 13 func (abiCache *AbiCache) ArticulateLog(log *types.Log) error { 14 if found, err := articulateLogFromMap(log, &abiCache.AbiMap); err != nil { 15 return err 16 17 } else if found != nil { 18 log.ArticulatedLog = found 19 return nil 20 21 } else { 22 address := log.Address 23 if !abiCache.loadedMap.GetValue(address) && !abiCache.skipMap.GetValue(address) { 24 if err = abi.LoadAbi(abiCache.Conn, address, &abiCache.AbiMap); err != nil { 25 abiCache.skipMap.SetValue(address, true) 26 if !errors.Is(err, rpc.ErrNotAContract) { 27 // Not being a contract is not an error because we want to articulate the input in case it's a message 28 return err 29 } 30 } else { 31 abiCache.loadedMap.SetValue(address, true) 32 } 33 } 34 35 if !abiCache.skipMap.GetValue(address) { 36 if log.ArticulatedLog, err = articulateLogFromMap(log, &abiCache.AbiMap); err != nil { 37 return err 38 } 39 } 40 return nil 41 } 42 } 43 44 func articulateLogFromMap(log *types.Log, abiMap *abi.SelectorSyncMap) (*types.Function, error) { 45 if len(log.Topics) < 1 { 46 return nil, nil 47 } 48 49 // Try to articulate the log using some common events 50 artLog := findCommonEvent(log) 51 52 // If we couldn't, then try to find the event in `abiMap` 53 if artLog == nil { 54 selector := "0x" + hex.EncodeToString(log.Topics[0].Bytes()) 55 if found := abiMap.GetValue(selector); found != nil { 56 artLog = found.Clone() 57 } else { 58 // If artLog is still nil, we don't have ABI for this event 59 return nil, nil 60 } 61 } 62 63 abiEvent, err := artLog.GetAbiEvent() 64 if err != nil { 65 return artLog, err 66 } 67 data := log.Data 68 if len(log.Data) > 1 { 69 data = log.Data[2:] 70 } 71 72 if err = articulateArguments(abiEvent.Inputs, data, log.Topics, artLog.Inputs); err != nil { 73 return artLog, err 74 } 75 76 return artLog, nil 77 } 78 79 func findCommonEvent(log *types.Log) *types.Function { 80 if artLog := parseTransferEvent(log); artLog != nil { 81 return artLog 82 83 } else if artLog = parseEnsTransferEvent(log); artLog != nil { 84 return artLog 85 86 } else if artLog = parseApprovalEvent(log); artLog != nil { 87 return artLog 88 } 89 90 return nil 91 }