github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/articulate/transaction.go (about) 1 package articulate 2 3 import ( 4 "errors" 5 6 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/abi" 7 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/decode" 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 func (abiCache *AbiCache) ArticulateTransaction(tx *types.Transaction) error { 13 // TODO: This `Articulate` function is different from the other ones (for Log, etc.) because it 14 // TODO: doesn't try to articulate the transaction by selector first. It should. But it doesn't. 15 // TODO: The reason it doesn't is because of conflicting four-bytes (for example, `donate`) 16 // if found, message, err := articulateTx(tx, &abiCache.AbiMap); err != nil { 17 // return err 18 // 19 // } else if found != nil { 20 // tx.ArticulatedTx = found 21 // tx.Message = message 22 // 23 // } else { 24 var err error 25 address := tx.To 26 if !abiCache.loadedMap.GetValue(address) && !abiCache.skipMap.GetValue(address) { 27 if err = abi.LoadAbi(abiCache.Conn, address, &abiCache.AbiMap); err != nil { 28 abiCache.skipMap.SetValue(address, true) 29 if !errors.Is(err, rpc.ErrNotAContract) { 30 // Not being a contract is not an error because we want to articulate the input in case it's a message 31 return err 32 } 33 } else { 34 abiCache.loadedMap.SetValue(address, true) 35 } 36 } 37 38 if !abiCache.skipMap.GetValue(address) { 39 if tx.ArticulatedTx, tx.Message, err = articulateTx(tx, &abiCache.AbiMap); err != nil { 40 return err 41 } 42 } else { 43 if message, ok := decode.ArticulateString(tx.Input); ok { 44 tx.Message = message 45 } 46 } 47 // } 48 49 if err = abiCache.ArticulateReceipt(tx.Receipt); err != nil { 50 return err 51 } 52 53 for index := range tx.Traces { 54 if err = abiCache.ArticulateTrace(&tx.Traces[index]); err != nil { 55 return err 56 } 57 } 58 59 return nil 60 } 61 62 func articulateTx(tx *types.Transaction, abiMap *abi.SelectorSyncMap) (*types.Function, string, error) { 63 var found *types.Function 64 var message string 65 var art *types.Function 66 var selector string 67 var input = tx.Input 68 var outputData string 69 if len(tx.Traces) > 0 && tx.Traces[0].Result != nil && len(tx.Traces[0].Result.Output) > 2 { 70 outputData = tx.Traces[0].Result.Output[2:] 71 } 72 73 if len(input) >= 10 { 74 selector = input[:10] 75 inputData := input[10:] 76 found = abiMap.GetValue(selector) 77 if found != nil { 78 art = found.Clone() 79 if err := ArticulateFunction(art, inputData, outputData); err != nil { 80 return found, "", err 81 } 82 } 83 } 84 85 if found == nil && len(input) > 0 { 86 var ok bool 87 var msg string 88 if msg, ok = decode.ArticulateString(tx.Input); ok { 89 message = msg 90 } 91 } 92 93 return art, message, nil 94 }