first pass at substreams
This commit is contained in:
18
substreams/Cargo.lock
generated
18
substreams/Cargo.lock
generated
@@ -322,6 +322,24 @@ dependencies = [
|
||||
"tycho-substreams 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-liquidityparty"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ethabi 18.0.0",
|
||||
"hex",
|
||||
"itertools 0.10.5",
|
||||
"num-bigint",
|
||||
"prost 0.11.9",
|
||||
"serde",
|
||||
"serde-sibor",
|
||||
"serde_qs",
|
||||
"substreams",
|
||||
"substreams-ethereum",
|
||||
"tycho-substreams 0.2.1 (git+https://github.com/propeller-heads/tycho-protocol-sdk.git?rev=52d5021)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-maverick-v2"
|
||||
version = "0.1.1"
|
||||
|
||||
@@ -17,6 +17,7 @@ members = [
|
||||
"ethereum-ekubo-v2",
|
||||
"ethereum-maverick-v2",
|
||||
"ethereum-balancer-v3",
|
||||
"ethereum-liquidityparty",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
|
||||
26
substreams/ethereum-liquidityparty/Cargo.toml
Normal file
26
substreams/ethereum-liquidityparty/Cargo.toml
Normal file
@@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "ethereum-liquidityparty"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "ethereum_liquidityparty"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
substreams = "0.5.22"
|
||||
substreams-ethereum = "0.9.9"
|
||||
prost = "0.11"
|
||||
tycho-substreams = { git = "https://github.com/propeller-heads/tycho-protocol-sdk.git", rev = "52d5021" }
|
||||
anyhow = "1.0.95"
|
||||
ethabi = "18.0.0"
|
||||
num-bigint = "0.4.6"
|
||||
hex = "0.4.3"
|
||||
itertools = "0.10.5"
|
||||
serde = "1.0.217"
|
||||
serde-sibor = "0.1.0"
|
||||
serde_qs = "0.13.0"
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = "1"
|
||||
substreams-ethereum = "0.9.9"
|
||||
2
substreams/ethereum-liquidityparty/Makefile
Normal file
2
substreams/ethereum-liquidityparty/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
build:
|
||||
cargo build --target wasm32-unknown-unknown --release
|
||||
543
substreams/ethereum-liquidityparty/abi/party_planner.abi.json
Normal file
543
substreams/ethereum-liquidityparty/abi/party_planner.abi.json
Normal file
@@ -0,0 +1,543 @@
|
||||
[
|
||||
{
|
||||
"type": "constructor",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "owner_",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "wrapper_",
|
||||
"type": "address",
|
||||
"internalType": "contract NativeWrapper"
|
||||
},
|
||||
{
|
||||
"name": "swapImpl_",
|
||||
"type": "address",
|
||||
"internalType": "contract PartyPoolSwapImpl"
|
||||
},
|
||||
{
|
||||
"name": "mintImpl_",
|
||||
"type": "address",
|
||||
"internalType": "contract PartyPoolMintImpl"
|
||||
},
|
||||
{
|
||||
"name": "deployer_",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPoolDeployer"
|
||||
},
|
||||
{
|
||||
"name": "balancedPairDeployer_",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPoolDeployer"
|
||||
},
|
||||
{
|
||||
"name": "protocolFeePpm_",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "protocolFeeAddress_",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "getAllPools",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "offset",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "pools",
|
||||
"type": "address[]",
|
||||
"internalType": "contract IPartyPool[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "getAllTokens",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "offset",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "tokens",
|
||||
"type": "address[]",
|
||||
"internalType": "address[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "getPoolSupported",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool",
|
||||
"internalType": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "getPoolsByToken",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "token",
|
||||
"type": "address",
|
||||
"internalType": "contract IERC20"
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "pools",
|
||||
"type": "address[]",
|
||||
"internalType": "contract IPartyPool[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "mintImpl",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address",
|
||||
"internalType": "contract PartyPoolMintImpl"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "newPool",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "name_",
|
||||
"type": "string",
|
||||
"internalType": "string"
|
||||
},
|
||||
{
|
||||
"name": "symbol_",
|
||||
"type": "string",
|
||||
"internalType": "string"
|
||||
},
|
||||
{
|
||||
"name": "tokens_",
|
||||
"type": "address[]",
|
||||
"internalType": "contract IERC20[]"
|
||||
},
|
||||
{
|
||||
"name": "bases_",
|
||||
"type": "uint256[]",
|
||||
"internalType": "uint256[]"
|
||||
},
|
||||
{
|
||||
"name": "kappa_",
|
||||
"type": "int128",
|
||||
"internalType": "int128"
|
||||
},
|
||||
{
|
||||
"name": "swapFeePpm_",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "flashFeePpm_",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "stable_",
|
||||
"type": "bool",
|
||||
"internalType": "bool"
|
||||
},
|
||||
{
|
||||
"name": "payer",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "receiver",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "initialDeposits",
|
||||
"type": "uint256[]",
|
||||
"internalType": "uint256[]"
|
||||
},
|
||||
{
|
||||
"name": "initialLpAmount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "deadline",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "lpAmount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "newPool",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "name_",
|
||||
"type": "string",
|
||||
"internalType": "string"
|
||||
},
|
||||
{
|
||||
"name": "symbol_",
|
||||
"type": "string",
|
||||
"internalType": "string"
|
||||
},
|
||||
{
|
||||
"name": "tokens_",
|
||||
"type": "address[]",
|
||||
"internalType": "contract IERC20[]"
|
||||
},
|
||||
{
|
||||
"name": "bases_",
|
||||
"type": "uint256[]",
|
||||
"internalType": "uint256[]"
|
||||
},
|
||||
{
|
||||
"name": "tradeFrac_",
|
||||
"type": "int128",
|
||||
"internalType": "int128"
|
||||
},
|
||||
{
|
||||
"name": "targetSlippage_",
|
||||
"type": "int128",
|
||||
"internalType": "int128"
|
||||
},
|
||||
{
|
||||
"name": "swapFeePpm_",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "flashFeePpm_",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "stable_",
|
||||
"type": "bool",
|
||||
"internalType": "bool"
|
||||
},
|
||||
{
|
||||
"name": "payer",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "receiver",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "initialDeposits",
|
||||
"type": "uint256[]",
|
||||
"internalType": "uint256[]"
|
||||
},
|
||||
{
|
||||
"name": "initialLpAmount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "deadline",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "lpAmount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "owner",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "poolCount",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "poolsByTokenCount",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "token",
|
||||
"type": "address",
|
||||
"internalType": "contract IERC20"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "protocolFeeAddress",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "protocolFeePpm",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "renounceOwnership",
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "swapImpl",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address",
|
||||
"internalType": "contract PartyPoolSwapImpl"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "tokenCount",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "transferOwnership",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newOwner",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "wrapper",
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address",
|
||||
"internalType": "contract NativeWrapper"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "OwnershipTransferred",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "previousOwner",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "newOwner",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "event",
|
||||
"name": "PartyStarted",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"indexed": true,
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"indexed": false,
|
||||
"internalType": "string"
|
||||
},
|
||||
{
|
||||
"name": "symbol",
|
||||
"type": "string",
|
||||
"indexed": false,
|
||||
"internalType": "string"
|
||||
},
|
||||
{
|
||||
"name": "tokens",
|
||||
"type": "address[]",
|
||||
"indexed": false,
|
||||
"internalType": "contract IERC20[]"
|
||||
}
|
||||
],
|
||||
"anonymous": false
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "OwnableInvalidOwner",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "owner",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "OwnableUnauthorizedAccount",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "account",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"name": "SafeERC20FailedOperation",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "token",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
1374
substreams/ethereum-liquidityparty/abi/party_pool.abi.json
Normal file
1374
substreams/ethereum-liquidityparty/abi/party_pool.abi.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,308 @@
|
||||
[
|
||||
{
|
||||
"type": "constructor",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "swapImpl_",
|
||||
"type": "address",
|
||||
"internalType": "contract PartyPoolSwapImpl"
|
||||
},
|
||||
{
|
||||
"name": "mintImpl",
|
||||
"type": "address",
|
||||
"internalType": "contract PartyPoolMintImpl"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "burnAmounts",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "lpTokenAmount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "withdrawAmounts",
|
||||
"type": "uint256[]",
|
||||
"internalType": "uint256[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "burnSwapAmounts",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "lpAmount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "inputTokenIndex",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "amountOut",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "flashFee",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
},
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "fee",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "flashRepaymentAmounts",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "loanAmounts",
|
||||
"type": "uint256[]",
|
||||
"internalType": "uint256[]"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "repaymentAmounts",
|
||||
"type": "uint256[]",
|
||||
"internalType": "uint256[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "maxFlashLoan",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"type": "address",
|
||||
"internalType": "address"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "mintAmounts",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "lpTokenAmount",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "depositAmounts",
|
||||
"type": "uint256[]",
|
||||
"internalType": "uint256[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "poolPrice",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "quoteTokenIndex",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "int128",
|
||||
"internalType": "int128"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "price",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "baseTokenIndex",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "quoteTokenIndex",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "int128",
|
||||
"internalType": "int128"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "swapMintAmounts",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "inputTokenIndex",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "maxAmountIn",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "amountInUsed",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "fee",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "lpMinted",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "swapToLimitAmounts",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pool",
|
||||
"type": "address",
|
||||
"internalType": "contract IPartyPool"
|
||||
},
|
||||
{
|
||||
"name": "inputTokenIndex",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "outputTokenIndex",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "limitPrice",
|
||||
"type": "int128",
|
||||
"internalType": "int128"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "amountIn",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "amountOut",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "fee",
|
||||
"type": "uint256",
|
||||
"internalType": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view"
|
||||
}
|
||||
]
|
||||
12
substreams/ethereum-liquidityparty/buf.gen.yaml
Normal file
12
substreams/ethereum-liquidityparty/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
|
||||
49
substreams/ethereum-liquidityparty/build.rs
Normal file
49
substreams/ethereum-liquidityparty/build.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use anyhow::Result;
|
||||
use std::{fs, io::Write};
|
||||
use substreams_ethereum::Abigen;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let abi_folder = "abi";
|
||||
let output_folder = "src/abi";
|
||||
|
||||
let abis = fs::read_dir(abi_folder)?;
|
||||
|
||||
let mut files = abis.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Sort the files by their name
|
||||
files.sort_by_key(|a| a.file_name());
|
||||
|
||||
let mut mod_rs_content = String::new();
|
||||
mod_rs_content.push_str("#![allow(clippy::all)]\n");
|
||||
|
||||
for file in files {
|
||||
let file_name = file.file_name();
|
||||
let file_name = file_name.to_string_lossy();
|
||||
|
||||
if !file_name.ends_with(".json") {
|
||||
continue;
|
||||
}
|
||||
|
||||
let contract_name = file_name.split('.').next().unwrap();
|
||||
|
||||
let input_path = format!("{abi_folder}/{file_name}");
|
||||
let output_path = format!("{output_folder}/{contract_name}.rs");
|
||||
|
||||
mod_rs_content.push_str(&format!("pub mod {contract_name};\n"));
|
||||
|
||||
if std::path::Path::new(&output_path).exists() {
|
||||
continue;
|
||||
}
|
||||
|
||||
Abigen::new(contract_name, &input_path)?
|
||||
.generate()?
|
||||
.write_to_file(&output_path)?;
|
||||
}
|
||||
|
||||
let mod_rs_path = format!("{output_folder}/mod.rs");
|
||||
let mut mod_rs_file = fs::File::create(mod_rs_path)?;
|
||||
|
||||
mod_rs_file.write_all(mod_rs_content.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
# Name of the substreams config file in your substreams module. Usually "./substreams.yaml"
|
||||
substreams_yaml_path: ./substreams.yaml
|
||||
# Name of the adapter contract, usually: ProtocolSwapAdapter"
|
||||
adapter_contract: "SwapAdapter"
|
||||
# Constructor signature of the Adapter contract"
|
||||
adapter_build_signature: "constructor(address)"
|
||||
# A comma separated list of args to be passed to the contructor of the Adapter contract"
|
||||
adapter_build_args: "0x0000000000000000000000000000000000000000"
|
||||
# Whether the testing script should skip checking balances of the protocol components.
|
||||
# If set to `true` please always add a reason why it's skipped.
|
||||
skip_balance_check: false
|
||||
# Accounts that will be automatically initialized at test start
|
||||
# IMPORTANT: These are TEST FIXTURES ONLY. Your actual code must still properly
|
||||
# initialize these accounts. This configuration only eliminates the need to include
|
||||
# historical blocks containing the initialization events in your test data.
|
||||
#
|
||||
# Example use case:
|
||||
# - Your substream would normally initialize account XYZ at block 10000
|
||||
# - Your test only includes blocks 20000-21000 for efficiency
|
||||
# - You list XYZ here so the test environment will automatically initialize the account XYZ with the state it had at block 20000
|
||||
# - Your actual substream code MUST STILL contain the initialization and state tracking logic for this contract
|
||||
#
|
||||
# Without this, you would need to include block 10000 in your test data or your
|
||||
# test would fail because the account appears uninitialized to your code.
|
||||
initialized_accounts:
|
||||
- "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84" # Needed for ....
|
||||
# A list of protocol types names created by your Substreams module.
|
||||
protocol_type_names:
|
||||
- "type_name_1"
|
||||
- "type_name_2"
|
||||
# A list of tests.
|
||||
# The name of the protocol system
|
||||
protocol_system: "protocol_name"
|
||||
tests:
|
||||
# Name of the test
|
||||
- name: test_pool_creation
|
||||
# Indexed block range
|
||||
start_block: 123
|
||||
stop_block: 456
|
||||
# Same as global `initialized_accounts` but only scoped to this test.
|
||||
initialized_accounts:
|
||||
- "0x0c0e5f2fF0ff18a3be9b835635039256dC4B4963" # Needed for ....
|
||||
# A list of expected component indexed in the block range. Each component must match perfectly the `ProtocolComponent` indexed by your subtreams module.
|
||||
expected_components:
|
||||
- id: "0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7"
|
||||
tokens:
|
||||
- "0xdac17f958d2ee523a2206206994597c13d831ec7"
|
||||
- "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
||||
- "0x6b175474e89094c44da98b954eedeac495271d0f"
|
||||
static_attributes: { }
|
||||
creation_tx: "0x20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6"
|
||||
# Whether the script should skip trying to simulate a swap on this component.
|
||||
# If set to `true` please always add a reason why it's skipped.
|
||||
skip_simulation: false
|
||||
# Whether the script should skip trying to simulate execution of a swap on this component.
|
||||
# If set to `true` please always add a reason why it's skipped.
|
||||
skip_execution: false
|
||||
- name: test_something_else
|
||||
start_block: 123
|
||||
stop_block: 456
|
||||
expected_components:
|
||||
- id: "0xdc24316b9ae028f1497c275eb9192a3ea0f67022"
|
||||
tokens:
|
||||
- "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
|
||||
- "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84"
|
||||
static_attributes: { }
|
||||
creation_tx: "0xfac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa"
|
||||
skip_simulation: true # If true, always add a reason
|
||||
skip_execution: true # If true, always add a reason
|
||||
4
substreams/ethereum-liquidityparty/rust-toolchain.toml
Normal file
4
substreams/ethereum-liquidityparty/rust-toolchain.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "1.83.0"
|
||||
components = [ "rustfmt" ]
|
||||
targets = [ "wasm32-unknown-unknown" ]
|
||||
@@ -0,0 +1,73 @@
|
||||
specVersion: v0.1.0
|
||||
package:
|
||||
name: "ethereum_liquidityparty"
|
||||
version: v0.1.0
|
||||
|
||||
protobuf:
|
||||
files:
|
||||
- tycho/evm/v1/vm.proto
|
||||
- tycho/evm/v1/common.proto
|
||||
- tycho/evm/v1/utils.proto
|
||||
importPaths:
|
||||
- ../../proto
|
||||
|
||||
binaries:
|
||||
default:
|
||||
type: wasm/rust-v1
|
||||
file: ../target/wasm32-unknown-unknown/release/ethereum_liquidityparty.wasm
|
||||
|
||||
network: sepolia
|
||||
networks:
|
||||
sepolia:
|
||||
initialBlock:
|
||||
map_protocol_components: 9460804
|
||||
params:
|
||||
map_protocol_components: planner=0x0ad06C08ab5049e6Fd4d7f5AF457115A1475326b&viewer=0x750d63a39a4ccfCfB69D2f5aFDa065909C717cAB&mint_impl=0x25bb10BA84944F8aAEf1fD247C3B7Fe7271C23F9&swap_impl=0x69b4F102e0747f61F8529b3bbFf2FC4b27438d0F&deployer=0x0939F93BAa3c96226853F9F39A95beF48eA8fF04&bp_deployer=0xfda454fF7876aad9408517Ed2F0d11AA229Ad0a4
|
||||
|
||||
modules:
|
||||
- name: map_protocol_components
|
||||
kind: map
|
||||
initialBlock: 1
|
||||
inputs:
|
||||
- params: string
|
||||
- source: sf.ethereum.type.v2.Block
|
||||
output:
|
||||
type: proto:tycho.evm.v1.BlockTransactionProtocolComponents
|
||||
|
||||
- name: store_protocol_components
|
||||
kind: store
|
||||
initialBlock: 1
|
||||
updatePolicy: set
|
||||
valueType: string
|
||||
inputs:
|
||||
- map: map_protocol_components
|
||||
|
||||
- name: map_relative_component_balance
|
||||
kind: map
|
||||
initialBlock: 1
|
||||
inputs:
|
||||
- source: sf.ethereum.type.v2.Block
|
||||
- store: store_protocol_components
|
||||
output:
|
||||
type: proto:tycho.evm.v1.BlockBalanceDeltas
|
||||
|
||||
- name: store_balances
|
||||
kind: store
|
||||
initialBlock: 1
|
||||
updatePolicy: add
|
||||
valueType: bigint
|
||||
inputs:
|
||||
- map: map_relative_component_balance
|
||||
|
||||
- name: map_protocol_changes
|
||||
kind: map
|
||||
initialBlock: 1
|
||||
inputs:
|
||||
- source: sf.ethereum.type.v2.Block
|
||||
- map: map_protocol_components
|
||||
- map: map_relative_component_balance
|
||||
- store: store_protocol_components
|
||||
- store: store_balances
|
||||
mode: deltas
|
||||
output:
|
||||
type: proto:tycho.evm.v1.BlockChanges
|
||||
4
substreams/ethereum-liquidityparty/src/abi/.gitignore
vendored
Normal file
4
substreams/ethereum-liquidityparty/src/abi/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
mod.rs
|
||||
party_planner.rs
|
||||
party_pool.rs
|
||||
party_pool_viewer.rs
|
||||
4
substreams/ethereum-liquidityparty/src/lib.rs
Normal file
4
substreams/ethereum-liquidityparty/src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
mod abi;
|
||||
mod modules;
|
||||
mod pool_factories;
|
||||
mod params;
|
||||
314
substreams/ethereum-liquidityparty/src/modules.rs
Normal file
314
substreams/ethereum-liquidityparty/src/modules.rs
Normal file
@@ -0,0 +1,314 @@
|
||||
//! Template for Protocols with contract factories
|
||||
//!
|
||||
//! This template provides foundational maps and store substream modules for indexing a
|
||||
//! protocol where each component (e.g., pool) is deployed to a separate contract. Each
|
||||
//! contract is expected to escrow its ERC-20 token balances.
|
||||
//!
|
||||
//! If your protocol supports native ETH, you may need to adjust the balance tracking
|
||||
//! logic in `map_relative_component_balance` to account for native token handling.
|
||||
//!
|
||||
//! ## Assumptions
|
||||
//! - Assumes each pool has a single newly deployed contract linked to it
|
||||
//! - Assumes pool identifier equals the deployed contract address
|
||||
//! - Assumes any price or liquidity updated correlates with a pools contract storage update.
|
||||
//!
|
||||
//! ## Alternative Module
|
||||
//! If your protocol uses a vault-like contract to manage balances, or if pools are
|
||||
//! registered within a singleton contract, refer to the `ethereum-template-singleton`
|
||||
//! substream for an appropriate alternative.
|
||||
//!
|
||||
//! ## Warning
|
||||
//! This template provides a general framework for indexing a protocol. However, it is
|
||||
//! likely that you will need to adapt the steps to suit your specific use case. Use the
|
||||
//! provided code with care and ensure you fully understand each step before proceeding
|
||||
//! with your implementation.
|
||||
//!
|
||||
//! ## Example Use Case
|
||||
//! For an Uniswap-like protocol where each liquidity pool is deployed as a separate
|
||||
//! contract, you can use this template to:
|
||||
//! - Track relative component balances (e.g., ERC-20 token balances in each pool).
|
||||
//! - Index individual pool contracts as they are created by the factory contract.
|
||||
//!
|
||||
//! Adjustments to the template may include:
|
||||
//! - Handling native ETH balances alongside token balances.
|
||||
//! - Customizing indexing logic for specific factory contract behavior.
|
||||
use crate::params::Params;
|
||||
use crate::{abi, pool_factories};
|
||||
use anyhow::Result;
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashMap;
|
||||
use substreams::{pb::substreams::StoreDeltas, prelude::*};
|
||||
use substreams_ethereum::{pb::eth, Event};
|
||||
use tycho_substreams::{
|
||||
balances::aggregate_balances_changes, contract::extract_contract_changes_builder,
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
/// Find and create all relevant protocol components
|
||||
///
|
||||
/// This method maps over blocks and instantiates ProtocolComponents with a unique ids
|
||||
/// as well as all necessary metadata for routing and encoding.
|
||||
#[substreams::handlers::map]
|
||||
fn map_protocol_components(
|
||||
param_string: String,
|
||||
block: eth::v2::Block
|
||||
) -> Result<BlockTransactionProtocolComponents> {
|
||||
let params = Params::parse(¶m_string)?;
|
||||
Ok(BlockTransactionProtocolComponents {
|
||||
tx_components: block
|
||||
.transactions()
|
||||
.filter_map(|tx| {
|
||||
let components = tx
|
||||
.logs_with_calls()
|
||||
.filter_map(|(log, call)| {
|
||||
pool_factories::maybe_create_component(¶ms, call.call, log, tx)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !components.is_empty() {
|
||||
Some(TransactionProtocolComponents { tx: Some(tx.into()), components })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Stores all protocol components in a store.
|
||||
///
|
||||
/// Stores information about components in a key value store. This is only necessary if
|
||||
/// you need to access the whole set of components within your indexing logic.
|
||||
///
|
||||
/// Popular use cases are:
|
||||
/// - Checking if a contract belongs to a component. In this case suggest to use an address as the
|
||||
/// store key so lookup operations are O(1).
|
||||
/// - Tallying up relative balances changes to calcualte absolute erc20 token balances per
|
||||
/// component.
|
||||
///
|
||||
/// Usually you can skip this step if:
|
||||
/// - You are interested in a static set of components only
|
||||
/// - Your protocol emits balance change events with absolute values
|
||||
#[substreams::handlers::store]
|
||||
fn store_protocol_components(
|
||||
map_protocol_components: BlockTransactionProtocolComponents,
|
||||
store: StoreSetRaw,
|
||||
) {
|
||||
map_protocol_components
|
||||
.tx_components
|
||||
.into_iter()
|
||||
.for_each(|tx_pc| {
|
||||
tx_pc
|
||||
.components
|
||||
.into_iter()
|
||||
.for_each(|pc| {
|
||||
// Assumes that the component id is a hex encoded contract address
|
||||
let key = pc.id.clone();
|
||||
// we store the components tokens
|
||||
// TODO: proper error handling
|
||||
let val = serde_sibor::to_bytes(&pc.tokens).unwrap();
|
||||
store.set(0, key, &val);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/// Extracts balance changes per component
|
||||
///
|
||||
/// This template function uses ERC20 transfer events to extract balance changes. It
|
||||
/// assumes that each component is deployed at a dedicated contract address. If a
|
||||
/// transfer to the component is detected, its balance is increased and if a transfer
|
||||
/// from the component is detected its balance is decreased.
|
||||
///
|
||||
/// ## Note:
|
||||
/// Changes are necessary if your protocol uses native ETH, uses a vault contract or if
|
||||
/// your component burn or mint tokens without emitting transfer events.
|
||||
///
|
||||
/// You may want to ignore LP tokens if your protocol emits transfer events for these
|
||||
/// here.
|
||||
#[substreams::handlers::map]
|
||||
fn map_relative_component_balance(
|
||||
block: eth::v2::Block,
|
||||
store: StoreGetRaw,
|
||||
) -> Result<BlockBalanceDeltas, anyhow::Error> {
|
||||
let mut res = Vec::new();
|
||||
|
||||
for log in block.logs() {
|
||||
let component_id = log.address().to_vec();
|
||||
if let Some(token_enc) = store.get_last(hex::encode(&component_id)) {
|
||||
let tokens = serde_sibor::from_bytes::<Vec<Vec<u8>>>(&token_enc)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to deserialize tokens: {}", e))?;
|
||||
|
||||
if let Some(event) = abi::party_pool::events::Mint::match_and_decode(log) {
|
||||
for (i, amount) in event.amounts.iter().enumerate() {
|
||||
if !amount.is_zero() {
|
||||
res.push(BalanceDelta {
|
||||
ord: log.ordinal(),
|
||||
tx: Some(log.receipt.transaction.into()),
|
||||
token: tokens[i].clone(),
|
||||
delta: amount.to_signed_bytes_be(),
|
||||
component_id: component_id.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if let Some(event) = abi::party_pool::events::Burn::match_and_decode(log) {
|
||||
for (i, amount) in event.amounts.iter().enumerate() {
|
||||
if !amount.is_zero() {
|
||||
res.push(BalanceDelta {
|
||||
ord: log.ordinal(),
|
||||
tx: Some(log.receipt.transaction.into()),
|
||||
token: tokens[i].clone(),
|
||||
delta: amount.neg().to_signed_bytes_be(),
|
||||
component_id: component_id.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if let Some(event) = abi::party_pool::events::Swap::match_and_decode(log) {
|
||||
// increase by amount_in
|
||||
res.push(BalanceDelta {
|
||||
ord: log.ordinal(),
|
||||
tx: Some(log.receipt.transaction.into()),
|
||||
token: event.token_in.to_vec(),
|
||||
delta: (event.amount_in - event.protocol_fee).to_signed_bytes_be(),
|
||||
component_id: component_id.clone(),
|
||||
});
|
||||
// decrease by amount_out plus protocol fees
|
||||
res.push(BalanceDelta {
|
||||
ord: log.ordinal(),
|
||||
tx: Some(log.receipt.transaction.into()),
|
||||
token: event.token_out.to_vec(),
|
||||
delta: event.amount_out.neg().to_signed_bytes_be(),
|
||||
component_id: component_id.clone(),
|
||||
});
|
||||
} else if let Some(event) = abi::party_pool::events::SwapMint::match_and_decode(log) {
|
||||
// increase by amount_in less the protocol fee
|
||||
res.push(BalanceDelta {
|
||||
ord: log.ordinal(),
|
||||
tx: Some(log.receipt.transaction.into()),
|
||||
token: event.token_in.to_vec(),
|
||||
delta: (event.amount_in - event.protocol_fee).to_signed_bytes_be(),
|
||||
component_id: component_id.clone(),
|
||||
});
|
||||
} else if let Some(event) = abi::party_pool::events::BurnSwap::match_and_decode(log) {
|
||||
// decrease by amount_out plus the protocol fee
|
||||
res.push(BalanceDelta {
|
||||
ord: log.ordinal(),
|
||||
tx: Some(log.receipt.transaction.into()),
|
||||
token: event.token_out.to_vec(),
|
||||
delta: (event.amount_out + event.protocol_fee).neg().to_signed_bytes_be(),
|
||||
component_id: component_id.clone(),
|
||||
});
|
||||
} else if let Some(event) = abi::party_pool::events::Flash::match_and_decode(log) {
|
||||
// increase by LP fees
|
||||
res.push(BalanceDelta {
|
||||
ord: log.ordinal(),
|
||||
tx: Some(log.receipt.transaction.into()),
|
||||
token: event.token.to_vec(),
|
||||
delta: event.lp_fee.to_signed_bytes_be(),
|
||||
component_id: component_id.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(BlockBalanceDeltas { balance_deltas: res })
|
||||
}
|
||||
|
||||
/// Aggregates relative balances values into absolute values
|
||||
///
|
||||
/// Aggregate the relative balances in an additive store since tycho-indexer expects
|
||||
/// absolute balance inputs.
|
||||
///
|
||||
/// ## Note:
|
||||
/// This method should usually not require any changes.
|
||||
#[substreams::handlers::store]
|
||||
pub fn store_balances(deltas: BlockBalanceDeltas, store: StoreAddBigInt) {
|
||||
tycho_substreams::balances::store_balance_changes(deltas, store);
|
||||
}
|
||||
|
||||
/// Aggregates protocol components and balance changes by transaction.
|
||||
///
|
||||
/// This is the main method that will aggregate all changes as well as extract all
|
||||
/// relevant contract storage deltas.
|
||||
///
|
||||
/// ## Note:
|
||||
/// You may have to change this method if your components have any default dynamic
|
||||
/// attributes, or if you need any additional static contracts indexed.
|
||||
#[substreams::handlers::map]
|
||||
fn map_protocol_changes(
|
||||
block: eth::v2::Block,
|
||||
new_components: BlockTransactionProtocolComponents,
|
||||
components_store: StoreGetRaw,
|
||||
balance_store: StoreDeltas,
|
||||
deltas: BlockBalanceDeltas,
|
||||
) -> 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();
|
||||
|
||||
// Aggregate newly created components per tx
|
||||
new_components
|
||||
.tx_components
|
||||
.iter()
|
||||
.for_each(|tx_component| {
|
||||
// initialise builder if not yet present for this tx
|
||||
let tx = tx_component.tx.as_ref().unwrap();
|
||||
let builder = transaction_changes
|
||||
.entry(tx.index)
|
||||
.or_insert_with(|| TransactionChangesBuilder::new(tx));
|
||||
|
||||
// iterate over individual components created within this tx
|
||||
tx_component
|
||||
.components
|
||||
.iter()
|
||||
.for_each(|component| {
|
||||
builder.add_protocol_component(component);
|
||||
// TODO: In case you require to add any dynamic attributes to the
|
||||
// component you can do so here:
|
||||
/*
|
||||
builder.add_entity_change(&EntityChanges {
|
||||
component_id: component.id.clone(),
|
||||
attributes: default_attributes.clone(),
|
||||
});
|
||||
*/
|
||||
});
|
||||
});
|
||||
|
||||
// Aggregate absolute balances per transaction.
|
||||
aggregate_balances_changes(balance_store, 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))
|
||||
});
|
||||
});
|
||||
|
||||
// Extract and insert any storage changes that happened for any of the components.
|
||||
extract_contract_changes_builder(
|
||||
&block,
|
||||
|addr| {
|
||||
// we assume that the store holds contract addresses as keys and if it
|
||||
// contains a value, that contract is of relevance.
|
||||
components_store
|
||||
.get_last(hex::encode(addr))
|
||||
.is_some()
|
||||
},
|
||||
&mut transaction_changes,
|
||||
);
|
||||
|
||||
// Process all `transaction_changes` for final output in the `BlockChanges`,
|
||||
// sorted by transaction index (the key).
|
||||
Ok(BlockChanges {
|
||||
block: Some((&block).into()),
|
||||
changes: transaction_changes
|
||||
.drain()
|
||||
.sorted_unstable_by_key(|(index, _)| *index)
|
||||
.filter_map(|(_, builder)| builder.build())
|
||||
.collect::<Vec<_>>(),
|
||||
})
|
||||
}
|
||||
54
substreams/ethereum-liquidityparty/src/params.rs
Normal file
54
substreams/ethereum-liquidityparty/src/params.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use anyhow::anyhow;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct StringParams {
|
||||
planner: String,
|
||||
viewer: String,
|
||||
mint_impl: String,
|
||||
swap_impl: String,
|
||||
deployer: String,
|
||||
bp_deployer: String,
|
||||
}
|
||||
|
||||
pub(crate) struct Params {
|
||||
pub planner: Vec<u8>,
|
||||
pub viewer: Vec<u8>,
|
||||
pub mint_impl: Vec<u8>,
|
||||
pub swap_impl: Vec<u8>,
|
||||
pub deployer: Vec<u8>,
|
||||
pub bp_deployer: Vec<u8>,
|
||||
}
|
||||
|
||||
impl StringParams {
|
||||
pub fn parse(input: &str) -> anyhow::Result<Self> {
|
||||
serde_qs::from_str(input).map_err(|e| anyhow!("Failed to parse query params: {}", e))
|
||||
}
|
||||
}
|
||||
|
||||
impl Params {
|
||||
pub fn parse(input: &str) -> anyhow::Result<Self> {
|
||||
let params = StringParams::parse(input)?;
|
||||
|
||||
fn decode_addr(s: &str) -> anyhow::Result<Vec<u8>> {
|
||||
let s = s.strip_prefix("0x").unwrap_or(s);
|
||||
if s.len() != 40 {
|
||||
return Err(anyhow!("address must be 20 bytes (40 hex chars), got len={}", s.len()));
|
||||
}
|
||||
let bytes = hex::decode(s)?;
|
||||
if bytes.len() != 20 {
|
||||
return Err(anyhow!("decoded address is not 20 bytes"));
|
||||
}
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
planner: decode_addr(¶ms.planner)?,
|
||||
viewer: decode_addr(¶ms.viewer)?,
|
||||
mint_impl: decode_addr(¶ms.mint_impl)?,
|
||||
swap_impl: decode_addr(¶ms.swap_impl)?,
|
||||
deployer: decode_addr(¶ms.deployer)?,
|
||||
bp_deployer: decode_addr(¶ms.bp_deployer)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
40
substreams/ethereum-liquidityparty/src/pool_factories.rs
Normal file
40
substreams/ethereum-liquidityparty/src/pool_factories.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use substreams_ethereum::pb::eth::v2::{Call, Log, TransactionTrace};
|
||||
use substreams_ethereum::Event;
|
||||
use tycho_substreams::models::{
|
||||
ChangeType, FinancialType, ImplementationType, ProtocolComponent, ProtocolType,
|
||||
};
|
||||
use crate::abi;
|
||||
use crate::params::Params;
|
||||
|
||||
/// Potentially constructs a new ProtocolComponent given a call
|
||||
///
|
||||
/// This method is given each individual call within a transaction, the corresponding
|
||||
/// logs emitted during that call as well as the full transaction trace.
|
||||
///
|
||||
/// If this call creates a component in your protocol please construct and return it
|
||||
/// here. Otherwise, simply return None.
|
||||
pub fn maybe_create_component(
|
||||
params: &Params,
|
||||
call: &Call,
|
||||
_log: &Log,
|
||||
_tx: &TransactionTrace,
|
||||
) -> Option<ProtocolComponent> {
|
||||
if call.address.as_slice() == params.planner {
|
||||
if let Some(event) = abi::party_planner::events::PartyStarted::match_and_decode(_log) {
|
||||
return Some(ProtocolComponent {
|
||||
id: hex::encode(&event.pool),
|
||||
tokens: event.tokens,
|
||||
contracts: vec![event.pool.clone(), params.mint_impl.clone(), params.swap_impl.clone()],
|
||||
static_att: vec![],
|
||||
change: ChangeType::Creation.into(),
|
||||
protocol_type: Some(ProtocolType {
|
||||
name: "liquidity_party".to_string(),
|
||||
financial_type: FinancialType::Swap.into(),
|
||||
attribute_schema: vec![],
|
||||
implementation_type: ImplementationType::Vm.into(),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
Reference in New Issue
Block a user