From 3bfe9595fab8dc923468c8e3dbfb8d7b67f10eef Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Wed, 26 Jul 2023 18:05:50 -0500 Subject: [PATCH 01/22] Use Part in Incentives::new --- src/incentives.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/incentives.rs b/src/incentives.rs index 2aa01a9a..480b78e1 100644 --- a/src/incentives.rs +++ b/src/incentives.rs @@ -16,7 +16,7 @@ pub struct Incentives { #[orga] pub struct Account { - testnet_participation: Coin, + testnet_participation: Part, } impl Incentives { @@ -47,7 +47,11 @@ impl Incentives { let mut account = Account::default(); let mut maybe_increment = |v| { if v == "true" { - account.testnet_participation.give(funds.take(rate)?)?; + account.testnet_participation = Part { + locked: 0, + claimable: funds.take(rate)?.amount.into(), + claimed: 0, + } } Ok::<_, Error>(()) }; From 774591ec439aaeecf486549bb66d39ba845a08ea Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Wed, 26 Jul 2023 18:06:17 -0500 Subject: [PATCH 02/22] Add claim_testnet_participation_incentives --- src/incentives.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/incentives.rs b/src/incentives.rs index 480b78e1..e066dcdf 100644 --- a/src/incentives.rs +++ b/src/incentives.rs @@ -19,6 +19,7 @@ pub struct Account { testnet_participation: Part, } +#[orga] impl Incentives { pub fn from_csv(data: &[u8], mut funds: Coin) -> Result { let mut accounts = Map::new(); @@ -63,4 +64,32 @@ impl Incentives { Ok(Incentives { accounts }) } + + pub fn signer_acct_mut(&mut self) -> OrgaResult> { + let signer = self + .context::() + .ok_or_else(|| OrgaError::Signer("No Signer context available".into()))? + .signer + .ok_or_else(|| OrgaError::Coins("Unauthorized account action".into()))?; + + self.accounts + .get_mut(signer)? + .ok_or_else(|| OrgaError::Coins("No airdrop account for signer".into())) + } + + fn pay_as_funding(&mut self, amount: u64) -> Result<()> { + let paid = self + .context::() + .ok_or_else(|| OrgaError::Coins("No Paid context found".into()))?; + + Ok(paid.give::(amount)?) + } + + #[call] + pub fn claim_testnet_participation_incentives(&mut self) -> OrgaResult<()> { + let mut acct = self.signer_acct_mut()?; + let amount = acct.testnet_participation.claim()?; + self.pay_as_funding(amount)?; + Ok(()) + } } From bab199978f6aca62c13952c6e14f15ea1faf0a2a Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Wed, 26 Jul 2023 18:06:53 -0500 Subject: [PATCH 03/22] Update imports --- src/incentives.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/incentives.rs b/src/incentives.rs index e066dcdf..9ce370c2 100644 --- a/src/incentives.rs +++ b/src/incentives.rs @@ -1,13 +1,16 @@ -use orga::{ - coins::{Address, Amount, Coin, Give, Take}, - collections::Map, - orga, -}; - +use crate::airdrop::Part; use crate::{ app::Nom, error::{Error, Result}, }; +use orga::{ + coins::{Address, Amount, Coin, Give, Take}, + collections::{ChildMut, Map}, + context::GetContext, + orga, + plugins::{Paid, Signer}, + Error as OrgaError, Result as OrgaResult, +}; #[orga] pub struct Incentives { From 4a2447cee21f372e0d1ee48e407f414d973a2b59 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Wed, 26 Jul 2023 18:07:25 -0500 Subject: [PATCH 04/22] Add MsgClaimTestnetIncentives --- src/app.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/app.rs b/src/app.rs index 61940b1b..91ad3f32 100644 --- a/src/app.rs +++ b/src/app.rs @@ -91,6 +91,7 @@ pub struct InnerApp { upgrade: Upgrade, #[orga(version(V2))] + #[call] pub incentives: Incentives, } @@ -878,6 +879,21 @@ impl ConvertSdkTx for InnerApp { Ok(PaidCall { payer, paid }) } + "nomic/MsgClaimTestnetIncentives" => { + let msg = msg + .value + .as_object() + .ok_or_else(|| Error::App("Invalid message value".to_string()))?; + if !msg.is_empty() { + return Err(Error::App("Message should be empty".to_string())); + } + let payer = + build_call!(self.incentives.claim_testnet_participation_incentives()); + let paid = build_call!(self.accounts.give_from_funding_all()); + + Ok(PaidCall { payer, paid }) + } + "nomic/MsgSetRecoveryAddress" => { let msg = msg .value From 49c99ba2dc38c92d02f19451d9b0da4b5773e307 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Thu, 27 Jul 2023 17:03:28 -0500 Subject: [PATCH 05/22] Rename call to MsgClaimTestnetParticipationIncentives --- src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.rs b/src/app.rs index 91ad3f32..80863691 100644 --- a/src/app.rs +++ b/src/app.rs @@ -879,7 +879,7 @@ impl ConvertSdkTx for InnerApp { Ok(PaidCall { payer, paid }) } - "nomic/MsgClaimTestnetIncentives" => { + "nomic/MsgClaimTestnetParticipationIncentives" => { let msg = msg .value .as_object() From 874000ee4e0e37b49237c27c52d8d45f2af16b79 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Thu, 27 Jul 2023 17:05:14 -0500 Subject: [PATCH 06/22] Add claim_testnet_participation_incentive to wasm --- wasm/src/lib.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index 66ab8299..d6069298 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -257,6 +257,22 @@ pub async fn claim_testnet_participation_airdrop(address: String) -> Result Result { + let address = address + .parse() + .map_err(|e| Error::Wasm(format!("{:?}", e)))?; + gen_call_bytes( + address, + sdk::Msg { + type_: "nomic/MsgClaimTestnetParticipationIncentives".to_string(), + value: serde_json::Map::new().into(), + }, + ) + .await +} + #[wasm_bindgen(js_name = claimIncomingIbcBtc)] pub async fn claim_incoming_ibc_btc(address: String) -> Result { let address = address @@ -643,6 +659,7 @@ async fn gen_call_bytes(address: String, msg: sdk::Msg) -> Result Date: Thu, 27 Jul 2023 17:09:54 -0500 Subject: [PATCH 07/22] Remove unused import --- src/incentives.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/incentives.rs b/src/incentives.rs index 9ce370c2..7d614f72 100644 --- a/src/incentives.rs +++ b/src/incentives.rs @@ -4,7 +4,7 @@ use crate::{ error::{Error, Result}, }; use orga::{ - coins::{Address, Amount, Coin, Give, Take}, + coins::{Address, Amount, Coin, Take}, collections::{ChildMut, Map}, context::GetContext, orga, From dfb92ac365042d217a791f1e11baf01a7899f998 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Thu, 27 Jul 2023 17:15:02 -0500 Subject: [PATCH 08/22] Rename MsgJoinAirdropAccounts --- src/app.rs | 2 +- wasm/src/lib.rs | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/app.rs b/src/app.rs index 80863691..c99d1790 100644 --- a/src/app.rs +++ b/src/app.rs @@ -861,7 +861,7 @@ impl ConvertSdkTx for InnerApp { Ok(PaidCall { payer, paid }) } - "nomic/MsgJoinAirdropAccounts" => { + "nomic/MsgJoinRewardAccounts" => { let msg = msg .value .as_object() diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index d6069298..e359f5f4 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(async_closure)] +#![e(async_closure)] #![feature(async_fn_in_trait)] mod error; mod types; @@ -594,8 +594,8 @@ pub async fn withdraw(address: String, dest_addr: String, amount: u64) -> Result .await } -#[wasm_bindgen(js_name = joinAirdropAccounts)] -pub async fn join_airdrop_accounts( +#[wasm_bindgen(js_name = joinRewardAccounts)] +pub async fn join_reward_accounts( source_address: String, destination_address: String, ) -> Result { @@ -612,7 +612,7 @@ pub async fn join_airdrop_accounts( gen_call_bytes( address.to_string(), sdk::Msg { - type_: "nomic/MsgJoinAirdropAccounts".to_string(), + type_: "nomic/MsgJoinRewardAccounts".to_string(), value: value.into(), }, ) @@ -659,7 +659,6 @@ async fn gen_call_bytes(address: String, msg: sdk::Msg) -> Result Date: Thu, 27 Jul 2023 17:29:56 -0500 Subject: [PATCH 09/22] Add Incentives::join_accounts --- src/incentives.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/incentives.rs b/src/incentives.rs index 7d614f72..151fe44b 100644 --- a/src/incentives.rs +++ b/src/incentives.rs @@ -18,10 +18,17 @@ pub struct Incentives { } #[orga] +#[derive(Clone, PartialEq, Eq)] pub struct Account { testnet_participation: Part, } +impl Account { + pub fn is_empty(&self) -> bool { + self == &Self::default() + } +} + #[orga] impl Incentives { pub fn from_csv(data: &[u8], mut funds: Coin) -> Result { @@ -95,4 +102,30 @@ impl Incentives { self.pay_as_funding(amount)?; Ok(()) } + + pub fn join_accounts(&mut self, dest_addr: Address) -> OrgaResult<()> { + let mut acct = self.signer_acct_mut()?; + if acct.is_empty() { + return Err(OrgaError::App("Account has no airdrop balance".to_string())); + } + + let src = acct.clone(); + *acct = Account::default(); + + let mut dest = self.accounts.entry(dest_addr)?.or_default()?; + + let add_part = |dest: &mut Part, src: Part| { + if dest.claimable > 0 || dest.claimed > 0 { + dest.claimable += src.locked; + } else { + dest.locked += src.locked; + } + dest.claimable += src.claimable; + dest.claimed += src.claimed; + }; + + add_part(&mut dest.testnet_participation, src.testnet_participation); + + Ok(()) + } } From 42b5e19f760cf3954feefd219c02eba8257bace4 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Thu, 27 Jul 2023 17:30:25 -0500 Subject: [PATCH 10/22] Remove fee from join_accounts --- src/airdrop.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/airdrop.rs b/src/airdrop.rs index 9baaadb0..ff3323f7 100644 --- a/src/airdrop.rs +++ b/src/airdrop.rs @@ -118,10 +118,7 @@ impl Airdrop { Ok(()) } - #[call] pub fn join_accounts(&mut self, dest_addr: Address) -> Result<()> { - self.pay_as_funding(MIN_FEE)?; - let mut acct = self.signer_acct_mut()?; if acct.is_empty() { return Err(Error::App("Account has no airdrop balance".to_string())); From 80b71ee51768eb1589038b0c5045ba194034b94f Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Thu, 27 Jul 2023 17:32:56 -0500 Subject: [PATCH 11/22] Join airdrop and incentives in JoinRewardAccounts --- src/app.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/app.rs b/src/app.rs index c99d1790..b3795683 100644 --- a/src/app.rs +++ b/src/app.rs @@ -33,7 +33,7 @@ use orga::macros::build_call; use orga::migrate::Migrate; use orga::orga; use orga::plugins::sdk_compat::{sdk, sdk::Tx as SdkTx, ConvertSdkTx}; -use orga::plugins::{DefaultPlugins, PaidCall, Signer, Time, MIN_FEE}; +use orga::plugins::{DefaultPlugins, Paid, PaidCall, Signer, Time, MIN_FEE}; use orga::prelude::*; use orga::upgrade::Version; use orga::upgrade::{Upgrade, UpgradeV0}; @@ -295,6 +295,20 @@ impl InnerApp { Ok(self.bitcoin.withdraw(script_pubkey, amount)?) } + #[call] + fn join_accounts(&mut self, dest_addr: Address) -> Result<()> { + let paid = self + .context::() + .ok_or_else(|| Error::Coins("No Paid context found".into()))?; + + paid.give::(MIN_FEE)?; + + self.airdrop.join_accounts(dest_addr)?; + self.incentives.join_accounts(dest_addr)?; + + Ok(()) + } + fn signer(&mut self) -> Result
{ self.context::() .ok_or_else(|| Error::Signer("No Signer context available".into()))? @@ -873,7 +887,7 @@ impl ConvertSdkTx for InnerApp { .parse() .map_err(|_| Error::App("Invalid destination address".to_string()))?; - let payer = build_call!(self.airdrop.join_accounts(dest_addr)); + let payer = build_call!(self.join_accounts(dest_addr)); let paid = build_call!(self.app_noop()); Ok(PaidCall { payer, paid }) From fdf7d0942dd87187aea17f353c65afc0aab3d1f3 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 14:39:30 -0500 Subject: [PATCH 12/22] Add get query for incentives --- src/incentives.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/incentives.rs b/src/incentives.rs index 151fe44b..07b6981b 100644 --- a/src/incentives.rs +++ b/src/incentives.rs @@ -75,6 +75,11 @@ impl Incentives { Ok(Incentives { accounts }) } + #[query] + pub fn get(&self, address: Address) -> Result> { + Ok(self.accounts.get(address)?.map(|a| a.clone())) + } + pub fn signer_acct_mut(&mut self) -> OrgaResult> { let signer = self .context::() From 3fa54ef324b69ba9b6ae8154c6900bdebfe0ce6e Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 14:40:02 -0500 Subject: [PATCH 13/22] Update incentive control flow --- src/incentives.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/incentives.rs b/src/incentives.rs index 07b6981b..7417fe61 100644 --- a/src/incentives.rs +++ b/src/incentives.rs @@ -89,7 +89,7 @@ impl Incentives { self.accounts .get_mut(signer)? - .ok_or_else(|| OrgaError::Coins("No airdrop account for signer".into())) + .ok_or_else(|| OrgaError::App("No airdrop account for signer".into())) } fn pay_as_funding(&mut self, amount: u64) -> Result<()> { @@ -108,10 +108,15 @@ impl Incentives { Ok(()) } - pub fn join_accounts(&mut self, dest_addr: Address) -> OrgaResult<()> { - let mut acct = self.signer_acct_mut()?; + pub fn join_accounts(&mut self, dest_addr: Address) -> OrgaResult { + let mut acct = match self.signer_acct_mut() { + Ok(acct) => acct, + Err(OrgaError::App(_)) => return Ok(0), + Err(e) => return Err(e), + }; + if acct.is_empty() { - return Err(OrgaError::App("Account has no airdrop balance".to_string())); + return Ok(0); } let src = acct.clone(); @@ -127,10 +132,13 @@ impl Incentives { } dest.claimable += src.claimable; dest.claimed += src.claimed; + + src.total() }; - add_part(&mut dest.testnet_participation, src.testnet_participation); + let testnet_participation = + add_part(&mut dest.testnet_participation, src.testnet_participation); - Ok(()) + Ok(testnet_participation) } } From 3bb143877385e92a7c41cec5b24b84370e280722 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 14:41:25 -0500 Subject: [PATCH 14/22] Update airdrop join_accounts control flow --- src/airdrop.rs | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/airdrop.rs b/src/airdrop.rs index ff3323f7..4ea10268 100644 --- a/src/airdrop.rs +++ b/src/airdrop.rs @@ -64,7 +64,7 @@ impl Airdrop { self.accounts .get_mut(signer)? - .ok_or_else(|| Error::Coins("No airdrop account for signer".into())) + .ok_or_else(|| Error::App("No airdrop account for signer".into())) } fn pay_as_funding(&mut self, amount: u64) -> Result<()> { @@ -107,21 +107,15 @@ impl Airdrop { Ok(()) } - #[call] - pub fn claim_testnet_participation(&mut self) -> Result<()> { - #[cfg(not(feature = "testnet"))] - { - let mut acct = self.signer_acct_mut()?; - let amount = acct.testnet_participation.claim()?; - self.pay_as_funding(amount)?; - } - Ok(()) - } + pub fn join_accounts(&mut self, dest_addr: Address) -> Result { + let mut acct = match self.signer_acct_mut() { + Ok(acct) => acct, + Err(Error::App(_)) => return Ok(0), + Err(e) => return Err(e), + }; - pub fn join_accounts(&mut self, dest_addr: Address) -> Result<()> { - let mut acct = self.signer_acct_mut()?; if acct.is_empty() { - return Err(Error::App("Account has no airdrop balance".to_string())); + return Ok(0); } let src = acct.clone(); @@ -137,17 +131,16 @@ impl Airdrop { } dest.claimable += src.claimable; dest.claimed += src.claimed; - }; - add_part(&mut dest.airdrop1, src.airdrop1); - add_part(&mut dest.btc_deposit, src.btc_deposit); - add_part(&mut dest.ibc_transfer, src.ibc_transfer); - add_part(&mut dest.btc_withdraw, src.btc_withdraw); + src.total() + }; - #[cfg(not(feature = "testnet"))] - add_part(&mut dest.testnet_participation, src.testnet_participation); + let airdrop_1 = add_part(&mut dest.airdrop1, src.airdrop1); + let btc_deposit = add_part(&mut dest.btc_deposit, src.btc_deposit); + let ibc_transfer = add_part(&mut dest.ibc_transfer, src.ibc_transfer); + let btc_withdraw = add_part(&mut dest.btc_withdraw, src.btc_withdraw); - Ok(()) + Ok(airdrop_1 + btc_deposit + ibc_transfer + btc_withdraw) } #[cfg(feature = "full")] From 90bf50cac09f99a14ebdb4109a868a45d6361cc9 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 14:42:08 -0500 Subject: [PATCH 15/22] Add incentive_balances to wasm --- wasm/src/lib.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index e359f5f4..027a8a40 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -424,6 +424,22 @@ pub async fn airdrop_balances(addr: String) -> Result { } } +#[wasm_bindgen(js_name = incentiveBalances)] +pub async fn incentive_balances(addr: String) -> Result { + let address = addr.parse().map_err(|e| Error::Wasm(format!("{:?}", e)))?; + + if let Some(account) = app_client() + .query(|app| Ok(app.incentives.get(address)?)) + .await? + { + Ok(Incentives { + testnet_participation: parse_part(account.testnet_participation), + }) + } else { + Ok(Incentives::default()) + } +} + #[wasm_bindgen] pub async fn nonce(addr: String) -> Result { let address = addr.parse().map_err(|e| Error::Wasm(format!("{:?}", e)))?; From 042f3b3f06565b8172d9f9f1912fcdc16137c3e0 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 14:42:49 -0500 Subject: [PATCH 16/22] Update types for incentives --- wasm/src/lib.rs | 6 ++--- wasm/src/types.rs | 62 ++++++++++++++++------------------------------- 2 files changed, 24 insertions(+), 44 deletions(-) diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index 027a8a40..314ab1d1 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -1,4 +1,4 @@ -#![e(async_closure)] +#![feature(async_closure)] #![feature(async_fn_in_trait)] mod error; mod types; @@ -399,8 +399,8 @@ pub async fn redelegate( .await } -fn parse_part(part: nomic::airdrop::Part) -> AirdropDetails { - AirdropDetails { +fn parse_part(part: nomic::airdrop::Part) -> RewardDetails { + RewardDetails { locked: part.locked, claimed: part.claimed, claimable: part.claimable, diff --git a/wasm/src/types.rs b/wasm/src/types.rs index 3ccf2c9b..84b6a90c 100644 --- a/wasm/src/types.rs +++ b/wasm/src/types.rs @@ -43,78 +43,58 @@ pub struct Coin { #[derive(Clone, Default)] #[wasm_bindgen] -pub struct AirdropDetails { +pub struct RewardDetails { pub locked: u64, pub claimed: u64, pub claimable: u64, pub amount: u64, } -#[cfg(feature = "testnet")] #[derive(Clone, Default)] #[wasm_bindgen(getter_with_clone)] pub struct Airdrop { - pub airdrop1: AirdropDetails, + pub airdrop1: RewardDetails, #[wasm_bindgen(js_name = btcDeposit)] - pub btc_deposit: AirdropDetails, + pub btc_deposit: RewardDetails, #[wasm_bindgen(js_name = btcWithdraw)] - pub btc_withdraw: AirdropDetails, + pub btc_withdraw: RewardDetails, #[wasm_bindgen(js_name = ibcTransfer)] - pub ibc_transfer: AirdropDetails, - // #[wasm_bindgen(js_name = testnetParticipation)] - // pub testnet_participation: AirdropDetails, -} - -#[cfg(not(feature = "testnet"))] -#[derive(Clone, Default)] -#[wasm_bindgen(getter_with_clone)] -pub struct Airdrop { - pub airdrop1: AirdropDetails, - #[wasm_bindgen(js_name = btcDeposit)] - pub btc_deposit: AirdropDetails, - #[wasm_bindgen(js_name = btcWithdraw)] - pub btc_withdraw: AirdropDetails, - #[wasm_bindgen(js_name = ibcTransfer)] - pub ibc_transfer: AirdropDetails, + pub ibc_transfer: RewardDetails, } #[wasm_bindgen] impl Airdrop { - #[cfg(feature = "testnet")] - #[wasm_bindgen(js_name = airdropTotal)] - pub fn airdrop_total(&self) -> u64 { - self.airdrop1.amount - + self.btc_deposit.amount - + self.btc_withdraw.amount - + self.ibc_transfer.amount - // + self.testnet_participation.amount - } - - #[cfg(not(feature = "testnet"))] - #[wasm_bindgen(js_name = airdropTotal)] - pub fn airdrop_total(&self) -> u64 { + pub fn total(&self) -> u64 { self.airdrop1.amount + self.btc_deposit.amount + self.btc_withdraw.amount + self.ibc_transfer.amount } - #[cfg(feature = "testnet")] #[wasm_bindgen(js_name = claimedTotal)] pub fn claimed_total(&self) -> u64 { self.airdrop1.claimed + self.btc_deposit.claimed + self.btc_withdraw.claimed + self.ibc_transfer.claimed - // + self.testnet_participation.claimed + } +} + +#[derive(Clone, Default)] +#[wasm_bindgen(getter_with_clone)] +pub struct Incentives { + #[wasm_bindgen(js_name = testnetParticipation)] + pub testnet_participation: RewardDetails, +} + +#[wasm_bindgen] +impl Incentives { + pub fn total(&self) -> u64 { + self.testnet_participation.amount } - #[cfg(not(feature = "testnet"))] #[wasm_bindgen(js_name = claimedTotal)] pub fn claimed_total(&self) -> u64 { - self.airdrop1.claimed - + self.btc_deposit.claimed - + self.btc_withdraw.claimed - + self.ibc_transfer.claimed + self.testnet_participation.claimed } } From 913e65aaa9f606de7c8fc222c59a381a8b8caab5 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 15:02:49 -0500 Subject: [PATCH 17/22] Fix clippy warnings --- src/airdrop.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/airdrop.rs b/src/airdrop.rs index 4ea10268..fe01dae7 100644 --- a/src/airdrop.rs +++ b/src/airdrop.rs @@ -1,10 +1,10 @@ -use orga::coins::Decimal; -use orga::coins::{Address, Amount}; +use orga::coins::Address; +#[cfg(feature = "full")] +use orga::coins::{Amount, Decimal}; use orga::collections::{ChildMut, Map}; use orga::context::GetContext; use orga::migrate::MigrateFrom; use orga::orga; -use orga::plugins::MIN_FEE; use orga::plugins::{Paid, Signer}; use orga::{Error, Result}; #[cfg(feature = "full")] From 942f370299e757a1fcc989ae38cd5899533c3a06 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 16:29:33 -0500 Subject: [PATCH 18/22] Force join_accounts to fail when account isn't present --- src/airdrop.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/airdrop.rs b/src/airdrop.rs index fe01dae7..c0d7d152 100644 --- a/src/airdrop.rs +++ b/src/airdrop.rs @@ -107,15 +107,14 @@ impl Airdrop { Ok(()) } - pub fn join_accounts(&mut self, dest_addr: Address) -> Result { - let mut acct = match self.signer_acct_mut() { - Ok(acct) => acct, - Err(Error::App(_)) => return Ok(0), - Err(e) => return Err(e), - }; + pub fn join_accounts(&mut self, dest_addr: Address) -> Result<()> { + let mut acct = self.signer_acct_mut()?; + if acct.joined { + return Err(Error::App("Account already joined".to_string())); + } if acct.is_empty() { - return Ok(0); + return Err(Error::App("Account has no airdrop balance".to_string())); } let src = acct.clone(); @@ -131,16 +130,14 @@ impl Airdrop { } dest.claimable += src.claimable; dest.claimed += src.claimed; - - src.total() }; - let airdrop_1 = add_part(&mut dest.airdrop1, src.airdrop1); - let btc_deposit = add_part(&mut dest.btc_deposit, src.btc_deposit); - let ibc_transfer = add_part(&mut dest.ibc_transfer, src.ibc_transfer); - let btc_withdraw = add_part(&mut dest.btc_withdraw, src.btc_withdraw); + add_part(&mut dest.airdrop1, src.airdrop1); + add_part(&mut dest.btc_deposit, src.btc_deposit); + add_part(&mut dest.ibc_transfer, src.ibc_transfer); + add_part(&mut dest.btc_withdraw, src.btc_withdraw); - Ok(airdrop_1 + btc_deposit + ibc_transfer + btc_withdraw) + Ok(()) } #[cfg(feature = "full")] From 46ae5db52f41e1e83d96590efd6a30cb72a434b5 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 16:30:25 -0500 Subject: [PATCH 19/22] Ensure joined funds can't be transfered --- src/airdrop.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/airdrop.rs b/src/airdrop.rs index c0d7d152..5d5c6c16 100644 --- a/src/airdrop.rs +++ b/src/airdrop.rs @@ -137,6 +137,8 @@ impl Airdrop { add_part(&mut dest.ibc_transfer, src.ibc_transfer); add_part(&mut dest.btc_withdraw, src.btc_withdraw); + dest.joined = true; + Ok(()) } @@ -367,6 +369,7 @@ pub struct Account { pub btc_deposit: Part, pub btc_withdraw: Part, pub ibc_transfer: Part, + pub joined: bool, } impl Account { From f2c85e6ae823a57a94fa49f41b323886e9d4f9dd Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 16:31:07 -0500 Subject: [PATCH 20/22] Use disable_fee in join_accounts --- src/app.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/app.rs b/src/app.rs index 5ff22e7f..7f459cae 100644 --- a/src/app.rs +++ b/src/app.rs @@ -33,7 +33,7 @@ use orga::macros::build_call; use orga::migrate::Migrate; use orga::orga; use orga::plugins::sdk_compat::{sdk, sdk::Tx as SdkTx, ConvertSdkTx}; -use orga::plugins::{DefaultPlugins, Paid, PaidCall, Signer, Time, MIN_FEE}; +use orga::plugins::{disable_fee, DefaultPlugins, Paid, PaidCall, Signer, Time, MIN_FEE}; use orga::prelude::*; use orga::upgrade::Version; use orga::upgrade::{Upgrade, UpgradeV0}; @@ -296,11 +296,7 @@ impl InnerApp { #[call] fn join_accounts(&mut self, dest_addr: Address) -> Result<()> { - let paid = self - .context::() - .ok_or_else(|| Error::Coins("No Paid context found".into()))?; - - paid.give::(MIN_FEE)?; + disable_fee(); self.airdrop.join_accounts(dest_addr)?; self.incentives.join_accounts(dest_addr)?; From 6e142b7789f2d07c4e0138be829e707849a7088c Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 16:31:26 -0500 Subject: [PATCH 21/22] Remove airdrop wording from incentives --- src/incentives.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/incentives.rs b/src/incentives.rs index 576391dc..b5a83017 100644 --- a/src/incentives.rs +++ b/src/incentives.rs @@ -114,7 +114,7 @@ impl Incentives { self.accounts .get_mut(signer)? - .ok_or_else(|| OrgaError::App("No airdrop account for signer".into())) + .ok_or_else(|| OrgaError::App("No incentive account for signer".into())) } fn pay_as_funding(&mut self, amount: u64) -> Result<()> { From 7d92a62d31fd5b4790d12d65932695433b124523 Mon Sep 17 00:00:00 2001 From: Charlie Little Date: Mon, 31 Jul 2023 16:55:04 -0500 Subject: [PATCH 22/22] Fold task based airdrop to airdrop2 --- src/airdrop.rs | 74 +++++++++++++++++++++++++++--------------------- src/app.rs | 56 ------------------------------------ src/bin/nomic.rs | 37 ++---------------------- wasm/src/lib.rs | 40 ++++---------------------- 4 files changed, 50 insertions(+), 157 deletions(-) diff --git a/src/airdrop.rs b/src/airdrop.rs index 5d5c6c16..5f21269b 100644 --- a/src/airdrop.rs +++ b/src/airdrop.rs @@ -84,25 +84,9 @@ impl Airdrop { } #[call] - pub fn claim_btc_deposit(&mut self) -> Result<()> { + pub fn claim_airdrop2(&mut self) -> Result<()> { let mut acct = self.signer_acct_mut()?; - let amount = acct.btc_deposit.claim()?; - self.pay_as_funding(amount)?; - Ok(()) - } - - #[call] - pub fn claim_btc_withdraw(&mut self) -> Result<()> { - let mut acct = self.signer_acct_mut()?; - let amount = acct.btc_withdraw.claim()?; - self.pay_as_funding(amount)?; - Ok(()) - } - - #[call] - pub fn claim_ibc_transfer(&mut self) -> Result<()> { - let mut acct = self.signer_acct_mut()?; - let amount = acct.ibc_transfer.claim()?; + let amount = acct.airdrop2.claim()?; self.pay_as_funding(amount)?; Ok(()) } @@ -133,9 +117,7 @@ impl Airdrop { }; add_part(&mut dest.airdrop1, src.airdrop1); - add_part(&mut dest.btc_deposit, src.btc_deposit); - add_part(&mut dest.ibc_transfer, src.ibc_transfer); - add_part(&mut dest.btc_withdraw, src.btc_withdraw); + add_part(&mut dest.airdrop2, src.airdrop2); dest.joined = true; @@ -222,18 +204,14 @@ impl Airdrop { #[cfg(feature = "testnet")] { - acct.btc_deposit.locked = unom / 3; - acct.btc_withdraw.locked = unom / 3; - acct.ibc_transfer.locked = unom / 3; + acct.airdrop2.claimable = unom; Ok((0, 0)) } #[cfg(not(feature = "testnet"))] { - acct.btc_deposit.locked = unom / 4; - acct.btc_withdraw.locked = unom / 4; - acct.ibc_transfer.locked = unom / 4; + acct.airdrop2.claimable = unom; assert!(testnet_completions <= 3); acct.testnet_participation.locked = unom / 12 * (3 - testnet_completions); acct.testnet_participation.claimable = unom / 12 * testnet_completions; @@ -343,7 +321,7 @@ impl Airdrop { // } #[cfg(not(feature = "testnet"))] -#[orga(version = 1)] +#[orga(version = 2)] #[derive(Clone, Debug, PartialEq, Eq)] pub struct Account { #[orga(version(V0))] @@ -359,16 +337,29 @@ pub struct Account { pub ibc_transfer: Part, #[orga(version(V1))] pub testnet_participation: Part, + + #[orga(version(V2))] + pub airdrop2: Part, + #[orga(version(V2))] + pub joined: bool, } #[cfg(feature = "testnet")] -#[orga(version = 1)] +#[orga(version = 2)] #[derive(Clone, Debug, PartialEq, Eq)] pub struct Account { pub airdrop1: Part, + + #[orga(version(V0, V1))] pub btc_deposit: Part, + #[orga(version(V0, V1))] pub btc_withdraw: Part, + #[orga(version(V0, V1))] pub ibc_transfer: Part, + + #[orga(version(V2))] + pub airdrop2: Part, + #[orga(version(V2))] pub joined: bool, } @@ -400,6 +391,27 @@ impl MigrateFrom for AccountV1 { } } +impl MigrateFrom for AccountV2 { + fn migrate_from(value: AccountV1) -> Result { + let add_part = |dest: &mut Part, src: Part| { + dest.claimable += src.claimable + src.locked; + dest.claimed += src.claimed; + }; + + let mut airdrop2 = Part::default(); + + add_part(&mut airdrop2, value.btc_deposit); + add_part(&mut airdrop2, value.btc_withdraw); + add_part(&mut airdrop2, value.ibc_transfer); + + Ok(Self { + airdrop1: value.airdrop1, + airdrop2, + joined: false, + }) + } +} + #[orga] #[derive(Clone, Debug, PartialEq, Eq)] pub struct Part { @@ -467,9 +479,7 @@ nomic100000aeu2lh0jrrnmn2npc88typ25u7t3aa64x,1,1,1,1,1,1,1,1,1,1,true,true,true" .get_mut(Address::from_str("nomic100000aeu2lh0jrrnmn2npc88typ25u7t3aa64x").unwrap()) .unwrap() .unwrap(); - let airdrop2_total = account.btc_deposit.total() - + account.btc_withdraw.total() - + account.ibc_transfer.total(); + let airdrop2_total = account.airdrop2.total(); assert_approx_eq(airdrop2_total, AIRDROP_II_TOTAL); } diff --git a/src/app.rs b/src/app.rs index 7f459cae..7ece9fdc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -159,9 +159,6 @@ impl InnerApp { let signer = self.signer()?; let mut coins = self.bitcoin.accounts.withdraw(signer, amount)?; - if let Some(mut acct) = self.airdrop.get_mut(signer)? { - acct.ibc_transfer.unlock(); - } let fee = ibc_fee(amount)?; let fee = coins.take(fee)?; @@ -233,9 +230,6 @@ impl InnerApp { )?; match dest { DepositCommitment::Address(addr) => { - if let Some(mut acct) = self.airdrop.get_mut(addr)? { - acct.btc_deposit.unlock(); - } self.bitcoin.accounts.deposit(addr, nbtc.into())? } DepositCommitment::Ibc(dest) => { @@ -286,11 +280,6 @@ impl InnerApp { script_pubkey: Adapter, amount: Amount, ) -> Result<()> { - let signer = self.signer()?; - if let Some(mut acct) = self.airdrop.get_mut(signer)? { - acct.btc_withdraw.unlock(); - } - Ok(self.bitcoin.withdraw(script_pubkey, amount)?) } @@ -705,51 +694,6 @@ impl ConvertSdkTx for InnerApp { Ok(PaidCall { payer, paid }) } - "nomic/MsgClaimBtcDepositAirdrop" => { - let msg = msg - .value - .as_object() - .ok_or_else(|| Error::App("Invalid message value".to_string()))?; - if !msg.is_empty() { - return Err(Error::App("Message should be empty".to_string())); - } - - let payer = build_call!(self.airdrop.claim_btc_deposit()); - let paid = build_call!(self.accounts.give_from_funding_all()); - - Ok(PaidCall { payer, paid }) - } - - "nomic/MsgClaimBtcWithdrawAirdrop" => { - let msg = msg - .value - .as_object() - .ok_or_else(|| Error::App("Invalid message value".to_string()))?; - if !msg.is_empty() { - return Err(Error::App("Message should be empty".to_string())); - } - - let payer = build_call!(self.airdrop.claim_btc_withdraw()); - let paid = build_call!(self.accounts.give_from_funding_all()); - - Ok(PaidCall { payer, paid }) - } - - "nomic/MsgClaimIbcTransferAirdrop" => { - let msg = msg - .value - .as_object() - .ok_or_else(|| Error::App("Invalid message value".to_string()))?; - if !msg.is_empty() { - return Err(Error::App("Message should be empty".to_string())); - } - - let payer = build_call!(self.airdrop.claim_ibc_transfer()); - let paid = build_call!(self.accounts.give_from_funding_all()); - - Ok(PaidCall { payer, paid }) - } - #[cfg(feature = "stakenet")] "nomic/MsgClaimTestnetParticipationAirdrop" => { let msg = msg diff --git a/src/bin/nomic.rs b/src/bin/nomic.rs index 114fdc75..8be19164 100644 --- a/src/bin/nomic.rs +++ b/src/bin/nomic.rs @@ -996,45 +996,14 @@ impl ClaimAirdropCmd { claimed = true; } - if acct.btc_deposit.claimable > 0 { + if acct.airdrop2.claimable > 0 { app_client() .call( - |app| build_call!(app.airdrop.claim_btc_deposit()), + |app| build_call!(app.airdrop.claim_airdrop2()), |app| build_call!(app.accounts.give_from_funding_all()), ) .await?; - println!( - "Claimed BTC deposit airdrop ({} uNOM)", - acct.btc_deposit.claimable - ); - claimed = true; - } - - if acct.btc_withdraw.claimable > 0 { - app_client() - .call( - |app| build_call!(app.airdrop.claim_btc_withdraw()), - |app| build_call!(app.accounts.give_from_funding_all()), - ) - .await?; - println!( - "Claimed BTC withdraw airdrop ({} uNOM)", - acct.btc_withdraw.claimable - ); - claimed = true; - } - - if acct.ibc_transfer.claimable > 0 { - app_client() - .call( - |app| build_call!(app.airdrop.claim_ibc_transfer()), - |app| build_call!(app.accounts.give_from_funding_all()), - ) - .await?; - println!( - "Claimed IBC transfer airdrop ({} uNOM)", - acct.ibc_transfer.claimable - ); + println!("Claimed airdrop 2 ({} uNOM)", acct.airdrop2.claimable); claimed = true; } diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index 83625031..8641aadb 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -183,8 +183,8 @@ pub async fn claim(address: String) -> Result { .await } -#[wasm_bindgen(js_name = claimAirdrop)] -pub async fn claim_airdrop(address: String) -> Result { +#[wasm_bindgen(js_name = claimAirdrop1)] +pub async fn claim_airdrop1(address: String) -> Result { let address = address .parse() .map_err(|e| Error::Wasm(format!("{:?}", e)))?; @@ -198,45 +198,15 @@ pub async fn claim_airdrop(address: String) -> Result { .await } -#[wasm_bindgen(js_name = claimBtcDepositAirdrop)] -pub async fn claim_btc_deposit_airdrop(address: String) -> Result { +#[wasm_bindgen(js_name = claimAirdrop2)] +pub async fn claim_airdrop2(address: String) -> Result { let address = address .parse() .map_err(|e| Error::Wasm(format!("{:?}", e)))?; gen_call_bytes( address, sdk::Msg { - type_: "nomic/MsgClaimBtcDepositAirdrop".to_string(), - value: serde_json::Map::new().into(), - }, - ) - .await -} - -#[wasm_bindgen(js_name = claimBtcWithdrawAirdrop)] -pub async fn claim_btc_withdraw_airdrop(address: String) -> Result { - let address = address - .parse() - .map_err(|e| Error::Wasm(format!("{:?}", e)))?; - gen_call_bytes( - address, - sdk::Msg { - type_: "nomic/MsgClaimBtcWithdrawAirdrop".to_string(), - value: serde_json::Map::new().into(), - }, - ) - .await -} - -#[wasm_bindgen(js_name = claimIbcTransferAirdrop)] -pub async fn claim_ibc_transfer_airdrop(address: String) -> Result { - let address = address - .parse() - .map_err(|e| Error::Wasm(format!("{:?}", e)))?; - gen_call_bytes( - address, - sdk::Msg { - type_: "nomic/MsgClaimIbcTransferAirdrop".to_string(), + type_: "nomic/MsgClaimAirdrop2".to_string(), value: serde_json::Map::new().into(), }, )