diff --git a/ci/script.sh b/ci/script.sh index bb7ea90cada23b..ff1b2ed44546d0 100755 --- a/ci/script.sh +++ b/ci/script.sh @@ -85,7 +85,8 @@ js_token_swap() { # TODO: Restore flow # time npm run flow || exit $? - # TODO reenable once all issues are fixed + # TODO re-enable after investigating CI issues + # https://github.com/solana-labs/solana-program-library/pull/408 # npm run cluster:localnet || exit $? # npm run localnet:down # npm run localnet:update || exit $? diff --git a/token-swap/js/cli/token-swap-test.js b/token-swap/js/cli/token-swap-test.js index 90688ae251c943..4103233a4060cb 100644 --- a/token-swap/js/cli/token-swap-test.js +++ b/token-swap/js/cli/token-swap-test.js @@ -281,6 +281,7 @@ export async function withdraw(): Promise { } export async function swap(): Promise { + console.log('Creating swap token a account'); let userAccountA = await mintA.createAccount(owner.publicKey); await mintA.mintTo(userAccountA, owner, [], USER_AMOUNT); await mintA.approve( @@ -290,9 +291,11 @@ export async function swap(): Promise { [], USER_AMOUNT, ); + console.log('Creating swap token b account'); let userAccountB = await mintB.createAccount(owner.publicKey); const [tokenProgramId,] = await GetPrograms(connection); + console.log('Swapping'); await tokenSwap.swap( authority, userAccountA, @@ -305,18 +308,13 @@ export async function swap(): Promise { await sleep(500); let info; info = await mintA.getAccountInfo(userAccountA); - console.log('userAccountA', info.amount.toNumber()); assert(info.amount.toNumber() == 0); info = await mintA.getAccountInfo(tokenAccountA); - console.log('tokenAccountA', info.amount.toNumber()); assert(info.amount.toNumber() == BASE_AMOUNT + USER_AMOUNT); info = await mintB.getAccountInfo(tokenAccountB); - console.log('tokenAccountB', info.amount.toNumber()); assert(info.amount.toNumber() == 931); info = await mintB.getAccountInfo(userAccountB); - console.log('userAccountB', info.amount.toNumber()); assert(info.amount.toNumber() == 69); info = await tokenPool.getAccountInfo(tokenAccountPool); - console.log('tokenAccountPool', info.amount.toNumber()); assert(info.amount.toNumber() == BASE_AMOUNT - USER_AMOUNT); } diff --git a/token-swap/js/client/token-swap.js b/token-swap/js/client/token-swap.js index 8da14e905d8a50..b86bf647115177 100644 --- a/token-swap/js/client/token-swap.js +++ b/token-swap/js/client/token-swap.js @@ -196,13 +196,14 @@ export class TokenSwap { const balanceNeeded = await TokenSwap.getMinBalanceRentForExemptTokenSwap( connection, ); - transaction = SystemProgram.createAccount({ + transaction = new Transaction(); + transaction.add(SystemProgram.createAccount({ fromPubkey: payer.publicKey, newAccountPubkey: tokenSwapAccount.publicKey, lamports: balanceNeeded, space: TokenSwapLayout.span, programId, - }); + })); await sendAndConfirmTransaction( 'createAccount', connection, @@ -292,17 +293,17 @@ export class TokenSwap { * * @param authority Authority * @param source Source account - * @param into Base account to swap into, must be a source token - * @param from Base account to swap from, must be a destination token - * @param dest Destination token + * @param swap_source Base account to swap into, must be a source token + * @param swap_destination Base account to swap from, must be a destination token + * @param destination Destination token account * @param tokenProgramId Token program id * @param amount Amount to transfer from source account */ async swap( authority: PublicKey, source: PublicKey, - into: PublicKey, - from: PublicKey, + swap_source: PublicKey, + swap_destination: PublicKey, destination: PublicKey, tokenProgramId: PublicKey, amount: number | Numberu64, @@ -314,8 +315,8 @@ export class TokenSwap { this.swapInstruction( authority, source, - into, - from, + swap_source, + swap_destination, destination, tokenProgramId, amount, @@ -324,11 +325,12 @@ export class TokenSwap { this.payer, ); } + swapInstruction( authority: PublicKey, source: PublicKey, - into: PublicKey, - from: PublicKey, + swap_source: PublicKey, + swap_destination: PublicKey, destination: PublicKey, tokenProgramId: PublicKey, amount: number | Numberu64, @@ -351,11 +353,10 @@ export class TokenSwap { {pubkey: this.tokenSwap, isSigner: false, isWritable: false}, {pubkey: authority, isSigner: false, isWritable: false}, {pubkey: source, isSigner: false, isWritable: true}, - {pubkey: into, isSigner: false, isWritable: true}, - {pubkey: from, isSigner: false, isWritable: true}, + {pubkey: swap_source, isSigner: false, isWritable: true}, + {pubkey: swap_destination, isSigner: false, isWritable: true}, {pubkey: destination, isSigner: false, isWritable: true}, {pubkey: tokenProgramId, isSigner: false, isWritable: false}, - ]; return new TransactionInstruction({ keys, @@ -443,7 +444,6 @@ export class TokenSwap { {pubkey: poolToken, isSigner: false, isWritable: true}, {pubkey: poolAccount, isSigner: false, isWritable: true}, {pubkey: tokenProgramId, isSigner: false, isWritable: false}, - ]; return new TransactionInstruction({ keys, diff --git a/token-swap/js/client/util/send-and-confirm-transaction.js b/token-swap/js/client/util/send-and-confirm-transaction.js index 1088c55dc1fbb8..e52f7e0c071583 100644 --- a/token-swap/js/client/util/send-and-confirm-transaction.js +++ b/token-swap/js/client/util/send-and-confirm-transaction.js @@ -15,7 +15,7 @@ export function sendAndConfirmTransaction( ...signers: Array ): Promise { return realSendAndConfirmTransaction(connection, transaction, signers, { - confirmations: 1, skipPreflight: true, + commitment: 'recent', }); } diff --git a/token-swap/program/src/instruction.rs b/token-swap/program/src/instruction.rs index c6918810bf2488..74c86212332755 100644 --- a/token-swap/program/src/instruction.rs +++ b/token-swap/program/src/instruction.rs @@ -52,11 +52,11 @@ pub enum SwapInstruction { /// 0. `[]` Token-swap /// 1. `[]` $authority /// 2. `[writable]` token_(A|B) SOURCE Account, amount is transferable by $authority, - /// 4. `[writable]` token_(A|B) Base Account to swap INTO. Must be the SOURCE token. - /// 5. `[writable]` token_(A|B) Base Account to swap FROM. Must be the DEST token. - /// 6. `[writable]` token_(A|B) DEST Account assigned to USER as the owner. - /// 7. '[]` Token program id - /// userdata: SOURCE amount to transfer, output to DEST is based on the exchange rate + /// 3. `[writable]` token_(A|B) Base Account to swap INTO. Must be the SOURCE token. + /// 4. `[writable]` token_(A|B) Base Account to swap FROM. Must be the DESTINATION token. + /// 5. `[writable]` token_(A|B) DESTINATION Account assigned to USER as the owner. + /// 6. '[]` Token program id + /// userdata: SOURCE amount to transfer, output to DESTINATION is based on the exchange rate Swap(u64), /// Deposit some tokens into the pool. The output is a "pool" token representing ownership @@ -160,7 +160,7 @@ pub fn initialize( token_a_pubkey: &Pubkey, token_b_pubkey: &Pubkey, pool_pubkey: &Pubkey, - user_output_pubkey: &Pubkey, + destination_pubkey: &Pubkey, nonce: u8, fee: Fee, ) -> Result { @@ -177,7 +177,7 @@ pub fn initialize( AccountMeta::new(*token_a_pubkey, false), AccountMeta::new(*token_b_pubkey, false), AccountMeta::new(*pool_pubkey, false), - AccountMeta::new(*user_output_pubkey, false), + AccountMeta::new(*destination_pubkey, false), AccountMeta::new(*token_program_id, false), ]; @@ -199,7 +199,7 @@ pub fn deposit( swap_token_a_pubkey: &Pubkey, swap_token_b_pubkey: &Pubkey, pool_mint_pubkey: &Pubkey, - user_output_pubkey: &Pubkey, + destination_pubkey: &Pubkey, amount: u64, ) -> Result { let data = SwapInstruction::Deposit(amount).serialize()?; @@ -212,7 +212,7 @@ pub fn deposit( AccountMeta::new(*swap_token_a_pubkey, false), AccountMeta::new(*swap_token_b_pubkey, false), AccountMeta::new(*pool_mint_pubkey, false), - AccountMeta::new(*user_output_pubkey, false), + AccountMeta::new(*destination_pubkey, false), AccountMeta::new(*token_program_id, false), ]; @@ -233,8 +233,8 @@ pub fn withdraw( source_pubkey: &Pubkey, swap_token_a_pubkey: &Pubkey, swap_token_b_pubkey: &Pubkey, - output_token_a_pubkey: &Pubkey, - output_token_b_pubkey: &Pubkey, + destination_token_a_pubkey: &Pubkey, + destination_token_b_pubkey: &Pubkey, amount: u64, ) -> Result { let data = SwapInstruction::Withdraw(amount).serialize()?; @@ -246,8 +246,39 @@ pub fn withdraw( AccountMeta::new(*source_pubkey, false), AccountMeta::new(*swap_token_a_pubkey, false), AccountMeta::new(*swap_token_b_pubkey, false), - AccountMeta::new(*output_token_a_pubkey, false), - AccountMeta::new(*output_token_b_pubkey, false), + AccountMeta::new(*destination_token_a_pubkey, false), + AccountMeta::new(*destination_token_b_pubkey, false), + AccountMeta::new(*token_program_id, false), + ]; + + Ok(Instruction { + program_id: *program_id, + accounts, + data, + }) +} + +/// Creates a 'swap' instruction. +pub fn swap( + program_id: &Pubkey, + token_program_id: &Pubkey, + swap_pubkey: &Pubkey, + authority_pubkey: &Pubkey, + source_pubkey: &Pubkey, + swap_source_pubkey: &Pubkey, + swap_destination_pubkey: &Pubkey, + destination_pubkey: &Pubkey, + amount: u64, +) -> Result { + let data = SwapInstruction::Swap(amount).serialize()?; + + let accounts = vec![ + AccountMeta::new(*swap_pubkey, false), + AccountMeta::new(*authority_pubkey, false), + AccountMeta::new(*source_pubkey, false), + AccountMeta::new(*swap_source_pubkey, false), + AccountMeta::new(*swap_destination_pubkey, false), + AccountMeta::new(*destination_pubkey, false), AccountMeta::new(*token_program_id, false), ]; diff --git a/token-swap/program/src/processor.rs b/token-swap/program/src/processor.rs index b432a5bb3cc35e..d6abac124c6418 100644 --- a/token-swap/program/src/processor.rs +++ b/token-swap/program/src/processor.rs @@ -145,7 +145,7 @@ impl Processor { let token_a_info = next_account_info(account_info_iter)?; let token_b_info = next_account_info(account_info_iter)?; let pool_info = next_account_info(account_info_iter)?; - let user_output_info = next_account_info(account_info_iter)?; + let user_destination_info = next_account_info(account_info_iter)?; let token_program_info = next_account_info(account_info_iter)?; if State::Unallocated != State::deserialize(&swap_info.data.borrow())? { @@ -187,7 +187,7 @@ impl Processor { swap_info.key, token_program_info.clone(), pool_info.clone(), - user_output_info.clone(), + user_destination_info.clone(), authority_info.clone(), nonce, amount, @@ -213,9 +213,9 @@ impl Processor { let swap_info = next_account_info(account_info_iter)?; let authority_info = next_account_info(account_info_iter)?; let source_info = next_account_info(account_info_iter)?; - let into_info = next_account_info(account_info_iter)?; - let from_info = next_account_info(account_info_iter)?; - let dest_info = next_account_info(account_info_iter)?; + let swap_source_info = next_account_info(account_info_iter)?; + let swap_destination_info = next_account_info(account_info_iter)?; + let destination_info = next_account_info(account_info_iter)?; let token_program_info = next_account_info(account_info_iter)?; let token_swap = State::deserialize(&swap_info.data.borrow())?.token_swap()?; @@ -223,43 +223,62 @@ impl Processor { if *authority_info.key != Self::authority_id(program_id, swap_info.key, token_swap.nonce)? { return Err(Error::InvalidProgramAddress.into()); } - if !(*into_info.key == token_swap.token_a || *into_info.key == token_swap.token_b) { + if !(*swap_source_info.key == token_swap.token_a + || *swap_source_info.key == token_swap.token_b) + { return Err(Error::InvalidInput.into()); } - if !(*from_info.key == token_swap.token_a || *from_info.key == token_swap.token_b) { + if !(*swap_destination_info.key == token_swap.token_a + || *swap_destination_info.key == token_swap.token_b) + { return Err(Error::InvalidOutput.into()); } - if *into_info.key == *from_info.key { + if *swap_source_info.key == *swap_destination_info.key { return Err(Error::InvalidInput.into()); } - let into_token = Self::token_account_deserialize(&into_info.data.borrow())?; - let from_token = Self::token_account_deserialize(&from_info.data.borrow())?; - let mut invariant = Invariant { - token_a: into_token.amount, - token_b: from_token.amount, - fee: token_swap.fee, + let source_account = Self::token_account_deserialize(&swap_source_info.data.borrow())?; + let dest_account = Self::token_account_deserialize(&swap_destination_info.data.borrow())?; + + let output = if *swap_source_info.key == token_swap.token_a { + let mut invariant = Invariant { + token_a: source_account.amount, + token_b: dest_account.amount, + fee: token_swap.fee, + }; + invariant + .swap_a_to_b(amount) + .ok_or(Error::CalculationFailure)? + } else { + let mut invariant = Invariant { + token_a: dest_account.amount, + token_b: source_account.amount, + fee: token_swap.fee, + }; + invariant + .swap_b_to_a(amount) + .ok_or(Error::CalculationFailure)? }; - let output = invariant.swap(amount).ok_or(Error::CalculationFailure)?; Self::token_transfer( - token_program_info.key, - swap_info.clone(), + swap_info.key, + token_program_info.clone(), source_info.clone(), - into_info.clone(), + swap_source_info.clone(), authority_info.clone(), token_swap.nonce, amount, )?; Self::token_transfer( - token_program_info.key, - swap_info.clone(), - from_info.clone(), - dest_info.clone(), + swap_info.key, + token_program_info.clone(), + swap_destination_info.clone(), + destination_info.clone(), authority_info.clone(), token_swap.nonce, output, )?; Ok(()) } + /// Processes an [Deposit](enum.Instruction.html). pub fn process_deposit( program_id: &Pubkey, @@ -501,7 +520,10 @@ solana_sdk::program_stubs!(); #[cfg(test)] mod tests { use super::*; - use crate::instruction::{deposit, initialize, withdraw}; + use crate::{ + instruction::{deposit, initialize, swap, withdraw}, + state::SwapResult, + }; use solana_sdk::{ account::Account, account_info::create_is_signer_account_infos, instruction::Instruction, rent::Rent, sysvar::rent, @@ -698,7 +720,6 @@ mod tests { token_b_amount, ); - // Swap Init let mut authority_account = Account::default(); do_process_instruction( initialize( @@ -785,7 +806,7 @@ mod tests { let numerator = 1; let denominator = 2; let token_a_amount = 1000; - let token_b_amount = 2000; + let token_b_amount = 8000; let mut accounts = initialize_swap(numerator, denominator, token_a_amount, token_b_amount); let seeds = [&accounts.swap_key.to_bytes()[..32], &[accounts.nonce]]; let authority_key = Pubkey::create_program_address(&seeds, &SWAP_PROGRAM_ID).unwrap(); @@ -934,4 +955,144 @@ mod tests { let pool_mint = Processor::mint_deserialize(&accounts.pool_mint_account.data).unwrap(); assert_eq!(pool_mint.supply, pool_account.amount); } + + #[test] + fn test_swap() { + let numerator = 1; + let denominator = 10; + let token_a_amount = 1000; + let token_b_amount = 5000; + let mut accounts = initialize_swap(numerator, denominator, token_a_amount, token_b_amount); + let seeds = [&accounts.swap_key.to_bytes()[..32], &[accounts.nonce]]; + let authority_key = Pubkey::create_program_address(&seeds, &SWAP_PROGRAM_ID).unwrap(); + + let initial_a = token_a_amount / 5; + let (user_token_a_key, mut user_token_a_account) = mint_token( + &TOKEN_PROGRAM_ID, + &accounts.token_a_mint_key, + &mut accounts.token_a_mint_account, + &authority_key, + initial_a, + ); + let initial_b = token_b_amount / 5; + let (user_token_b_key, mut user_token_b_account) = mint_token( + &TOKEN_PROGRAM_ID, + &accounts.token_b_mint_key, + &mut accounts.token_b_mint_account, + &authority_key, + initial_b, + ); + + let a_to_b_amount = initial_a / 10; + do_process_instruction( + swap( + &SWAP_PROGRAM_ID, + &TOKEN_PROGRAM_ID, + &accounts.swap_key, + &authority_key, + &user_token_a_key, + &accounts.token_a_key, + &accounts.token_b_key, + &user_token_b_key, + a_to_b_amount, + ) + .unwrap(), + vec![ + &mut accounts.swap_account, + &mut Account::default(), + &mut user_token_a_account, + &mut accounts.token_a_account, + &mut accounts.token_b_account, + &mut user_token_b_account, + &mut Account::default(), + ], + ) + .unwrap(); + + let results = SwapResult::swap_to( + a_to_b_amount, + token_a_amount, + token_b_amount, + &Fee { + numerator, + denominator, + }, + ) + .unwrap(); + + let swap_token_a = + Processor::token_account_deserialize(&accounts.token_a_account.data).unwrap(); + let token_a_amount = swap_token_a.amount; + assert_eq!(token_a_amount, results.new_source); + let user_token_a = + Processor::token_account_deserialize(&user_token_a_account.data).unwrap(); + assert_eq!(user_token_a.amount, initial_a - a_to_b_amount); + + let swap_token_b = + Processor::token_account_deserialize(&accounts.token_b_account.data).unwrap(); + let token_b_amount = swap_token_b.amount; + assert_eq!(token_b_amount, results.new_destination); + let user_token_b = + Processor::token_account_deserialize(&user_token_b_account.data).unwrap(); + assert_eq!(user_token_b.amount, initial_b + results.amount_swapped); + + let first_swap_amount = results.amount_swapped; + + let b_to_a_amount = initial_b / 10; + do_process_instruction( + swap( + &SWAP_PROGRAM_ID, + &TOKEN_PROGRAM_ID, + &accounts.swap_key, + &authority_key, + &user_token_b_key, + &accounts.token_b_key, + &accounts.token_a_key, + &user_token_a_key, + b_to_a_amount, + ) + .unwrap(), + vec![ + &mut accounts.swap_account, + &mut Account::default(), + &mut user_token_b_account, + &mut accounts.token_b_account, + &mut accounts.token_a_account, + &mut user_token_a_account, + &mut Account::default(), + ], + ) + .unwrap(); + + let results = SwapResult::swap_to( + b_to_a_amount, + token_b_amount, + token_a_amount, + &Fee { + numerator, + denominator, + }, + ) + .unwrap(); + + let swap_token_a = + Processor::token_account_deserialize(&accounts.token_a_account.data).unwrap(); + assert_eq!(swap_token_a.amount, results.new_destination); + let user_token_a = + Processor::token_account_deserialize(&user_token_a_account.data).unwrap(); + assert_eq!( + user_token_a.amount, + initial_a - a_to_b_amount + results.amount_swapped + ); + + let swap_token_b = + Processor::token_account_deserialize(&accounts.token_b_account.data).unwrap(); + assert_eq!(swap_token_b.amount, results.new_source); + let user_token_b = + Processor::token_account_deserialize(&user_token_b_account.data).unwrap(); + assert_eq!( + user_token_b.amount, + initial_b + first_swap_amount - b_to_a_amount + ); + } } diff --git a/token-swap/program/src/state.rs b/token-swap/program/src/state.rs index 61a49020654346..11255ae747edd6 100644 --- a/token-swap/program/src/state.rs +++ b/token-swap/program/src/state.rs @@ -85,6 +85,42 @@ impl State { } } +/// Encodes all results of swapping from a source token to a destination token +pub struct SwapResult { + /// New amount of source token + pub new_source: u64, + /// New amount of destination token + pub new_destination: u64, + /// Amount of destination token swapped + pub amount_swapped: u64, +} + +impl SwapResult { + /// SwapResult for swap from one currency into another, given pool information + /// and fee + pub fn swap_to( + source: u64, + source_amount: u64, + dest_amount: u64, + fee: &Fee, + ) -> Option { + let invariant = source_amount.checked_mul(dest_amount)?; + let new_source = source_amount.checked_add(source)?; + let new_destination = invariant.checked_div(new_source)?; + let remove = dest_amount.checked_sub(new_destination)?; + let fee = remove + .checked_mul(fee.numerator)? + .checked_div(fee.denominator)?; + let new_destination = new_destination.checked_add(fee)?; + let amount_swapped = remove.checked_sub(fee)?; + Some(SwapResult { + new_source, + new_destination, + amount_swapped, + }) + } +} + /// The Uniswap invariant calculator. pub struct Invariant { /// Token A @@ -96,21 +132,22 @@ pub struct Invariant { } impl Invariant { - /// Swap - pub fn swap(&mut self, token_a: u64) -> Option { - let invariant = self.token_a.checked_mul(self.token_b)?; - let new_a = self.token_a.checked_add(token_a)?; - let new_b = invariant.checked_div(new_a)?; - let remove = self.token_b.checked_sub(new_b)?; - let fee = remove - .checked_mul(self.fee.numerator)? - .checked_div(self.fee.denominator)?; - let new_b_with_fee = new_b.checked_add(fee)?; - let remove_less_fee = remove.checked_sub(fee)?; - self.token_a = new_a; - self.token_b = new_b_with_fee; - Some(remove_less_fee) + /// Swap token a to b + pub fn swap_a_to_b(&mut self, token_a: u64) -> Option { + let result = SwapResult::swap_to(token_a, self.token_a, self.token_b, &self.fee)?; + self.token_a = result.new_source; + self.token_b = result.new_destination; + Some(result.amount_swapped) } + + /// Swap token b to a + pub fn swap_b_to_a(&mut self, token_b: u64) -> Option { + let result = SwapResult::swap_to(token_b, self.token_b, self.token_a, &self.fee)?; + self.token_b = result.new_source; + self.token_a = result.new_destination; + Some(result.amount_swapped) + } + /// Exchange rate pub fn exchange_rate(&self, token_a: u64) -> Option { token_a.checked_mul(self.token_b)?.checked_div(self.token_a) diff --git a/token/js/cli/token-test.js b/token/js/cli/token-test.js index 98d1f9c99f2590..49eae735121a38 100644 --- a/token/js/cli/token-test.js +++ b/token/js/cli/token-test.js @@ -1,7 +1,13 @@ // @flow import fs from 'mz/fs'; -import {Account, Connection, BpfLoader, PublicKey} from '@solana/web3.js'; +import { + Account, + Connection, + BpfLoader, + PublicKey, + BPF_LOADER_PROGRAM_ID, +} from '@solana/web3.js'; import semver from 'semver'; import {Token} from '../client/token'; @@ -71,7 +77,13 @@ async function loadProgram( const from = await newAccountWithLamports(connection, balanceNeeded); const program_account = new Account(); console.log('Loading program:', path); - await BpfLoader.load(connection, from, program_account, data, 2); + await BpfLoader.load( + connection, + from, + program_account, + data, + BPF_LOADER_PROGRAM_ID, + ); return program_account.publicKey; } diff --git a/token/js/client/token.js b/token/js/client/token.js index 5516b7fc3dc372..3fbf1e52e91b8e 100644 --- a/token/js/client/token.js +++ b/token/js/client/token.js @@ -352,13 +352,14 @@ export class Token { connection, ); - const transaction = SystemProgram.createAccount({ + const transaction = new Transaction(); + transaction.add(SystemProgram.createAccount({ fromPubkey: payer.publicKey, newAccountPubkey: mintAccount.publicKey, lamports: balanceNeeded, space: MintLayout.span, programId, - }); + })); transaction.add( Token.createInitMintInstruction( @@ -397,13 +398,14 @@ export class Token { ); const newAccount = new Account(); - const transaction = SystemProgram.createAccount({ + const transaction = new Transaction(); + transaction.add(SystemProgram.createAccount({ fromPubkey: this.payer.publicKey, newAccountPubkey: newAccount.publicKey, lamports: balanceNeeded, space: AccountLayout.span, programId: this.programId, - }); + })); const mintPublicKey = this.publicKey; transaction.add( @@ -441,19 +443,19 @@ export class Token { signers: Array, ): Promise { const multisigAccount = new Account(); - let transaction; // Allocate memory for the account const balanceNeeded = await Token.getMinBalanceRentForExemptMultisig( this.connection, ); - transaction = SystemProgram.createAccount({ + const transaction = new Transaction(); + transaction.add(SystemProgram.createAccount({ fromPubkey: this.payer.publicKey, newAccountPubkey: multisigAccount.publicKey, lamports: balanceNeeded, space: MultisigLayout.span, programId: this.programId, - }); + })); // create the new account let keys = [ diff --git a/token/js/client/util/send-and-confirm-transaction.js b/token/js/client/util/send-and-confirm-transaction.js index 1088c55dc1fbb8..e52f7e0c071583 100644 --- a/token/js/client/util/send-and-confirm-transaction.js +++ b/token/js/client/util/send-and-confirm-transaction.js @@ -15,7 +15,7 @@ export function sendAndConfirmTransaction( ...signers: Array ): Promise { return realSendAndConfirmTransaction(connection, transaction, signers, { - confirmations: 1, skipPreflight: true, + commitment: 'recent', }); } diff --git a/token/js/package-lock.json b/token/js/package-lock.json index 979b914bcedb89..e6be35195c19cb 100644 --- a/token/js/package-lock.json +++ b/token/js/package-lock.json @@ -2202,9 +2202,9 @@ "dev": true }, "@solana/web3.js": { - "version": "0.71.6", - "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.71.6.tgz", - "integrity": "sha512-mVCqVSEsBacL0xHHwuciHg8qJmFF7Yao9ItASLokYvUYfgwocNS0urnCytOqAFwfE27JRXLHOMOPq6mLbX/2Kg==", + "version": "0.75.0", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.75.0.tgz", + "integrity": "sha512-goWSloQQbd7MLBxi/ViUvNIKg/uVQNVw/TvjsilZNnFiHv6WtNdUOnZFQbF8Nc7UDxeh+5TUbGkjavf0qzEbbA==", "requires": { "@babel/runtime": "^7.3.1", "bn.js": "^5.0.0", @@ -2217,7 +2217,7 @@ "mz": "^2.7.0", "node-fetch": "^2.2.0", "npm-run-all": "^4.1.5", - "rpc-websockets": "^5.0.8", + "rpc-websockets": "^7.4.2", "superstruct": "^0.8.3", "tweetnacl": "^1.0.0", "ws": "^7.0.0" @@ -2265,9 +2265,9 @@ "dev": true }, "@types/express-serve-static-core": { - "version": "4.17.9", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.9.tgz", - "integrity": "sha512-DG0BYg6yO+ePW+XoDENYz8zhNGC3jDDEpComMYn7WJc4mY1Us8Rw9ax2YhJXxpyk2SF47PQAoQ0YyVT1a0bEkA==", + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.12.tgz", + "integrity": "sha512-EaEdY+Dty1jEU7U6J4CUWwxL+hyEGMkO5jan5gplfegUgCUsIUWqXxqw47uGjimeT4Qgkz/XUfwoau08+fgvKA==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -2315,9 +2315,9 @@ } }, "@types/lodash": { - "version": "4.14.160", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.160.tgz", - "integrity": "sha512-aP03BShJoO+WVndoVj/WNcB/YBPt+CIU1mvaao2GRAHy2yg4pT/XS4XnVHEQBjPJGycWf/9seKEO9vopTJGkvA==" + "version": "4.14.161", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.161.tgz", + "integrity": "sha512-EP6O3Jkr7bXvZZSZYlsgt5DIjiGr0dXP1/jVEwVLTFgg0d+3lWVQkRavYVQszV7dYUwvg0B8R0MBDpcmXg7XIA==" }, "@types/minimatch": { "version": "3.0.3", @@ -2490,11 +2490,6 @@ "dev": true, "optional": true }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -2542,15 +2537,6 @@ "object.assign": "^4.1.0" } }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -2779,6 +2765,15 @@ "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", "dev": true }, + "bufferutil": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", + "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", + "optional": true, + "requires": { + "node-gyp-build": "~3.7.0" + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3080,11 +3075,6 @@ "dev": true, "optional": true }, - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" - }, "core-js-compat": { "version": "3.6.5", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", @@ -3792,9 +3782,9 @@ "dev": true }, "eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, "exec-sh": { "version": "0.2.2", @@ -5392,9 +5382,9 @@ }, "dependencies": { "@types/node": { - "version": "12.12.54", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.54.tgz", - "integrity": "sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w==" + "version": "12.12.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.56.tgz", + "integrity": "sha512-8OdIupOIZtmObR13fvGyTvpcuzKmMugkATeVcfNwCjGtHxhjEKmOvLqXwR8U9VOtNnZ4EXaSfNiLVsPinaCXkQ==" }, "lodash": { "version": "4.17.20", @@ -6123,6 +6113,12 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" }, + "node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "optional": true + }, "node-modules-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", @@ -6943,11 +6939,6 @@ "regenerate": "^1.4.0" } }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, "regenerator-transform": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", @@ -7153,26 +7144,24 @@ } }, "rpc-websockets": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-5.3.1.tgz", - "integrity": "sha512-rIxEl1BbXRlIA9ON7EmY/2GUM7RLMy8zrUPTiLPFiYnYOz0I3PXfCmDDrge5vt4pW4oIcAXBDvgZuJ1jlY5+VA==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.4.2.tgz", + "integrity": "sha512-kUpYcnbEU/BeAxGTlfySZ/tp9FU+TLSgONbViyx6hQsIh8876uxggJWzVOCe+CztBvuCOAOd0BXyPlKfcflykw==", "requires": { - "@babel/runtime": "^7.8.7", + "@babel/runtime": "^7.11.2", "assert-args": "^1.2.1", - "babel-runtime": "^6.26.0", + "bufferutil": "^4.0.1", "circular-json": "^0.5.9", - "eventemitter3": "^3.1.2", - "uuid": "^3.4.0", - "ws": "^5.2.2" + "eventemitter3": "^4.0.7", + "utf-8-validate": "^5.0.2", + "uuid": "^8.3.0", + "ws": "^7.3.1" }, "dependencies": { - "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", - "requires": { - "async-limiter": "~1.0.0" - } + "uuid": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==" } } }, @@ -8115,6 +8104,15 @@ "dev": true, "optional": true }, + "utf-8-validate": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", + "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", + "optional": true, + "requires": { + "node-gyp-build": "~3.7.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/token/js/package.json b/token/js/package.json index dbfabbe8808465..3eb7360b09151c 100644 --- a/token/js/package.json +++ b/token/js/package.json @@ -44,7 +44,7 @@ }, "dependencies": { "@babel/runtime": "^7.10.5", - "@solana/web3.js": "^0.71.6", + "@solana/web3.js": "^0.75.0", "bn.js": "^5.0.0", "buffer-layout": "^1.2.0", "dotenv": "8.2.0",