diff --git a/substrate/client/src/serai/coins.rs b/substrate/client/src/serai/coins.rs index b73f0e7d..3c91a285 100644 --- a/substrate/client/src/serai/coins.rs +++ b/substrate/client/src/serai/coins.rs @@ -5,9 +5,7 @@ use serai_runtime::{ pub use coins::primitives; use primitives::OutInstructionWithBalance; -use subxt::tx::Payload; - -use crate::{TemporalSerai, SeraiError, Composite, scale_value, scale_composite}; +use crate::{TemporalSerai, SeraiError, scale_value}; const PALLET: &str = "Coins"; @@ -56,23 +54,22 @@ impl<'a> SeraiCoins<'a> { )) } - pub fn transfer(to: SeraiAddress, balance: Balance) -> Payload> { - Payload::new( - PALLET, - "transfer", - scale_composite(serai_runtime::coins::Call::::transfer { to: to.into(), balance }), - ) + pub fn transfer(to: SeraiAddress, balance: Balance) -> serai_runtime::RuntimeCall { + serai_runtime::RuntimeCall::Coins(serai_runtime::coins::Call::::transfer { + to: to.into(), + balance, + }) } - pub fn burn(balance: Balance) -> Payload> { - Payload::new(PALLET, "burn", scale_composite(coins::Call::::burn { balance })) + pub fn burn(balance: Balance) -> serai_runtime::RuntimeCall { + serai_runtime::RuntimeCall::Coins(serai_runtime::coins::Call::::burn { balance }) } - pub fn burn_with_instruction(instruction: OutInstructionWithBalance) -> Payload> { - Payload::new( - PALLET, - "burn_with_instruction", - scale_composite(coins::Call::::burn_with_instruction { instruction }), + pub fn burn_with_instruction( + instruction: OutInstructionWithBalance, + ) -> serai_runtime::RuntimeCall { + serai_runtime::RuntimeCall::Coins( + serai_runtime::coins::Call::::burn_with_instruction { instruction }, ) } } diff --git a/substrate/client/src/serai/dex.rs b/substrate/client/src/serai/dex.rs index 1b1f15f8..685e2f49 100644 --- a/substrate/client/src/serai/dex.rs +++ b/substrate/client/src/serai/dex.rs @@ -4,11 +4,7 @@ use serai_runtime::{ dex, Dex, Runtime, }; -use subxt::tx::Payload; - -use crate::{SeraiError, Composite, TemporalSerai, scale_composite}; - -const PALLET: &str = "Dex"; +use crate::{SeraiError, TemporalSerai}; pub type DexEvent = dex::Event; @@ -26,19 +22,15 @@ impl<'a> SeraiDex<'a> { min_coin_amount: Amount, min_sri_amount: Amount, address: SeraiAddress, - ) -> Payload> { - Payload::new( - PALLET, - "add_liquidity", - scale_composite(dex::Call::::add_liquidity { - coin, - coin_desired: coin_amount.0, - sri_desired: sri_amount.0, - coin_min: min_coin_amount.0, - sri_min: min_sri_amount.0, - mint_to: address.into(), - }), - ) + ) -> serai_runtime::RuntimeCall { + serai_runtime::RuntimeCall::Dex(dex::Call::::add_liquidity { + coin, + coin_desired: coin_amount.0, + sri_desired: sri_amount.0, + coin_min: min_coin_amount.0, + sri_min: min_sri_amount.0, + mint_to: address.into(), + }) } pub fn swap( @@ -47,7 +39,7 @@ impl<'a> SeraiDex<'a> { amount_in: Amount, amount_out_min: Amount, address: SeraiAddress, - ) -> Payload> { + ) -> serai_runtime::RuntimeCall { let path = if to_coin.is_native() { BoundedVec::try_from(vec![from_coin, Coin::Serai]).unwrap() } else if from_coin.is_native() { @@ -56,15 +48,11 @@ impl<'a> SeraiDex<'a> { BoundedVec::try_from(vec![from_coin, Coin::Serai, to_coin]).unwrap() }; - Payload::new( - PALLET, - "swap_exact_tokens_for_tokens", - scale_composite(dex::Call::::swap_exact_tokens_for_tokens { - path, - amount_in: amount_in.0, - amount_out_min: amount_out_min.0, - send_to: address.into(), - }), - ) + serai_runtime::RuntimeCall::Dex(dex::Call::::swap_exact_tokens_for_tokens { + path, + amount_in: amount_in.0, + amount_out_min: amount_out_min.0, + send_to: address.into(), + }) } } diff --git a/substrate/client/src/serai/in_instructions.rs b/substrate/client/src/serai/in_instructions.rs index ab737fcb..7b8b3a75 100644 --- a/substrate/client/src/serai/in_instructions.rs +++ b/substrate/client/src/serai/in_instructions.rs @@ -2,8 +2,6 @@ use serai_runtime::{in_instructions, InInstructions, Runtime}; pub use in_instructions::primitives; use primitives::SignedBatch; -use subxt::utils::Encoded; - use crate::{ primitives::{BlockHash, NetworkId}, SeraiError, Serai, TemporalSerai, scale_value, @@ -41,7 +39,7 @@ impl<'a> SeraiInInstructions<'a> { .await } - pub fn execute_batch(batch: SignedBatch) -> Encoded { + pub fn execute_batch(batch: SignedBatch) -> Vec { Serai::unsigned::(&in_instructions::Call::::execute_batch { batch }) } } diff --git a/substrate/client/src/serai/mod.rs b/substrate/client/src/serai/mod.rs index d14caba4..35a67f01 100644 --- a/substrate/client/src/serai/mod.rs +++ b/substrate/client/src/serai/mod.rs @@ -4,7 +4,7 @@ use futures::stream::{Stream, StreamExt}; use scale::{Encode, Decode, Compact}; mod scale_value; -pub(crate) use scale_value::{Value, Composite, scale_value, scale_composite}; +pub(crate) use scale_value::{Value, scale_value}; pub use sp_core::{ Pair as PairTrait, @@ -14,13 +14,12 @@ pub use sp_core::{ pub use subxt; use subxt::{ error::Error as SubxtError, - utils::Encoded, config::{ Header as HeaderTrait, substrate::{BlakeTwo256, SubstrateHeader}, - extrinsic_params::{BaseExtrinsicParams, BaseExtrinsicParamsBuilder}, + extrinsic_params::BaseExtrinsicParams, }, - tx::{Signer, Payload, TxClient}, + tx::Signer, rpc::types::{ChainBlock, ChainBlockExtrinsic}, Config as SubxtConfig, OnlineClient, }; @@ -149,7 +148,7 @@ impl Serai { Ok(Serai(OnlineClient::::from_url(url).await.map_err(SeraiError::RpcError)?)) } - fn unsigned(call: &C) -> Encoded { + fn unsigned(call: &C) -> Vec { // TODO: Should Serai purge the old transaction code AND set this to 0/1? const TRANSACTION_VERSION: u8 = 4; @@ -162,30 +161,54 @@ impl Serai { bytes.extend(call.encode()); // Prefix the length - let mut complete_bytes = scale::Compact(u32::try_from(bytes.len()).unwrap()).encode(); + let mut complete_bytes = Compact(u32::try_from(bytes.len()).unwrap()).encode(); complete_bytes.extend(bytes); - Encoded(complete_bytes) + complete_bytes } pub fn sign>( &self, signer: &S, - payload: &Payload>, + call: &serai_runtime::RuntimeCall, nonce: u32, - params: BaseExtrinsicParamsBuilder, - ) -> Result { - TxClient::new(self.0.offline()) - .create_signed_with_nonce(payload, signer, nonce, params) - .map(|tx| Encoded(tx.into_encoded())) - // TODO: Don't have this potentially return an error (requires modifying the Payload type) - .map_err(|_| SeraiError::InvalidRuntime) + tip: Tip, + ) -> Vec { + const SPEC_VERSION: u32 = 100; + const IMPL_VERSION: u32 = 1; + const TRANSACTION_VERSION: u8 = 4; + + let era = subxt::config::substrate::Era::Immortal; + let extra = (era, Compact(nonce), tip); + let genesis = self.0.genesis_hash(); + let mortality_checkpoint = genesis; + let mut signature_payload = + (call, extra, SPEC_VERSION, IMPL_VERSION, genesis, mortality_checkpoint).encode(); + if signature_payload.len() > 256 { + use subxt::config::Hasher; + signature_payload = BlakeTwo256::hash(&signature_payload).0.to_vec(); + } + let signature = signer.sign(&signature_payload); + + let signed = 1 << 7; + let extrinsic = + (signed + TRANSACTION_VERSION, signer.address(), signature, extra, call).encode(); + let mut res = Compact(u32::try_from(extrinsic.len()).unwrap()).encode(); + res.extend(&extrinsic); + res } - pub async fn publish(&self, tx: &Encoded) -> Result<(), SeraiError> { - // Drop the hash, which is the hash of the raw TX, as TXs are allowed to share hashes and this - // hash is practically useless/unsafe - // If we are to return something, it should be block included in and position within block - self.0.rpc().submit_extrinsic(tx).await.map(|_| ()).map_err(SeraiError::RpcError) + pub async fn publish(&self, tx: &[u8]) -> Result<(), SeraiError> { + self + .0 + .rpc() + .deref() + .request::<[u8; 32]>("author_submitExtrinsic", subxt::rpc::rpc_params![tx]) + .await + // Drop the hash, which is the hash of the raw extrinsic, as extrinsics are allowed to share + // hashes and this hash is accordingly useless/unsafe + // If we are to return something, it should be block included in and position within block + .map(|_| ()) + .map_err(SeraiError::RpcError) } pub async fn latest_block_hash(&self) -> Result<[u8; 32], SeraiError> { diff --git a/substrate/client/src/serai/scale_value.rs b/substrate/client/src/serai/scale_value.rs index 17b5c3ad..9e310a31 100644 --- a/substrate/client/src/serai/scale_value.rs +++ b/substrate/client/src/serai/scale_value.rs @@ -2,8 +2,8 @@ use ::scale::Encode; use scale_info::{MetaType, TypeInfo, Registry, PortableRegistry}; use subxt::ext::scale_value; -pub(crate) use scale_value::{Composite, Value}; -use scale_value::{ValueDef, scale}; +pub(crate) use scale_value::Value; +use scale_value::scale; pub(crate) fn scale_value(value: V) -> Value { let mut registry = Registry::new(); @@ -11,11 +11,3 @@ pub(crate) fn scale_value(value: V) -> Value { let registry = PortableRegistry::from(registry); scale::decode_as_type(&mut value.encode().as_ref(), id, ®istry).unwrap().remove_context() } - -pub(crate) fn scale_composite(value: V) -> Composite<()> { - match scale_value(value).value { - ValueDef::Composite(composite) => composite, - ValueDef::Variant(variant) => variant.values, - _ => panic!("not composite"), - } -} diff --git a/substrate/client/src/serai/validator_sets.rs b/substrate/client/src/serai/validator_sets.rs index bd586879..09dfe943 100644 --- a/substrate/client/src/serai/validator_sets.rs +++ b/substrate/client/src/serai/validator_sets.rs @@ -4,8 +4,6 @@ use serai_runtime::{primitives::Amount, validator_sets, ValidatorSets, Runtime}; pub use validator_sets::primitives; use primitives::{Session, ValidatorSet, KeyPair}; -use subxt::utils::Encoded; - use crate::{primitives::NetworkId, Serai, TemporalSerai, SeraiError, scale_value}; const PALLET: &str = "ValidatorSets"; @@ -82,7 +80,7 @@ impl<'a> SeraiValidatorSets<'a> { self.0.storage(PALLET, "Keys", Some(vec![scale_value(set)])).await } - pub fn set_keys(network: NetworkId, key_pair: KeyPair, signature: Signature) -> Encoded { + pub fn set_keys(network: NetworkId, key_pair: KeyPair, signature: Signature) -> Vec { Serai::unsigned::(&validator_sets::Call::::set_keys { network, key_pair, diff --git a/substrate/client/tests/burn.rs b/substrate/client/tests/burn.rs index 456dc131..704ca2b4 100644 --- a/substrate/client/tests/burn.rs +++ b/substrate/client/tests/burn.rs @@ -11,7 +11,6 @@ use serai_runtime::coins::primitives::OutInstructionWithBalance; use sp_core::Pair; use serai_client::{ - subxt::config::extrinsic_params::BaseExtrinsicParamsBuilder, primitives::{ Amount, NetworkId, Coin, Balance, BlockHash, SeraiAddress, Data, ExternalAddress, insecure_pair_from_name, @@ -95,9 +94,8 @@ serai_test!( &PairSigner::new(pair), &SeraiCoins::burn_with_instruction(instruction.clone()), 0, - BaseExtrinsicParamsBuilder::new(), + Default::default(), ) - .unwrap(), ) .await; diff --git a/substrate/client/tests/common/dex.rs b/substrate/client/tests/common/dex.rs index b020e850..1f446e00 100644 --- a/substrate/client/tests/common/dex.rs +++ b/substrate/client/tests/common/dex.rs @@ -3,8 +3,6 @@ use serai_runtime::primitives::{Coin, Amount}; use serai_client::{Serai, SeraiDex, PairSigner}; use sp_core::{sr25519::Pair, Pair as PairTrait}; -use subxt::config::extrinsic_params::BaseExtrinsicParamsBuilder; - use crate::common::tx::publish_tx; #[allow(dead_code)] @@ -18,14 +16,12 @@ pub async fn add_liquidity( ) -> [u8; 32] { let address = pair.public(); - let tx = serai - .sign( - &PairSigner::new(pair), - &SeraiDex::add_liquidity(coin, coin_amount, sri_amount, Amount(1), Amount(1), address.into()), - nonce, - BaseExtrinsicParamsBuilder::new(), - ) - .unwrap(); + let tx = serai.sign( + &PairSigner::new(pair), + &SeraiDex::add_liquidity(coin, coin_amount, sri_amount, Amount(1), Amount(1), address.into()), + nonce, + Default::default(), + ); publish_tx(serai, &tx).await } @@ -42,14 +38,12 @@ pub async fn swap( ) -> [u8; 32] { let address = pair.public(); - let tx = serai - .sign( - &PairSigner::new(pair), - &SeraiDex::swap(from_coin, to_coin, amount_in, amount_out_min, address.into()), - nonce, - BaseExtrinsicParamsBuilder::new(), - ) - .unwrap(); + let tx = serai.sign( + &PairSigner::new(pair), + &SeraiDex::swap(from_coin, to_coin, amount_in, amount_out_min, address.into()), + nonce, + Default::default(), + ); publish_tx(serai, &tx).await } diff --git a/substrate/client/tests/common/tx.rs b/substrate/client/tests/common/tx.rs index 4d12041c..a2ab4961 100644 --- a/substrate/client/tests/common/tx.rs +++ b/substrate/client/tests/common/tx.rs @@ -2,10 +2,10 @@ use core::time::Duration; use tokio::time::sleep; -use serai_client::{subxt::utils::Encoded, Serai}; +use serai_client::Serai; #[allow(dead_code)] -pub async fn publish_tx(serai: &Serai, tx: &Encoded) -> [u8; 32] { +pub async fn publish_tx(serai: &Serai, tx: &[u8]) -> [u8; 32] { let mut latest = serai.block(serai.latest_block_hash().await.unwrap()).await.unwrap().unwrap().number(); @@ -34,7 +34,7 @@ pub async fn publish_tx(serai: &Serai, tx: &Encoded) -> [u8; 32] { }; for transaction in block.transactions() { - if transaction.0 == tx.0[2 ..] { + if transaction.0 == tx[2 ..] { return block.hash(); } }