mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-22 19:49:22 +00:00
Replace substrate/client's use of Payload with usage of RuntimeCall
Gains explicit typing.
This commit is contained in:
parent
fcfdadc791
commit
08e6669403
9 changed files with 93 additions and 105 deletions
|
@ -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<Composite<()>> {
|
||||
Payload::new(
|
||||
PALLET,
|
||||
"transfer",
|
||||
scale_composite(serai_runtime::coins::Call::<Runtime>::transfer { to: to.into(), balance }),
|
||||
)
|
||||
pub fn transfer(to: SeraiAddress, balance: Balance) -> serai_runtime::RuntimeCall {
|
||||
serai_runtime::RuntimeCall::Coins(serai_runtime::coins::Call::<Runtime>::transfer {
|
||||
to: to.into(),
|
||||
balance,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn burn(balance: Balance) -> Payload<Composite<()>> {
|
||||
Payload::new(PALLET, "burn", scale_composite(coins::Call::<Runtime>::burn { balance }))
|
||||
pub fn burn(balance: Balance) -> serai_runtime::RuntimeCall {
|
||||
serai_runtime::RuntimeCall::Coins(serai_runtime::coins::Call::<Runtime>::burn { balance })
|
||||
}
|
||||
|
||||
pub fn burn_with_instruction(instruction: OutInstructionWithBalance) -> Payload<Composite<()>> {
|
||||
Payload::new(
|
||||
PALLET,
|
||||
"burn_with_instruction",
|
||||
scale_composite(coins::Call::<Runtime>::burn_with_instruction { instruction }),
|
||||
pub fn burn_with_instruction(
|
||||
instruction: OutInstructionWithBalance,
|
||||
) -> serai_runtime::RuntimeCall {
|
||||
serai_runtime::RuntimeCall::Coins(
|
||||
serai_runtime::coins::Call::<Runtime>::burn_with_instruction { instruction },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Runtime>;
|
||||
|
||||
|
@ -26,19 +22,15 @@ impl<'a> SeraiDex<'a> {
|
|||
min_coin_amount: Amount,
|
||||
min_sri_amount: Amount,
|
||||
address: SeraiAddress,
|
||||
) -> Payload<Composite<()>> {
|
||||
Payload::new(
|
||||
PALLET,
|
||||
"add_liquidity",
|
||||
scale_composite(dex::Call::<Runtime>::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::<Runtime>::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<Composite<()>> {
|
||||
) -> 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::<Runtime>::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::<Runtime>::swap_exact_tokens_for_tokens {
|
||||
path,
|
||||
amount_in: amount_in.0,
|
||||
amount_out_min: amount_out_min.0,
|
||||
send_to: address.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<u8> {
|
||||
Serai::unsigned::<InInstructions, _>(&in_instructions::Call::<Runtime>::execute_batch { batch })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::<SeraiConfig>::from_url(url).await.map_err(SeraiError::RpcError)?))
|
||||
}
|
||||
|
||||
fn unsigned<P: 'static, C: Encode>(call: &C) -> Encoded {
|
||||
fn unsigned<P: 'static, C: Encode>(call: &C) -> Vec<u8> {
|
||||
// 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<S: Send + Sync + Signer<SeraiConfig>>(
|
||||
&self,
|
||||
signer: &S,
|
||||
payload: &Payload<Composite<()>>,
|
||||
call: &serai_runtime::RuntimeCall,
|
||||
nonce: u32,
|
||||
params: BaseExtrinsicParamsBuilder<SeraiConfig, Tip>,
|
||||
) -> Result<Encoded, SeraiError> {
|
||||
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<u8> {
|
||||
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> {
|
||||
|
|
|
@ -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<V: 'static + Encode + TypeInfo>(value: V) -> Value {
|
||||
let mut registry = Registry::new();
|
||||
|
@ -11,11 +11,3 @@ pub(crate) fn scale_value<V: 'static + Encode + TypeInfo>(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<V: 'static + Encode + TypeInfo>(value: V) -> Composite<()> {
|
||||
match scale_value(value).value {
|
||||
ValueDef::Composite(composite) => composite,
|
||||
ValueDef::Variant(variant) => variant.values,
|
||||
_ => panic!("not composite"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<u8> {
|
||||
Serai::unsigned::<ValidatorSets, _>(&validator_sets::Call::<Runtime>::set_keys {
|
||||
network,
|
||||
key_pair,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue