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

webapp: add liquidity correct call #62

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions contract/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl NearCLP {
from: AccountId,
to: AccountId,
amount: u128,
// gas: Gas,
deposit: u128, // gas: Gas,
) -> Promise {
let gas = env::prepaid_gas();
assert!(gas >= 20 * TGAS, "Not enough gas");
Expand All @@ -62,7 +62,7 @@ impl NearCLP {
to,
amount.into(),
token,
util::NEP21_STORAGE_DEPOSIT,
deposit,
env::prepaid_gas() / 3,
)
}
Expand Down Expand Up @@ -142,7 +142,13 @@ impl NearCLP {
p.reserve -= reserve;
p.ynear += near;

self.schedule_nep21_tx(token, env::current_account_id(), recipient, reserve);
self.schedule_nep21_tx(
token,
env::current_account_id(),
recipient,
reserve,
NEP21_STORAGE_DEPOSIT,
);
// TODO: this updated should be done after nep21 transfer
self.set_pool(token, p);
}
Expand Down Expand Up @@ -209,8 +215,14 @@ impl NearCLP {
p.ynear -= near;

// firstly get tokens from the buyer, then send NEAR to recipient
self.schedule_nep21_tx(token, buyer, env::current_account_id(), reserve)
.then(Promise::new(recipient).transfer(near));
self.schedule_nep21_tx(
token,
buyer,
env::current_account_id(),
reserve,
NEP21_STORAGE_DEPOSIT,
)
.then(Promise::new(recipient).transfer(near));
// TODO - this should be in a promise.
self.set_pool(&token, p);
}
Expand Down Expand Up @@ -278,8 +290,20 @@ impl NearCLP {

let caller = env::current_account_id();
// firstly get tokens from buyer, then send to the recipient
self.schedule_nep21_tx(token1, buyer, caller.clone(), token1_in)
.then(self.schedule_nep21_tx(token2, caller, recipient, token2_out));
self.schedule_nep21_tx(
token1,
buyer,
caller.clone(),
token1_in,
NEP21_STORAGE_DEPOSIT,
)
.then(self.schedule_nep21_tx(
token2,
caller,
recipient,
token2_out,
NEP21_STORAGE_DEPOSIT,
));
// TODO: make updates after nep21 transfers (together with promise2)
self.set_pool(&token1, &p1);
self.set_pool(&token2, &p2);
Expand Down
54 changes: 44 additions & 10 deletions contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,24 @@ impl NearCLP {

/// Increases Near and the Reserve token liquidity.
/// The supplied funds must preserve current ratio of the liquidity pool.
/// `transfer_deposit`: amount of yNEAR attached to the NEP21.transfer_from AND
/// deduced from the attached deposit (hence removed from the new pool supply).
/// Usually, on subsequent add_liquidity calls for the given token, we don't need
/// to attach extra deposit for `transfer_from` calls.
/// Returns amount of LP Shares is minted for the user.
#[payable]
pub fn add_liquidity(&mut self, token: AccountId, max_tokens: U128, min_shares: U128) -> U128 {
pub fn add_liquidity(
&mut self,
token: AccountId,
max_tokens: U128,
min_shares: U128,
transfer_deposit: U128,
) -> U128 {
let mut p = self.must_get_pool(&token);
let caller = env::predecessor_account_id();
let transfer_deposit = u128::from(transfer_deposit);
let shares_minted;
let ynear_amount = env::attached_deposit() - NEP21_STORAGE_DEPOSIT;
let ynear_amount = env::attached_deposit() - transfer_deposit;
let added_reserve;
let max_tokens: Balance = max_tokens.into();
assert!(
Expand Down Expand Up @@ -234,8 +245,14 @@ impl NearCLP {
0,
5 * TGAS,
);
self.schedule_nep21_tx(&token, caller, env::current_account_id(), added_reserve)
.then(callback); //after that, the callback will check success/failure
self.schedule_nep21_tx(
&token,
caller,
env::current_account_id(),
added_reserve,
transfer_deposit,
)
.then(callback); //after that, the callback will check success/failure

// TODO:
// Handling exception is work-in-progress in NEAR runtime
Expand Down Expand Up @@ -303,6 +320,7 @@ impl NearCLP {
env::current_account_id(),
caller.clone(),
token_amount,
NEP21_STORAGE_DEPOSIT,
)
.then(Promise::new(caller).transfer(ynear_amount));

Expand Down Expand Up @@ -877,10 +895,16 @@ mod tests {

let ynear_deposit = 30 * NDENOM;
let token_deposit = 10 * NDENOM;
let ynear_deposit_with_storage = ynear_deposit + NEP21_STORAGE_DEPOSIT;
let ynear_deposit_with_storage = ynear_deposit + 2 * NEP21_STORAGE_DEPOSIT;
let transfer_deposit = U128::from(2 * NEP21_STORAGE_DEPOSIT);
ctx.set_deposit(ynear_deposit_with_storage);

c.add_liquidity(t.clone(), token_deposit.into(), ynear_deposit.into());
c.add_liquidity(
t.clone(),
token_deposit.into(),
ynear_deposit.into(),
transfer_deposit,
);

let mut p = c.pool_info(&t).expect("Pool should exist");
let mut expected_pool = PoolInfo {
Expand Down Expand Up @@ -909,7 +933,12 @@ mod tests {

println!(">> adding liquidity - second time");

c.add_liquidity(t.clone(), (token_deposit * 10).into(), ynear_deposit.into());
c.add_liquidity(
t.clone(),
(token_deposit * 10).into(),
ynear_deposit.into(),
transfer_deposit,
);
p = c.pool_info(&t).expect("Pool should exist");
expected_pool = PoolInfo {
ynear: (ynear_deposit * 2).into(),
Expand All @@ -933,9 +962,9 @@ mod tests {
fn add_liquidity2_happy_path() {
let ynear_deposit = 3 * NDENOM;
let token_deposit = 1 * NDENOM + 1;
let ynear_deposit_with_storage = ynear_deposit + NEP21_STORAGE_DEPOSIT;
let transfer_deposit = U128::from(0);

let (ctx, mut c) = _init(ynear_deposit_with_storage);
let (ctx, mut c) = _init(ynear_deposit);
let t = ctx.accounts.token1.clone();
let a = ctx.accounts.predecessor.clone();

Expand All @@ -950,7 +979,12 @@ mod tests {
};
c.pools.insert(&t, &p);

c.add_liquidity(t.clone(), token_deposit.into(), ynear_deposit.into());
c.add_liquidity(
t.clone(),
token_deposit.into(),
ynear_deposit.into(),
transfer_deposit,
);

let p_info = c.pool_info(&t).expect("Pool should exist");
let expected_pool = PoolInfo {
Expand Down
2 changes: 1 addition & 1 deletion contract/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub const TGAS: Gas = 1_000_000_000_000;
pub const MAX_GAS: Gas = 200 * TGAS;

/// nep21 may require NEAR deposit for storage to create a new balance
pub const NEP21_STORAGE_DEPOSIT: u128 = 4 * NDENOM / 100; //0.04 NEAR
pub const NEP21_STORAGE_DEPOSIT: u128 = 5 * NDENOM / 100; //0.05 NEAR

// TODO: should we make it customizable?
/// Price per 1 byte of storage from mainnet genesis config. 100e18
Expand Down
4 changes: 2 additions & 2 deletions contract/tests/simulation_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,15 @@ fn add_liquidity(

show_nep21_bal(r, &token.account_id, &liquidity_provider.account_id);

//add_liquidity
call(
r,
&liquidity_provider,
&clp,
"add_liquidity",
&json!({"token": token.account_id,
"max_tokens": token_amount.to_string(),
"min_shares": near_amount.to_string()}),
"min_shares": near_amount.to_string(),
"transfer_deposit": NEP21_STORAGE_DEPOSIT.to_string()}),
(near_amount + NEP21_STORAGE_DEPOSIT).into(), //send NEAR
);

Expand Down
22 changes: 10 additions & 12 deletions webapp/src/services/near-nep21-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Contract} from 'near-api-js'
const e22 = '0'.repeat(22);
const maxGas = '300000000000000';
const attach60NearCents = '6' + e22;
const nep21AllowanceFee = '4' + e22;
const nep21AllowanceFee = '5' + e22;
const NDENOM = 1e24;

export async function getBalanceNEP( contractName ) {
Expand Down Expand Up @@ -315,34 +315,32 @@ export async function swapFromOut( tokenIN, tokenOUT ) {
maxGas,
attach60NearCents
);

}
else {
console.error("Error: Token type error");
}
}
}

export async function addLiquiduty( tokenDetails, maxTokenAmount, minSharesAmount ) {
await window.contract.add_liquidity( { token: tokenDetails.address,
max_tokens: maxTokenAmount,
min_shares: minSharesAmount},
maxGas,
attach60NearCents
);
export function addLiquidity( tokenDetails, maxTokenAmount, minSharesAmount, ynear, transferDeposit ) {
return window.contract.add_liquidity( { token: tokenDetails.address,
max_tokens: maxTokenAmount,
min_shares: minSharesAmount,
transfer_deposit: transferDeposit},
maxGas,
ynear);
}

// returns true if pool already exists
export async function createPool( tokenDetails, maxTokenAmount, minSharesAmount ) {
export async function createPool( tokenDetails, tokenAmount, ynearAmount ) {
const info = await window.contract.pool_info( { token: tokenDetails.address} );

if(info !== null) {
// Pool already exists.
return true;
}
await window.contract.create_pool( { token: tokenDetails.address });

await addLiquiduty( tokenDetails.address, maxTokenAmount, minSharesAmount);
await addLiquidity( tokenDetails.address, tokenAmount, ynearAmount, ynearAmount, nep21AllowanceFee);

return false;
}
Expand Down