Turbo pipelines SQL transforms are powered by Apache DataFusion and include custom functions designed specifically for blockchain and Web3 data processing. These functions extend standard SQL with capabilities for:
Decoding EVM logs and Solana instructions
Working with 256-bit integers (U256/I256) common in smart contracts
Processing blockchain-specific data formats
Advanced array and JSON manipulation
Cryptographic operations
All standard DataFusion SQL functions are also available. This reference focuses on Turbo-specific custom functions.
abi_json - Contract ABI as JSON string (can be full ABI or just event definitions)
topics - Event topics array (topic[0] is event signature)
data - Event data field (hex string)
Returns: Struct containing:
name - Event name (e.g., “Transfer”)
event_params - Array of decoded parameter values as strings
Example: Decode ERC-20 Transfer Events
Copy
Ask AI
transforms: decoded_transfers: type: sql primary_key: id sql: | SELECT id, transaction_hash, address as contract_address, -- Decode the Transfer event evm_log_decode( '[{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]', topics, data ) as decoded, block_timestamp FROM ethereum_logs WHERE topics[1] = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' -- Transfer signature
Accessing decoded fields:
Copy
Ask AI
sql: | WITH decoded AS ( SELECT id, evm_log_decode(abi, topics, data) as evt FROM ethereum_logs ) SELECT id, evt.name as event_name, evt.event_params[1] as from_address, evt.event_params[2] as to_address, evt.event_params[3] as value FROM decoded
The decoder uses caching internally for performance. The same ABI can be reused across millions of records efficiently.
Turbo pipelines include specialized functions for decoding Solana program instructions and analyzing transaction data.Many of the below are already used in our default solana.instructions dataset and other datasets.
Decode Solana program instruction or event data using an IDL (Interface Definition Language) specification. This is the most flexible Solana decoding function - it works with any custom Solana program that has an IDL.Signature:
idl_json - IDL specification as JSON string (can be fetched with _gs_fetch_abi())
instruction_data - Base58-encoded instruction data
Returns: Struct containing:
name - Instruction or event name (e.g., “initialize”, “swap”, “transfer”)
value - JSON string with decoded parameter values
How it works:
Parses the IDL JSON specification
Attempts to decode as an instruction first
Falls back to event decoding if instruction decoding fails
Returns both the name and decoded values
Example: Access Decoded Fields after decoding
Copy
Ask AI
sql: | WITH decoded AS ( SELECT id, _gs_decode_instruction_data( _gs_fetch_abi('https://api.example.com/jupiter-v6.json', 'raw'), data ) as decoded_ix, accounts FROM solana_instructions WHERE program_id = 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4' ) SELECT id, decoded_ix.name as instruction_name, -- Parse the JSON value to extract specific fields json_value(decoded_ix.value, '$.amountIn') as amount_in, json_value(decoded_ix.value, '$.minimumAmountOut') as min_amount_out, accounts[1] as user_account FROM decoded WHERE decoded_ix.name = 'sharedAccountsRoute'
Example: Decode with Inline IDLFor simpler programs, you can provide the IDL directly:
Copy
Ask AI
sql: | SELECT id, _gs_decode_instruction_data( '{"instructions":[{"name":"initialize","accounts":[{"name":"authority","isMut":false,"isSigner":true}],"args":[{"name":"bump","type":"u8"}]}]}', data ) as decoded FROM solana_instructions
Performance: IDL decoders are cached internally. Reusing the same IDL JSON string (via _gs_fetch_abi()) across multiple rows is very efficient - the IDL is only parsed once.
When to use:
Custom Solana programs with available IDL specifications
Decoding instructions from DEXes, DeFi protocols, NFT marketplaces
Any program where you need flexible, schema-driven decoding
Use program-specific decoders instead for:
Solana system programs (Token, System, Stake, Vote, etc.) - use gs_solana_decode_* functions below
Better performance for known programs with hardcoded decoders
sql: | SELECT signature, gs_solana_get_accounts(transaction) as accounts, array_length(gs_solana_get_accounts(transaction)) as account_count FROM solana_transactions
sql: | WITH balance_changes AS ( SELECT signature, gs_solana_get_balance_changes(transaction) as changes FROM solana_transactions ) SELECT signature, change.account, change.post_balance - change.pre_balance as net_change FROM balance_changes CROSS JOIN UNNEST(changes) AS change WHERE ABS(change.post_balance - change.pre_balance) > 1000000000 -- > 1 SOL
Blockchain smart contracts frequently use 256-bit integers for token amounts, balances, and calculations. These functions provide precise arithmetic without JavaScript’s number precision limits.
u256_add(a, b) -> U256u256_sub(a, b) -> U256u256_mul(a, b) -> U256u256_div(a, b) -> U256u256_mod(a, b) -> U256
Automatic Operator Rewriting: Once values are cast to U256 or I256 types, you can use standard SQL operators (+, -, *, /, %) instead of explicit function calls. Turbo’s SQL preprocessor automatically rewrites these to the appropriate functions.
Copy
Ask AI
-- These are equivalent:to_u256(value) / to_u256('1000000')u256_div(to_u256(value), to_u256('1000000'))-- Use the cleaner syntax:to_u256(value) + to_u256(fee) -- Automatically becomes u256_add()to_u256(balance) * to_u256(2) -- Automatically becomes u256_mul()
Example: Calculate Token Amounts in ETH
Copy
Ask AI
transforms: token_amounts_eth: type: sql primary_key: id sql: | SELECT id, from_address, to_address, value, -- Convert wei to ETH (divide by 10^18) - using clean operator syntax u256_to_string( to_u256(value) / to_u256('1000000000000000000') ) as amount_eth, -- Calculate 1% fee u256_to_string( to_u256(value) / to_u256('100') ) as fee_1_percent FROM erc20_transfers
Example: Sum Multiple Token Amounts
Copy
Ask AI
sql: | SELECT to_address, -- Add two transfer amounts - using clean operator syntax u256_to_string( to_u256(transfer1_value) + to_u256(transfer2_value) ) as total_received FROM combined_transfers
U256 division truncates (no decimals). For percentage calculations or conversions to smaller units, multiply first, then divide.Good: (amount * to_u256('100')) / to_u256('1000000') (multiply by 100 first)Bad: (amount / to_u256('1000000')) * to_u256('100') (loses precision)
Similar to U256 but supports negative numbers.Available functions:
to_i256(value) - Convert to I256
i256_to_string(i256_value) - Convert to string
i256_add(a, b) / i256_sub(a, b) - Addition/subtraction
i256_mul(a, b) / i256_div(a, b) / i256_mod(a, b) - Multiplication/division/modulo
i256_neg(value) - Negate (multiply by -1)
i256_abs(value) - Absolute value
Example: Track Profit/Loss
Copy
Ask AI
sql: | SELECT address, -- Calculate profit/loss using clean operator syntax i256_to_string( to_i256(current_balance) - to_i256(initial_balance) ) as profit_loss, -- Get absolute value of change i256_to_string( i256_abs( to_i256(current_balance) - to_i256(initial_balance) ) ) as abs_change FROM balances
I256 and U256 operators work the same way - standard operators (+, -, *, /, %) are automatically rewritten to their corresponding function calls by the SQL preprocessor.
Filter array elements based on field value.Signature:
Copy
Ask AI
array_filter(array, field_name, value) -> LIST
Parameters:
array - Array of structs to filter
field_name - Name of field to match
value - Value to match against
Example: Filter Logs by Event Name
Copy
Ask AI
sql: | SELECT signature, -- Get only 'Transfer' events from instruction logs array_filter( instruction_logs, 'event_name', 'Transfer' ) as transfer_events FROM solana_transactions
Example: Filter Failed Instructions
Copy
Ask AI
sql: | SELECT slot, array_filter( transactions, 'err', null ) as successful_transactions FROM solana_blocks
Parse JSON string to validate or convert.Signatures:
Copy
Ask AI
parse_json(json_string) -> JSON -- Errors on invalid JSONtry_parse_json(json_string) -> JSON -- Returns NULL on invalid JSON
Example: Safe JSON Parsing
Copy
Ask AI
sql: | SELECT token_id, try_parse_json(metadata_string) as parsed_metadata, -- Check if JSON is valid CASE WHEN try_parse_json(metadata_string) IS NOT NULL THEN true ELSE false END as is_valid_json FROM nft_tokens
now() -> TIMESTAMPcurrent_time() -> TIMEcurrent_date() -> DATE
These functions are volatile - they return different values on each call. Use them for adding processing timestamps, not for filtering historical data.
Example: Add Processing Timestamp
Copy
Ask AI
sql: | SELECT *, now() as processed_at, current_date() as processing_date FROM ethereum_transactions
sql: | SELECT date_part('hour', to_timestamp(blockTime)) as hour_of_day, date_part('epoch', to_timestamp(blockTime)) - blockTime as age_seconds FROM solana_blocks
Functions can be composed to build complex transformations.Example: Decode Log and Convert Value
Copy
Ask AI
sql: | WITH decoded AS ( SELECT id, evm_log_decode(abi, topics, data) as evt, block_timestamp FROM ethereum_logs ) SELECT id, evt.name as event_name, evt.event_params[1] as from_address, evt.event_params[2] as to_address, -- Convert wei to ETH using U256 with clean operator syntax u256_to_string( to_u256(evt.event_params[3]) / to_u256('1000000000000000000') ) as amount_eth, block_timestamp FROM decoded
Example: Filter Array and Decode First Match
Copy
Ask AI
sql: | SELECT signature, gs_solana_decode_token_program_instruction( array_filter_first( instructions, 'programId', 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' ).data ) as decoded_token_instruction FROM solana_transactions
transforms: decoded_erc20_transfers: type: sql primary_key: id sql: | WITH decoded AS ( SELECT id, address as contract_address, transaction_hash, evm_log_decode( '[{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]', topics, data ) as evt, block_number, block_timestamp FROM ethereum_logs WHERE topics[1] = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' ) SELECT id, contract_address, transaction_hash, lower(evt.event_params[1]) as from_address, lower(evt.event_params[2]) as to_address, evt.event_params[3] as value_wei, u256_to_string( to_u256(evt.event_params[3]) / to_u256('1000000000000000000') ) as value_eth, block_number, block_timestamp FROM decoded