@@ -72,7 +72,14 @@ func (n *Engine) runBlockTriggerImmediately(triggerConfig map[string]interface{}
72
72
73
73
// Check if a specific block number is requested
74
74
if configBlockNumber , ok := triggerConfig ["blockNumber" ]; ok {
75
- if blockNum , err := n .parseUint64 (configBlockNumber ); err == nil {
75
+ blockNum , err := n .parseUint64 (configBlockNumber )
76
+ if err != nil {
77
+ if n .logger != nil {
78
+ n .logger .Debug ("Failed to parse blockNumber from trigger config, using latest block" ,
79
+ "blockNumber" , configBlockNumber ,
80
+ "error" , err )
81
+ }
82
+ } else {
76
83
blockNumber = blockNum
77
84
}
78
85
}
@@ -351,7 +358,7 @@ func (n *Engine) runEventTriggerWithTenderlySimulation(ctx context.Context, quer
351
358
}
352
359
353
360
metadata := map [string ]interface {}{
354
- "tokenContract " : simulatedLog .Address .Hex (), // Renamed for clarity
361
+ "address " : simulatedLog .Address .Hex (), // Original contract address
355
362
"topics" : topicsMetadata , // Now protobuf-compatible
356
363
"data" : "0x" + common .Bytes2Hex (simulatedLog .Data ),
357
364
"blockNumber" : simulatedLog .BlockNumber ,
@@ -1080,7 +1087,7 @@ func (n *Engine) runEventTriggerWithHistoricalSearch(ctx context.Context, querie
1080
1087
1081
1088
// Build raw metadata (the original blockchain event data)
1082
1089
metadata := map [string ]interface {}{
1083
- "tokenContract " : mostRecentEvent .Address .Hex (), // Renamed for clarity
1090
+ "address " : mostRecentEvent .Address .Hex (), // Original contract address
1084
1091
"topics" : topics ,
1085
1092
"data" : "0x" + common .Bytes2Hex (mostRecentEvent .Data ),
1086
1093
"blockNumber" : mostRecentEvent .BlockNumber ,
@@ -1501,7 +1508,7 @@ func (n *Engine) runProcessingNodeWithInputs(nodeType string, nodeConfig map[str
1501
1508
secrets = make (map [string ]string )
1502
1509
}
1503
1510
1504
- // Create a clean VM for isolated execution with proper secrets
1511
+ // Create a clean VM for isolated execution with proper secrets (no task needed for immediate execution)
1505
1512
vm , err := NewVMWithData (nil , nil , n .smartWalletConfig , secrets )
1506
1513
if err != nil {
1507
1514
return nil , fmt .Errorf ("failed to create VM: %w" , err )
@@ -1679,16 +1686,32 @@ func (n *Engine) extractExecutionResult(executionStep *avsproto.Execution_Step)
1679
1686
result ["success" ] = true
1680
1687
} else if contractWrite := executionStep .GetContractWrite (); contractWrite != nil {
1681
1688
// ContractWrite output now contains enhanced results structure
1689
+ // Data contains decoded events (flattened by method name), Metadata contains method results
1690
+
1691
+ // Extract data if available (decoded events organized by method name)
1682
1692
if contractWrite .GetData () != nil {
1683
- // Extract results using helper function
1684
- allResults := ExtractResultsFromProtobufValue (contractWrite .GetData ())
1693
+ iface := contractWrite .GetData ().AsInterface ()
1694
+ if m , ok := iface .(map [string ]interface {}); ok {
1695
+ result ["data" ] = m
1696
+ } else {
1697
+ result ["data" ] = iface
1698
+ }
1699
+ }
1685
1700
1686
- // Return results array directly without backward compatibility
1701
+ // Extract metadata if available (method results array)
1702
+ if contractWrite .GetMetadata () != nil {
1703
+ // Extract results from metadata (method results array)
1704
+ allResults := ExtractResultsFromProtobufValue (contractWrite .GetMetadata ())
1687
1705
result ["results" ] = allResults
1688
1706
1689
- return result , nil
1707
+ if metadataArray := gow .ValueToSlice (contractWrite .GetMetadata ()); metadataArray != nil {
1708
+ result ["metadata" ] = metadataArray
1709
+ } else {
1710
+ result ["metadata" ] = contractWrite .GetMetadata ().AsInterface ()
1711
+ }
1690
1712
}
1691
- return map [string ]interface {}{"status" : "success" }, nil
1713
+
1714
+ return result , nil
1692
1715
} else if loop := executionStep .GetLoop (); loop != nil {
1693
1716
// Loop output contains the array of iteration results
1694
1717
if loop .GetData () != nil {
@@ -1709,6 +1732,19 @@ func (n *Engine) extractExecutionResult(executionStep *avsproto.Execution_Step)
1709
1732
result ["data" ] = iface
1710
1733
}
1711
1734
}
1735
+ } else if graphql := executionStep .GetGraphql (); graphql != nil {
1736
+ // GraphQL output contains the query results
1737
+ if graphql .GetData () != nil {
1738
+ // Extract the actual GraphQL response data
1739
+ iface := graphql .GetData ().AsInterface ()
1740
+ // Return the GraphQL data directly (it should already be in the correct format)
1741
+ if graphqlData , ok := iface .(map [string ]interface {}); ok {
1742
+ return graphqlData , nil
1743
+ } else {
1744
+ // Fallback: wrap in data field
1745
+ result ["data" ] = iface
1746
+ }
1747
+ }
1712
1748
}
1713
1749
1714
1750
// If no specific data was extracted, include basic execution info
@@ -1976,10 +2012,15 @@ func (n *Engine) RunNodeImmediatelyRPC(user *model.User, req *avsproto.RunNodeWi
1976
2012
case NodeTypeContractWrite :
1977
2013
// For contract write nodes - always set output structure to avoid OUTPUT_DATA_NOT_SET
1978
2014
contractWriteOutput := & avsproto.ContractWriteNode_Output {}
2015
+ // Always create the data structure, even if result is nil/empty
2016
+ var resultsArray []interface {}
2017
+ var decodedEventsData = make (map [string ]interface {})
2018
+
1979
2019
if result != nil && len (result ) > 0 {
1980
- // Convert result to the new data structure
1981
- var resultsArray []interface {}
1982
- var decodedEventsData = make (map [string ]interface {})
2020
+ // First, try to extract data directly (flattened events organized by method name)
2021
+ if dataFromVM , ok := result ["data" ].(map [string ]interface {}); ok {
2022
+ decodedEventsData = dataFromVM
2023
+ }
1983
2024
1984
2025
// Check if we have the new results array format (from VM execution)
1985
2026
if resultsFromVM , ok := result ["results" ].([]interface {}); ok {
@@ -2012,12 +2053,13 @@ func (n *Engine) RunNodeImmediatelyRPC(user *model.User, req *avsproto.RunNodeWi
2012
2053
2013
2054
resultsArray = append (resultsArray , convertedResult )
2014
2055
2015
- // 🚀 NEW: Decode event logs from transaction receipt
2056
+ // 🚀 NEW: Parse events for this specific method and store by method name
2057
+ methodEvents := make (map [string ]interface {})
2016
2058
if methodResult .Receipt != nil {
2017
2059
receiptData := methodResult .Receipt .AsInterface ()
2018
2060
if receiptMap , ok := receiptData .(map [string ]interface {}); ok {
2019
2061
if logs , hasLogs := receiptMap ["logs" ]; hasLogs {
2020
- if logsArray , ok := logs .([]interface {}); ok {
2062
+ if logsArray , ok := logs .([]interface {}); ok && len ( logsArray ) > 0 {
2021
2063
// Get contract ABI for event decoding
2022
2064
var contractABI * abi.ABI
2023
2065
if methodResult .MethodAbi != nil {
@@ -2034,7 +2076,7 @@ func (n *Engine) RunNodeImmediatelyRPC(user *model.User, req *avsproto.RunNodeWi
2034
2076
}
2035
2077
}
2036
2078
2037
- // Decode each event log
2079
+ // Decode each event log for this method
2038
2080
for _ , logInterface := range logsArray {
2039
2081
if logMap , ok := logInterface .(map [string ]interface {}); ok {
2040
2082
if contractABI != nil {
@@ -2070,39 +2112,12 @@ func (n *Engine) RunNodeImmediatelyRPC(user *model.User, req *avsproto.RunNodeWi
2070
2112
2071
2113
// Decode the event using existing logic
2072
2114
if decodedEvent , err := n .parseEventWithParsedABI (eventLog , contractABI , nil ); err == nil {
2073
- // Add decoded event data to flattened result
2115
+ // Flatten event fields into methodEvents
2074
2116
for key , value := range decodedEvent {
2075
- // Use eventName.fieldName format with dot notation to avoid conflicts
2076
- if eventName , hasEventName := decodedEvent ["eventName" ]; hasEventName {
2077
- if eventNameStr , ok := eventName .(string ); ok && key != "eventName" {
2078
- flatKey := fmt .Sprintf ("%s.%s" , eventNameStr , key )
2079
- decodedEventsData [flatKey ] = value
2080
- }
2117
+ if key != "eventName" { // Skip meta field
2118
+ methodEvents [key ] = value
2081
2119
}
2082
2120
}
2083
-
2084
- // Also add the complete event object with a descriptive key for multiple events
2085
- var eventKey string
2086
- if eventName , hasEventName := decodedEvent ["eventName" ]; hasEventName {
2087
- if eventNameStr , ok := eventName .(string ); ok {
2088
- // Try to get transaction hash or log index for uniqueness
2089
- var uniqueSuffix string
2090
- if txHash , hasTxHash := logMap ["transactionHash" ]; hasTxHash {
2091
- if txHashStr , ok := txHash .(string ); ok {
2092
- uniqueSuffix = txHashStr
2093
- }
2094
- } else if logIndex , hasLogIndex := logMap ["logIndex" ]; hasLogIndex {
2095
- uniqueSuffix = fmt .Sprintf ("%x" , logIndex )
2096
- } else {
2097
- // Fallback to eventLog.Index if logMap doesn't have logIndex
2098
- uniqueSuffix = fmt .Sprintf ("%d" , eventLog .Index )
2099
- }
2100
- eventKey = fmt .Sprintf ("%s_%s" , eventNameStr , uniqueSuffix )
2101
- }
2102
- } else {
2103
- eventKey = fmt .Sprintf ("event_%d" , eventLog .Index )
2104
- }
2105
- decodedEventsData [eventKey ] = decodedEvent
2106
2121
}
2107
2122
}
2108
2123
}
@@ -2111,6 +2126,9 @@ func (n *Engine) RunNodeImmediatelyRPC(user *model.User, req *avsproto.RunNodeWi
2111
2126
}
2112
2127
}
2113
2128
}
2129
+
2130
+ // Store events for this method (empty object if no events)
2131
+ decodedEventsData [methodResult .MethodName ] = methodEvents
2114
2132
} else if methodResultMap , ok := resultInterface .(map [string ]interface {}); ok {
2115
2133
// Already in map format
2116
2134
resultsArray = append (resultsArray , methodResultMap )
@@ -2139,18 +2157,18 @@ func (n *Engine) RunNodeImmediatelyRPC(user *model.User, req *avsproto.RunNodeWi
2139
2157
}
2140
2158
}
2141
2159
2142
- // 🚀 NEW: Set data field with decoded events (flattened format like ContractRead)
2143
- if len (decodedEventsData ) > 0 {
2144
- if dataValue , err := structpb .NewValue (decodedEventsData ); err == nil {
2145
- contractWriteOutput .Data = dataValue
2146
- }
2147
- }
2160
+ }
2148
2161
2149
- // 🚀 NEW: Set metadata field with detailed method information
2150
- if len (resultsArray ) > 0 {
2151
- if metadataValue , err := structpb .NewValue (resultsArray ); err == nil {
2152
- contractWriteOutput .Metadata = metadataValue
2153
- }
2162
+ // 🚀 NEW: Set data field with decoded events (flattened format like ContractRead)
2163
+ // Always set data field - empty object if no events, flattened events if present
2164
+ if dataValue , err := structpb .NewValue (decodedEventsData ); err == nil {
2165
+ contractWriteOutput .Data = dataValue
2166
+ }
2167
+
2168
+ // 🚀 NEW: Set metadata field with detailed method information
2169
+ if len (resultsArray ) > 0 {
2170
+ if metadataValue , err := structpb .NewValue (resultsArray ); err == nil {
2171
+ contractWriteOutput .Metadata = metadataValue
2154
2172
}
2155
2173
}
2156
2174
resp .OutputData = & avsproto.RunNodeWithInputsResp_ContractWrite {
0 commit comments