refactor(curve): stateless contracts as state attribute instead of static.
This commit is contained in:
@@ -36,63 +36,69 @@ impl PartialEq for TransactionWrapper {
|
||||
}
|
||||
|
||||
#[substreams::handlers::map]
|
||||
pub fn map_components(
|
||||
params: String,
|
||||
block: eth::v2::Block,
|
||||
) -> Result<BlockTransactionProtocolComponents> {
|
||||
// Gather contract changes by indexing `PoolCreated` events and analysing the `Create` call
|
||||
// We store these as a hashmap by tx hash since we need to agg by tx hash later
|
||||
Ok(BlockTransactionProtocolComponents {
|
||||
tx_components: block
|
||||
.transactions()
|
||||
.filter_map(|tx| {
|
||||
let mut components = tx
|
||||
.logs_with_calls()
|
||||
.filter(|(_, call)| !call.call.state_reverted)
|
||||
.filter_map(|(log, call)| {
|
||||
pool_factories::address_map(
|
||||
call.call
|
||||
.address
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.ok()?, // this shouldn't fail
|
||||
log,
|
||||
call.call,
|
||||
tx,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// Map all created components and their related entity changes.
|
||||
pub fn map_components(params: String, block: eth::v2::Block) -> Result<BlockChanges> {
|
||||
let changes = block
|
||||
.transactions()
|
||||
.filter_map(|tx| {
|
||||
let mut entity_changes = vec![];
|
||||
let mut components = vec![];
|
||||
|
||||
if let Some(component) = emit_specific_pools(¶ms, tx).expect(
|
||||
"An unexpected error occured when parsing params for emitting specific pools",
|
||||
for (log, call) in tx
|
||||
.logs_with_calls()
|
||||
.filter(|(_, call)| !call.call.state_reverted)
|
||||
{
|
||||
if let Some((component, mut state)) = pool_factories::address_map(
|
||||
call.call
|
||||
.address
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.ok()?, // this shouldn't fail
|
||||
log,
|
||||
call.call,
|
||||
tx,
|
||||
) {
|
||||
components.push(component)
|
||||
entity_changes.append(&mut state);
|
||||
components.push(component);
|
||||
}
|
||||
}
|
||||
|
||||
if !components.is_empty() {
|
||||
Some(TransactionProtocolComponents {
|
||||
tx: Some(Transaction {
|
||||
hash: tx.hash.clone(),
|
||||
from: tx.from.clone(),
|
||||
to: tx.to.clone(),
|
||||
index: Into::<u64>::into(tx.index),
|
||||
}),
|
||||
components,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
})
|
||||
if let Some((component, mut state)) = emit_specific_pools(¶ms, tx).expect(
|
||||
"An unexpected error occured when parsing params for emitting specific pools",
|
||||
) {
|
||||
entity_changes.append(&mut state);
|
||||
components.push(component);
|
||||
}
|
||||
|
||||
if components.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(TransactionChanges {
|
||||
tx: Some(Transaction {
|
||||
hash: tx.hash.clone(),
|
||||
from: tx.from.clone(),
|
||||
to: tx.to.clone(),
|
||||
index: tx.index.into(),
|
||||
}),
|
||||
contract_changes: vec![],
|
||||
entity_changes,
|
||||
component_changes: components,
|
||||
balance_changes: vec![],
|
||||
})
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(BlockChanges { block: None, changes })
|
||||
}
|
||||
|
||||
/// Simply stores the `ProtocolComponent`s with the pool id as the key and tokens as the value
|
||||
/// Get result `map_components` and stores the created `ProtocolComponent`s with the pool id as the
|
||||
/// key and tokens as the value
|
||||
#[substreams::handlers::store]
|
||||
pub fn store_component_tokens(map: BlockTransactionProtocolComponents, store: StoreSetString) {
|
||||
map.tx_components
|
||||
pub fn store_component_tokens(map: BlockChanges, store: StoreSetString) {
|
||||
map.changes
|
||||
.iter()
|
||||
.flat_map(|tx_components| &tx_components.components)
|
||||
.flat_map(|tx_changes| &tx_changes.component_changes)
|
||||
.for_each(|component| {
|
||||
store.set(
|
||||
0,
|
||||
@@ -110,10 +116,10 @@ pub fn store_component_tokens(map: BlockTransactionProtocolComponents, store: St
|
||||
/// pool.
|
||||
/// This is later used to index them with `extract_contract_changes`
|
||||
#[substreams::handlers::store]
|
||||
pub fn store_non_component_accounts(map: BlockTransactionProtocolComponents, store: StoreSetInt64) {
|
||||
map.tx_components
|
||||
pub fn store_non_component_accounts(map: BlockChanges, store: StoreSetInt64) {
|
||||
map.changes
|
||||
.iter()
|
||||
.flat_map(|tx_components| &tx_components.components)
|
||||
.flat_map(|tx_changes| &tx_changes.component_changes)
|
||||
.for_each(|component| {
|
||||
// Crypto pool factory creates LP token separated from the pool, we need to index it so
|
||||
// we add it to the store if the new protocol component comes from this factory
|
||||
@@ -194,7 +200,7 @@ pub fn store_balances(deltas: BlockBalanceDeltas, store: StoreAddBigInt) {
|
||||
#[substreams::handlers::map]
|
||||
pub fn map_protocol_changes(
|
||||
block: eth::v2::Block,
|
||||
grouped_components: BlockTransactionProtocolComponents,
|
||||
grouped_components: BlockChanges,
|
||||
deltas: BlockBalanceDeltas,
|
||||
components_store: StoreGetString,
|
||||
non_component_accounts_store: StoreGetInt64,
|
||||
@@ -204,14 +210,14 @@ pub fn map_protocol_changes(
|
||||
// sort them at the very end.
|
||||
let mut transaction_changes: HashMap<_, TransactionChanges> = HashMap::new();
|
||||
|
||||
// `ProtocolComponents` are gathered from `map_pools_created` which just need a bit of work to
|
||||
// convert into `TransactionChanges`
|
||||
// `ProtocolComponents` are gathered with some entity changes from `map_pools_created` which
|
||||
// just need a bit of work to convert into `TransactionChanges`
|
||||
grouped_components
|
||||
.tx_components
|
||||
.changes
|
||||
.into_iter()
|
||||
.for_each(|tx_component| {
|
||||
let tx = tx_component.tx.as_ref().unwrap();
|
||||
transaction_changes
|
||||
.for_each(|tx_changes| {
|
||||
let tx = tx_changes.tx.as_ref().unwrap();
|
||||
let transaction_entry = transaction_changes
|
||||
.entry(tx.index)
|
||||
.or_insert_with(|| TransactionChanges {
|
||||
tx: Some(tx.clone()),
|
||||
@@ -219,18 +225,23 @@ pub fn map_protocol_changes(
|
||||
component_changes: vec![],
|
||||
balance_changes: vec![],
|
||||
entity_changes: vec![],
|
||||
})
|
||||
});
|
||||
|
||||
let formated_components: Vec<_> = tx_changes //TODO: format directly at creation
|
||||
.component_changes
|
||||
.extend_from_slice(
|
||||
&(tx_component
|
||||
.components
|
||||
.into_iter()
|
||||
.map(|mut component| {
|
||||
component.id = format!("0x{}", component.id);
|
||||
component
|
||||
})
|
||||
.collect::<Vec<_>>()),
|
||||
);
|
||||
.into_iter()
|
||||
.map(|mut component| {
|
||||
component.id = format!("0x{}", component.id);
|
||||
component
|
||||
})
|
||||
.collect();
|
||||
|
||||
transaction_entry
|
||||
.component_changes
|
||||
.extend(formated_components);
|
||||
transaction_entry
|
||||
.entity_changes
|
||||
.extend(tx_changes.entity_changes);
|
||||
});
|
||||
|
||||
// Balance changes are gathered by the `StoreDelta` based on `TokenExchange`, etc. creating
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,8 @@ struct PoolQueryParams {
|
||||
contracts: Option<Vec<String>>,
|
||||
tx_hash: String,
|
||||
tokens: Vec<String>,
|
||||
static_attribute_keys: Option<Vec<String>>,
|
||||
static_attribute_vals: Option<Vec<String>>,
|
||||
attribute_keys: Option<Vec<String>>,
|
||||
attribute_vals: Option<Vec<String>>,
|
||||
}
|
||||
@@ -32,7 +34,7 @@ struct PoolQueryParams {
|
||||
pub fn emit_specific_pools(
|
||||
params: &str,
|
||||
tx: &TransactionTrace,
|
||||
) -> Result<Option<ProtocolComponent>> {
|
||||
) -> Result<Option<(ProtocolComponent, Vec<EntityChanges>)>> {
|
||||
let pools = parse_params(params)?;
|
||||
create_component(tx, pools)
|
||||
}
|
||||
@@ -40,61 +42,81 @@ pub fn emit_specific_pools(
|
||||
fn create_component(
|
||||
tx: &TransactionTrace,
|
||||
pools: HashMap<String, PoolQueryParams>,
|
||||
) -> Result<Option<ProtocolComponent>> {
|
||||
) -> Result<Option<(ProtocolComponent, Vec<EntityChanges>)>> {
|
||||
let encoded_hash = hex::encode(tx.hash.clone());
|
||||
if let Some(pool) = pools.get(&encoded_hash) {
|
||||
Ok(Some(ProtocolComponent {
|
||||
id: pool.address.clone(),
|
||||
tx: Some(Transaction {
|
||||
to: tx.to.clone(),
|
||||
from: tx.from.clone(),
|
||||
hash: tx.hash.clone(),
|
||||
index: tx.index.into(),
|
||||
}),
|
||||
tokens: pool
|
||||
.tokens
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|token| Result::Ok(hex::decode(token)?))
|
||||
.collect::<Result<Vec<_>>>()
|
||||
.with_context(|| "Token addresses were not formatted properly")?,
|
||||
static_att: zip(
|
||||
pool.attribute_keys
|
||||
Ok(Some((
|
||||
ProtocolComponent {
|
||||
id: pool.address.clone(),
|
||||
tx: Some(Transaction {
|
||||
to: tx.to.clone(),
|
||||
from: tx.from.clone(),
|
||||
hash: tx.hash.clone(),
|
||||
index: tx.index.into(),
|
||||
}),
|
||||
tokens: pool
|
||||
.tokens
|
||||
.clone()
|
||||
.unwrap_or(vec![]),
|
||||
pool.attribute_vals
|
||||
.clone()
|
||||
.unwrap_or(vec![]),
|
||||
)
|
||||
.clone()
|
||||
.map(|(key, value)| Attribute {
|
||||
name: key,
|
||||
value: value.into(),
|
||||
change: ChangeType::Creation.into(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
contracts: pool
|
||||
.contracts
|
||||
.into_iter()
|
||||
.map(|token| Result::Ok(hex::decode(token)?))
|
||||
.collect::<Result<Vec<_>>>()
|
||||
.with_context(|| "Token addresses were not formatted properly")?,
|
||||
static_att: zip(
|
||||
pool.static_attribute_keys
|
||||
.clone()
|
||||
.unwrap_or(vec![]),
|
||||
pool.static_attribute_vals
|
||||
.clone()
|
||||
.unwrap_or(vec![]),
|
||||
)
|
||||
.clone()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|contract| {
|
||||
hex::decode(contract)
|
||||
.with_context(|| "Pool contracts was not formatted properly")
|
||||
.map(|(key, value)| Attribute {
|
||||
name: key,
|
||||
value: value.into(),
|
||||
change: ChangeType::Creation.into(),
|
||||
})
|
||||
.chain(std::iter::once(
|
||||
hex::decode(&pool.address)
|
||||
.with_context(|| "Pool address was not formatted properly"),
|
||||
))
|
||||
.collect::<Result<Vec<Vec<u8>>>>()?,
|
||||
change: ChangeType::Creation.into(),
|
||||
protocol_type: Some(ProtocolType {
|
||||
name: "curve_pool".into(),
|
||||
financial_type: FinancialType::Swap.into(),
|
||||
attribute_schema: Vec::new(),
|
||||
implementation_type: ImplementationType::Vm.into(),
|
||||
}),
|
||||
}))
|
||||
.collect::<Vec<_>>(),
|
||||
contracts: pool
|
||||
.contracts
|
||||
.clone()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|contract| {
|
||||
hex::decode(contract)
|
||||
.with_context(|| "Pool contracts was not formatted properly")
|
||||
})
|
||||
.chain(std::iter::once(
|
||||
hex::decode(&pool.address)
|
||||
.with_context(|| "Pool address was not formatted properly"),
|
||||
))
|
||||
.collect::<Result<Vec<Vec<u8>>>>()?,
|
||||
change: ChangeType::Creation.into(),
|
||||
protocol_type: Some(ProtocolType {
|
||||
name: "curve_pool".into(),
|
||||
financial_type: FinancialType::Swap.into(),
|
||||
attribute_schema: Vec::new(),
|
||||
implementation_type: ImplementationType::Vm.into(),
|
||||
}),
|
||||
},
|
||||
vec![EntityChanges {
|
||||
component_id: format!("0x{}", pool.address.clone()),
|
||||
attributes: zip(
|
||||
pool.attribute_keys
|
||||
.clone()
|
||||
.unwrap_or(vec![]),
|
||||
pool.attribute_vals
|
||||
.clone()
|
||||
.unwrap_or(vec![]),
|
||||
)
|
||||
.clone()
|
||||
.map(|(key, value)| Attribute {
|
||||
name: key,
|
||||
value: value.into(),
|
||||
change: ChangeType::Creation.into(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
}],
|
||||
)))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
@@ -134,6 +156,8 @@ mod tests {
|
||||
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48".to_string(),
|
||||
"0xdac17f958d2ee523a2206206994597c13d831ec7".to_string(),
|
||||
],
|
||||
static_attribute_keys: None,
|
||||
static_attribute_vals: None,
|
||||
attribute_keys: Some(vec!["key1".to_string()]),
|
||||
attribute_vals: Some(vec!["val1".to_string()]),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user