Skip to content

Commit

Permalink
Fix/resolve signed ints (#109)
Browse files Browse the repository at this point in the history
* fix: handle signed integers throughout rindexer

* fix: generating global types would repeat the same code on a regenerate causing issues

* fix: format

* docs: update EthereumSqlTypeWrapper
  • Loading branch information
joshstevens19 authored Sep 19, 2024
1 parent a80f8f6 commit 3288694
Show file tree
Hide file tree
Showing 25 changed files with 5,904 additions and 99 deletions.
4 changes: 3 additions & 1 deletion cli/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@ start_xenea:
codegen_typings_lens:
RUSTFLAGS='-C target-cpu=native' cargo run --release --features jemalloc -- codegen --path $(CURDIR)/../../lens-backend/crates/indexer typings
codegen_indexer_lens:
RUSTFLAGS='-C target-cpu=native' cargo run --release --features jemalloc -- codegen --path $(CURDIR)/../../lens-backend/crates/indexer indexer
RUSTFLAGS='-C target-cpu=native' cargo run --release --features jemalloc -- codegen --path $(CURDIR)/../../lens-backend/crates/indexer indexer
start_uniswap_base:
RUSTFLAGS='-C target-cpu=native' cargo run --release --features jemalloc -- start --path $(CURDIR)/../examples/uniswap_v3_base indexer
482 changes: 404 additions & 78 deletions core/src/database/postgres/sql_type_wrapper.rs

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion core/src/generator/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,23 @@ fn write_networks(output: &Path, networks: &[Network]) -> Result<(), WriteNetwor
pub enum WriteGlobalError {
#[error("{0}")]
CanNotWriteGlobalCode(#[from] WriteFileError),

#[error("{0}")]
CouldNotDeleteGlobalContractFile(#[from] std::io::Error),
}

fn write_global(
output: &Path,
global: &Global,
networks: &[Network],
) -> Result<(), WriteGlobalError> {
let global_contract_file_path = generate_file_location(output, "global_contracts");
if global_contract_file_path.exists() {
fs::remove_file(&global_contract_file_path)?;
}

let context_code = generate_context_code(&global.contracts, networks);
write_file(&generate_file_location(output, "global_contracts"), context_code.as_str())?;
write_file(&global_contract_file_path, context_code.as_str())?;

Ok(())
}
Expand Down
26 changes: 25 additions & 1 deletion core/src/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::{
};

use dotenv::dotenv;
use ethers::prelude::{I256, U256};
pub use file::{
create_mod_file, format_all_files_for_project, load_env_from_path, write_file,
CreateModFileError, WriteFileError,
Expand All @@ -27,6 +28,7 @@ pub fn camel_to_snake_advanced(s: &str, numbers_attach_to_last_word: bool) -> St
let mut snake_case = String::new();
let mut previous_was_uppercase = false;
let mut previous_was_digit = false;
let mut uppercase_sequence_length = 0;

for (i, c) in s.chars().enumerate() {
if c.is_alphanumeric() || c == '_' {
Expand All @@ -44,21 +46,25 @@ pub fn camel_to_snake_advanced(s: &str, numbers_attach_to_last_word: bool) -> St
snake_case.push(c.to_ascii_lowercase());
previous_was_uppercase = true;
previous_was_digit = false;
uppercase_sequence_length += 1;
} else if c.is_ascii_digit() {
if !numbers_attach_to_last_word &&
i > 0 &&
!previous_was_digit &&
!snake_case.ends_with('_')
!snake_case.ends_with('_') &&
uppercase_sequence_length != 1
{
snake_case.push('_');
}
snake_case.push(c);
previous_was_uppercase = false;
previous_was_digit = true;
uppercase_sequence_length = 0;
} else {
snake_case.push(c);
previous_was_uppercase = false;
previous_was_digit = false;
uppercase_sequence_length = 0;
}
}
}
Expand Down Expand Up @@ -167,6 +173,23 @@ pub fn replace_env_variable_to_raw_name(rpc: &str) -> String {
}
}

pub fn u256_to_i256(value: U256) -> I256 {
let max_i256_as_u256 = U256::from_str_radix(
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
16,
)
.unwrap();

if value <= max_i256_as_u256 {
// If the value is less than or equal to I256::MAX, it's a positive number
I256::from_raw(value)
} else {
// If it's larger, it represents a negative number in two's complement
let twos_complement = (!value).overflowing_add(U256::one()).0;
I256::from_raw(twos_complement).wrapping_neg()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -182,6 +205,7 @@ mod tests {
assert_eq!(camel_to_snake("collectNFTId"), "collect_nft_id");
assert_eq!(camel_to_snake("ERC20"), "erc_20");
assert_eq!(camel_to_snake("arg1"), "arg_1");
assert_eq!(camel_to_snake("sqrtPriceX96"), "sqrt_price_x96");

assert_eq!(camel_to_snake_advanced("ERC20", false), "erc_20");
assert_eq!(camel_to_snake_advanced("ERC20", true), "erc20");
Expand Down
14 changes: 12 additions & 2 deletions core/src/indexer/log_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use ethers::{
utils::keccak256,
};

use crate::helpers::u256_to_i256;

pub fn parse_log(event: &Event, log: &Log) -> Option<ParsedLog> {
let raw_log = RawLog { topics: log.topics.clone(), data: log.data.to_vec() };

Expand All @@ -32,8 +34,16 @@ fn map_token_to_raw_values(token: &Token) -> Vec<String> {
match token {
Token::Address(addr) => vec![format!("{:?}", addr)],
Token::FixedBytes(bytes) | Token::Bytes(bytes) => vec![format!("{:?}", bytes)],
Token::Int(int) => vec![int.to_string()],
Token::Uint(uint) => vec![uint.to_string()],
Token::Int(int) => {
// handle two’s complement without adding a new type
let i256_value = u256_to_i256(*int);
vec![i256_value.to_string()]
}
Token::Uint(uint) => {
// handle two’s complement without adding a new type
let i256_value = u256_to_i256(*uint);
vec![i256_value.to_string()]
}
Token::Bool(b) => vec![b.to_string()],
Token::String(s) => vec![s.clone()],
Token::FixedArray(tokens) | Token::Array(tokens) => {
Expand Down
6 changes: 6 additions & 0 deletions documentation/docs/pages/docs/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@

### Bug fixes
-------------------------------------------------
- fix: handle signed integers throughout rindexer
- fix: generating global types would repeat the same code on a regenerate causing issues

### Breaking changes
-------------------------------------------------
- breaking: rindexer had an parsing error meaning stuff like `UniswapV3Pool` would parse to uniswap_v_3_pool. This caused
some other issues with mapping to object names so now it has been fixed and in the example above it will be `uniswap_v3_pool`,
if you have any running indexers with these buggy names in your db you just need to rename them and same with the `rindexer.internal` tables which will
have these odd names as well.

## Releases
-------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -760,32 +760,65 @@ called EthereumSqlTypeWrapper which has all the types you need to pass into the
```rs
#[derive(Debug, Clone)]
pub enum EthereumSqlTypeWrapper {
// Boolean
Bool(bool),
VecBool(Vec<bool>),
// 8-bit integers
U8(u8),
I8(i8),
VecU8(Vec<u8>),
VecI8(Vec<i8>),
// 16-bit integers
U16(u16),
I16(i16),
VecU16(Vec<u16>),
VecI16(Vec<i16>),
// 32-bit integers
U32(u32),
I32(i32),
VecU32(Vec<u32>),
VecI32(Vec<i32>),
// 64-bit integers
U64(U64),
I64(i64),
VecU64(Vec<U64>),
U128(U128),
VecU128(Vec<U128>),
VecI64(Vec<i64>),
// 128-bit integers
U128(u128),
I128(i128),
VecU128(Vec<u128>),
VecI128(Vec<i128>),
// 256-bit integers
U256(U256),
I256(I256),
VecU256(Vec<U256>),
VecI256(Vec<I256>),
// 512-bit integers
U512(U512),
VecU512(Vec<U512>),
// Hashes
H128(H128),
VecH128(Vec<H128>),
H160(H160),
VecH160(Vec<H160>),
H256(H256),
VecH256(Vec<H256>),
H512(H512),
VecH128(Vec<H128>),
VecH160(Vec<H160>),
VecH256(Vec<H256>),
VecH512(Vec<H512>),
// Address
Address(Address),
VecAddress(Vec<Address>),
Bool(bool),
VecBool(Vec<bool>),
U32(u32),
VecU32(Vec<u32>),
U16(u16),
VecU16(Vec<u16>),
U8(u8),
VecU8(Vec<u8>),
// Strings and Bytes
String(String),
VecString(Vec<String>),
Bytes(Bytes),
Expand Down
87 changes: 87 additions & 0 deletions rindexer_rust_playground/abis/playground-types-abi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
[
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"indexed": false,
"internalType": "int256",
"name": "amount0",
"type": "int256"
},
{
"indexed": false,
"internalType": "int256",
"name": "amount1",
"type": "int256"
},
{
"indexed": false,
"internalType": "uint160",
"name": "sqrtPriceX96",
"type": "uint160"
},
{
"indexed": false,
"internalType": "uint128",
"name": "liquidity",
"type": "uint128"
},
{
"indexed": false,
"internalType": "int24",
"name": "tick",
"type": "int24"
},
{
"indexed": false,
"internalType": "int24",
"name": "tick2",
"type": "int8"
},
{
"indexed": false,
"internalType": "int24",
"name": "tick3",
"type": "int16"
},
{
"indexed": false,
"internalType": "int24",
"name": "tick4",
"type": "int32"
},
{
"indexed": false,
"internalType": "int24",
"name": "tick5",
"type": "int64"
},
{
"indexed": false,
"internalType": "int24",
"name": "tick6",
"type": "int128"
},
{
"indexed": false,
"internalType": "int24",
"name": "tick7",
"type": "int192"
}
],
"name": "Swap",
"type": "event"
}
]
Loading

0 comments on commit 3288694

Please sign in to comment.