Skip to content

Commit

Permalink
chore: merge from main
Browse files Browse the repository at this point in the history
  • Loading branch information
albert-llimos committed Nov 11, 2024
2 parents 87e8d80 + 420429c commit ef4eb94
Show file tree
Hide file tree
Showing 52 changed files with 1,992 additions and 1,450 deletions.
4 changes: 4 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ tree --no-default-features --depth 1 --edges=features,normal
# - RUSTSEC-2024-0320: Unmaintained transitive `yaml-rust` dependency of `insta` crate. We only use insta for testing.
# - RUSTSEC-2024-0370: Unmaintained transitive dependency. Only affects macro generation efficiency.
# - RUSTSEC-2024-0375: Unmaintained transitive dependency used by clap.
# - RUSTSEC-2024-0388: Unmaintained transitive dependency `derivative` used by substrate.
# - RUSTSEC-2024-0384: Unmaintained transitive dependency `instant` used by substrate.
cf-audit = '''
audit -D unmaintained -D unsound
--ignore RUSTSEC-2022-0093
Expand All @@ -56,4 +58,6 @@ audit -D unmaintained -D unsound
--ignore RUSTSEC-2024-0344
--ignore RUSTSEC-2024-0370
--ignore RUSTSEC-2024-0375
--ignore RUSTSEC-2024-0388
--ignore RUSTSEC-2024-0384
'''
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ quickcheck_macros = { version = "1" }
quote = { version = "1.0.35" }
rayon = { version = "1.7.0" }
rand = { version = "0.8.5", default-features = false }
redis = { version = "0.27.2" }
redis = { version = "0.27.5" }
regex = { version = "1.10.2" }
reqwest = { version = "0.11.4" }
rlp = { version = "0.5.2", default-features = false }
Expand Down
25 changes: 15 additions & 10 deletions api/bin/chainflip-broker-api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ use cf_utilities::{
use chainflip_api::{
self,
primitives::{
state_chain_runtime::runtime_apis::{ChainAccounts, TaintedTransactionEvents},
AccountRole, Affiliates, Asset, BasisPoints, CcmChannelMetadata, DcaParameters,
state_chain_runtime::runtime_apis::{
ChainAccounts, TaintedTransactionEvents, VaultSwapDetails,
},
AccountRole, Affiliates, Asset, BasisPoints, BlockNumber, CcmChannelMetadata,
DcaParameters,
},
settings::StateChain,
AccountId32, AddressString, BlockUpdate, BrokerApi, ChainApi, DepositMonitorApi, OperatorApi,
RefundParameters, SignedExtrinsicApi, StateChainApi, SwapDepositAddress, SwapPayload,
TransactionInId, WithdrawFeesDetail,
RefundParameters, SignedExtrinsicApi, StateChainApi, SwapDepositAddress, TransactionInId,
WithdrawFeesDetail,
};
use clap::Parser;
use custom_rpc::CustomApiClient;
Expand Down Expand Up @@ -108,11 +111,11 @@ pub trait Rpc {
destination_address: AddressString,
broker_commission: BasisPoints,
min_output_amount: NumberOrHex,
retry_duration: u32,
retry_duration: BlockNumber,
boost_fee: Option<BasisPoints>,
affiliate_fees: Option<Affiliates<AccountId32>>,
dca_parameters: Option<DcaParameters>,
) -> RpcResult<SwapPayload>;
) -> RpcResult<VaultSwapDetails<AddressString>>;

#[method(name = "mark_transaction_as_tainted", aliases = ["broker_markTransactionAsTainted"])]
async fn mark_transaction_as_tainted(&self, tx_id: TransactionInId) -> RpcResult<()>;
Expand Down Expand Up @@ -198,15 +201,16 @@ impl RpcServer for RpcServerImpl {
destination_address: AddressString,
broker_commission: BasisPoints,
min_output_amount: NumberOrHex,
retry_duration: u32,
retry_duration: BlockNumber,
boost_fee: Option<BasisPoints>,
affiliate_fees: Option<Affiliates<AccountId32>>,
dca_parameters: Option<DcaParameters>,
) -> RpcResult<SwapPayload> {
) -> RpcResult<VaultSwapDetails<AddressString>> {
Ok(self
.api
.broker_api()
.request_swap_parameter_encoding(
.raw_client()
.cf_get_vault_swap_details(
self.api.state_chain_client.account_id(),
source_asset,
destination_asset,
destination_address,
Expand All @@ -216,6 +220,7 @@ impl RpcServer for RpcServerImpl {
boost_fee,
affiliate_fees,
dca_parameters,
None,
)
.await?)
}
Expand Down
3 changes: 2 additions & 1 deletion api/bin/chainflip-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ use api::{
lp::LpApi,
primitives::{EpochIndex, RedemptionAmount, FLIP_DECIMALS},
queries::QueryApi,
AccountId32, BrokerApi, GovernanceApi, KeyPair, OperatorApi, StateChainApi, ValidatorApi,
AccountId32, GovernanceApi, KeyPair, OperatorApi, StateChainApi, ValidatorApi,
};
use bigdecimal::BigDecimal;
use cf_chains::eth::Address as EthereumAddress;
use cf_utilities::{clean_hex_address, round_f64, task_scope::task_scope};
use chainflip_api::{
self as api,
primitives::{state_chain_runtime, FLIPPERINOS_PER_FLIP},
BrokerApi,
};
use clap::Parser;
use futures::FutureExt;
Expand Down
178 changes: 22 additions & 156 deletions api/lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
use std::{fmt, str::FromStr, sync::Arc};
use std::{fmt, sync::Arc};

use anyhow::{anyhow, bail, Context, Result};
use async_trait::async_trait;
pub use cf_chains::address::AddressString;
use cf_chains::{
address::{try_from_encoded_address, EncodedAddress},
btc::vault_swap_encoding::{
encode_swap_params_in_nulldata_utxo, SharedCfParameters, UtxoEncodedData,
},
dot::PolkadotAccountId,
evm::to_evm_address,
sol::SolAddress,
CcmChannelMetadata, Chain, ChainCrypto, ChannelRefundParametersEncoded,
ChannelRefundParametersGeneric, ForeignChain, ForeignChainAddress,
evm::to_evm_address, CcmChannelMetadata, Chain, ChainCrypto, ChannelRefundParametersEncoded,
ChannelRefundParametersGeneric, ForeignChain,
};
use cf_primitives::DcaParameters;
pub use cf_primitives::{AccountRole, Affiliates, Asset, BasisPoints, ChannelId, SemVer};
use cf_primitives::{AssetAmount, BlockNumber, DcaParameters, NetworkEnvironment};
use pallet_cf_account_roles::MAX_LENGTH_FOR_VANITY_NAME;
use pallet_cf_governance::ExecutionMode;
use serde::{Deserialize, Serialize};
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_consensus_grandpa::AuthorityId as GrandpaId;
pub use sp_core::crypto::AccountId32;
use sp_core::{
bounded_vec, ed25519::Public as EdPublic, sr25519::Public as SrPublic, Bytes, Pair, H256, U256,
};
use sp_core::{ed25519::Public as EdPublic, sr25519::Public as SrPublic, Bytes, Pair, H256, U256};
pub use state_chain_runtime::chainflip::BlockUpdate;
use state_chain_runtime::{opaque::SessionKeys, RuntimeCall};
use zeroize::Zeroize;
Expand Down Expand Up @@ -54,7 +46,7 @@ pub mod queries;

pub use chainflip_node::chain_spec::use_chainflip_account_id_encoding;

use cf_utilities::{clean_hex_address, rpc::NumberOrHex, task_scope::Scope};
use cf_utilities::{rpc::NumberOrHex, task_scope::Scope};
use chainflip_engine::state_chain_observer::client::{
base_rpc_api::BaseRpcClient, extrinsic_api::signed::UntilInBlock, DefaultRpcClient,
StateChainClient,
Expand Down Expand Up @@ -113,11 +105,6 @@ pub async fn request_block(
.ok_or_else(|| anyhow!("unknown block hash"))
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SwapPayload {
Bitcoin { nulldata_utxo: Bytes },
}

pub struct StateChainApi {
pub state_chain_client: Arc<StateChainClient>,
}
Expand Down Expand Up @@ -168,16 +155,20 @@ impl StateChainApi {
pub fn query_api(&self) -> queries::QueryApi {
queries::QueryApi { state_chain_client: self.state_chain_client.clone() }
}

pub fn base_rpc_api(&self) -> Arc<impl BaseRpcApi + Send + Sync + 'static> {
self.state_chain_client.base_rpc_client.clone()
}

pub fn raw_client(&self) -> &jsonrpsee::ws_client::WsClient {
&self.state_chain_client.base_rpc_client.raw_rpc_client
}
}

#[async_trait]
impl GovernanceApi for StateChainClient {}
#[async_trait]
impl BrokerApi for StateChainClient {
fn base_rpc_api(&self) -> Arc<dyn BaseRpcApi + Send + Sync + 'static> {
self.base_rpc_client.clone()
}
}
impl BrokerApi for StateChainClient {}
#[async_trait]
impl OperatorApi for StateChainClient {}
#[async_trait]
Expand Down Expand Up @@ -313,42 +304,6 @@ pub trait GovernanceApi: SignedExtrinsicApi {
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddressString(String);

impl FromStr for AddressString {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(s.to_string()))
}
}

impl AddressString {
pub fn try_parse_to_encoded_address(self, chain: ForeignChain) -> Result<EncodedAddress> {
clean_foreign_chain_address(chain, self.0.as_str())
}

pub fn try_parse_to_foreign_chain_address(
self,
chain: ForeignChain,
network: NetworkEnvironment,
) -> Result<ForeignChainAddress> {
try_from_encoded_address(self.try_parse_to_encoded_address(chain)?, move || network)
.map_err(|_| anyhow!("Failed to parse address"))
}

pub fn from_encoded_address<T: std::borrow::Borrow<EncodedAddress>>(address: T) -> Self {
Self(address.borrow().to_string())
}
}

impl fmt::Display for AddressString {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}", self.0)
}
}

pub type RefundParameters = ChannelRefundParametersGeneric<AddressString>;

#[derive(Serialize, Deserialize, Debug, Clone)]
Expand Down Expand Up @@ -392,7 +347,6 @@ impl fmt::Display for WithdrawFeesDetail {

#[async_trait]
pub trait BrokerApi: SignedExtrinsicApi + StorageApi + Sized + Send + Sync + 'static {
fn base_rpc_api(&self) -> Arc<dyn BaseRpcApi + Send + Sync + 'static>;
async fn request_swap_deposit_address(
&self,
source_asset: Asset,
Expand All @@ -405,8 +359,9 @@ pub trait BrokerApi: SignedExtrinsicApi + StorageApi + Sized + Send + Sync + 'st
refund_parameters: Option<RefundParameters>,
dca_parameters: Option<DcaParameters>,
) -> Result<SwapDepositAddress> {
let destination_address =
destination_address.try_parse_to_encoded_address(destination_asset.into())?;
let destination_address = destination_address
.try_parse_to_encoded_address(destination_asset.into())
.map_err(anyhow::Error::msg)?;
let (_tx_hash, events, header, ..) = self
.submit_signed_extrinsic_with_dry_run(
pallet_cf_swapping::Call::request_swap_deposit_address_with_affiliates {
Expand Down Expand Up @@ -477,7 +432,8 @@ pub trait BrokerApi: SignedExtrinsicApi + StorageApi + Sized + Send + Sync + 'st
.submit_signed_extrinsic(RuntimeCall::from(pallet_cf_swapping::Call::withdraw {
asset,
destination_address: destination_address
.try_parse_to_encoded_address(asset.into())?,
.try_parse_to_encoded_address(asset.into())
.map_err(anyhow::Error::msg)?,
}))
.await
.until_in_block()
Expand Down Expand Up @@ -518,81 +474,6 @@ pub trait BrokerApi: SignedExtrinsicApi + StorageApi + Sized + Send + Sync + 'st
self.simple_submission_with_dry_run(pallet_cf_swapping::Call::deregister_as_broker {})
.await
}

async fn request_swap_parameter_encoding(
&self,
source_asset: Asset,
destination_asset: Asset,
destination_address: AddressString,
broker_commission: BasisPoints,
min_output_amount: AssetAmount,
retry_duration: BlockNumber,
boost_fee: Option<BasisPoints>,
affiliate_fees: Option<Affiliates<AccountId32>>,
dca_parameters: Option<DcaParameters>,
) -> Result<SwapPayload> {
// Check if safe mode is active
let block_hash = self.base_rpc_api().latest_finalized_block_hash().await?;
let safe_mode = self
.storage_value::<pallet_cf_environment::RuntimeSafeMode<state_chain_runtime::Runtime>>(
block_hash,
)
.await?;
if !safe_mode.swapping.swaps_enabled {
bail!("Safe mode is active. Swaps are disabled.");
}

// Validate params
frame_support::ensure!(
broker_commission == 0 && affiliate_fees.map_or(true, |fees| fees.is_empty()),
anyhow!("Broker/Affi fees are not yet supported for vault swaps. Request a deposit address or remove the broker fees.")
);
self.base_rpc_api()
.validate_refund_params(retry_duration, Some(block_hash))
.await?;
if let Some(params) = dca_parameters.as_ref() {
self.base_rpc_api()
.validate_dca_params(
params.number_of_chunks,
params.chunk_interval,
Some(block_hash),
)
.await?;
}

// Encode swap
match ForeignChain::from(source_asset) {
ForeignChain::Bitcoin => {
let params = UtxoEncodedData {
output_asset: destination_asset,
output_address: destination_address
.try_parse_to_encoded_address(destination_asset.into())?,
parameters: SharedCfParameters {
retry_duration: retry_duration.try_into()?,
min_output_amount,
number_of_chunks: dca_parameters
.as_ref()
.map(|params| params.number_of_chunks)
.unwrap_or(1)
.try_into()?,
chunk_interval: dca_parameters
.as_ref()
.map(|params| params.chunk_interval)
.unwrap_or(2)
.try_into()?,
boost_fee: boost_fee.unwrap_or_default().try_into()?,
broker_fee: broker_commission.try_into()?,
// TODO: lookup affiliate mapping to convert affiliate ids and use them here
affiliates: bounded_vec![],
},
};
Ok(SwapPayload::Bitcoin {
nulldata_utxo: encode_swap_params_in_nulldata_utxo(params).raw().into(),
})
},
_ => bail!("Unsupported input asset"),
}
}
}

#[async_trait]
Expand All @@ -610,22 +491,6 @@ pub trait SimpleSubmissionApi: SignedExtrinsicApi {
#[async_trait]
impl<T: SignedExtrinsicApi + Sized + Send + Sync + 'static> SimpleSubmissionApi for T {}

/// Sanitize the given address (hex or base58) and turn it into a EncodedAddress of the given
/// chain.
pub fn clean_foreign_chain_address(chain: ForeignChain, address: &str) -> Result<EncodedAddress> {
Ok(match chain {
ForeignChain::Ethereum => EncodedAddress::Eth(clean_hex_address(address)?),
ForeignChain::Polkadot =>
EncodedAddress::Dot(PolkadotAccountId::from_str(address).map(|id| *id.aliased_ref())?),
ForeignChain::Bitcoin => EncodedAddress::Btc(address.as_bytes().to_vec()),
ForeignChain::Arbitrum => EncodedAddress::Arb(clean_hex_address(address)?),
ForeignChain::Solana => match SolAddress::from_str(address) {
Ok(sol_address) => EncodedAddress::Sol(sol_address.into()),
Err(_) => EncodedAddress::Sol(clean_hex_address(address)?),
},
})
}

pub type TransactionInIdFor<C> = <<C as Chain>::ChainCrypto as ChainCrypto>::TransactionInId;

#[derive(Serialize, Deserialize)]
Expand Down Expand Up @@ -756,6 +621,7 @@ mod tests {
mod key_generation {

use super::*;
use cf_chains::address::clean_foreign_chain_address;
use sp_core::crypto::Ss58Codec;

#[test]
Expand Down
Loading

0 comments on commit ef4eb94

Please sign in to comment.