use core::marker::PhantomData; use scale::{Encode, Decode}; use serai_abi::Call; use crate::{ Vec, primitives::{PublicKey, SeraiAddress}, timestamp, coins, dex, genesis_liquidity, validator_sets::{self, MembershipProof}, in_instructions, signals, babe, grandpa, RuntimeCall, }; impl From for RuntimeCall { fn from(call: Call) -> RuntimeCall { match call { Call::Timestamp(serai_abi::timestamp::Call::set { now }) => { RuntimeCall::Timestamp(timestamp::Call::set { now }) } Call::Coins(coins) => match coins { serai_abi::coins::Call::transfer { to, balance } => { RuntimeCall::Coins(coins::Call::transfer { to: to.into(), balance }) } serai_abi::coins::Call::burn { balance } => { RuntimeCall::Coins(coins::Call::burn { balance }) } serai_abi::coins::Call::burn_with_instruction { instruction } => { RuntimeCall::Coins(coins::Call::burn_with_instruction { instruction }) } }, Call::LiquidityTokens(lt) => match lt { serai_abi::liquidity_tokens::Call::transfer { to, balance } => { RuntimeCall::LiquidityTokens(coins::Call::transfer { to: to.into(), balance }) } serai_abi::liquidity_tokens::Call::burn { balance } => { RuntimeCall::LiquidityTokens(coins::Call::burn { balance }) } }, Call::Dex(dex) => match dex { serai_abi::dex::Call::add_liquidity { coin, coin_desired, sri_desired, coin_min, sri_min, mint_to, } => RuntimeCall::Dex(dex::Call::add_liquidity { coin, coin_desired, sri_desired, coin_min, sri_min, mint_to: mint_to.into(), }), serai_abi::dex::Call::remove_liquidity { coin, lp_token_burn, coin_min_receive, sri_min_receive, withdraw_to, } => RuntimeCall::Dex(dex::Call::remove_liquidity { coin, lp_token_burn, coin_min_receive, sri_min_receive, withdraw_to: withdraw_to.into(), }), serai_abi::dex::Call::swap_exact_tokens_for_tokens { path, amount_in, amount_out_min, send_to, } => RuntimeCall::Dex(dex::Call::swap_exact_tokens_for_tokens { path, amount_in, amount_out_min, send_to: send_to.into(), }), serai_abi::dex::Call::swap_tokens_for_exact_tokens { path, amount_out, amount_in_max, send_to, } => RuntimeCall::Dex(dex::Call::swap_tokens_for_exact_tokens { path, amount_out, amount_in_max, send_to: send_to.into(), }), }, Call::ValidatorSets(vs) => match vs { serai_abi::validator_sets::Call::set_keys { network, key_pair, signature_participants, signature, } => RuntimeCall::ValidatorSets(validator_sets::Call::set_keys { network, key_pair, signature_participants, signature, }), serai_abi::validator_sets::Call::set_embedded_elliptic_curve_key { embedded_elliptic_curve, key, } => RuntimeCall::ValidatorSets(validator_sets::Call::set_embedded_elliptic_curve_key { embedded_elliptic_curve, key, }), serai_abi::validator_sets::Call::report_slashes { network, slashes, signature } => { RuntimeCall::ValidatorSets(validator_sets::Call::report_slashes { network, slashes: <_>::try_from( slashes .into_iter() .map(|(addr, slash)| (PublicKey::from(addr), slash)) .collect::>(), ) .unwrap(), signature, }) } serai_abi::validator_sets::Call::allocate { network, amount } => { RuntimeCall::ValidatorSets(validator_sets::Call::allocate { network, amount }) } serai_abi::validator_sets::Call::deallocate { network, amount } => { RuntimeCall::ValidatorSets(validator_sets::Call::deallocate { network, amount }) } serai_abi::validator_sets::Call::claim_deallocation { network, session } => { RuntimeCall::ValidatorSets(validator_sets::Call::claim_deallocation { network, session }) } }, Call::GenesisLiquidity(gl) => match gl { serai_abi::genesis_liquidity::Call::remove_coin_liquidity { balance } => { RuntimeCall::GenesisLiquidity(genesis_liquidity::Call::remove_coin_liquidity { balance }) } serai_abi::genesis_liquidity::Call::oraclize_values { values, signature } => { RuntimeCall::GenesisLiquidity(genesis_liquidity::Call::oraclize_values { values, signature, }) } }, Call::InInstructions(ii) => match ii { serai_abi::in_instructions::Call::execute_batch { batch } => { RuntimeCall::InInstructions(in_instructions::Call::execute_batch { batch }) } }, Call::Signals(signals) => match signals { serai_abi::signals::Call::register_retirement_signal { in_favor_of } => { RuntimeCall::Signals(signals::Call::register_retirement_signal { in_favor_of }) } serai_abi::signals::Call::revoke_retirement_signal { retirement_signal_id } => { RuntimeCall::Signals(signals::Call::revoke_retirement_signal { retirement_signal_id }) } serai_abi::signals::Call::favor { signal_id, for_network } => { RuntimeCall::Signals(signals::Call::favor { signal_id, for_network }) } serai_abi::signals::Call::revoke_favor { signal_id, for_network } => { RuntimeCall::Signals(signals::Call::revoke_favor { signal_id, for_network }) } serai_abi::signals::Call::stand_against { signal_id, for_network } => { RuntimeCall::Signals(signals::Call::stand_against { signal_id, for_network }) } }, Call::Babe(babe) => match babe { serai_abi::babe::Call::report_equivocation(report) => { RuntimeCall::Babe(babe::Call::report_equivocation { // TODO: Find a better way to go from Proof<[u8; 32]> to Proof equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) .unwrap(), key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), }) } serai_abi::babe::Call::report_equivocation_unsigned(report) => { RuntimeCall::Babe(babe::Call::report_equivocation_unsigned { // TODO: Find a better way to go from Proof<[u8; 32]> to Proof equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) .unwrap(), key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), }) } }, Call::Grandpa(grandpa) => match grandpa { serai_abi::grandpa::Call::report_equivocation(report) => { RuntimeCall::Grandpa(grandpa::Call::report_equivocation { // TODO: Find a better way to go from Proof<[u8; 32]> to Proof equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) .unwrap(), key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), }) } serai_abi::grandpa::Call::report_equivocation_unsigned(report) => { RuntimeCall::Grandpa(grandpa::Call::report_equivocation_unsigned { // TODO: Find a better way to go from Proof<[u8; 32]> to Proof equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) .unwrap(), key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), }) } }, } } } impl TryInto for RuntimeCall { type Error = (); fn try_into(self) -> Result { Ok(match self { RuntimeCall::Timestamp(timestamp::Call::set { now }) => { Call::Timestamp(serai_abi::timestamp::Call::set { now }) } RuntimeCall::Coins(call) => Call::Coins(match call { coins::Call::transfer { to, balance } => { serai_abi::coins::Call::transfer { to: to.into(), balance } } coins::Call::burn { balance } => serai_abi::coins::Call::burn { balance }, coins::Call::burn_with_instruction { instruction } => { serai_abi::coins::Call::burn_with_instruction { instruction } } _ => Err(())?, }), RuntimeCall::LiquidityTokens(call) => Call::LiquidityTokens(match call { coins::Call::transfer { to, balance } => { serai_abi::liquidity_tokens::Call::transfer { to: to.into(), balance } } coins::Call::burn { balance } => serai_abi::liquidity_tokens::Call::burn { balance }, _ => Err(())?, }), RuntimeCall::Dex(call) => Call::Dex(match call { dex::Call::add_liquidity { coin, coin_desired, sri_desired, coin_min, sri_min, mint_to, } => serai_abi::dex::Call::add_liquidity { coin, coin_desired, sri_desired, coin_min, sri_min, mint_to: mint_to.into(), }, dex::Call::remove_liquidity { coin, lp_token_burn, coin_min_receive, sri_min_receive, withdraw_to, } => serai_abi::dex::Call::remove_liquidity { coin, lp_token_burn, coin_min_receive, sri_min_receive, withdraw_to: withdraw_to.into(), }, dex::Call::swap_exact_tokens_for_tokens { path, amount_in, amount_out_min, send_to } => { serai_abi::dex::Call::swap_exact_tokens_for_tokens { path, amount_in, amount_out_min, send_to: send_to.into(), } } dex::Call::swap_tokens_for_exact_tokens { path, amount_out, amount_in_max, send_to } => { serai_abi::dex::Call::swap_tokens_for_exact_tokens { path, amount_out, amount_in_max, send_to: send_to.into(), } } _ => Err(())?, }), RuntimeCall::GenesisLiquidity(call) => Call::GenesisLiquidity(match call { genesis_liquidity::Call::remove_coin_liquidity { balance } => { serai_abi::genesis_liquidity::Call::remove_coin_liquidity { balance } } genesis_liquidity::Call::oraclize_values { values, signature } => { serai_abi::genesis_liquidity::Call::oraclize_values { values, signature } } _ => Err(())?, }), RuntimeCall::ValidatorSets(call) => Call::ValidatorSets(match call { validator_sets::Call::set_keys { network, key_pair, signature_participants, signature } => { serai_abi::validator_sets::Call::set_keys { network, key_pair, signature_participants, signature, } } validator_sets::Call::set_embedded_elliptic_curve_key { embedded_elliptic_curve, key } => { serai_abi::validator_sets::Call::set_embedded_elliptic_curve_key { embedded_elliptic_curve, key, } } validator_sets::Call::report_slashes { network, slashes, signature } => { serai_abi::validator_sets::Call::report_slashes { network, slashes: <_>::try_from( slashes .into_iter() .map(|(addr, slash)| (SeraiAddress::from(addr), slash)) .collect::>(), ) .unwrap(), signature, } } validator_sets::Call::allocate { network, amount } => { serai_abi::validator_sets::Call::allocate { network, amount } } validator_sets::Call::deallocate { network, amount } => { serai_abi::validator_sets::Call::deallocate { network, amount } } validator_sets::Call::claim_deallocation { network, session } => { serai_abi::validator_sets::Call::claim_deallocation { network, session } } _ => Err(())?, }), RuntimeCall::InInstructions(call) => Call::InInstructions(match call { in_instructions::Call::execute_batch { batch } => { serai_abi::in_instructions::Call::execute_batch { batch } } _ => Err(())?, }), RuntimeCall::Signals(call) => Call::Signals(match call { signals::Call::register_retirement_signal { in_favor_of } => { serai_abi::signals::Call::register_retirement_signal { in_favor_of } } signals::Call::revoke_retirement_signal { retirement_signal_id } => { serai_abi::signals::Call::revoke_retirement_signal { retirement_signal_id } } signals::Call::favor { signal_id, for_network } => { serai_abi::signals::Call::favor { signal_id, for_network } } signals::Call::revoke_favor { signal_id, for_network } => { serai_abi::signals::Call::revoke_favor { signal_id, for_network } } signals::Call::stand_against { signal_id, for_network } => { serai_abi::signals::Call::stand_against { signal_id, for_network } } _ => Err(())?, }), RuntimeCall::Babe(call) => Call::Babe(match call { babe::Call::report_equivocation { equivocation_proof, key_owner_proof } => { serai_abi::babe::Call::report_equivocation(serai_abi::babe::ReportEquivocation { // TODO: Find a better way to go from Proof to Proof<[u8; 32]> equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), key_owner_proof: key_owner_proof.0.into(), }) } babe::Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } => { serai_abi::babe::Call::report_equivocation_unsigned(serai_abi::babe::ReportEquivocation { // TODO: Find a better way to go from Proof to Proof<[u8; 32]> equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), key_owner_proof: key_owner_proof.0.into(), }) } _ => Err(())?, }), RuntimeCall::Grandpa(call) => Call::Grandpa(match call { grandpa::Call::report_equivocation { equivocation_proof, key_owner_proof } => { serai_abi::grandpa::Call::report_equivocation(serai_abi::grandpa::ReportEquivocation { // TODO: Find a better way to go from Proof to Proof<[u8; 32]> equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), key_owner_proof: key_owner_proof.0.into(), }) } grandpa::Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } => { serai_abi::grandpa::Call::report_equivocation_unsigned( serai_abi::grandpa::ReportEquivocation { // TODO: Find a better way to go from Proof to Proof<[u8; 32]> equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), key_owner_proof: key_owner_proof.0.into(), }, ) } _ => Err(())?, }), _ => Err(())?, }) } }