feat: add Pancakeswap v3 Substreams module (#178)
* feat: Add Pancakeswap V3 Substreams module At this point it's just hard copy of Uniswap V3. It will be adapted in the following commits to make reviewing easier. * refactor: adapt uniswapv3 module logic for pancakeswap v3 The main change is how they handle protocol fees. Protocol fees are set by default depending on the fee of the pool. * refactor: use new protobuf structs The "EntityChanges" got deprecated in favor of the hybrid messages. This commit makes PancakeswapV3 module use the new structs. * fix: set correct factory address --------- Co-authored-by: zizou <111426680+flopell@users.noreply.github.com> Co-authored-by: Louise Poole <louise@datarevenue.com>
This commit is contained in:
20
substreams/Cargo.lock
generated
20
substreams/Cargo.lock
generated
@@ -260,6 +260,26 @@ dependencies = [
|
||||
"tycho-substreams 0.2.0 (git+https://github.com/propeller-heads/tycho-protocol-sdk.git?rev=b8aeaa3)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-pancakeswap-v3"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ethabi 18.0.0",
|
||||
"getrandom",
|
||||
"hex",
|
||||
"hex-literal 0.4.1",
|
||||
"itertools 0.13.0",
|
||||
"num-bigint",
|
||||
"prost 0.11.9",
|
||||
"substreams",
|
||||
"substreams-entity-change",
|
||||
"substreams-ethereum",
|
||||
"substreams-helper 0.0.2 (git+https://github.com/propeller-heads/tycho-protocol-sdk.git?rev=b8aeaa3)",
|
||||
"tiny-keccak",
|
||||
"tycho-substreams 0.2.0 (git+https://github.com/propeller-heads/tycho-protocol-sdk.git?rev=b8aeaa3)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-sfrax"
|
||||
version = "0.1.0"
|
||||
|
||||
@@ -7,6 +7,7 @@ members = [
|
||||
"ethereum-ambient",
|
||||
"ethereum-uniswap-v2",
|
||||
"ethereum-uniswap-v3",
|
||||
"ethereum-pancakeswap-v3",
|
||||
"ethereum-sfrax",
|
||||
"ethereum-sfraxeth",
|
||||
"ethereum-uniswap-v3-logs-only",
|
||||
|
||||
30
substreams/ethereum-pancakeswap-v3/Cargo.toml
Normal file
30
substreams/ethereum-pancakeswap-v3/Cargo.toml
Normal file
@@ -0,0 +1,30 @@
|
||||
[package]
|
||||
name = "ethereum-pancakeswap-v3"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "ethereum_pancakeswap_v3"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
substreams = "0.5.22"
|
||||
substreams-ethereum = "0.9.9"
|
||||
prost = "0.11"
|
||||
ethabi = "18.0.0"
|
||||
anyhow = "1.0.75"
|
||||
hex-literal = "0.4.1"
|
||||
substreams-helper = { git = "https://github.com/propeller-heads/tycho-protocol-sdk.git", rev = "b8aeaa3" }
|
||||
tycho-substreams = { git = "https://github.com/propeller-heads/tycho-protocol-sdk.git", rev = "b8aeaa3" }
|
||||
num-bigint = "0.4.4"
|
||||
hex = "0.4.3"
|
||||
tiny-keccak = "2.0"
|
||||
substreams-entity-change = "1.3"
|
||||
itertools = "0.13.0"
|
||||
|
||||
[target.wasm32-unknown-unknown.dependencies]
|
||||
getrandom = { version = "0.2", features = ["custom"] }
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = "1.0.75"
|
||||
substreams-ethereum = "0.9.9"
|
||||
2
substreams/ethereum-pancakeswap-v3/Makefile
Normal file
2
substreams/ethereum-pancakeswap-v3/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
build:
|
||||
cargo build --target wasm32-unknown-unknown --profile substreams
|
||||
300
substreams/ethereum-pancakeswap-v3/abi/Factory.json
Normal file
300
substreams/ethereum-pancakeswap-v3/abi/Factory.json
Normal file
@@ -0,0 +1,300 @@
|
||||
[
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "_poolDeployer", "type": "address" }
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "uint24",
|
||||
"name": "fee",
|
||||
"type": "uint24"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickSpacing",
|
||||
"type": "int24"
|
||||
}
|
||||
],
|
||||
"name": "FeeAmountEnabled",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "uint24",
|
||||
"name": "fee",
|
||||
"type": "uint24"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "bool",
|
||||
"name": "whitelistRequested",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "bool",
|
||||
"name": "enabled",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"name": "FeeAmountExtraInfoUpdated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "oldOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnerChanged",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "token0",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "token1",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "uint24",
|
||||
"name": "fee",
|
||||
"type": "uint24"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "int24",
|
||||
"name": "tickSpacing",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "pool",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "PoolCreated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "lmPoolDeployer",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "SetLmPoolDeployer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "bool",
|
||||
"name": "verified",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"name": "WhiteListAdded",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "pool", "type": "address" },
|
||||
{ "internalType": "address", "name": "recipient", "type": "address" },
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount0Requested",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount1Requested",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "collectProtocol",
|
||||
"outputs": [
|
||||
{ "internalType": "uint128", "name": "amount0", "type": "uint128" },
|
||||
{ "internalType": "uint128", "name": "amount1", "type": "uint128" }
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "tokenA", "type": "address" },
|
||||
{ "internalType": "address", "name": "tokenB", "type": "address" },
|
||||
{ "internalType": "uint24", "name": "fee", "type": "uint24" }
|
||||
],
|
||||
"name": "createPool",
|
||||
"outputs": [
|
||||
{ "internalType": "address", "name": "pool", "type": "address" }
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "uint24", "name": "fee", "type": "uint24" },
|
||||
{ "internalType": "int24", "name": "tickSpacing", "type": "int24" }
|
||||
],
|
||||
"name": "enableFeeAmount",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "uint24", "name": "", "type": "uint24" }],
|
||||
"name": "feeAmountTickSpacing",
|
||||
"outputs": [{ "internalType": "int24", "name": "", "type": "int24" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "uint24", "name": "", "type": "uint24" }],
|
||||
"name": "feeAmountTickSpacingExtraInfo",
|
||||
"outputs": [
|
||||
{ "internalType": "bool", "name": "whitelistRequested", "type": "bool" },
|
||||
{ "internalType": "bool", "name": "enabled", "type": "bool" }
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "", "type": "address" },
|
||||
{ "internalType": "address", "name": "", "type": "address" },
|
||||
{ "internalType": "uint24", "name": "", "type": "uint24" }
|
||||
],
|
||||
"name": "getPool",
|
||||
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "lmPoolDeployer",
|
||||
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "poolDeployer",
|
||||
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "uint24", "name": "fee", "type": "uint24" },
|
||||
{ "internalType": "bool", "name": "whitelistRequested", "type": "bool" },
|
||||
{ "internalType": "bool", "name": "enabled", "type": "bool" }
|
||||
],
|
||||
"name": "setFeeAmountExtraInfo",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "pool", "type": "address" },
|
||||
{ "internalType": "uint32", "name": "feeProtocol0", "type": "uint32" },
|
||||
{ "internalType": "uint32", "name": "feeProtocol1", "type": "uint32" }
|
||||
],
|
||||
"name": "setFeeProtocol",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "pool", "type": "address" },
|
||||
{ "internalType": "address", "name": "lmPool", "type": "address" }
|
||||
],
|
||||
"name": "setLmPool",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_lmPoolDeployer",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "setLmPoolDeployer",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "_owner", "type": "address" }
|
||||
],
|
||||
"name": "setOwner",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "user", "type": "address" },
|
||||
{ "internalType": "bool", "name": "verified", "type": "bool" }
|
||||
],
|
||||
"name": "setWhiteListAddress",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
739
substreams/ethereum-pancakeswap-v3/abi/Pool.json
Normal file
739
substreams/ethereum-pancakeswap-v3/abi/Pool.json
Normal file
@@ -0,0 +1,739 @@
|
||||
[
|
||||
{ "inputs": [], "stateMutability": "nonpayable", "type": "constructor" },
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickLower",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickUpper",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount1",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Burn",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickLower",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickUpper",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount0",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount1",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "Collect",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount0",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount1",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "CollectProtocol",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "recipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount1",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "paid0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "paid1",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Flash",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint16",
|
||||
"name": "observationCardinalityNextOld",
|
||||
"type": "uint16"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint16",
|
||||
"name": "observationCardinalityNextNew",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"name": "IncreaseObservationCardinalityNext",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceX96",
|
||||
"type": "uint160"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "int24",
|
||||
"name": "tick",
|
||||
"type": "int24"
|
||||
}
|
||||
],
|
||||
"name": "Initialize",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickLower",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "int24",
|
||||
"name": "tickUpper",
|
||||
"type": "int24"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "amount",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount1",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Mint",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint32",
|
||||
"name": "feeProtocol0Old",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint32",
|
||||
"name": "feeProtocol1Old",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint32",
|
||||
"name": "feeProtocol0New",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint32",
|
||||
"name": "feeProtocol1New",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "SetFeeProtocol",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "addr",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "SetLmPoolEvent",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"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": "uint128",
|
||||
"name": "protocolFeesToken0",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint128",
|
||||
"name": "protocolFeesToken1",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "Swap",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "int24", "name": "tickLower", "type": "int24" },
|
||||
{ "internalType": "int24", "name": "tickUpper", "type": "int24" },
|
||||
{ "internalType": "uint128", "name": "amount", "type": "uint128" }
|
||||
],
|
||||
"name": "burn",
|
||||
"outputs": [
|
||||
{ "internalType": "uint256", "name": "amount0", "type": "uint256" },
|
||||
{ "internalType": "uint256", "name": "amount1", "type": "uint256" }
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "recipient", "type": "address" },
|
||||
{ "internalType": "int24", "name": "tickLower", "type": "int24" },
|
||||
{ "internalType": "int24", "name": "tickUpper", "type": "int24" },
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount0Requested",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount1Requested",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "collect",
|
||||
"outputs": [
|
||||
{ "internalType": "uint128", "name": "amount0", "type": "uint128" },
|
||||
{ "internalType": "uint128", "name": "amount1", "type": "uint128" }
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "recipient", "type": "address" },
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount0Requested",
|
||||
"type": "uint128"
|
||||
},
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "amount1Requested",
|
||||
"type": "uint128"
|
||||
}
|
||||
],
|
||||
"name": "collectProtocol",
|
||||
"outputs": [
|
||||
{ "internalType": "uint128", "name": "amount0", "type": "uint128" },
|
||||
{ "internalType": "uint128", "name": "amount1", "type": "uint128" }
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "factory",
|
||||
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "fee",
|
||||
"outputs": [{ "internalType": "uint24", "name": "", "type": "uint24" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "feeGrowthGlobal0X128",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "feeGrowthGlobal1X128",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "recipient", "type": "address" },
|
||||
{ "internalType": "uint256", "name": "amount0", "type": "uint256" },
|
||||
{ "internalType": "uint256", "name": "amount1", "type": "uint256" },
|
||||
{ "internalType": "bytes", "name": "data", "type": "bytes" }
|
||||
],
|
||||
"name": "flash",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "observationCardinalityNext",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"name": "increaseObservationCardinalityNext",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "uint160", "name": "sqrtPriceX96", "type": "uint160" }
|
||||
],
|
||||
"name": "initialize",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "liquidity",
|
||||
"outputs": [{ "internalType": "uint128", "name": "", "type": "uint128" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "lmPool",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IPancakeV3LmPool",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "maxLiquidityPerTick",
|
||||
"outputs": [{ "internalType": "uint128", "name": "", "type": "uint128" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "recipient", "type": "address" },
|
||||
{ "internalType": "int24", "name": "tickLower", "type": "int24" },
|
||||
{ "internalType": "int24", "name": "tickUpper", "type": "int24" },
|
||||
{ "internalType": "uint128", "name": "amount", "type": "uint128" },
|
||||
{ "internalType": "bytes", "name": "data", "type": "bytes" }
|
||||
],
|
||||
"name": "mint",
|
||||
"outputs": [
|
||||
{ "internalType": "uint256", "name": "amount0", "type": "uint256" },
|
||||
{ "internalType": "uint256", "name": "amount1", "type": "uint256" }
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"name": "observations",
|
||||
"outputs": [
|
||||
{ "internalType": "uint32", "name": "blockTimestamp", "type": "uint32" },
|
||||
{ "internalType": "int56", "name": "tickCumulative", "type": "int56" },
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "secondsPerLiquidityCumulativeX128",
|
||||
"type": "uint160"
|
||||
},
|
||||
{ "internalType": "bool", "name": "initialized", "type": "bool" }
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "uint32[]", "name": "secondsAgos", "type": "uint32[]" }
|
||||
],
|
||||
"name": "observe",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "int56[]",
|
||||
"name": "tickCumulatives",
|
||||
"type": "int56[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160[]",
|
||||
"name": "secondsPerLiquidityCumulativeX128s",
|
||||
"type": "uint160[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }],
|
||||
"name": "positions",
|
||||
"outputs": [
|
||||
{ "internalType": "uint128", "name": "liquidity", "type": "uint128" },
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "feeGrowthInside0LastX128",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "feeGrowthInside1LastX128",
|
||||
"type": "uint256"
|
||||
},
|
||||
{ "internalType": "uint128", "name": "tokensOwed0", "type": "uint128" },
|
||||
{ "internalType": "uint128", "name": "tokensOwed1", "type": "uint128" }
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "protocolFees",
|
||||
"outputs": [
|
||||
{ "internalType": "uint128", "name": "token0", "type": "uint128" },
|
||||
{ "internalType": "uint128", "name": "token1", "type": "uint128" }
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "uint32", "name": "feeProtocol0", "type": "uint32" },
|
||||
{ "internalType": "uint32", "name": "feeProtocol1", "type": "uint32" }
|
||||
],
|
||||
"name": "setFeeProtocol",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "_lmPool", "type": "address" }
|
||||
],
|
||||
"name": "setLmPool",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "slot0",
|
||||
"outputs": [
|
||||
{ "internalType": "uint160", "name": "sqrtPriceX96", "type": "uint160" },
|
||||
{ "internalType": "int24", "name": "tick", "type": "int24" },
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "observationIndex",
|
||||
"type": "uint16"
|
||||
},
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "observationCardinality",
|
||||
"type": "uint16"
|
||||
},
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "observationCardinalityNext",
|
||||
"type": "uint16"
|
||||
},
|
||||
{ "internalType": "uint32", "name": "feeProtocol", "type": "uint32" },
|
||||
{ "internalType": "bool", "name": "unlocked", "type": "bool" }
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "int24", "name": "tickLower", "type": "int24" },
|
||||
{ "internalType": "int24", "name": "tickUpper", "type": "int24" }
|
||||
],
|
||||
"name": "snapshotCumulativesInside",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "int56",
|
||||
"name": "tickCumulativeInside",
|
||||
"type": "int56"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "secondsPerLiquidityInsideX128",
|
||||
"type": "uint160"
|
||||
},
|
||||
{ "internalType": "uint32", "name": "secondsInside", "type": "uint32" }
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "recipient", "type": "address" },
|
||||
{ "internalType": "bool", "name": "zeroForOne", "type": "bool" },
|
||||
{ "internalType": "int256", "name": "amountSpecified", "type": "int256" },
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "sqrtPriceLimitX96",
|
||||
"type": "uint160"
|
||||
},
|
||||
{ "internalType": "bytes", "name": "data", "type": "bytes" }
|
||||
],
|
||||
"name": "swap",
|
||||
"outputs": [
|
||||
{ "internalType": "int256", "name": "amount0", "type": "int256" },
|
||||
{ "internalType": "int256", "name": "amount1", "type": "int256" }
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "int16", "name": "", "type": "int16" }],
|
||||
"name": "tickBitmap",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "tickSpacing",
|
||||
"outputs": [{ "internalType": "int24", "name": "", "type": "int24" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "int24", "name": "", "type": "int24" }],
|
||||
"name": "ticks",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint128",
|
||||
"name": "liquidityGross",
|
||||
"type": "uint128"
|
||||
},
|
||||
{ "internalType": "int128", "name": "liquidityNet", "type": "int128" },
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "feeGrowthOutside0X128",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "feeGrowthOutside1X128",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "int56",
|
||||
"name": "tickCumulativeOutside",
|
||||
"type": "int56"
|
||||
},
|
||||
{
|
||||
"internalType": "uint160",
|
||||
"name": "secondsPerLiquidityOutsideX128",
|
||||
"type": "uint160"
|
||||
},
|
||||
{ "internalType": "uint32", "name": "secondsOutside", "type": "uint32" },
|
||||
{ "internalType": "bool", "name": "initialized", "type": "bool" }
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "token0",
|
||||
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "token1",
|
||||
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
12
substreams/ethereum-pancakeswap-v3/buf.gen.yaml
Normal file
12
substreams/ethereum-pancakeswap-v3/buf.gen.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
version: v1
|
||||
plugins:
|
||||
- plugin: buf.build/community/neoeinstein-prost:v0.2.2
|
||||
out: src/pb
|
||||
opt:
|
||||
- file_descriptor_set=false
|
||||
|
||||
- plugin: buf.build/community/neoeinstein-prost-crate:v0.3.1
|
||||
out: src/pb
|
||||
opt:
|
||||
- no_features
|
||||
12
substreams/ethereum-pancakeswap-v3/build.rs
Normal file
12
substreams/ethereum-pancakeswap-v3/build.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use anyhow::{Ok, Result};
|
||||
use substreams_ethereum::Abigen;
|
||||
|
||||
fn main() -> Result<(), anyhow::Error> {
|
||||
Abigen::new("Factory", "abi/Factory.json")?
|
||||
.generate()?
|
||||
.write_to_file("src/abi/factory.rs")?;
|
||||
Abigen::new("Pool", "abi/Pool.json")?
|
||||
.generate()?
|
||||
.write_to_file("src/abi/pool.rs")?;
|
||||
Ok(())
|
||||
}
|
||||
125
substreams/ethereum-pancakeswap-v3/ethereum-pancakeswap-v3.yaml
Normal file
125
substreams/ethereum-pancakeswap-v3/ethereum-pancakeswap-v3.yaml
Normal file
@@ -0,0 +1,125 @@
|
||||
specVersion: v0.1.0
|
||||
package:
|
||||
name: "ethereum_pancakeswap_v3"
|
||||
version: v0.1.1
|
||||
|
||||
protobuf:
|
||||
files:
|
||||
- tycho/evm/v1/entity.proto
|
||||
- tycho/evm/v1/common.proto
|
||||
- tycho/evm/v1/utils.proto
|
||||
- pancakeswap.proto
|
||||
importPaths:
|
||||
- ./proto/v1
|
||||
- ../../proto/
|
||||
|
||||
binaries:
|
||||
default:
|
||||
type: wasm/rust-v1
|
||||
file: ../target/wasm32-unknown-unknown/release/ethereum_pancakeswap_v3.wasm
|
||||
|
||||
modules:
|
||||
- name: map_pools_created
|
||||
kind: map
|
||||
initialBlock: 16950686
|
||||
inputs:
|
||||
- params: string
|
||||
- source: sf.ethereum.type.v2.Block
|
||||
output:
|
||||
type: proto:tycho.evm.v1.BlockChanges
|
||||
|
||||
- name: store_pools
|
||||
kind: store
|
||||
initialBlock: 16950686
|
||||
updatePolicy: set_if_not_exists
|
||||
valueType: proto:pancakeswap.v3.Pool
|
||||
inputs:
|
||||
- map: map_pools_created
|
||||
|
||||
- name: map_events
|
||||
kind: map
|
||||
initialBlock: 16950686
|
||||
inputs:
|
||||
- source: sf.ethereum.type.v2.Block
|
||||
- store: store_pools
|
||||
output:
|
||||
type: proto:pancakeswap.v3.Events
|
||||
|
||||
- name: map_balance_changes
|
||||
kind: map
|
||||
initialBlock: 16950686
|
||||
inputs:
|
||||
- map: map_events
|
||||
output:
|
||||
type: proto:tycho.evm.v1.BlockBalanceDeltas
|
||||
|
||||
- name: store_pools_balances
|
||||
kind: store
|
||||
initialBlock: 16950686
|
||||
updatePolicy: add
|
||||
valueType: bigint
|
||||
inputs:
|
||||
- map: map_balance_changes
|
||||
|
||||
- name: map_ticks_changes
|
||||
kind: map
|
||||
initialBlock: 16950686
|
||||
inputs:
|
||||
- map: map_events
|
||||
output:
|
||||
type: proto:pancakeswap.v3.TickDeltas
|
||||
|
||||
- name: store_ticks_liquidity
|
||||
kind: store
|
||||
initialBlock: 16950686
|
||||
updatePolicy: add
|
||||
valueType: bigint
|
||||
inputs:
|
||||
- map: map_ticks_changes
|
||||
|
||||
- name: store_pool_current_tick
|
||||
kind: store
|
||||
initialBlock: 16950686
|
||||
updatePolicy: set
|
||||
valueType: int64
|
||||
inputs:
|
||||
- map: map_events
|
||||
|
||||
- name: map_liquidity_changes
|
||||
kind: map
|
||||
initialBlock: 16950686
|
||||
inputs:
|
||||
- map: map_events
|
||||
- store: store_pool_current_tick
|
||||
output:
|
||||
type: proto:pancakeswap.v3.LiquidityChanges
|
||||
|
||||
- name: store_liquidity
|
||||
kind: store
|
||||
initialBlock: 16950686
|
||||
updatePolicy: set_sum
|
||||
valueType: bigint
|
||||
inputs:
|
||||
- map: map_liquidity_changes
|
||||
|
||||
- name: map_protocol_changes
|
||||
kind: map
|
||||
initialBlock: 16950686
|
||||
inputs:
|
||||
- source: sf.ethereum.type.v2.Block
|
||||
- map: map_pools_created
|
||||
- map: map_events
|
||||
- map: map_balance_changes
|
||||
- store: store_pools_balances
|
||||
mode: deltas
|
||||
- map: map_ticks_changes
|
||||
- store: store_ticks_liquidity
|
||||
mode: deltas
|
||||
- map: map_liquidity_changes
|
||||
- store: store_liquidity
|
||||
mode: deltas
|
||||
output:
|
||||
type: proto:tycho.evm.v1.BlockChanges
|
||||
|
||||
params:
|
||||
map_pools_created: "0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865"
|
||||
179
substreams/ethereum-pancakeswap-v3/proto/v1/pancakeswap.proto
Normal file
179
substreams/ethereum-pancakeswap-v3/proto/v1/pancakeswap.proto
Normal file
@@ -0,0 +1,179 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package pancakeswap.v3;
|
||||
|
||||
message Pool {
|
||||
bytes address = 1;
|
||||
bytes token0 = 2;
|
||||
bytes token1 = 3;
|
||||
uint64 fee = 4;
|
||||
bytes created_tx_hash = 5;
|
||||
}
|
||||
|
||||
// A struct describing a transaction.
|
||||
message Transaction {
|
||||
// The transaction hash.
|
||||
bytes hash = 1;
|
||||
// The sender of the transaction.
|
||||
bytes from = 2;
|
||||
// The receiver of the transaction.
|
||||
bytes to = 3;
|
||||
// The transactions index within the block.
|
||||
uint64 index = 4;
|
||||
}
|
||||
|
||||
// A change to a pool's tick.
|
||||
message TickDelta {
|
||||
// The address of the pool.
|
||||
bytes pool_address = 1;
|
||||
// The index of the tick.
|
||||
int32 tick_index = 2;
|
||||
// The liquidity net delta of this tick. Bigint encoded as signed little endian bytes.
|
||||
bytes liquidity_net_delta = 3;
|
||||
// Used to determine the order of the balance changes. Necessary for the balance store.
|
||||
uint64 ordinal = 4;
|
||||
Transaction transaction = 5;
|
||||
}
|
||||
|
||||
// A group of TickDelta
|
||||
message TickDeltas {
|
||||
repeated TickDelta deltas = 1;
|
||||
}
|
||||
|
||||
// A change to a pool's liquidity.
|
||||
message LiquidityChange {
|
||||
// The address of the pool.
|
||||
bytes pool_address = 1;
|
||||
// The liquidity changed amount. Bigint encoded as signed little endian bytes.
|
||||
bytes value = 2;
|
||||
// The type of update, can be absolute or delta.
|
||||
LiquidityChangeType change_type = 3;
|
||||
// Used to determine the order of the balance changes. Necessary for the balance store.
|
||||
uint64 ordinal = 4;
|
||||
Transaction transaction = 5;
|
||||
}
|
||||
|
||||
// A group of LiquidityChange
|
||||
message LiquidityChanges {
|
||||
repeated LiquidityChange changes = 1;
|
||||
}
|
||||
|
||||
|
||||
enum LiquidityChangeType {
|
||||
DELTA = 0;
|
||||
ABSOLUTE = 1;
|
||||
}
|
||||
|
||||
message Events {
|
||||
repeated PoolEvent pool_events = 3;
|
||||
|
||||
message PoolEvent {
|
||||
oneof type {
|
||||
Initialize initialize = 1;
|
||||
Mint mint = 2;
|
||||
Collect collect = 3;
|
||||
Burn burn = 4;
|
||||
Swap swap = 5;
|
||||
Flash flash = 6;
|
||||
SetFeeProtocol set_fee_protocol = 7;
|
||||
CollectProtocol collect_protocol = 8;
|
||||
}
|
||||
uint64 log_ordinal = 100;
|
||||
string pool_address = 102;
|
||||
string token0 = 103;
|
||||
string token1 = 104;
|
||||
uint64 fee = 105;
|
||||
Transaction transaction = 106;
|
||||
|
||||
message Initialize {
|
||||
// Unsigned
|
||||
string sqrt_price = 1;
|
||||
int32 tick = 2;
|
||||
}
|
||||
|
||||
message Mint {
|
||||
string sender = 1;
|
||||
string owner = 2;
|
||||
// Signed
|
||||
int32 tick_lower = 3;
|
||||
// Signed
|
||||
int32 tick_upper = 4;
|
||||
// Unsigned
|
||||
string amount = 5;
|
||||
// Unsigned
|
||||
string amount_0 = 6;
|
||||
// Unsigned
|
||||
string amount_1 = 7;
|
||||
}
|
||||
|
||||
message Collect {
|
||||
string owner = 1;
|
||||
string recipient = 2;
|
||||
int32 tick_lower = 3;
|
||||
int32 tick_upper = 4;
|
||||
// Unsigned
|
||||
string amount_0 = 5;
|
||||
// Unsigned
|
||||
string amount_1 = 6;
|
||||
}
|
||||
|
||||
message Burn {
|
||||
string owner = 1;
|
||||
int32 tick_lower = 2;
|
||||
int32 tick_upper = 3;
|
||||
// Unsigned
|
||||
string amount = 4;
|
||||
// Unsigned
|
||||
string amount_0 = 5;
|
||||
// Unsigned
|
||||
string amount_1 = 6;
|
||||
}
|
||||
|
||||
message Swap {
|
||||
string sender = 1;
|
||||
string recipient = 2;
|
||||
// Signed
|
||||
string amount_0 = 3;
|
||||
// Signed
|
||||
string amount_1 = 4;
|
||||
// Unsigned
|
||||
string sqrt_price = 6;
|
||||
// Unsigned
|
||||
string liquidity = 7;
|
||||
int32 tick = 8;
|
||||
}
|
||||
|
||||
message Flash {
|
||||
string sender = 1;
|
||||
string recipient = 2;
|
||||
// Unsigned
|
||||
string amount_0 = 3;
|
||||
// Unsigned
|
||||
string amount_1 = 4;
|
||||
// Unsigned
|
||||
string paid_0 = 5;
|
||||
// Unsigned
|
||||
string paid_1 = 6;
|
||||
}
|
||||
|
||||
message SetFeeProtocol {
|
||||
// Unsigned
|
||||
uint64 fee_protocol_0_old = 1;
|
||||
// Unsigned
|
||||
uint64 fee_protocol_1_old = 2;
|
||||
// Unsigned
|
||||
uint64 fee_protocol_0_new = 3;
|
||||
// Unsigned
|
||||
uint64 fee_protocol_1_new = 4;
|
||||
}
|
||||
|
||||
message CollectProtocol {
|
||||
string sender = 1;
|
||||
string recipient = 2;
|
||||
// Unsigned
|
||||
string amount_0 = 3;
|
||||
// Unsigned
|
||||
string amount_1 = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
4
substreams/ethereum-pancakeswap-v3/rust-toolchain.toml
Normal file
4
substreams/ethereum-pancakeswap-v3/rust-toolchain.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "1.83.0"
|
||||
components = [ "rustfmt" ]
|
||||
targets = [ "wasm32-unknown-unknown" ]
|
||||
2157
substreams/ethereum-pancakeswap-v3/src/abi/factory.rs
Normal file
2157
substreams/ethereum-pancakeswap-v3/src/abi/factory.rs
Normal file
File diff suppressed because it is too large
Load Diff
4
substreams/ethereum-pancakeswap-v3/src/abi/mod.rs
Normal file
4
substreams/ethereum-pancakeswap-v3/src/abi/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
#![allow(clippy::all, clippy::pedantic, clippy::nursery)]
|
||||
|
||||
pub mod factory;
|
||||
pub mod pool;
|
||||
5168
substreams/ethereum-pancakeswap-v3/src/abi/pool.rs
Normal file
5168
substreams/ethereum-pancakeswap-v3/src/abi/pool.rs
Normal file
File diff suppressed because it is too large
Load Diff
7
substreams/ethereum-pancakeswap-v3/src/lib.rs
Normal file
7
substreams/ethereum-pancakeswap-v3/src/lib.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
#![allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
|
||||
mod abi;
|
||||
mod modules;
|
||||
mod pb;
|
||||
|
||||
pub use modules::*;
|
||||
@@ -0,0 +1,115 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use ethabi::ethereum_types::Address;
|
||||
use substreams::scalar::BigInt;
|
||||
use substreams_ethereum::pb::eth::v2::{self as eth};
|
||||
|
||||
use substreams_helper::{event_handler::EventHandler, hex::Hexable};
|
||||
|
||||
use crate::abi::factory::events::PoolCreated;
|
||||
|
||||
use tycho_substreams::prelude::*;
|
||||
|
||||
#[substreams::handlers::map]
|
||||
pub fn map_pools_created(
|
||||
params: String,
|
||||
block: eth::Block,
|
||||
) -> Result<BlockChanges, substreams::errors::Error> {
|
||||
let mut new_pools: Vec<TransactionChanges> = vec![];
|
||||
let factory_address = params.as_str();
|
||||
|
||||
get_new_pools(&block, &mut new_pools, factory_address);
|
||||
|
||||
Ok(BlockChanges { block: None, changes: new_pools })
|
||||
}
|
||||
|
||||
// Extract new pools from PoolCreated events
|
||||
fn get_new_pools(
|
||||
block: ð::Block,
|
||||
new_pools: &mut Vec<TransactionChanges>,
|
||||
factory_address: &str,
|
||||
) {
|
||||
// Extract new pools from PoolCreated events
|
||||
let mut on_pool_created = |event: PoolCreated, _tx: ð::TransactionTrace, _log: ð::Log| {
|
||||
let tycho_tx: Transaction = _tx.into();
|
||||
|
||||
new_pools.push(TransactionChanges {
|
||||
tx: Some(tycho_tx.clone()),
|
||||
entity_changes: vec![EntityChanges {
|
||||
component_id: event.pool.clone().to_hex(),
|
||||
attributes: vec![
|
||||
Attribute {
|
||||
name: "liquidity".to_string(),
|
||||
value: BigInt::from(0).to_signed_bytes_be(),
|
||||
change: ChangeType::Creation.into(),
|
||||
},
|
||||
Attribute {
|
||||
name: "tick".to_string(),
|
||||
value: BigInt::from(0).to_signed_bytes_be(),
|
||||
change: ChangeType::Creation.into(),
|
||||
},
|
||||
Attribute {
|
||||
name: "sqrt_price_x96".to_string(),
|
||||
value: BigInt::from(0).to_signed_bytes_be(),
|
||||
change: ChangeType::Creation.into(),
|
||||
},
|
||||
],
|
||||
}],
|
||||
component_changes: vec![ProtocolComponent {
|
||||
id: event.pool.to_hex(),
|
||||
tokens: vec![event.token0.clone(), event.token1.clone()],
|
||||
contracts: vec![],
|
||||
static_att: vec![
|
||||
Attribute {
|
||||
name: "fee".to_string(),
|
||||
value: event.fee.to_signed_bytes_be(),
|
||||
change: ChangeType::Creation.into(),
|
||||
},
|
||||
Attribute {
|
||||
name: "tick_spacing".to_string(),
|
||||
value: event.tick_spacing.to_signed_bytes_be(),
|
||||
change: ChangeType::Creation.into(),
|
||||
},
|
||||
Attribute {
|
||||
name: "pool_address".to_string(),
|
||||
value: event.pool.clone(),
|
||||
change: ChangeType::Creation.into(),
|
||||
},
|
||||
],
|
||||
change: i32::from(ChangeType::Creation),
|
||||
protocol_type: Option::from(ProtocolType {
|
||||
name: "pancakeswap_v3_pool".to_string(),
|
||||
financial_type: FinancialType::Swap.into(),
|
||||
attribute_schema: vec![],
|
||||
implementation_type: ImplementationType::Custom.into(),
|
||||
}),
|
||||
tx: Some(tycho_tx),
|
||||
}],
|
||||
balance_changes: vec![
|
||||
BalanceChange {
|
||||
token: event.token0,
|
||||
balance: BigInt::from(0).to_signed_bytes_be(),
|
||||
component_id: event
|
||||
.pool
|
||||
.clone()
|
||||
.to_hex()
|
||||
.as_bytes()
|
||||
.to_vec(),
|
||||
},
|
||||
BalanceChange {
|
||||
token: event.token1,
|
||||
balance: BigInt::from(0).to_signed_bytes_be(),
|
||||
component_id: event.pool.to_hex().as_bytes().to_vec(),
|
||||
},
|
||||
],
|
||||
contract_changes: vec![],
|
||||
})
|
||||
};
|
||||
|
||||
let mut eh = EventHandler::new(block);
|
||||
|
||||
eh.filter_by_address(vec![Address::from_str(factory_address).unwrap()]);
|
||||
|
||||
eh.on::<PoolCreated, _>(&mut on_pool_created);
|
||||
eh.handle_events();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
use std::str;
|
||||
|
||||
use substreams::{
|
||||
scalar::BigInt,
|
||||
store::{StoreNew, StoreSetIfNotExists, StoreSetIfNotExistsProto},
|
||||
};
|
||||
use tycho_substreams::models::BlockChanges;
|
||||
|
||||
use crate::pb::pancakeswap::v3::Pool;
|
||||
|
||||
#[substreams::handlers::store]
|
||||
pub fn store_pools(pools_created: BlockChanges, store: StoreSetIfNotExistsProto<Pool>) {
|
||||
// Store pools. Required so the next maps can match any event to a known pool by their address
|
||||
|
||||
for change in pools_created.changes {
|
||||
for component_change in &change.component_changes {
|
||||
let pool_address: &str = &component_change.id;
|
||||
let pool: Pool = Pool {
|
||||
address: hex::decode(pool_address.trim_start_matches("0x")).unwrap(),
|
||||
token0: component_change.tokens[0].clone(),
|
||||
token1: component_change.tokens[1].clone(),
|
||||
created_tx_hash: change.tx.as_ref().unwrap().hash.clone(),
|
||||
fee: BigInt::from_signed_bytes_be(
|
||||
&component_change
|
||||
.static_att
|
||||
.iter()
|
||||
.find(|attr| attr.name == "fee")
|
||||
.expect("every pool should have fee as static attribute")
|
||||
.value,
|
||||
)
|
||||
.to_u64(),
|
||||
};
|
||||
store.set_if_not_exists(0, format!("{}:{}", "Pool", pool_address), &pool);
|
||||
}
|
||||
}
|
||||
}
|
||||
195
substreams/ethereum-pancakeswap-v3/src/modules/3_map_events.rs
Normal file
195
substreams/ethereum-pancakeswap-v3/src/modules/3_map_events.rs
Normal file
@@ -0,0 +1,195 @@
|
||||
use anyhow::Ok;
|
||||
use substreams::{
|
||||
store::{StoreGet, StoreGetProto},
|
||||
Hex,
|
||||
};
|
||||
use substreams_ethereum::{
|
||||
pb::eth::v2::{self as eth, Log, TransactionTrace},
|
||||
Event,
|
||||
};
|
||||
use substreams_helper::hex::Hexable;
|
||||
|
||||
use crate::{
|
||||
abi::pool::events::{
|
||||
Burn, Collect, CollectProtocol, Flash, Initialize, Mint, SetFeeProtocol, Swap,
|
||||
},
|
||||
pb::pancakeswap::v3::{
|
||||
events::{
|
||||
pool_event::{self, Type},
|
||||
PoolEvent,
|
||||
},
|
||||
Events, Pool,
|
||||
},
|
||||
};
|
||||
|
||||
#[substreams::handlers::map]
|
||||
pub fn map_events(
|
||||
block: eth::Block,
|
||||
pools_store: StoreGetProto<Pool>,
|
||||
) -> Result<Events, anyhow::Error> {
|
||||
let mut pool_events = block
|
||||
.transaction_traces
|
||||
.into_iter()
|
||||
.filter(|tx| tx.status == 1)
|
||||
.flat_map(|tx| {
|
||||
let receipt = tx
|
||||
.receipt
|
||||
.as_ref()
|
||||
.expect("all transaction traces have a receipt");
|
||||
|
||||
receipt
|
||||
.logs
|
||||
.iter()
|
||||
.filter_map(|log| {
|
||||
let key = format!("{}:{}", "Pool", log.address.to_hex());
|
||||
// Skip if the log is not from a known pool.
|
||||
if let Some(pool) = pools_store.get_last(key) {
|
||||
log_to_event(log, pool, &tx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
pool_events.sort_unstable_by_key(|e| e.log_ordinal);
|
||||
|
||||
Ok(Events { pool_events })
|
||||
}
|
||||
|
||||
fn log_to_event(event: &Log, pool: Pool, tx: &TransactionTrace) -> Option<PoolEvent> {
|
||||
if let Some(init) = Initialize::match_and_decode(event) {
|
||||
Some(PoolEvent {
|
||||
log_ordinal: event.ordinal,
|
||||
pool_address: Hex(pool.address).to_string(),
|
||||
token0: Hex(pool.token0).to_string(),
|
||||
token1: Hex(pool.token1).to_string(),
|
||||
fee: pool.fee,
|
||||
transaction: Some(tx.into()),
|
||||
r#type: Some(Type::Initialize(pool_event::Initialize {
|
||||
sqrt_price: init.sqrt_price_x96.to_string(),
|
||||
tick: init.tick.into(),
|
||||
})),
|
||||
})
|
||||
} else if let Some(swap) = Swap::match_and_decode(event) {
|
||||
Some(PoolEvent {
|
||||
log_ordinal: event.ordinal,
|
||||
pool_address: Hex(pool.address).to_string(),
|
||||
token0: Hex(pool.token0).to_string(),
|
||||
token1: Hex(pool.token1).to_string(),
|
||||
fee: pool.fee,
|
||||
transaction: Some(tx.into()),
|
||||
r#type: Some(Type::Swap(pool_event::Swap {
|
||||
sender: Hex(swap.sender).to_string(),
|
||||
recipient: Hex(swap.recipient).to_string(),
|
||||
amount_0: swap.amount0.to_string(),
|
||||
amount_1: swap.amount1.to_string(),
|
||||
sqrt_price: swap.sqrt_price_x96.to_string(),
|
||||
liquidity: swap.liquidity.to_string(),
|
||||
tick: swap.tick.into(),
|
||||
})),
|
||||
})
|
||||
} else if let Some(flash) = Flash::match_and_decode(event) {
|
||||
Some(PoolEvent {
|
||||
log_ordinal: event.ordinal,
|
||||
pool_address: Hex(pool.address).to_string(),
|
||||
token0: Hex(pool.token0).to_string(),
|
||||
token1: Hex(pool.token1).to_string(),
|
||||
fee: pool.fee,
|
||||
transaction: Some(tx.into()),
|
||||
r#type: Some(Type::Flash(pool_event::Flash {
|
||||
sender: Hex(flash.sender).to_string(),
|
||||
recipient: Hex(flash.recipient).to_string(),
|
||||
amount_0: flash.amount0.to_string(),
|
||||
amount_1: flash.amount1.to_string(),
|
||||
paid_0: flash.paid0.to_string(),
|
||||
paid_1: flash.paid1.to_string(),
|
||||
})),
|
||||
})
|
||||
} else if let Some(mint) = Mint::match_and_decode(event) {
|
||||
Some(PoolEvent {
|
||||
log_ordinal: event.ordinal,
|
||||
pool_address: Hex(pool.address).to_string(),
|
||||
token0: Hex(pool.token0).to_string(),
|
||||
token1: Hex(pool.token1).to_string(),
|
||||
fee: pool.fee,
|
||||
transaction: Some(tx.into()),
|
||||
r#type: Some(Type::Mint(pool_event::Mint {
|
||||
sender: Hex(mint.sender).to_string(),
|
||||
owner: Hex(mint.owner).to_string(),
|
||||
tick_lower: mint.tick_lower.into(),
|
||||
tick_upper: mint.tick_upper.into(),
|
||||
amount: mint.amount.to_string(),
|
||||
amount_0: mint.amount0.to_string(),
|
||||
amount_1: mint.amount1.to_string(),
|
||||
})),
|
||||
})
|
||||
} else if let Some(burn) = Burn::match_and_decode(event) {
|
||||
Some(PoolEvent {
|
||||
log_ordinal: event.ordinal,
|
||||
pool_address: Hex(pool.address).to_string(),
|
||||
token0: Hex(pool.token0).to_string(),
|
||||
token1: Hex(pool.token1).to_string(),
|
||||
fee: pool.fee,
|
||||
transaction: Some(tx.into()),
|
||||
r#type: Some(Type::Burn(pool_event::Burn {
|
||||
owner: Hex(burn.owner).to_string(),
|
||||
tick_lower: burn.tick_lower.into(),
|
||||
tick_upper: burn.tick_upper.into(),
|
||||
amount: burn.amount.to_string(),
|
||||
amount_0: burn.amount0.to_string(),
|
||||
amount_1: burn.amount1.to_string(),
|
||||
})),
|
||||
})
|
||||
} else if let Some(collect) = Collect::match_and_decode(event) {
|
||||
Some(PoolEvent {
|
||||
log_ordinal: event.ordinal,
|
||||
pool_address: Hex(pool.address).to_string(),
|
||||
token0: Hex(pool.token0).to_string(),
|
||||
token1: Hex(pool.token1).to_string(),
|
||||
fee: pool.fee,
|
||||
transaction: Some(tx.into()),
|
||||
r#type: Some(Type::Collect(pool_event::Collect {
|
||||
owner: Hex(collect.owner).to_string(),
|
||||
recipient: Hex(collect.recipient).to_string(),
|
||||
tick_lower: collect.tick_lower.into(),
|
||||
tick_upper: collect.tick_upper.into(),
|
||||
amount_0: collect.amount0.to_string(),
|
||||
amount_1: collect.amount1.to_string(),
|
||||
})),
|
||||
})
|
||||
} else if let Some(set_fp) = SetFeeProtocol::match_and_decode(event) {
|
||||
Some(PoolEvent {
|
||||
log_ordinal: event.ordinal,
|
||||
pool_address: Hex(pool.address).to_string(),
|
||||
token0: Hex(pool.token0).to_string(),
|
||||
token1: Hex(pool.token1).to_string(),
|
||||
fee: pool.fee,
|
||||
transaction: Some(tx.into()),
|
||||
r#type: Some(Type::SetFeeProtocol(pool_event::SetFeeProtocol {
|
||||
fee_protocol_0_old: set_fp.fee_protocol0_old.to_u64(),
|
||||
fee_protocol_1_old: set_fp.fee_protocol1_old.to_u64(),
|
||||
fee_protocol_0_new: set_fp.fee_protocol0_new.to_u64(),
|
||||
fee_protocol_1_new: set_fp.fee_protocol1_new.to_u64(),
|
||||
})),
|
||||
})
|
||||
} else if let Some(cp) = CollectProtocol::match_and_decode(event) {
|
||||
Some(PoolEvent {
|
||||
log_ordinal: event.ordinal,
|
||||
pool_address: Hex(pool.address).to_string(),
|
||||
token0: Hex(pool.token0).to_string(),
|
||||
token1: Hex(pool.token1).to_string(),
|
||||
fee: pool.fee,
|
||||
transaction: Some(tx.into()),
|
||||
r#type: Some(Type::CollectProtocol(pool_event::CollectProtocol {
|
||||
sender: Hex(cp.sender).to_string(),
|
||||
recipient: Hex(cp.recipient).to_string(),
|
||||
amount_0: cp.amount0.to_string(),
|
||||
amount_1: cp.amount1.to_string(),
|
||||
})),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Ok;
|
||||
use tycho_substreams::models::{BalanceDelta, BlockBalanceDeltas};
|
||||
|
||||
use crate::pb::pancakeswap::v3::{
|
||||
events::{pool_event, PoolEvent},
|
||||
Events,
|
||||
};
|
||||
use substreams::{
|
||||
scalar::BigInt,
|
||||
store::{StoreAddBigInt, StoreNew},
|
||||
};
|
||||
|
||||
#[substreams::handlers::map]
|
||||
pub fn map_balance_changes(events: Events) -> Result<BlockBalanceDeltas, anyhow::Error> {
|
||||
let balance_deltas = events
|
||||
.pool_events
|
||||
.into_iter()
|
||||
.flat_map(event_to_balance_deltas)
|
||||
.collect();
|
||||
|
||||
Ok(BlockBalanceDeltas { balance_deltas })
|
||||
}
|
||||
|
||||
#[substreams::handlers::store]
|
||||
pub fn store_pools_balances(balances_deltas: BlockBalanceDeltas, store: StoreAddBigInt) {
|
||||
tycho_substreams::balances::store_balance_changes(balances_deltas, store);
|
||||
}
|
||||
|
||||
fn event_to_balance_deltas(event: PoolEvent) -> Vec<BalanceDelta> {
|
||||
let address = format!("0x{}", event.pool_address)
|
||||
.as_bytes()
|
||||
.to_vec();
|
||||
match event.r#type.unwrap() {
|
||||
pool_event::Type::Mint(e) => vec![
|
||||
BalanceDelta {
|
||||
token: hex::decode(event.token0).unwrap(),
|
||||
delta: BigInt::from_str(&e.amount_0)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
component_id: address.clone(),
|
||||
ord: event.log_ordinal,
|
||||
tx: event
|
||||
.transaction
|
||||
.as_ref()
|
||||
.map(Into::into),
|
||||
},
|
||||
BalanceDelta {
|
||||
token: hex::decode(event.token1).unwrap(),
|
||||
delta: BigInt::from_str(&e.amount_1)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
component_id: address,
|
||||
ord: event.log_ordinal,
|
||||
tx: event.transaction.map(Into::into),
|
||||
},
|
||||
],
|
||||
pool_event::Type::Collect(e) => vec![
|
||||
BalanceDelta {
|
||||
token: hex::decode(event.token0).unwrap(),
|
||||
delta: BigInt::from_str(&e.amount_0)
|
||||
.unwrap()
|
||||
.neg()
|
||||
.to_signed_bytes_be(),
|
||||
component_id: address.clone(),
|
||||
ord: event.log_ordinal,
|
||||
tx: event
|
||||
.transaction
|
||||
.as_ref()
|
||||
.map(Into::into),
|
||||
},
|
||||
BalanceDelta {
|
||||
token: hex::decode(event.token1).unwrap(),
|
||||
delta: BigInt::from_str(&e.amount_1)
|
||||
.unwrap()
|
||||
.neg()
|
||||
.to_signed_bytes_be(),
|
||||
component_id: address,
|
||||
ord: event.log_ordinal,
|
||||
tx: event.transaction.map(Into::into),
|
||||
},
|
||||
],
|
||||
//Burn balance changes are accounted for in the Collect event.
|
||||
pool_event::Type::Burn(_) => vec![],
|
||||
pool_event::Type::Swap(e) => {
|
||||
vec![
|
||||
BalanceDelta {
|
||||
token: hex::decode(event.token0).unwrap(),
|
||||
delta: BigInt::from_str(&e.amount_0)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
component_id: address.clone(),
|
||||
ord: event.log_ordinal,
|
||||
tx: event
|
||||
.transaction
|
||||
.as_ref()
|
||||
.map(Into::into),
|
||||
},
|
||||
BalanceDelta {
|
||||
token: hex::decode(event.token1).unwrap(),
|
||||
delta: BigInt::from_str(&e.amount_1)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
component_id: address,
|
||||
ord: event.log_ordinal,
|
||||
tx: event.transaction.map(Into::into),
|
||||
},
|
||||
]
|
||||
}
|
||||
pool_event::Type::Flash(e) => vec![
|
||||
BalanceDelta {
|
||||
token: hex::decode(event.token0).unwrap(),
|
||||
delta: BigInt::from_str(&e.paid_0)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
component_id: address.clone(),
|
||||
ord: event.log_ordinal,
|
||||
tx: event
|
||||
.transaction
|
||||
.as_ref()
|
||||
.map(Into::into),
|
||||
},
|
||||
BalanceDelta {
|
||||
token: hex::decode(event.token1).unwrap(),
|
||||
delta: BigInt::from_str(&e.paid_1)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
component_id: address,
|
||||
ord: event.log_ordinal,
|
||||
tx: event.transaction.map(Into::into),
|
||||
},
|
||||
],
|
||||
pool_event::Type::CollectProtocol(e) => {
|
||||
vec![
|
||||
BalanceDelta {
|
||||
token: hex::decode(event.token0).unwrap(),
|
||||
delta: BigInt::from_str(&e.amount_0)
|
||||
.unwrap()
|
||||
.neg()
|
||||
.to_signed_bytes_be(),
|
||||
component_id: address.clone(),
|
||||
ord: event.log_ordinal,
|
||||
tx: event
|
||||
.transaction
|
||||
.as_ref()
|
||||
.map(Into::into),
|
||||
},
|
||||
BalanceDelta {
|
||||
token: hex::decode(event.token1).unwrap(),
|
||||
delta: BigInt::from_str(&e.amount_1)
|
||||
.unwrap()
|
||||
.neg()
|
||||
.to_signed_bytes_be(),
|
||||
component_id: address,
|
||||
ord: event.log_ordinal,
|
||||
tx: event.transaction.map(Into::into),
|
||||
},
|
||||
]
|
||||
}
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use substreams::store::{
|
||||
StoreGet, StoreGetInt64, StoreSet, StoreSetInt64, StoreSetSum, StoreSetSumBigInt,
|
||||
};
|
||||
|
||||
use crate::pb::pancakeswap::v3::{
|
||||
events::{pool_event, PoolEvent},
|
||||
Events, LiquidityChange, LiquidityChangeType, LiquidityChanges,
|
||||
};
|
||||
|
||||
use substreams::{scalar::BigInt, store::StoreNew};
|
||||
|
||||
use anyhow::Ok;
|
||||
|
||||
#[substreams::handlers::store]
|
||||
pub fn store_pool_current_tick(events: Events, store: StoreSetInt64) {
|
||||
events
|
||||
.pool_events
|
||||
.into_iter()
|
||||
.filter_map(event_to_current_tick)
|
||||
.for_each(|(pool, ordinal, new_tick_index)| {
|
||||
store.set(ordinal, format!("pool:{0}", pool), &new_tick_index.into())
|
||||
});
|
||||
}
|
||||
|
||||
#[substreams::handlers::map]
|
||||
pub fn map_liquidity_changes(
|
||||
events: Events,
|
||||
pools_current_tick_store: StoreGetInt64,
|
||||
) -> Result<LiquidityChanges, anyhow::Error> {
|
||||
let mut changes = events
|
||||
.pool_events
|
||||
.into_iter()
|
||||
.filter(PoolEvent::can_introduce_liquidity_changes)
|
||||
.map(|e| {
|
||||
(
|
||||
pools_current_tick_store
|
||||
.get_at(e.log_ordinal, format!("pool:{0}", &e.pool_address))
|
||||
.unwrap_or(0),
|
||||
e,
|
||||
)
|
||||
})
|
||||
.filter_map(|(current_tick, event)| event_to_liquidity_deltas(current_tick, event))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
changes.sort_unstable_by_key(|l| l.ordinal);
|
||||
Ok(LiquidityChanges { changes })
|
||||
}
|
||||
|
||||
#[substreams::handlers::store]
|
||||
pub fn store_liquidity(ticks_deltas: LiquidityChanges, store: StoreSetSumBigInt) {
|
||||
ticks_deltas
|
||||
.changes
|
||||
.iter()
|
||||
.for_each(|changes| match changes.change_type() {
|
||||
LiquidityChangeType::Delta => {
|
||||
store.sum(
|
||||
changes.ordinal,
|
||||
format!("pool:{0}", hex::encode(&changes.pool_address)),
|
||||
BigInt::from_signed_bytes_be(&changes.value),
|
||||
);
|
||||
}
|
||||
LiquidityChangeType::Absolute => {
|
||||
store.set(
|
||||
changes.ordinal,
|
||||
format!("pool:{0}", hex::encode(&changes.pool_address)),
|
||||
BigInt::from_signed_bytes_be(&changes.value),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn event_to_liquidity_deltas(current_tick: i64, event: PoolEvent) -> Option<LiquidityChange> {
|
||||
match event.r#type.as_ref().unwrap() {
|
||||
pool_event::Type::Mint(mint) => {
|
||||
if current_tick >= mint.tick_lower.into() && current_tick < mint.tick_upper.into() {
|
||||
Some(LiquidityChange {
|
||||
pool_address: hex::decode(event.pool_address).unwrap(),
|
||||
value: BigInt::from_str(&mint.amount)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
change_type: LiquidityChangeType::Delta.into(),
|
||||
ordinal: event.log_ordinal,
|
||||
transaction: Some(event.transaction.unwrap()),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pool_event::Type::Burn(burn) => {
|
||||
if current_tick >= burn.tick_lower.into() && current_tick < burn.tick_upper.into() {
|
||||
Some(LiquidityChange {
|
||||
pool_address: hex::decode(event.pool_address).unwrap(),
|
||||
value: BigInt::from_str(&burn.amount)
|
||||
.unwrap()
|
||||
.neg()
|
||||
.to_signed_bytes_be(),
|
||||
change_type: LiquidityChangeType::Delta.into(),
|
||||
ordinal: event.log_ordinal,
|
||||
transaction: Some(event.transaction.unwrap()),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pool_event::Type::Swap(swap) => Some(LiquidityChange {
|
||||
pool_address: hex::decode(event.pool_address).unwrap(),
|
||||
value: BigInt::from_str(&swap.liquidity)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
change_type: LiquidityChangeType::Absolute.into(),
|
||||
ordinal: event.log_ordinal,
|
||||
transaction: Some(event.transaction.unwrap()),
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
impl PoolEvent {
|
||||
fn can_introduce_liquidity_changes(&self) -> bool {
|
||||
matches!(
|
||||
self.r#type.as_ref().unwrap(),
|
||||
pool_event::Type::Mint(_) | pool_event::Type::Burn(_) | pool_event::Type::Swap(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn event_to_current_tick(event: PoolEvent) -> Option<(String, u64, i32)> {
|
||||
match event.r#type.as_ref().unwrap() {
|
||||
pool_event::Type::Initialize(initialize) => {
|
||||
Some((event.pool_address, event.log_ordinal, initialize.tick))
|
||||
}
|
||||
pool_event::Type::Swap(swap) => Some((event.pool_address, event.log_ordinal, swap.tick)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use substreams::store::StoreAddBigInt;
|
||||
|
||||
use crate::pb::pancakeswap::v3::{
|
||||
events::{pool_event, PoolEvent},
|
||||
Events, TickDelta, TickDeltas,
|
||||
};
|
||||
|
||||
use substreams::{
|
||||
scalar::BigInt,
|
||||
store::{StoreAdd, StoreNew},
|
||||
};
|
||||
|
||||
use anyhow::Ok;
|
||||
|
||||
#[substreams::handlers::map]
|
||||
pub fn map_ticks_changes(events: Events) -> Result<TickDeltas, anyhow::Error> {
|
||||
let ticks_deltas = events
|
||||
.pool_events
|
||||
.into_iter()
|
||||
.flat_map(event_to_ticks_deltas)
|
||||
.collect();
|
||||
|
||||
Ok(TickDeltas { deltas: ticks_deltas })
|
||||
}
|
||||
|
||||
#[substreams::handlers::store]
|
||||
pub fn store_ticks_liquidity(ticks_deltas: TickDeltas, store: StoreAddBigInt) {
|
||||
let mut deltas = ticks_deltas.deltas;
|
||||
|
||||
deltas.sort_unstable_by_key(|delta| delta.ordinal);
|
||||
|
||||
deltas.iter().for_each(|delta| {
|
||||
store.add(
|
||||
delta.ordinal,
|
||||
format!("pool:{0}:tick:{1}", hex::encode(&delta.pool_address), delta.tick_index,),
|
||||
BigInt::from_signed_bytes_be(&delta.liquidity_net_delta),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn event_to_ticks_deltas(event: PoolEvent) -> Vec<TickDelta> {
|
||||
match event.r#type.as_ref().unwrap() {
|
||||
pool_event::Type::Mint(mint) => {
|
||||
vec![
|
||||
TickDelta {
|
||||
pool_address: hex::decode(&event.pool_address).unwrap(),
|
||||
tick_index: mint.tick_lower,
|
||||
liquidity_net_delta: BigInt::from_str(&mint.amount)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
ordinal: event.log_ordinal,
|
||||
transaction: event.transaction.clone(),
|
||||
},
|
||||
TickDelta {
|
||||
pool_address: hex::decode(&event.pool_address).unwrap(),
|
||||
tick_index: mint.tick_upper,
|
||||
liquidity_net_delta: BigInt::from_str(&mint.amount)
|
||||
.unwrap()
|
||||
.neg()
|
||||
.to_signed_bytes_be(),
|
||||
ordinal: event.log_ordinal,
|
||||
transaction: event.transaction,
|
||||
},
|
||||
]
|
||||
}
|
||||
pool_event::Type::Burn(burn) => vec![
|
||||
TickDelta {
|
||||
pool_address: hex::decode(&event.pool_address).unwrap(),
|
||||
tick_index: burn.tick_lower,
|
||||
liquidity_net_delta: BigInt::from_str(&burn.amount)
|
||||
.unwrap()
|
||||
.neg()
|
||||
.to_signed_bytes_be(),
|
||||
ordinal: event.log_ordinal,
|
||||
transaction: event.transaction.clone(),
|
||||
},
|
||||
TickDelta {
|
||||
pool_address: hex::decode(&event.pool_address).unwrap(),
|
||||
tick_index: burn.tick_upper,
|
||||
liquidity_net_delta: BigInt::from_str(&burn.amount)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
ordinal: event.log_ordinal,
|
||||
transaction: event.transaction,
|
||||
},
|
||||
],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
use crate::pb::pancakeswap::v3::{
|
||||
events::{pool_event, PoolEvent},
|
||||
Events, LiquidityChanges, TickDeltas,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use std::{collections::HashMap, str::FromStr, vec};
|
||||
use substreams::{pb::substreams::StoreDeltas, scalar::BigInt};
|
||||
use substreams_ethereum::pb::eth::v2::{self as eth};
|
||||
use substreams_helper::hex::Hexable;
|
||||
use tycho_substreams::{balances::aggregate_balances_changes, prelude::*};
|
||||
|
||||
type PoolAddress = Vec<u8>;
|
||||
|
||||
#[substreams::handlers::map]
|
||||
pub fn map_protocol_changes(
|
||||
block: eth::Block,
|
||||
created_pools: BlockChanges,
|
||||
events: Events,
|
||||
balances_map_deltas: BlockBalanceDeltas,
|
||||
balances_store_deltas: StoreDeltas,
|
||||
ticks_map_deltas: TickDeltas,
|
||||
ticks_store_deltas: StoreDeltas,
|
||||
pool_liquidity_changes: LiquidityChanges,
|
||||
pool_liquidity_store_deltas: StoreDeltas,
|
||||
) -> Result<BlockChanges, substreams::errors::Error> {
|
||||
// We merge contract changes by transaction (identified by transaction index) making it easy to
|
||||
// sort them at the very end.
|
||||
let mut transaction_changes: HashMap<_, TransactionChangesBuilder> = HashMap::new();
|
||||
|
||||
// Add created pools to the tx_changes_map
|
||||
for change in created_pools.changes.into_iter() {
|
||||
let tx = change.tx.as_ref().unwrap();
|
||||
let builder = transaction_changes
|
||||
.entry(tx.index)
|
||||
.or_insert_with(|| TransactionChangesBuilder::new(tx));
|
||||
change
|
||||
.component_changes
|
||||
.iter()
|
||||
.for_each(|c| {
|
||||
builder.add_protocol_component(c);
|
||||
});
|
||||
change
|
||||
.entity_changes
|
||||
.iter()
|
||||
.for_each(|ec| {
|
||||
builder.add_entity_change(ec);
|
||||
});
|
||||
change
|
||||
.balance_changes
|
||||
.iter()
|
||||
.for_each(|bc| {
|
||||
builder.add_balance_change(bc);
|
||||
});
|
||||
}
|
||||
|
||||
// Balance changes are gathered by the `StoreDelta` based on `PoolBalanceChanged` creating
|
||||
// `BlockBalanceDeltas`. We essentially just process the changes that occurred to the `store`
|
||||
// this block. Then, these balance changes are merged onto the existing map of tx contract
|
||||
// changes, inserting a new one if it doesn't exist.
|
||||
aggregate_balances_changes(balances_store_deltas, balances_map_deltas)
|
||||
.into_iter()
|
||||
.for_each(|(_, (tx, balances))| {
|
||||
let builder = transaction_changes
|
||||
.entry(tx.index)
|
||||
.or_insert_with(|| TransactionChangesBuilder::new(&tx));
|
||||
balances
|
||||
.values()
|
||||
.for_each(|token_bc_map| {
|
||||
token_bc_map
|
||||
.values()
|
||||
.for_each(|bc| builder.add_balance_change(bc))
|
||||
});
|
||||
});
|
||||
|
||||
// Insert ticks net-liquidity changes
|
||||
ticks_store_deltas
|
||||
.deltas
|
||||
.into_iter()
|
||||
.zip(ticks_map_deltas.deltas)
|
||||
.for_each(|(store_delta, tick_delta)| {
|
||||
let new_value_bigint =
|
||||
BigInt::from_str(&String::from_utf8(store_delta.new_value).unwrap()).unwrap();
|
||||
|
||||
// If old value is empty or the int value is 0, it's considered as a creation.
|
||||
let is_creation = store_delta.old_value.is_empty() ||
|
||||
BigInt::from_str(&String::from_utf8(store_delta.old_value).unwrap())
|
||||
.unwrap()
|
||||
.is_zero();
|
||||
let attribute_name = format!("ticks/{}/net-liquidity", tick_delta.tick_index);
|
||||
let attribute = Attribute {
|
||||
name: attribute_name,
|
||||
value: new_value_bigint.to_signed_bytes_be(),
|
||||
change: if is_creation {
|
||||
ChangeType::Creation.into()
|
||||
} else if new_value_bigint.is_zero() {
|
||||
ChangeType::Deletion.into()
|
||||
} else {
|
||||
ChangeType::Update.into()
|
||||
},
|
||||
};
|
||||
let tx = tick_delta.transaction.unwrap();
|
||||
let builder = transaction_changes
|
||||
.entry(tx.index)
|
||||
.or_insert_with(|| TransactionChangesBuilder::new(&tx.into()));
|
||||
|
||||
builder.add_entity_change(&EntityChanges {
|
||||
component_id: tick_delta.pool_address.to_hex(),
|
||||
attributes: vec![attribute],
|
||||
});
|
||||
});
|
||||
|
||||
// Insert liquidity changes
|
||||
pool_liquidity_store_deltas
|
||||
.deltas
|
||||
.into_iter()
|
||||
.zip(pool_liquidity_changes.changes)
|
||||
.for_each(|(store_delta, change)| {
|
||||
let new_value_bigint = BigInt::from_str(
|
||||
String::from_utf8(store_delta.new_value)
|
||||
.unwrap()
|
||||
.split(':')
|
||||
.nth(1)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let tx = change.transaction.unwrap();
|
||||
let builder = transaction_changes
|
||||
.entry(tx.index)
|
||||
.or_insert_with(|| TransactionChangesBuilder::new(&tx.into()));
|
||||
|
||||
builder.add_entity_change(&EntityChanges {
|
||||
component_id: change.pool_address.to_hex(),
|
||||
attributes: vec![Attribute {
|
||||
name: "liquidity".to_string(),
|
||||
value: new_value_bigint.to_signed_bytes_be(),
|
||||
change: ChangeType::Update.into(),
|
||||
}],
|
||||
});
|
||||
});
|
||||
|
||||
// Insert others changes
|
||||
events
|
||||
.pool_events
|
||||
.into_iter()
|
||||
.flat_map(event_to_attributes_updates)
|
||||
.for_each(|(tx, pool_address, attr)| {
|
||||
let builder = transaction_changes
|
||||
.entry(tx.index)
|
||||
.or_insert_with(|| TransactionChangesBuilder::new(&tx));
|
||||
builder.add_entity_change(&EntityChanges {
|
||||
component_id: pool_address.to_hex(),
|
||||
attributes: vec![attr],
|
||||
});
|
||||
});
|
||||
|
||||
Ok(BlockChanges {
|
||||
block: Some((&block).into()),
|
||||
changes: transaction_changes
|
||||
.drain()
|
||||
.sorted_unstable_by_key(|(index, _)| *index)
|
||||
.filter_map(|(_, builder)| builder.build())
|
||||
.collect::<Vec<_>>(),
|
||||
})
|
||||
}
|
||||
|
||||
fn event_to_attributes_updates(event: PoolEvent) -> Vec<(Transaction, PoolAddress, Attribute)> {
|
||||
match event.r#type.as_ref().unwrap() {
|
||||
pool_event::Type::Initialize(initalize) => {
|
||||
let (zero_to_one, one_to_zero) = fee_to_default_protocol_fees(event.fee);
|
||||
vec![
|
||||
(
|
||||
event
|
||||
.transaction
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into(),
|
||||
hex::decode(&event.pool_address).unwrap(),
|
||||
Attribute {
|
||||
name: "sqrt_price_x96".to_string(),
|
||||
value: BigInt::from_str(&initalize.sqrt_price)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
change: ChangeType::Update.into(),
|
||||
},
|
||||
),
|
||||
(
|
||||
event
|
||||
.transaction
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into(),
|
||||
hex::decode(&event.pool_address).unwrap(),
|
||||
Attribute {
|
||||
name: "tick".to_string(),
|
||||
value: BigInt::from(initalize.tick).to_signed_bytes_be(),
|
||||
change: ChangeType::Update.into(),
|
||||
},
|
||||
),
|
||||
(
|
||||
event
|
||||
.transaction
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into(),
|
||||
hex::decode(&event.pool_address).unwrap(),
|
||||
Attribute {
|
||||
name: "protocol_fees/zeroForOne".to_string(),
|
||||
value: BigInt::from(zero_to_one).to_signed_bytes_be(),
|
||||
change: ChangeType::Update.into(),
|
||||
},
|
||||
),
|
||||
(
|
||||
event.transaction.unwrap().into(),
|
||||
hex::decode(event.pool_address).unwrap(),
|
||||
Attribute {
|
||||
name: "protocol_fees/oneForZero".to_string(),
|
||||
value: BigInt::from(one_to_zero).to_signed_bytes_be(),
|
||||
change: ChangeType::Update.into(),
|
||||
},
|
||||
),
|
||||
]
|
||||
}
|
||||
pool_event::Type::Swap(swap) => vec![
|
||||
(
|
||||
event
|
||||
.transaction
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into(),
|
||||
hex::decode(&event.pool_address).unwrap(),
|
||||
Attribute {
|
||||
name: "sqrt_price_x96".to_string(),
|
||||
value: BigInt::from_str(&swap.sqrt_price)
|
||||
.unwrap()
|
||||
.to_signed_bytes_be(),
|
||||
change: ChangeType::Update.into(),
|
||||
},
|
||||
),
|
||||
(
|
||||
event.transaction.unwrap().into(),
|
||||
hex::decode(event.pool_address).unwrap(),
|
||||
Attribute {
|
||||
name: "tick".to_string(),
|
||||
value: BigInt::from(swap.tick).to_signed_bytes_be(),
|
||||
change: ChangeType::Update.into(),
|
||||
},
|
||||
),
|
||||
],
|
||||
pool_event::Type::SetFeeProtocol(sfp) => vec![
|
||||
(
|
||||
event
|
||||
.transaction
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into(),
|
||||
hex::decode(&event.pool_address).unwrap(),
|
||||
Attribute {
|
||||
name: "protocol_fees/zeroForOne".to_string(),
|
||||
value: BigInt::from(sfp.fee_protocol_0_new).to_signed_bytes_be(),
|
||||
change: ChangeType::Update.into(),
|
||||
},
|
||||
),
|
||||
(
|
||||
event.transaction.unwrap().into(),
|
||||
hex::decode(event.pool_address).unwrap(),
|
||||
Attribute {
|
||||
name: "protocol_fees/oneForZero".to_string(),
|
||||
value: BigInt::from(sfp.fee_protocol_1_new).to_signed_bytes_be(),
|
||||
change: ChangeType::Update.into(),
|
||||
},
|
||||
),
|
||||
],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
// Map the pool fee to the default protocol fees.
|
||||
// For the reference implementation see https://github.com/pancakeswap/pancake-v3-contracts/blob/5cc479f0c5a98966c74d94700057b8c3ca629afd/projects/v3-core/contracts/PancakeV3Pool.sol#L298-L306
|
||||
fn fee_to_default_protocol_fees(fee: u64) -> (u64, u64) {
|
||||
match fee {
|
||||
100 => (3300, 3300),
|
||||
500 => (3400, 3400),
|
||||
2500 => (3200, 3200),
|
||||
10000 => (3200, 3200),
|
||||
_ => panic!("Unexpected fee value"),
|
||||
}
|
||||
}
|
||||
61
substreams/ethereum-pancakeswap-v3/src/modules/mod.rs
Normal file
61
substreams/ethereum-pancakeswap-v3/src/modules/mod.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
pub use map_pool_created::map_pools_created;
|
||||
pub use map_protocol_changes::map_protocol_changes;
|
||||
pub use store_pools::store_pools;
|
||||
use substreams_ethereum::pb::eth::v2::TransactionTrace;
|
||||
|
||||
use crate::pb::pancakeswap::v3::Transaction;
|
||||
|
||||
#[path = "1_map_pool_created.rs"]
|
||||
mod map_pool_created;
|
||||
|
||||
#[path = "2_store_pools.rs"]
|
||||
mod store_pools;
|
||||
|
||||
#[path = "3_map_events.rs"]
|
||||
mod map_events;
|
||||
|
||||
#[path = "4_map_and_store_balance_changes.rs"]
|
||||
mod map_store_balance_changes;
|
||||
|
||||
#[path = "4_map_and_store_ticks.rs"]
|
||||
mod map_store_ticks;
|
||||
|
||||
#[path = "4_map_and_store_liquidity.rs"]
|
||||
mod map_store_liquidity;
|
||||
|
||||
#[path = "5_map_protocol_changes.rs"]
|
||||
mod map_protocol_changes;
|
||||
|
||||
impl From<TransactionTrace> for Transaction {
|
||||
fn from(value: TransactionTrace) -> Self {
|
||||
Self { hash: value.hash, from: value.from, to: value.to, index: value.index.into() }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&TransactionTrace> for Transaction {
|
||||
fn from(value: &TransactionTrace) -> Self {
|
||||
Self {
|
||||
hash: value.hash.clone(),
|
||||
from: value.from.clone(),
|
||||
to: value.to.clone(),
|
||||
index: value.index.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Transaction> for tycho_substreams::prelude::Transaction {
|
||||
fn from(value: &Transaction) -> Self {
|
||||
Self {
|
||||
hash: value.hash.clone(),
|
||||
from: value.from.clone(),
|
||||
to: value.to.clone(),
|
||||
index: value.index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Transaction> for tycho_substreams::prelude::Transaction {
|
||||
fn from(value: Transaction) -> Self {
|
||||
Self { hash: value.hash, from: value.from, to: value.to, index: value.index }
|
||||
}
|
||||
}
|
||||
8
substreams/ethereum-pancakeswap-v3/src/pb/mod.rs
Normal file
8
substreams/ethereum-pancakeswap-v3/src/pb/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
// @generated
|
||||
pub mod pancakeswap {
|
||||
// @@protoc_insertion_point(attribute:pancakeswap.v3)
|
||||
pub mod v3 {
|
||||
include!("pancakeswap.v3.rs");
|
||||
// @@protoc_insertion_point(pancakeswap.v3)
|
||||
}
|
||||
}
|
||||
302
substreams/ethereum-pancakeswap-v3/src/pb/pancakeswap.v3.rs
Normal file
302
substreams/ethereum-pancakeswap-v3/src/pb/pancakeswap.v3.rs
Normal file
@@ -0,0 +1,302 @@
|
||||
// @generated
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Pool {
|
||||
#[prost(bytes="vec", tag="1")]
|
||||
pub address: ::prost::alloc::vec::Vec<u8>,
|
||||
#[prost(bytes="vec", tag="2")]
|
||||
pub token0: ::prost::alloc::vec::Vec<u8>,
|
||||
#[prost(bytes="vec", tag="3")]
|
||||
pub token1: ::prost::alloc::vec::Vec<u8>,
|
||||
#[prost(uint64, tag="4")]
|
||||
pub fee: u64,
|
||||
#[prost(bytes="vec", tag="5")]
|
||||
pub created_tx_hash: ::prost::alloc::vec::Vec<u8>,
|
||||
}
|
||||
/// A struct describing a transaction.
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Transaction {
|
||||
/// The transaction hash.
|
||||
#[prost(bytes="vec", tag="1")]
|
||||
pub hash: ::prost::alloc::vec::Vec<u8>,
|
||||
/// The sender of the transaction.
|
||||
#[prost(bytes="vec", tag="2")]
|
||||
pub from: ::prost::alloc::vec::Vec<u8>,
|
||||
/// The receiver of the transaction.
|
||||
#[prost(bytes="vec", tag="3")]
|
||||
pub to: ::prost::alloc::vec::Vec<u8>,
|
||||
/// The transactions index within the block.
|
||||
#[prost(uint64, tag="4")]
|
||||
pub index: u64,
|
||||
}
|
||||
/// A change to a pool's tick.
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct TickDelta {
|
||||
/// The address of the pool.
|
||||
#[prost(bytes="vec", tag="1")]
|
||||
pub pool_address: ::prost::alloc::vec::Vec<u8>,
|
||||
/// The index of the tick.
|
||||
#[prost(int32, tag="2")]
|
||||
pub tick_index: i32,
|
||||
/// The liquidity net delta of this tick. Bigint encoded as signed little endian bytes.
|
||||
#[prost(bytes="vec", tag="3")]
|
||||
pub liquidity_net_delta: ::prost::alloc::vec::Vec<u8>,
|
||||
/// Used to determine the order of the balance changes. Necessary for the balance store.
|
||||
#[prost(uint64, tag="4")]
|
||||
pub ordinal: u64,
|
||||
#[prost(message, optional, tag="5")]
|
||||
pub transaction: ::core::option::Option<Transaction>,
|
||||
}
|
||||
/// A group of TickDelta
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct TickDeltas {
|
||||
#[prost(message, repeated, tag="1")]
|
||||
pub deltas: ::prost::alloc::vec::Vec<TickDelta>,
|
||||
}
|
||||
/// A change to a pool's liquidity.
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct LiquidityChange {
|
||||
/// The address of the pool.
|
||||
#[prost(bytes="vec", tag="1")]
|
||||
pub pool_address: ::prost::alloc::vec::Vec<u8>,
|
||||
/// The liquidity changed amount. Bigint encoded as signed little endian bytes.
|
||||
#[prost(bytes="vec", tag="2")]
|
||||
pub value: ::prost::alloc::vec::Vec<u8>,
|
||||
/// The type of update, can be absolute or delta.
|
||||
#[prost(enumeration="LiquidityChangeType", tag="3")]
|
||||
pub change_type: i32,
|
||||
/// Used to determine the order of the balance changes. Necessary for the balance store.
|
||||
#[prost(uint64, tag="4")]
|
||||
pub ordinal: u64,
|
||||
#[prost(message, optional, tag="5")]
|
||||
pub transaction: ::core::option::Option<Transaction>,
|
||||
}
|
||||
/// A group of LiquidityChange
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct LiquidityChanges {
|
||||
#[prost(message, repeated, tag="1")]
|
||||
pub changes: ::prost::alloc::vec::Vec<LiquidityChange>,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Events {
|
||||
#[prost(message, repeated, tag="3")]
|
||||
pub pool_events: ::prost::alloc::vec::Vec<events::PoolEvent>,
|
||||
}
|
||||
/// Nested message and enum types in `Events`.
|
||||
pub mod events {
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct PoolEvent {
|
||||
#[prost(uint64, tag="100")]
|
||||
pub log_ordinal: u64,
|
||||
#[prost(string, tag="102")]
|
||||
pub pool_address: ::prost::alloc::string::String,
|
||||
#[prost(string, tag="103")]
|
||||
pub token0: ::prost::alloc::string::String,
|
||||
#[prost(string, tag="104")]
|
||||
pub token1: ::prost::alloc::string::String,
|
||||
#[prost(uint64, tag="105")]
|
||||
pub fee: u64,
|
||||
#[prost(message, optional, tag="106")]
|
||||
pub transaction: ::core::option::Option<super::Transaction>,
|
||||
#[prost(oneof="pool_event::Type", tags="1, 2, 3, 4, 5, 6, 7, 8")]
|
||||
pub r#type: ::core::option::Option<pool_event::Type>,
|
||||
}
|
||||
/// Nested message and enum types in `PoolEvent`.
|
||||
pub mod pool_event {
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Initialize {
|
||||
/// Unsigned
|
||||
#[prost(string, tag="1")]
|
||||
pub sqrt_price: ::prost::alloc::string::String,
|
||||
#[prost(int32, tag="2")]
|
||||
pub tick: i32,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Mint {
|
||||
#[prost(string, tag="1")]
|
||||
pub sender: ::prost::alloc::string::String,
|
||||
#[prost(string, tag="2")]
|
||||
pub owner: ::prost::alloc::string::String,
|
||||
/// Signed
|
||||
#[prost(int32, tag="3")]
|
||||
pub tick_lower: i32,
|
||||
/// Signed
|
||||
#[prost(int32, tag="4")]
|
||||
pub tick_upper: i32,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="5")]
|
||||
pub amount: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="6")]
|
||||
pub amount_0: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="7")]
|
||||
pub amount_1: ::prost::alloc::string::String,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Collect {
|
||||
#[prost(string, tag="1")]
|
||||
pub owner: ::prost::alloc::string::String,
|
||||
#[prost(string, tag="2")]
|
||||
pub recipient: ::prost::alloc::string::String,
|
||||
#[prost(int32, tag="3")]
|
||||
pub tick_lower: i32,
|
||||
#[prost(int32, tag="4")]
|
||||
pub tick_upper: i32,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="5")]
|
||||
pub amount_0: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="6")]
|
||||
pub amount_1: ::prost::alloc::string::String,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Burn {
|
||||
#[prost(string, tag="1")]
|
||||
pub owner: ::prost::alloc::string::String,
|
||||
#[prost(int32, tag="2")]
|
||||
pub tick_lower: i32,
|
||||
#[prost(int32, tag="3")]
|
||||
pub tick_upper: i32,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="4")]
|
||||
pub amount: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="5")]
|
||||
pub amount_0: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="6")]
|
||||
pub amount_1: ::prost::alloc::string::String,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Swap {
|
||||
#[prost(string, tag="1")]
|
||||
pub sender: ::prost::alloc::string::String,
|
||||
#[prost(string, tag="2")]
|
||||
pub recipient: ::prost::alloc::string::String,
|
||||
/// Signed
|
||||
#[prost(string, tag="3")]
|
||||
pub amount_0: ::prost::alloc::string::String,
|
||||
/// Signed
|
||||
#[prost(string, tag="4")]
|
||||
pub amount_1: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="6")]
|
||||
pub sqrt_price: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="7")]
|
||||
pub liquidity: ::prost::alloc::string::String,
|
||||
#[prost(int32, tag="8")]
|
||||
pub tick: i32,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Flash {
|
||||
#[prost(string, tag="1")]
|
||||
pub sender: ::prost::alloc::string::String,
|
||||
#[prost(string, tag="2")]
|
||||
pub recipient: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="3")]
|
||||
pub amount_0: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="4")]
|
||||
pub amount_1: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="5")]
|
||||
pub paid_0: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="6")]
|
||||
pub paid_1: ::prost::alloc::string::String,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct SetFeeProtocol {
|
||||
/// Unsigned
|
||||
#[prost(uint64, tag="1")]
|
||||
pub fee_protocol_0_old: u64,
|
||||
/// Unsigned
|
||||
#[prost(uint64, tag="2")]
|
||||
pub fee_protocol_1_old: u64,
|
||||
/// Unsigned
|
||||
#[prost(uint64, tag="3")]
|
||||
pub fee_protocol_0_new: u64,
|
||||
/// Unsigned
|
||||
#[prost(uint64, tag="4")]
|
||||
pub fee_protocol_1_new: u64,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct CollectProtocol {
|
||||
#[prost(string, tag="1")]
|
||||
pub sender: ::prost::alloc::string::String,
|
||||
#[prost(string, tag="2")]
|
||||
pub recipient: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="3")]
|
||||
pub amount_0: ::prost::alloc::string::String,
|
||||
/// Unsigned
|
||||
#[prost(string, tag="4")]
|
||||
pub amount_1: ::prost::alloc::string::String,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Oneof)]
|
||||
pub enum Type {
|
||||
#[prost(message, tag="1")]
|
||||
Initialize(Initialize),
|
||||
#[prost(message, tag="2")]
|
||||
Mint(Mint),
|
||||
#[prost(message, tag="3")]
|
||||
Collect(Collect),
|
||||
#[prost(message, tag="4")]
|
||||
Burn(Burn),
|
||||
#[prost(message, tag="5")]
|
||||
Swap(Swap),
|
||||
#[prost(message, tag="6")]
|
||||
Flash(Flash),
|
||||
#[prost(message, tag="7")]
|
||||
SetFeeProtocol(SetFeeProtocol),
|
||||
#[prost(message, tag="8")]
|
||||
CollectProtocol(CollectProtocol),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||
#[repr(i32)]
|
||||
pub enum LiquidityChangeType {
|
||||
Delta = 0,
|
||||
Absolute = 1,
|
||||
}
|
||||
impl LiquidityChangeType {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
LiquidityChangeType::Delta => "DELTA",
|
||||
LiquidityChangeType::Absolute => "ABSOLUTE",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"DELTA" => Some(Self::Delta),
|
||||
"ABSOLUTE" => Some(Self::Absolute),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
// @@protoc_insertion_point(module)
|
||||
@@ -18,5 +18,6 @@ ignore = [
|
||||
"ethereum-uniswap-v2/src/abi",
|
||||
"ethereum-uniswap-v3/src/abi",
|
||||
"ethereum-uniswap-v3-logs-only/src/abi",
|
||||
"ethereum-pancakeswap-v3/src/abi",
|
||||
"ethereum-uniswap-v4/src/abi",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user