Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature claim and withdraw #45

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion ref-farming/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ref_farming"
version = "1.0.1"
version = "1.0.2"
marco-sundsk marked this conversation as resolved.
Show resolved Hide resolved
authors = ["Marco Sun <[email protected]>"]
edition = "2018"

Expand Down
101 changes: 81 additions & 20 deletions ref-farming/src/actions_of_reward.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

use std::convert::TryInto;
use std::collections::HashMap;
use near_sdk::json_types::{ValidAccountId, U128};
use near_sdk::{assert_one_yocto, env, near_bindgen, AccountId, Balance, PromiseResult};
use near_sdk::{assert_one_yocto, env, near_bindgen,
AccountId, Balance, Promise, PromiseResult};

use crate::utils::{ext_fungible_token, ext_self, GAS_FOR_FT_TRANSFER, GAS_FOR_RESOLVE_TRANSFER, parse_farm_id};
use crate::errors::*;
Expand Down Expand Up @@ -44,9 +44,30 @@ impl Contract {
self.assert_storage_usage(&sender_id);
}

/// if withdraw_all_tokens is true, withdraw all tokens,
/// or just withdraw the reward token of this farm.
pub fn claim_and_withdraw_by_farm(&mut self, farm_id: FarmId, withdraw_all_tokens: bool) {
let sender_id = env::predecessor_account_id();
self.claim_reward_by_farm(farm_id.clone());
if withdraw_all_tokens {
self.internal_withdraw_all_rewards(&sender_id, None);
} else {
if let Some(farm) = self.data().farms.get(&farm_id) {
let token_id = farm.get_reward_token();
self.internal_withdraw_all_rewards(&sender_id, Some(&token_id));
}
}
}

pub fn claim_and_withdraw_by_seed(&mut self, seed_id: SeedId) {
let sender_id = env::predecessor_account_id();
self.claim_reward_by_seed(seed_id.clone());
self.internal_withdraw_all_rewards(&sender_id, None);
}

/// Withdraws given reward token of given user.
#[payable]
pub fn withdraw_reward(&mut self, token_id: ValidAccountId, amount: Option<U128>) {
pub fn withdraw_reward(&mut self, token_id: ValidAccountId, amount: Option<U128>) -> Promise {
assert_one_yocto();

let token_id: AccountId = token_id.into();
Expand All @@ -59,22 +80,9 @@ impl Contract {
// Note: subtraction, will be reverted if the promise fails.
let amount = farmer.get_ref_mut().sub_reward(&token_id, amount);
self.data_mut().farmers.insert(&sender_id, &farmer);
ext_fungible_token::ft_transfer(
sender_id.clone().try_into().unwrap(),
amount.into(),
None,
&token_id,
1,
GAS_FOR_FT_TRANSFER,
)
.then(ext_self::callback_post_withdraw_reward(
token_id,
sender_id,
amount.into(),
&env::current_account_id(),
0,
GAS_FOR_RESOLVE_TRANSFER,
));

self.internal_send_tokens(&sender_id, &token_id, amount)

}

#[private]
Expand Down Expand Up @@ -153,6 +161,59 @@ fn claim_user_reward_from_farm(
}

impl Contract {

/// if token was given, then just withdraw that token, or withdraw all tokens
pub(crate) fn internal_withdraw_all_rewards(&mut self, farmer_id: &AccountId, token: Option<&AccountId>) {

let view_farmer = self.get_farmer(&farmer_id);
let tokens = {
if let Some(token) = token {
vec![token]
} else {
view_farmer.get_ref().rewards.keys().collect::<Vec<_>>()
}
};

let mut farmer = self.get_farmer(&farmer_id);
marco-sundsk marked this conversation as resolved.
Show resolved Hide resolved
let mut withdraw_tasks = HashMap::<AccountId, u128>::new();
for token_id in tokens {
let amount = farmer.get_ref_mut().sub_reward(&token_id, 0);
withdraw_tasks.insert(token_id.clone(), amount);
}
self.data_mut().farmers.insert(farmer_id, &farmer);

for (token_id, amount) in withdraw_tasks {
marco-sundsk marked this conversation as resolved.
Show resolved Hide resolved
if amount > 0 {
self.internal_send_tokens(farmer_id, &token_id, amount);
}
}
}

/// Sends given amount to given user and if it fails, returns it back to user's balance.
/// Tokens must already be subtracted from internal balance.
pub(crate) fn internal_send_tokens(
&self,
sender_id: &AccountId,
token_id: &AccountId,
amount: Balance,
) -> Promise {
ext_fungible_token::ft_transfer(
sender_id.clone(),
U128(amount),
None,
token_id,
1,
GAS_FOR_FT_TRANSFER,
)
.then(ext_self::callback_post_withdraw_reward(
token_id.clone(),
sender_id.clone(),
U128(amount),
&env::current_account_id(),
0,
GAS_FOR_RESOLVE_TRANSFER,
))
}

pub(crate) fn internal_claim_user_reward_by_seed_id(
&mut self,
Expand Down
2 changes: 1 addition & 1 deletion ref-farming/src/farmer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl Farmer {
pub(crate) fn sub_reward(&mut self, token: &AccountId, amount: Balance) -> Balance {
let value = *self.rewards.get(token).expect(ERR21_TOKEN_NOT_REG);
assert!(value >= amount, "{}", ERR22_NOT_ENOUGH_TOKENS);
if amount == 0 {
if amount == 0 || amount == value {
self.rewards.remove(&token.clone());
marco-sundsk marked this conversation as resolved.
Show resolved Hide resolved
value
} else {
Expand Down
7 changes: 7 additions & 0 deletions ref-farming/tests/common/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use near_sdk_sim::{view, ContractAccount};

use super::utils::to_va;
use ref_farming::{ContractContract as Farming, FarmInfo};
use test_token::ContractContract as TestToken;
use std::collections::HashMap;

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
Expand Down Expand Up @@ -184,6 +185,12 @@ pub(crate) fn show_storage_balance(farming: &ContractAccount<Farming>, farmer: S
ret
}

pub(crate) fn balance_of(token: &ContractAccount<TestToken>, account_id: String) -> u128 {
view!(token.ft_balance_of(to_va(account_id.clone())))
.unwrap_json::<U128>()
.0
}

// ============= Assertions ===============
#[allow(dead_code)]
pub(crate) fn assert_farming(
Expand Down
Loading