Skip to content

Commit

Permalink
feat(pop-api): cross chain messaging (#33)
Browse files Browse the repository at this point in the history
* feat: cross_chain module

* chore:typo

* feat(pop-api): buy on demand - WIP

* refactor(pop-api): sending cross chain messages

Used more message-based terms to try provide clarity that it is not a sync call to local runtime, but a send of message to a runtime on another chain.

* refactor: duplicated code into helper functions

* style: cargo fmt

* fix: limit function visibility to extensions module and update log_prefix

* refactor: simplify types

* refactor: remove unnecessary module

---------

Co-authored-by: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com>
Co-authored-by: Peter White <petras9789@gmail.com>
  • Loading branch information
3 people authored Mar 10, 2024
1 parent f53a608 commit b0de30c
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 45 deletions.
19 changes: 19 additions & 0 deletions pop-api/primitives/src/cross_chain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use scale::{Decode, Encode, MaxEncodedLen};

#[derive(Encode, Decode, Debug, MaxEncodedLen)]
pub enum CrossChainMessage {
Relay(RelayChainMessage),
}

#[derive(Encode, Decode, Debug, MaxEncodedLen)]
pub enum RelayChainMessage {
// Rococo index: https://github.com/paritytech/polkadot-sdk/blob/629506ce061db76d31d4f7a81f4a497752b27259/polkadot/runtime/rococo/src/lib.rs#L1423
#[codec(index = 66)]
OnDemand(OnDemand),
}

#[derive(Encode, Decode, Debug, MaxEncodedLen)]
pub enum OnDemand {
#[codec(index = 1)]
PlaceOrderKeepAlive { max_amount: u128, para_id: u32 },
}
1 change: 1 addition & 0 deletions pop-api/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub use bounded_collections::{BoundedBTreeMap, BoundedBTreeSet, BoundedVec, ConstU32};
//use scale::{Decode, Encode, MaxEncodedLen};

pub mod cross_chain;
pub mod storage_keys;

// /// Some way of identifying an account on the chain.
Expand Down
15 changes: 13 additions & 2 deletions pop-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ pub mod v0;

use crate::PopApiError::{Balances, Nfts, UnknownStatusCode};
use ink::{prelude::vec::Vec, ChainExtensionInstance};
use primitives::storage_keys::*;
use primitives::{cross_chain::*, storage_keys::*};
pub use sp_runtime::{BoundedVec, MultiAddress, MultiSignature};
use v0::RuntimeCall;
pub use v0::{balances, nfts, relay_chain_block_number, state};
pub use v0::{balances, cross_chain, nfts, relay_chain_block_number, state};

type AccountId = <Environment as ink::env::Environment>::AccountId;
type Balance = <Environment as ink::env::Environment>::Balance;
Expand All @@ -25,6 +25,7 @@ pub enum PopApiError {
DecodingFailed,
Balances(balances::Error),
Nfts(nfts::Error),
Xcm(cross_chain::Error),
}

impl ink::env::chain_extension::FromStatusCode for PopApiError {
Expand Down Expand Up @@ -72,6 +73,10 @@ pub trait PopApi {
#[ink(extension = 1)]
#[allow(private_interfaces)]
fn read_state(key: RuntimeStateKeys) -> Result<Vec<u8>>;

#[ink(extension = 2)]
#[allow(private_interfaces)]
fn send_xcm(xcm: CrossChainMessage) -> Result<()>;
}

fn dispatch(call: RuntimeCall) -> Result<()> {
Expand All @@ -85,3 +90,9 @@ fn read_state(key: RuntimeStateKeys) -> Result<Vec<u8>> {
)
.read_state(key)
}

fn send_xcm(xcm: CrossChainMessage) -> Result<()> {
<<Environment as ink::env::Environment>::ChainExtension as ChainExtensionInstance>::instantiate(
)
.send_xcm(xcm)
}
11 changes: 11 additions & 0 deletions pop-api/src/v0/cross_chain/coretime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use crate::{
primitives::cross_chain::{CrossChainMessage, OnDemand, RelayChainMessage},
send_xcm,
};

/// Send a cross-chain message to place a sport order for instantaneous coretime.
pub fn place_spot_order(max_amount: u128, para_id: u32) -> crate::cross_chain::Result<()> {
Ok(send_xcm(CrossChainMessage::Relay(RelayChainMessage::OnDemand(
OnDemand::PlaceOrderKeepAlive { max_amount, para_id },
)))?)
}
107 changes: 107 additions & 0 deletions pop-api/src/v0/cross_chain/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
pub mod coretime;

use crate::{PopApiError::UnknownStatusCode, *};

type Result<T> = core::result::Result<T, Error>;

#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum Error {
/// The desired destination was unreachable, generally because there is a no way of routing
/// to it.
Unreachable,
/// There was some other issue (i.e. not to do with routing) in sending the message.
/// Perhaps a lack of space for buffering the message.
SendFailure,
/// The message execution fails the filter.
Filtered,
/// The message's weight could not be determined.
UnweighableMessage,
/// The destination `Location` provided cannot be inverted.
DestinationNotInvertible,
/// The assets to be sent are empty.
Empty,
/// Could not re-anchor the assets to declare the fees for the destination chain.
CannotReanchor,
/// Too many assets have been attempted for transfer.
TooManyAssets,
/// Origin is invalid for sending.
InvalidOrigin,
/// The version of the `Versioned` value used is not able to be interpreted.
BadVersion,
/// The given location could not be used (e.g. because it cannot be expressed in the
/// desired version of XCM).
BadLocation,
/// The referenced subscription could not be found.
NoSubscription,
/// The location is invalid since it already has a subscription from us.
AlreadySubscribed,
/// Could not check-out the assets for teleportation to the destination chain.
CannotCheckOutTeleport,
/// The owner does not own (all) of the asset that they wish to do the operation on.
LowBalance,
/// The asset owner has too many locks on the asset.
TooManyLocks,
/// The given account is not an identifiable sovereign account for any location.
AccountNotSovereign,
/// The operation required fees to be paid which the initiator could not meet.
FeesNotMet,
/// A remote lock with the corresponding data could not be found.
LockNotFound,
/// The unlock operation cannot succeed because there are still consumers of the lock.
InUse,
/// Invalid non-concrete asset.
InvalidAssetNotConcrete,
/// Invalid asset, reserve chain could not be determined for it.
InvalidAssetUnknownReserve,
/// Invalid asset, do not support remote asset reserves with different fees reserves.
InvalidAssetUnsupportedReserve,
/// Too many assets with different reserve locations have been attempted for transfer.
TooManyReserves,
/// Local XCM execution incomplete.
LocalExecutionIncomplete,
}

impl TryFrom<u32> for Error {
type Error = PopApiError;

fn try_from(status_code: u32) -> core::result::Result<Self, Self::Error> {
use Error::*;
match status_code {
0 => Ok(Unreachable),
1 => Ok(SendFailure),
2 => Ok(Filtered),
3 => Ok(UnweighableMessage),
4 => Ok(DestinationNotInvertible),
5 => Ok(Empty),
6 => Ok(CannotReanchor),
7 => Ok(TooManyAssets),
8 => Ok(InvalidOrigin),
9 => Ok(BadVersion),
10 => Ok(BadLocation),
11 => Ok(NoSubscription),
12 => Ok(AlreadySubscribed),
13 => Ok(CannotCheckOutTeleport),
14 => Ok(LowBalance),
15 => Ok(TooManyLocks),
16 => Ok(AccountNotSovereign),
17 => Ok(FeesNotMet),
18 => Ok(LockNotFound),
19 => Ok(InUse),
20 => Ok(InvalidAssetNotConcrete),
21 => Ok(InvalidAssetUnknownReserve),
22 => Ok(InvalidAssetUnsupportedReserve),
23 => Ok(TooManyReserves),
_ => Err(UnknownStatusCode(status_code)),
}
}
}

impl From<PopApiError> for Error {
fn from(error: PopApiError) -> Self {
match error {
PopApiError::Xcm(e) => e,
_ => panic!("expected xcm error"),
}
}
}
1 change: 1 addition & 0 deletions pop-api/src/v0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
};

pub mod balances;
pub mod cross_chain;
pub mod nfts;
pub mod state;

Expand Down
Loading

0 comments on commit b0de30c

Please sign in to comment.