From ee382e2a52a345e0cf5e9ebc6e4e25191cb6cb99 Mon Sep 17 00:00:00 2001 From: Andrew Dibble Date: Fri, 13 Oct 2023 16:27:45 +0200 Subject: [PATCH 1/2] feat(custom-rpc): add flip balance to account info --- state-chain/custom-rpc/src/lib.rs | 90 +++++++++++++++---------- state-chain/runtime/src/lib.rs | 29 ++++---- state-chain/runtime/src/runtime_apis.rs | 3 +- 3 files changed, 72 insertions(+), 50 deletions(-) diff --git a/state-chain/custom-rpc/src/lib.rs b/state-chain/custom-rpc/src/lib.rs index c1f6747ad7..8a85f9c3df 100644 --- a/state-chain/custom-rpc/src/lib.rs +++ b/state-chain/custom-rpc/src/lib.rs @@ -35,14 +35,19 @@ use std::{ #[derive(Serialize, Deserialize)] #[serde(tag = "role", rename_all = "snake_case")] pub enum RpcAccountInfo { - None, - Broker, + None { + flip_balance: NumberOrHex, + }, + Broker { + flip_balance: NumberOrHex, + }, LiquidityProvider { balances: HashMap>, refund_addresses: HashMap>, + flip_balance: NumberOrHex, }, Validator { - balance: NumberOrHex, + flip_balance: NumberOrHex, bond: NumberOrHex, last_heartbeat: u32, online_credits: u32, @@ -59,15 +64,15 @@ pub enum RpcAccountInfo { } impl RpcAccountInfo { - fn none() -> Self { - Self::None + fn none(balance: u128) -> Self { + Self::None { flip_balance: balance.into() } } - fn broker() -> Self { - Self::Broker + fn broker(balance: u128) -> Self { + Self::Broker { flip_balance: balance.into() } } - fn lp(info: LiquidityProviderInfo) -> Self { + fn lp(info: LiquidityProviderInfo, balance: u128) -> Self { let mut balances = HashMap::new(); for (asset, balance) in info.balances { @@ -78,6 +83,7 @@ impl RpcAccountInfo { } Self::LiquidityProvider { + flip_balance: balance.into(), balances, refund_addresses: info .refund_addresses @@ -96,7 +102,7 @@ impl RpcAccountInfo { fn validator(info: RuntimeApiAccountInfoV2) -> Self { Self::Validator { - balance: info.balance.into(), + flip_balance: info.balance.into(), bond: info.bond.into(), last_heartbeat: info.last_heartbeat, online_credits: info.online_credits, @@ -529,26 +535,28 @@ where ) -> RpcResult { let api = self.client.runtime_api(); + let hash = self.unwrap_or_best(at); + + let balance = api.cf_account_flip_balance(hash, &account_id).map_err(to_rpc_error)?; + Ok( match api - .cf_account_role(self.unwrap_or_best(at), account_id.clone()) + .cf_account_role(hash, account_id.clone()) .map_err(to_rpc_error)? .unwrap_or(AccountRole::None) { - AccountRole::None => RpcAccountInfo::none(), - AccountRole::Broker => RpcAccountInfo::broker(), + AccountRole::None => RpcAccountInfo::none(balance), + AccountRole::Broker => RpcAccountInfo::broker(balance), AccountRole::LiquidityProvider => { let info = api - .cf_liquidity_provider_info(self.unwrap_or_best(at), account_id) + .cf_liquidity_provider_info(hash, account_id) .map_err(to_rpc_error)? .expect("role already validated"); - RpcAccountInfo::lp(info) + RpcAccountInfo::lp(info, balance) }, AccountRole::Validator => { - let info = api - .cf_account_info_v2(self.unwrap_or_best(at), account_id) - .map_err(to_rpc_error)?; + let info = api.cf_account_info_v2(hash, &account_id).map_err(to_rpc_error)?; RpcAccountInfo::validator(info) }, @@ -564,7 +572,7 @@ where let account_info = self .client .runtime_api() - .cf_account_info_v2(self.unwrap_or_best(at), account_id) + .cf_account_info_v2(self.unwrap_or_best(at), &account_id) .map_err(to_rpc_error)?; Ok(RpcAccountInfoV2 { @@ -939,33 +947,41 @@ mod test { #[test] fn test_account_info_serialization() { assert_eq!( - serde_json::to_value(RpcAccountInfo::none()).unwrap(), - json!({ "role": "none" }) + serde_json::to_value(RpcAccountInfo::none(0)).unwrap(), + json!({ "role": "none", "flip_balance": 0 }) ); assert_eq!( - serde_json::to_value(RpcAccountInfo::broker()).unwrap(), - json!({ "role":"broker" }) + serde_json::to_value(RpcAccountInfo::broker(0)).unwrap(), + json!({ "role":"broker", "flip_balance": 0 }) ); - let lp = RpcAccountInfo::lp(LiquidityProviderInfo { - refund_addresses: vec![ - ( - ForeignChain::Ethereum, - Some(cf_chains::ForeignChainAddress::Eth(H160::from([1; 20]))), - ), - ( - ForeignChain::Polkadot, - Some(cf_chains::ForeignChainAddress::Dot(Default::default())), - ), - (ForeignChain::Bitcoin, None), - ], - balances: vec![(Asset::Eth, u128::MAX), (Asset::Btc, 0), (Asset::Flip, u128::MAX / 2)], - }); + let lp = RpcAccountInfo::lp( + LiquidityProviderInfo { + refund_addresses: vec![ + ( + ForeignChain::Ethereum, + Some(cf_chains::ForeignChainAddress::Eth(H160::from([1; 20]))), + ), + ( + ForeignChain::Polkadot, + Some(cf_chains::ForeignChainAddress::Dot(Default::default())), + ), + (ForeignChain::Bitcoin, None), + ], + balances: vec![ + (Asset::Eth, u128::MAX), + (Asset::Btc, 0), + (Asset::Flip, u128::MAX / 2), + ], + }, + 0, + ); assert_eq!( serde_json::to_value(lp).unwrap(), json!({ "role": "liquidity_provider", + "flip_balance": 0, "balances": { "Ethereum": { "Flip": "0x7fffffffffffffffffffffffffffffff", @@ -999,7 +1015,7 @@ mod test { assert_eq!( serde_json::to_value(validator).unwrap(), json!({ - "balance": "0xde0b6b3a7640000", + "flip_balance": "0xde0b6b3a7640000", "bond": "0xde0b6b3a7640000", "bound_redeem_address": "0x0101010101010101010101010101010101010101", "is_bidding": false, diff --git a/state-chain/runtime/src/lib.rs b/state-chain/runtime/src/lib.rs index 0107bb062b..fd16b909c4 100644 --- a/state-chain/runtime/src/lib.rs +++ b/state-chain/runtime/src/lib.rs @@ -913,27 +913,32 @@ impl_runtime_apis! { }) .collect() } - fn cf_account_info_v2(account_id: AccountId) -> RuntimeApiAccountInfoV2 { - let is_current_backup = pallet_cf_validator::Backups::::get().contains_key(&account_id); - let key_holder_epochs = pallet_cf_validator::HistoricalActiveEpochs::::get(&account_id); - let is_qualified = <::KeygenQualification as QualifyNode<_>>::is_qualified(&account_id); - let is_current_authority = pallet_cf_validator::CurrentAuthorities::::get().contains(&account_id); - let is_bidding = pallet_cf_funding::ActiveBidder::::get(&account_id); - let bound_redeem_address = pallet_cf_funding::BoundRedeemAddress::::get(&account_id); - let reputation_info = pallet_cf_reputation::Reputations::::get(&account_id); - let account_info = pallet_cf_flip::Account::::get(&account_id); - let restricted_balances = pallet_cf_funding::RestrictedBalances::::get(&account_id); + + fn cf_account_flip_balance(account_id: &AccountId) -> u128 { + pallet_cf_flip::Account::::get(account_id).total() + } + + fn cf_account_info_v2(account_id: &AccountId) -> RuntimeApiAccountInfoV2 { + let is_current_backup = pallet_cf_validator::Backups::::get().contains_key(account_id); + let key_holder_epochs = pallet_cf_validator::HistoricalActiveEpochs::::get(account_id); + let is_qualified = <::KeygenQualification as QualifyNode<_>>::is_qualified(account_id); + let is_current_authority = pallet_cf_validator::CurrentAuthorities::::get().contains(account_id); + let is_bidding = pallet_cf_funding::ActiveBidder::::get(account_id); + let bound_redeem_address = pallet_cf_funding::BoundRedeemAddress::::get(account_id); + let reputation_info = pallet_cf_reputation::Reputations::::get(account_id); + let account_info = pallet_cf_flip::Account::::get(account_id); + let restricted_balances = pallet_cf_funding::RestrictedBalances::::get(account_id); RuntimeApiAccountInfoV2 { balance: account_info.total(), bond: account_info.bond(), - last_heartbeat: pallet_cf_reputation::LastHeartbeat::::get(&account_id).unwrap_or(0), + last_heartbeat: pallet_cf_reputation::LastHeartbeat::::get(account_id).unwrap_or(0), online_credits: reputation_info.online_credits, reputation_points: reputation_info.reputation_points, keyholder_epochs: key_holder_epochs, is_current_authority, is_current_backup, is_qualified: is_bidding && is_qualified, - is_online: Reputation::is_qualified(&account_id), + is_online: Reputation::is_qualified(account_id), is_bidding, bound_redeem_address, restricted_balances, diff --git a/state-chain/runtime/src/runtime_apis.rs b/state-chain/runtime/src/runtime_apis.rs index 9da9b759bf..a02a0e7838 100644 --- a/state-chain/runtime/src/runtime_apis.rs +++ b/state-chain/runtime/src/runtime_apis.rs @@ -103,7 +103,8 @@ decl_runtime_apis!( /// Returns the flip supply in the form [total_issuance, offchain_funds] fn cf_flip_supply() -> (u128, u128); fn cf_accounts() -> Vec<(AccountId32, VanityName)>; - fn cf_account_info_v2(account_id: AccountId32) -> RuntimeApiAccountInfoV2; + fn cf_account_flip_balance(account_id: &AccountId32) -> u128; + fn cf_account_info_v2(account_id: &AccountId32) -> RuntimeApiAccountInfoV2; fn cf_penalties() -> Vec<(Offence, RuntimeApiPenalty)>; fn cf_suspensions() -> Vec<(Offence, Vec<(u32, AccountId32)>)>; fn cf_generate_gov_key_call_hash(call: Vec) -> GovCallHash; From 472b8bfda29b597ffc90c2d9e044e6d6c289af00 Mon Sep 17 00:00:00 2001 From: Andrew Dibble Date: Fri, 13 Oct 2023 16:44:43 +0200 Subject: [PATCH 2/2] expect strings --- state-chain/custom-rpc/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/state-chain/custom-rpc/src/lib.rs b/state-chain/custom-rpc/src/lib.rs index 8a85f9c3df..91dc192e9b 100644 --- a/state-chain/custom-rpc/src/lib.rs +++ b/state-chain/custom-rpc/src/lib.rs @@ -948,11 +948,11 @@ mod test { fn test_account_info_serialization() { assert_eq!( serde_json::to_value(RpcAccountInfo::none(0)).unwrap(), - json!({ "role": "none", "flip_balance": 0 }) + json!({ "role": "none", "flip_balance": "0x0" }) ); assert_eq!( serde_json::to_value(RpcAccountInfo::broker(0)).unwrap(), - json!({ "role":"broker", "flip_balance": 0 }) + json!({ "role":"broker", "flip_balance": "0x0" }) ); let lp = RpcAccountInfo::lp( @@ -981,7 +981,7 @@ mod test { serde_json::to_value(lp).unwrap(), json!({ "role": "liquidity_provider", - "flip_balance": 0, + "flip_balance": "0x0", "balances": { "Ethereum": { "Flip": "0x7fffffffffffffffffffffffffffffff",