Skip to content

Commit

Permalink
New API progress
Browse files Browse the repository at this point in the history
  • Loading branch information
fluiderson committed Apr 1, 2024
1 parent 1cf307d commit bbd7185
Show file tree
Hide file tree
Showing 10 changed files with 1,934 additions and 1,720 deletions.
297 changes: 154 additions & 143 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,23 @@ keywords = ["substrate", "blockchain", "finance", "service", "middleware"]
categories = ["finance"]

[dependencies]
env_logger = { version = "0.11", default-features = false, features = ["humantime", "auto-color"] }
toml_edit = { version = "0.22", default-features = false, features = ["parse", "serde"] }
axum = { version = "0.7", default-features = false, features = ["tokio", "http1", "query", "json", "matched-path"] }
tracing-subscriber = { version = "0.3", default-features = false, features = ["smallvec", "ansi", "env-filter", "time"] }
ureq = { version = "2", default-features = false, features = ["json"] }

names = { version = "0.14", default-features = false }

subxt = { version = "=0.35", features = ["substrate-compat", "unstable-reconnecting-rpc-client"] }
tokio-util = { version = "0.7", features = ["rt"] }
tokio = { version = "1", features = ["signal"] }

ureq = { version = "2", default-features = false }
names = { version = "0.14", default-features = false }

hex-simd = "0.8"
serde = "1"
anyhow = "1"
log = "0.4"
redb = "2"
humantime = "2"
tracing = "0.1"
scale-info = "2"

[profile.release]
strip = true
Expand Down
34 changes: 29 additions & 5 deletions kalatori-test.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
recipient = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
account-lifetime = 3600 # 1 hour.
depth = 86400 # 1 day.
account-lifetime = 86400000 # 1 day.
depth = 3600000 # 1 hour.
debug = true

[[chain]]
Expand All @@ -17,10 +17,9 @@ name = "westmint"
native-token = "WND AH"
decimals = 12
endpoints = [
"wss://polkadot-asset-hub-rpc.polkadot.io",
"wss://statemint-rpc.dwellir.com",
"wss://westend-asset-hub-rpc.polkadot.io",
"wss://westmint-rpc.dwellir.com",
]
multi-location-assets = true

[[chain.asset]]
name = "JOE"
Expand All @@ -29,3 +28,28 @@ id = 8
[[chain.asset]]
name = "TEST"
id = 1234

[[chain]]
name = "rococo"
native-token = "ROC"
decimals = 12
endpoints = [
"wss://rococo-rpc.polkadot.io",
]

[[chain]]
name = "assethub-rococo"
native-token = "ROC AH"
decimals = 12
endpoints = [
"wss://rococo-asset-hub-rpc.polkadot.io",
"wss://rococo-asset-hub-rpc.dwellir.com",
]

[[chain.asset]]
name = "USDT"
id = 1984

[[chain.asset]]
name = "TUSDT"
id = 7777
15 changes: 13 additions & 2 deletions kalatori.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
recipient = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
account-lifetime = 86400 # 1 day.
depth = 604800 # 1 week.
account-lifetime = 604800000 # 1 week.
depth = 86400000 # 1 day.

[[chain]]
name = "polkadot"
Expand Down Expand Up @@ -34,3 +34,14 @@ endpoints = [
"wss://kusama-rpc.polkadot.io",
"wss://1rpc.io/ksm",
]

[[chain]]
name = "assethub-kusama"
endpoints = [
"wss://kusama-asset-hub-rpc.polkadot.io",
"wss://statemine-rpc.dwellir.com",
]

[[chain.asset]]
name = "RMRK"
id = 8
244 changes: 244 additions & 0 deletions src/asset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
use crate::{AssetId, PalletIndex};
use std::marker::PhantomData;
use subxt::ext::{
codec::{Encode, Output},
scale_decode::{
self,
error::ErrorKind,
visitor::{
types::{Composite, Tuple},
TypeIdFor,
},
DecodeAsType, IntoVisitor, TypeResolver, Visitor,
},
scale_encode::{self, EncodeAsType},
};

#[derive(Clone, Debug)]
pub enum Asset {
Id(AssetId),
MultiLocation(PalletIndex, AssetId),
}

impl Asset {
const ID: &'static str = "Id";
const MULTI_LOCATION: &'static str = "MultiLocation";
}

pub struct AssetVisitor<R>(PhantomData<R>);

fn try_into_asset_id(
number: impl TryInto<AssetId> + ToString + Copy,
) -> Result<AssetId, scale_decode::Error> {
number.try_into().map_err(|_| {
scale_decode::Error::new(ErrorKind::NumberOutOfRange {
value: number.to_string(),
})
})
}

macro_rules! visit_number {
($visit:ident, $number:ty) => {
fn $visit<'scale, 'resolver>(
self,
number: $number,
type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
self.visit_u32(try_into_asset_id(number)?, type_id)
}
};
}

macro_rules! visit_composite_or_tuple {
($visit:ident, $composite_or_tuple:ident) => {
fn $visit<'scale, 'resolver>(
self,
composite_or_tuple: &mut $composite_or_tuple<'scale, 'resolver, Self::TypeResolver>,
type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
if composite_or_tuple.remaining() == 1 {
// Shouldn't panic. We've just checked remaining items above.
return composite_or_tuple
.decode_item(self)
.unwrap()
.map_err(|error| error.at_variant(Self::Value::ID));
}

let (pallet_index, asset_id) = (|| {
let MultiLocation {
interior: Junctions::X2(first, second),
..
} = MultiLocation::into_visitor().$visit(composite_or_tuple, type_id)?;

let Junction::PalletInstance(pallet_index) = first else {
return Err(scale_decode::Error::new(ErrorKind::CannotFindVariant {
got: first.name().into(),
expected: vec![Junction::PALLET_INSTANCE],
})
.at_idx(0));
};

let asset_id = (|| {
let Junction::GeneralIndex(general_index) = second else {
return Err(scale_decode::Error::new(ErrorKind::CannotFindVariant {
got: first.name().into(),
expected: vec![Junction::GENERAL_INDEX],
}));
};

let asset_id = general_index.try_into().map_err(|_| {
scale_decode::Error::new(ErrorKind::NumberOutOfRange {
value: general_index.to_string(),
})
})?;

Ok(asset_id)
})()
.map_err(|error| error.at_idx(1))?;

Ok((pallet_index, asset_id))
})()
.map_err(|error| error.at_variant(Self::Value::MULTI_LOCATION))?;

Ok(Self::Value::MultiLocation(pallet_index, asset_id))
}
};
}

impl<R: TypeResolver> Visitor for AssetVisitor<R> {
type Value<'scale, 'resolver> = Asset;
type Error = scale_decode::Error;
type TypeResolver = R;

fn visit_u32<'scale, 'resolver>(
self,
value: u32,
_: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Self::Value::Id(value))
}

fn visit_u8<'scale, 'resolver>(
self,
value: u8,
type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
self.visit_u32(value.into(), type_id)
}

fn visit_u16<'scale, 'resolver>(
self,
value: u16,
type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
self.visit_u32(value.into(), type_id)
}

visit_number!(visit_i8, i8);
visit_number!(visit_i16, i16);
visit_number!(visit_i32, i32);
visit_number!(visit_u64, u64);
visit_number!(visit_i64, i64);
visit_number!(visit_i128, i128);
visit_number!(visit_u128, u128);

visit_composite_or_tuple!(visit_tuple, Tuple);
visit_composite_or_tuple!(visit_composite, Composite);
}

impl IntoVisitor for Asset {
type AnyVisitor<R: TypeResolver> = AssetVisitor<R>;

fn into_visitor<R: TypeResolver>() -> Self::AnyVisitor<R> {
AssetVisitor(PhantomData)
}
}

impl EncodeAsType for Asset {
fn encode_as_type_to<R: TypeResolver>(
&self,
type_id: &R::TypeId,
types: &R,
out: &mut Vec<u8>,
) -> Result<(), scale_encode::Error> {
match self {
Self::Id(id) => id.encode_as_type_to(type_id, types, out),
Self::MultiLocation(assets_pallet, asset_id) => {
MultiLocation::new(*assets_pallet, *asset_id).encode_as_type_to(type_id, types, out)
}
}
}
}

impl Encode for Asset {
fn size_hint(&self) -> usize {
match self {
Self::Id(id) => id.size_hint(),
Self::MultiLocation(assets_pallet, asset_id) => {
MultiLocation::new(*assets_pallet, *asset_id).size_hint()
}
}
}

fn encode_to<T: Output + ?Sized>(&self, dest: &mut T) {
match self {
Self::Id(id) => id.encode_to(dest),
Self::MultiLocation(assets_pallet, asset_id) => {
MultiLocation::new(*assets_pallet, *asset_id).encode_to(dest);
}
}
}
}

#[derive(EncodeAsType, DecodeAsType, Encode)]
#[encode_as_type(crate_path = "subxt::ext::scale_encode")]
#[decode_as_type(crate_path = "subxt::ext::scale_decode")]
#[codec(crate = subxt::ext::codec)]
struct MultiLocation {
parents: u8,
interior: Junctions,
}

impl MultiLocation {
fn new(assets_pallet: PalletIndex, asset_id: AssetId) -> Self {
Self {
parents: 0,
interior: Junctions::X2(
Junction::PalletInstance(assets_pallet),
Junction::GeneralIndex(asset_id.into()),
),
}
}
}

#[derive(EncodeAsType, DecodeAsType, Encode)]
#[encode_as_type(crate_path = "subxt::ext::scale_encode")]
#[decode_as_type(crate_path = "subxt::ext::scale_decode")]
#[codec(crate = subxt::ext::codec)]
enum Junctions {
#[codec(index = 2)]
X2(Junction, Junction),
}

#[derive(EncodeAsType, DecodeAsType, Encode)]
#[encode_as_type(crate_path = "subxt::ext::scale_encode")]
#[decode_as_type(crate_path = "subxt::ext::scale_decode")]
#[codec(crate = subxt::ext::codec)]
enum Junction {
#[codec(index = 4)]
PalletInstance(PalletIndex),
#[codec(index = 5)]
GeneralIndex(u128),
}

impl Junction {
const PALLET_INSTANCE: &'static str = "PalletInstance";
const GENERAL_INDEX: &'static str = "GeneralIndex";

fn name(&self) -> &str {
match self {
Self::PalletInstance(_) => Self::PALLET_INSTANCE,
Self::GeneralIndex(_) => Self::GENERAL_INDEX,
}
}
}
1 change: 0 additions & 1 deletion src/callback.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@

pub const MODULE: &str = module_path!();
Loading

0 comments on commit bbd7185

Please sign in to comment.