From 70d5fc1c3ef2afc649589720e98b0b6414ca108b Mon Sep 17 00:00:00 2001 From: Austin Date: Wed, 10 Dec 2025 12:58:54 -0500 Subject: [PATCH] updates --- macros/streamline/configs.yaml.sql | 86 ++++++++++++++++++++++ macros/streamline/functions.py.sql | 111 ++++++++++++++++++++++++++++- packages.yml | 4 -- 3 files changed, 196 insertions(+), 5 deletions(-) diff --git a/macros/streamline/configs.yaml.sql b/macros/streamline/configs.yaml.sql index 47ef2b7..d46b6b4 100644 --- a/macros/streamline/configs.yaml.sql +++ b/macros/streamline/configs.yaml.sql @@ -307,5 +307,91 @@ sql: | {{ fsc_utils.create_udf_encode_contract_call() | indent(4) }} +- name: {{ schema }}.udf_create_eth_call + signature: + - [contract_address, STRING] + - [encoded_calldata, STRING] + return_type: OBJECT + options: | + NULL + LANGUAGE SQL + STRICT IMMUTABLE + COMMENT = 'Creates an eth_call JSON-RPC request object with default block parameter "latest".' + sql: | + {{ schema }}.udf_json_rpc_call( + 'eth_call', + ARRAY_CONSTRUCT( + OBJECT_CONSTRUCT( + 'to', contract_address, + 'data', encoded_calldata + ), + 'latest' + ) + ) + +- name: {{ schema }}.udf_create_eth_call + signature: + - [contract_address, STRING] + - [encoded_calldata, STRING] + - [block_parameter, VARIANT] + return_type: OBJECT + options: | + NULL + LANGUAGE SQL + STRICT IMMUTABLE + COMMENT = 'Creates an eth_call JSON-RPC request object. Accepts contract address, encoded calldata, and optional block parameter (string or number). If block_parameter is a number, it will be converted to hex format using ai.utils.udf_int_to_hex.' + sql: | + {{ schema }}.udf_json_rpc_call( + 'eth_call', + ARRAY_CONSTRUCT( + OBJECT_CONSTRUCT( + 'to', contract_address, + 'data', encoded_calldata + ), + CASE + WHEN block_parameter IS NULL THEN 'latest' + WHEN TYPEOF(block_parameter) IN ('INTEGER', 'NUMBER', 'FIXED', 'FLOAT') THEN + {{ schema }}.udf_int_to_hex(block_parameter::NUMBER) + ELSE block_parameter::STRING + END + ) + ) + +- name: {{ schema }}.udf_create_eth_call_from_abi + signature: + - [contract_address, STRING] + - [function_abi, VARIANT] + - [input_values, ARRAY] + return_type: OBJECT + options: | + NULL + LANGUAGE SQL + STRICT IMMUTABLE + COMMENT = '{{ fsc_utils.udf_create_eth_call_from_abi_comment() }}' + sql: | + {{ schema }}.udf_create_eth_call( + contract_address, + {{ schema }}.udf_encode_contract_call(function_abi, input_values) + ) + +- name: {{ schema }}.udf_create_eth_call_from_abi + signature: + - [contract_address, STRING] + - [function_abi, VARIANT] + - [input_values, ARRAY] + - [block_parameter, VARIANT] + return_type: OBJECT + options: | + NULL + LANGUAGE SQL + STRICT IMMUTABLE + COMMENT = '{{ fsc_utils.udf_create_eth_call_from_abi_comment() }}' + sql: | + {{ schema }}.udf_create_eth_call( + contract_address, + {{ schema }}.udf_encode_contract_call(function_abi, input_values), + block_parameter + ) + {% endmacro %} diff --git a/macros/streamline/functions.py.sql b/macros/streamline/functions.py.sql index 769e9d2..3c7378e 100644 --- a/macros/streamline/functions.py.sql +++ b/macros/streamline/functions.py.sql @@ -1099,7 +1099,7 @@ TYPICAL WORKFLOW: 1. Get function ABI from crosschain.evm.dim_contract_abis 2. Prepare input values as Snowflake arrays 3. Encode using this function - 4. Execute via eth_call RPC (ai.live.udf_api) + 4. Execute via eth_call RPC (live.udf_api) 5. Decode response using utils.udf_evm_decode_trace SUPPORTED TYPES: @@ -1130,4 +1130,113 @@ RELATED FUNCTIONS: - utils.udf_keccak256: Calculate function selector - utils.udf_evm_decode_trace: Decode call results +{% endmacro %} + +{% macro udf_create_eth_call_from_abi_comment() %} +Convenience function that combines contract call encoding and JSON-RPC request creation for eth_call. + +PURPOSE: + Simplifies the workflow of creating eth_call JSON-RPC requests by combining ABI encoding + and RPC call construction into a single function call. This is the recommended approach for + most use cases where you want to query contract state via eth_call. + +PARAMETERS: + contract_address (STRING): + - Ethereum contract address (with or without 0x prefix) + - Example: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' + + function_abi (VARIANT): + - JSON object containing the function ABI definition + - Must include: "name" (string) and "inputs" (array of input definitions) + - Each input needs: "name", "type", and optionally "components" for tuples + - Can be retrieved from tables like crosschain.evm.dim_contract_abis or ethereum.silver.flat_function_abis + + input_values (ARRAY): + - Array of values matching the function inputs in order + - Values should be provided as native Snowflake types: + * addresses: strings (with or without 0x prefix) + * uint/int: numbers + * bool: booleans + * bytes/bytes32: hex strings (with or without 0x prefix) + * arrays: Snowflake arrays + * tuples: Snowflake arrays in component order + + block_parameter (VARIANT, optional): + - Block identifier for the eth_call request + - If NULL or omitted: defaults to 'latest' + - If NUMBER: automatically converted to hex format (e.g., 18500000 -> '0x11a7f80') + - If STRING: used directly (e.g., 'latest', '0x11a7f80', 'pending') + +RETURNS: + OBJECT: Complete JSON-RPC request object ready for eth_call + - Format: {"jsonrpc": "2.0", "method": "eth_call", "params": [...], "id": "..."} + - Can be used directly with RPC execution functions like live.udf_api + +EXAMPLES: + + -- Simple balanceOf call with default 'latest' block + SELECT utils.udf_create_eth_call_from_abi( + '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + PARSE_JSON('{ + "name": "balanceOf", + "inputs": [{"name": "account", "type": "address"}] + }'), + ARRAY_CONSTRUCT('0xBcca60bB61934080951369a648Fb03DF4F96263C') + ); + + -- Same call but at a specific block number + SELECT utils.udf_create_eth_call_from_abi( + '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + PARSE_JSON('{ + "name": "balanceOf", + "inputs": [{"name": "account", "type": "address"}] + }'), + ARRAY_CONSTRUCT('0xBcca60bB61934080951369a648Fb03DF4F96263C'), + 18500000 + ); + + -- Using ABI from a table + WITH abi_data AS ( + SELECT + abi, + '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' as contract_address, + '0xBcca60bB61934080951369a648Fb03DF4F96263C' as user_address + FROM ethereum.silver.flat_function_abis + WHERE contract_address = LOWER('0x43506849D7C04F9138D1A2050bbF3A0c054402dd') + AND function_name = 'balanceOf' + ) + SELECT + utils.udf_create_eth_call_from_abi( + contract_address, + abi, + ARRAY_CONSTRUCT(user_address) + ) as rpc_call + FROM abi_data; + +TYPICAL WORKFLOW: + 1. Get function ABI from contract ABI tables (crosschain.evm.dim_contract_abis, etc.) + 2. Prepare input values as Snowflake arrays matching the function signature + 3. Call this function with contract address, ABI, and inputs + 4. Execute the returned RPC call object via live.udf_api or similar + 5. Decode the response using utils.udf_evm_decode_trace or similar decoder + +ADVANTAGES OVER MODULAR APPROACH: + - Single function call instead of two (encode + create) + - Cleaner, more readable SQL + - Better for AI systems (fewer steps to explain) + - Less error-prone (no intermediate variables) + - More intuitive function name + +WHEN TO USE MODULAR FUNCTIONS INSTEAD: + - When you need to reuse encoded calldata for multiple RPC calls + - When you need encoded calldata for transaction construction + - When building complex workflows with intermediate steps + +RELATED FUNCTIONS: + - utils.udf_encode_contract_call: Encode function calls to calldata (used internally) + - utils.udf_create_eth_call: Create RPC call from encoded calldata (used internally) + - utils.udf_evm_text_signature: Generate function signature from ABI + - utils.udf_keccak256: Calculate function selector hash + - utils.udf_evm_decode_trace: Decode eth_call response results + {% endmacro %} \ No newline at end of file diff --git a/packages.yml b/packages.yml index 3ddb98c..1ba733a 100644 --- a/packages.yml +++ b/packages.yml @@ -1,7 +1,3 @@ packages: - - package: calogica/dbt_expectations - version: [">=0.8.0", "<0.9.0"] - - package: dbt-labs/dbt_utils - version: [">=1.0.0", "<1.1.0"] - git: https://github.com/FlipsideCrypto/livequery-models.git revision: "v1.10.2"