From ac3ed8e1f57b45c3b934bc5d40289d9b2e5e3f93 Mon Sep 17 00:00:00 2001 From: Jamie Ford Date: Tue, 12 Nov 2024 15:29:55 +1100 Subject: [PATCH 1/3] feat: btc vault swap bouncer test can open private channel --- api/bin/chainflip-broker-api/src/main.rs | 20 ++++++++-- api/lib/src/lib.rs | 50 ++++++++++++++++++++++++ bouncer/tests/all_concurrent_tests.ts | 2 + bouncer/tests/btc_vault_swap.ts | 21 +++++++++- state-chain/runtime/src/lib.rs | 3 +- 5 files changed, 90 insertions(+), 6 deletions(-) diff --git a/api/bin/chainflip-broker-api/src/main.rs b/api/bin/chainflip-broker-api/src/main.rs index 3b70c4c529..c393b0d057 100644 --- a/api/bin/chainflip-broker-api/src/main.rs +++ b/api/bin/chainflip-broker-api/src/main.rs @@ -14,9 +14,9 @@ use chainflip_api::{ DcaParameters, }, settings::StateChain, - AccountId32, AddressString, BlockUpdate, BrokerApi, ChainApi, DepositMonitorApi, OperatorApi, - RefundParameters, SignedExtrinsicApi, StateChainApi, SwapDepositAddress, TransactionInId, - WithdrawFeesDetail, + AccountId32, AddressString, BlockUpdate, BrokerApi, ChainApi, ChannelId, DepositMonitorApi, + OperatorApi, RefundParameters, SignedExtrinsicApi, StateChainApi, SwapDepositAddress, + TransactionInId, WithdrawFeesDetail, }; use clap::Parser; use custom_rpc::CustomApiClient; @@ -128,6 +128,12 @@ pub trait Rpc { #[subscription(name = "subscribe_tainted_transaction_events", item = BlockUpdate)] async fn subscribe_tainted_transaction_events(&self) -> SubscriptionResult; + + #[method(name = "open_private_btc_channel", aliases = ["broker_openPrivateBtcChannel"])] + async fn open_private_btc_channel(&self) -> RpcResult; + + #[method(name = "close_private_btc_channel", aliases = ["broker_closePrivateBtcChannel"])] + async fn close_private_btc_channel(&self) -> RpcResult; } pub struct RpcServerImpl { @@ -298,6 +304,14 @@ impl RpcServer for RpcServerImpl { }); Ok(()) } + + async fn open_private_btc_channel(&self) -> RpcResult { + Ok(self.api.broker_api().open_private_btc_channel().await?) + } + + async fn close_private_btc_channel(&self) -> RpcResult { + Ok(self.api.broker_api().close_private_btc_channel().await?) + } } #[derive(Parser, Debug, Clone, Default)] diff --git a/api/lib/src/lib.rs b/api/lib/src/lib.rs index 20e2e1e0a1..fa10f9e343 100644 --- a/api/lib/src/lib.rs +++ b/api/lib/src/lib.rs @@ -474,6 +474,56 @@ 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 open_private_btc_channel(&self) -> Result { + let (_, events, ..) = self + .submit_signed_extrinsic(RuntimeCall::from( + pallet_cf_swapping::Call::open_private_btc_channel {}, + )) + .await + .until_in_block() + .await?; + + if let Some(state_chain_runtime::RuntimeEvent::Swapping( + pallet_cf_swapping::Event::PrivateBrokerChannelOpened { channel_id, .. }, + )) = events.iter().find(|event| { + matches!( + event, + state_chain_runtime::RuntimeEvent::Swapping( + pallet_cf_swapping::Event::PrivateBrokerChannelOpened { .. } + ) + ) + }) { + Ok(*channel_id) + } else { + bail!("No PrivateBrokerChannelOpened event was found"); + } + } + + async fn close_private_btc_channel(&self) -> Result { + let (_, events, ..) = self + .submit_signed_extrinsic(RuntimeCall::from( + pallet_cf_swapping::Call::close_private_btc_channel {}, + )) + .await + .until_in_block() + .await?; + + if let Some(state_chain_runtime::RuntimeEvent::Swapping( + pallet_cf_swapping::Event::PrivateBrokerChannelClosed { channel_id, .. }, + )) = events.iter().find(|event| { + matches!( + event, + state_chain_runtime::RuntimeEvent::Swapping( + pallet_cf_swapping::Event::PrivateBrokerChannelClosed { .. } + ) + ) + }) { + Ok(*channel_id) + } else { + bail!("No PrivateBrokerChannelClosed event was found"); + } + } } #[async_trait] diff --git a/bouncer/tests/all_concurrent_tests.ts b/bouncer/tests/all_concurrent_tests.ts index 28b3628b32..d5b26a92b5 100755 --- a/bouncer/tests/all_concurrent_tests.ts +++ b/bouncer/tests/all_concurrent_tests.ts @@ -15,6 +15,7 @@ import { testAllSwaps } from './all_swaps'; import { depositChannelCreation } from './request_swap_deposit_address_with_affiliates'; import { testDCASwaps } from './DCA_test'; import { testBrokerLevelScreening } from './broker_level_screening'; +import { testBtcVaultSwap } from './btc_vault_swap'; async function runAllConcurrentTests() { // Specify the number of nodes via providing an argument to this script. @@ -46,6 +47,7 @@ async function runAllConcurrentTests() { testDCASwaps.run(), testCancelOrdersBatch.run(), depositChannelCreation.run(), + testBtcVaultSwap.run(), ]; // Tests that only work if there is more than one node diff --git a/bouncer/tests/btc_vault_swap.ts b/bouncer/tests/btc_vault_swap.ts index dd491288b7..f0c9d12ad8 100644 --- a/bouncer/tests/btc_vault_swap.ts +++ b/bouncer/tests/btc_vault_swap.ts @@ -12,6 +12,7 @@ import { } from '../shared/utils'; import { getChainflipApi, observeEvent } from '../shared/utils/substrate'; import { getBalance } from '../shared/get_balance'; +import { jsonRpc } from '../shared/json_rpc'; /* eslint-disable @typescript-eslint/no-use-before-define */ export const testBtcVaultSwap = new ExecutableTest('Btc-Vault-Swap', main, 100); @@ -51,6 +52,7 @@ async function buildAndSendBtcVaultSwap( assert.strictEqual(vaultSwapDetails.chain, 'Bitcoin'); testBtcVaultSwap.debugLog('nulldata_utxo:', vaultSwapDetails.nulldata_utxo); + testBtcVaultSwap.debugLog('deposit_address:', vaultSwapDetails.deposit_address); // The `createRawTransaction` function will add the op codes, so we have to remove them here. const nullDataWithoutOpCodes = vaultSwapDetails.nulldata_utxo.replace('0x', '').substring(4); @@ -112,8 +114,25 @@ async function testVaultSwap(depositAmountBtc: number, brokerUri: string, destin testBtcVaultSwap.log(`Balance increased, Vault Swap Complete`); } +async function openPrivateBtcChannel(brokerUri: string) { + // TODO: Use chainflip SDK instead so we can support any broker uri + assert.strictEqual(brokerUri, '//BROKER_1', 'Support for other brokers is not implemented'); + + // TODO: use chainflip SDK to check if the channel is already open + try { + await jsonRpc('broker_open_private_btc_channel', [], 'http://127.0.0.1:10997'); + testBtcVaultSwap.log('Private Btc channel opened'); + } catch (error) { + // We expect this to fail if the channel already exists from a previous run + testBtcVaultSwap.debugLog('Failed to open private Btc channel', error); + } +} + async function main() { const btcDepositAmount = 0.1; + const brokerUri = '//BROKER_1'; + + await openPrivateBtcChannel(brokerUri); - await testVaultSwap(btcDepositAmount, '//BROKER_1', 'Flip'); + await testVaultSwap(btcDepositAmount, brokerUri, 'Flip'); } diff --git a/state-chain/runtime/src/lib.rs b/state-chain/runtime/src/lib.rs index 2683c293ca..31e9c19400 100644 --- a/state-chain/runtime/src/lib.rs +++ b/state-chain/runtime/src/lib.rs @@ -2132,8 +2132,7 @@ impl_runtime_apis! { Ok(()) } }) - .map_err(|()| pallet_cf_swapping::Error::::InvalidDestinationAddress)?; - + .map_err(|_| pallet_cf_swapping::Error::::InvalidDestinationAddress)?; // Encode swap match ForeignChain::from(source_asset) { From ffb44c21b61b6f8d61349a408712832aec275089 Mon Sep 17 00:00:00 2001 From: Jamie Ford Date: Tue, 12 Nov 2024 15:52:36 +1100 Subject: [PATCH 2/3] chore: remove unneeded validate params functions in base rpc api --- .../client/base_rpc_api.rs | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/engine/src/state_chain_observer/client/base_rpc_api.rs b/engine/src/state_chain_observer/client/base_rpc_api.rs index 7eade20f09..d83bbc241c 100644 --- a/engine/src/state_chain_observer/client/base_rpc_api.rs +++ b/engine/src/state_chain_observer/client/base_rpc_api.rs @@ -1,5 +1,4 @@ use async_trait::async_trait; -use cf_primitives::BlockNumber; use jsonrpsee::core::client::{ClientT, Subscription, SubscriptionClientT}; use sc_transaction_pool_api::TransactionStatus; use sp_core::{ @@ -168,19 +167,6 @@ pub trait BaseRpcApi { params: Option>, unsub: &str, ) -> RpcResult>>; - - async fn validate_refund_params( - &self, - retry_duration: BlockNumber, - block_hash: Option, - ) -> RpcResult<()>; - - async fn validate_dca_params( - &self, - number_of_chunks: u32, - chunk_interval: u32, - block_hash: Option, - ) -> RpcResult<()>; } pub struct BaseRpcClient { @@ -318,25 +304,6 @@ impl BaseRpcApi for BaseRpcClient RpcResult>> { self.raw_rpc_client.subscribe(sub, Params(params), unsub).await } - - async fn validate_refund_params( - &self, - retry_duration: BlockNumber, - block_hash: Option, - ) -> RpcResult<()> { - self.raw_rpc_client.cf_validate_refund_params(retry_duration, block_hash).await - } - - async fn validate_dca_params( - &self, - number_of_chunks: u32, - chunk_interval: u32, - block_hash: Option, - ) -> RpcResult<()> { - self.raw_rpc_client - .cf_validate_dca_params(number_of_chunks, chunk_interval, block_hash) - .await - } } struct Params(Option>); From 303f28f48f858494c16ddaaafc5db1afbcd4d555 Mon Sep 17 00:00:00 2001 From: Jamie Ford Date: Wed, 13 Nov 2024 15:11:07 +1100 Subject: [PATCH 3/3] chore: use dry run. --- api/lib/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/lib/src/lib.rs b/api/lib/src/lib.rs index fa10f9e343..c9203ff8d3 100644 --- a/api/lib/src/lib.rs +++ b/api/lib/src/lib.rs @@ -477,10 +477,10 @@ pub trait BrokerApi: SignedExtrinsicApi + StorageApi + Sized + Send + Sync + 'st async fn open_private_btc_channel(&self) -> Result { let (_, events, ..) = self - .submit_signed_extrinsic(RuntimeCall::from( + .submit_signed_extrinsic_with_dry_run(RuntimeCall::from( pallet_cf_swapping::Call::open_private_btc_channel {}, )) - .await + .await? .until_in_block() .await?; @@ -502,10 +502,10 @@ pub trait BrokerApi: SignedExtrinsicApi + StorageApi + Sized + Send + Sync + 'st async fn close_private_btc_channel(&self) -> Result { let (_, events, ..) = self - .submit_signed_extrinsic(RuntimeCall::from( + .submit_signed_extrinsic_with_dry_run(RuntimeCall::from( pallet_cf_swapping::Call::close_private_btc_channel {}, )) - .await + .await? .until_in_block() .await?;