diff --git a/.gitignore b/.gitignore index 1c5fcc4..b509744 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ target node_modules test-ledger .vscode +.yarn + diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 0000000..3186f3f --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/Anchor.toml b/Anchor.toml index 45ce766..bf0cfc7 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -10,11 +10,8 @@ members = ["programs/cp-swap"] seeds = false skip-lint = false -[programs.mainnet] -token_swap = "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C" - -[programs.devnet] -token_swap = "CPMDWBwJDtYax9qW7AyRuVC19Cc4L4Vcy4n2BHAbHkCW" +[programs.Localnet] +cp_swap = "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C" [registry] @@ -26,3 +23,12 @@ wallet = "~/.config/solana/id.json" [scripts] test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" + +[test] +startup_wait = 10000 + +[test.validator] +url = "https://api.mainnet-beta.solana.com" + +[[test.validator.clone]] +address = "DNXgeM9EiiaAbaWvwjHj9fQQLAX5ZsfHyvmYUNRAdNC8" diff --git a/package.json b/package.json new file mode 100644 index 0000000..d603e3c --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@coral-xyz/anchor": "^0.29.0", + "@solana/spl-token": "^0.4.0", + "@solana/web3.js": "^1.90.0" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^4.3.5" + } +} diff --git a/programs/cp-swap/src/curve/calculator.rs b/programs/cp-swap/src/curve/calculator.rs index 68c1659..6ea76cd 100644 --- a/programs/cp-swap/src/curve/calculator.rs +++ b/programs/cp-swap/src/curve/calculator.rs @@ -1,8 +1,8 @@ //! Swap calculations +use crate::curve::{constant_product::ConstantProductCurve, fees::Fees}; use anchor_lang::prelude::*; use {crate::error::ErrorCode, std::fmt::Debug}; -use crate::curve::{constant_product::ConstantProductCurve, fees::Fees}; /// Helper function for mapping to ErrorCode::CalculationFailure pub fn map_zero_to_none(x: u128) -> Option { @@ -153,16 +153,17 @@ impl CurveCalculator { swap_destination_amount, )?; - let source_amount = Fees::calculate_pre_fee_amount( source_amount_swapped, trade_fee_rate).unwrap(); + let source_amount = + Fees::calculate_pre_fee_amount(source_amount_swapped, trade_fee_rate).unwrap(); let trade_fee = Fees::trading_fee(source_amount, trade_fee_rate)?; let protocol_fee = Fees::protocol_fee(trade_fee, protocol_fee_rate)?; let fund_fee = Fees::fund_fee(trade_fee, fund_fee_rate)?; - + Some(SwapResult { new_swap_source_amount: swap_source_amount.checked_add(source_amount)?, new_swap_destination_amount: swap_destination_amount .checked_sub(destination_amount_swapped)?, - source_amount_swapped:source_amount, + source_amount_swapped: source_amount, destination_amount_swapped, trade_fee, protocol_fee, @@ -243,7 +244,9 @@ pub mod test { TradeDirection::ZeroForOne => (swap_source_amount, swap_destination_amount), TradeDirection::OneForZero => (swap_destination_amount, swap_source_amount), }; - let previous_value = normalized_value(swap_token_0_amount, swap_token_1_amount).unwrap(); + let previous_value = swap_token_0_amount + .checked_mul(swap_token_1_amount) + .unwrap(); let new_swap_source_amount = swap_source_amount .checked_add(results.source_amount_swapped) @@ -256,16 +259,10 @@ pub mod test { TradeDirection::OneForZero => (new_swap_destination_amount, new_swap_source_amount), }; - let new_value = normalized_value(swap_token_0_amount, swap_token_1_amount).unwrap(); - assert!(new_value.greater_than_or_equal(&previous_value)); - - let epsilon = 1; // Extremely close! - let difference = new_value - .checked_sub(&previous_value) - .unwrap() - .to_imprecise() + let new_value = swap_token_0_amount + .checked_mul(swap_token_1_amount) .unwrap(); - assert!(difference <= epsilon); + assert!(new_value >= previous_value); } /// Test function checking that a deposit never reduces the value of pool diff --git a/programs/cp-swap/src/curve/constant_product.rs b/programs/cp-swap/src/curve/constant_product.rs index 0edc9af..9f4ca6d 100644 --- a/programs/cp-swap/src/curve/constant_product.rs +++ b/programs/cp-swap/src/curve/constant_product.rs @@ -1,10 +1,8 @@ //! The Uniswap invariantConstantProductCurve:: -use { - crate::curve::calculator::{ - map_zero_to_none, RoundDirection, SwapWithoutFeesResult, TradingTokenResult, - }, - spl_math::checked_ceil_div::CheckedCeilDiv, +use crate::{ + curve::calculator::{RoundDirection, SwapWithoutFeesResult, TradingTokenResult}, + utils::CheckedCeilDiv, }; /// ConstantProductCurve struct implementing CurveCalculator @@ -23,18 +21,14 @@ impl ConstantProductCurve { swap_source_amount: u128, swap_destination_amount: u128, ) -> Option { - let invariant = swap_source_amount.checked_mul(swap_destination_amount)?; - - let new_swap_source_amount = swap_source_amount.checked_add(source_amount)?; - let (new_swap_destination_amount, new_swap_source_amount) = - invariant.checked_ceil_div(new_swap_source_amount)?; - - let source_amount_swapped = new_swap_source_amount.checked_sub(swap_source_amount)?; - let destination_amount_swapped = - map_zero_to_none(swap_destination_amount.checked_sub(new_swap_destination_amount)?)?; + // (x + delta_x) * (y - delta_y) = x * y + // delta_y = (delta_x * y) / (x + delta_x) + let numerator = source_amount.checked_mul(swap_destination_amount).unwrap(); + let denominator = swap_source_amount.checked_add(source_amount).unwrap(); + let destination_amount_swapped = numerator.checked_div(denominator).unwrap(); Some(SwapWithoutFeesResult { - source_amount_swapped, + source_amount_swapped: source_amount, destination_amount_swapped, }) } @@ -44,19 +38,17 @@ impl ConstantProductCurve { swap_source_amount: u128, swap_destination_amount: u128, ) -> Option { - let invariant = swap_source_amount.checked_mul(swap_destination_amount)?; - - let new_swap_destination_amount = swap_destination_amount.checked_sub(destinsation_amount)?; - let (new_swap_source_amount,new_swap_destination_amount) = - invariant.checked_ceil_div(new_swap_destination_amount)?; - - let source_amount_swapped = new_swap_source_amount.checked_sub(swap_source_amount)?; - let destination_amount_swapped = - map_zero_to_none(swap_destination_amount.checked_sub(new_swap_destination_amount)?)?; + // (x + delta_x) * (y - delta_y) = x * y + // delta_x = (x * delta_y) / (y - delta_y) + let numerator = swap_source_amount.checked_mul(destinsation_amount).unwrap(); + let denominator = swap_destination_amount + .checked_sub(destinsation_amount) + .unwrap(); + let (source_amount_swapped, _) = numerator.checked_ceil_div(denominator).unwrap(); Some(SwapWithoutFeesResult { source_amount_swapped, - destination_amount_swapped, + destination_amount_swapped: destinsation_amount, }) } @@ -115,10 +107,9 @@ mod tests { crate::curve::calculator::{ test::{ check_curve_value_from_swap, check_pool_value_from_deposit, - check_pool_value_from_withdraw, total_and_intermediate + check_pool_value_from_withdraw, total_and_intermediate, }, - RoundDirection, - TradeDirection + RoundDirection, TradeDirection, }, proptest::prelude::*, }; @@ -196,21 +187,13 @@ mod tests { #[test] fn constant_product_swap_rounding() { - // much too small - assert!(ConstantProductCurve::swap_base_input_without_fees( - 10, - 70_000_000_000, - 4_000_000, - ) - .is_none()); // spot: 10 * 4m / 70b = 0 - let tests: &[(u128, u128, u128, u128, u128)] = &[ // spot: 10 * 70b / ~4m = 174,999.99 (10, 4_000_000, 70_000_000_000, 10, 174_999), // spot: 20 * 1 / 3.000 = 6.6667 (source can be 18 to get 6 dest.) - (20, 30_000 - 20, 10_000, 18, 6), + (20, 30_000 - 20, 10_000, 20, 6), // spot: 19 * 1 / 2.999 = 6.3334 (source can be 18 to get 6 dest.) - (19, 30_000 - 20, 10_000, 18, 6), + (19, 30_000 - 20, 10_000, 19, 6), // spot: 18 * 1 / 2.999 = 6.0001 (18, 30_000 - 20, 10_000, 18, 6), // spot: 10 * 3 / 2.0010 = 14.99 @@ -220,11 +203,11 @@ mod tests { // spot: 10 * 3 / 2.0000 = 15 (10, 20_000 - 10, 30_000, 10, 15), // spot: 100 * 3 / 6.001 = 49.99 (source can be 99 to get 49 dest.) - (100, 60_000, 30_000, 99, 49), + (100, 60_000, 30_000, 100, 49), // spot: 99 * 3 / 6.001 = 49.49 (99, 60_000, 30_000, 99, 49), // spot: 98 * 3 / 6.001 = 48.99 (source can be 97 to get 48 dest.) - (98, 60_000, 30_000, 97, 48), + (98, 60_000, 30_000, 98, 48), ]; for ( source_amount, diff --git a/programs/cp-swap/src/curve/fees.rs b/programs/cp-swap/src/curve/fees.rs index e16031b..55583fa 100644 --- a/programs/cp-swap/src/curve/fees.rs +++ b/programs/cp-swap/src/curve/fees.rs @@ -54,15 +54,14 @@ impl Fees { if trade_fee_rate == 0 { Some(post_fee_amount) } else { - let numerator = - post_fee_amount.checked_mul(u128::from(FEE_RATE_DENOMINATOR_VALUE))?; + let numerator = post_fee_amount.checked_mul(u128::from(FEE_RATE_DENOMINATOR_VALUE))?; let denominator = u128::from(FEE_RATE_DENOMINATOR_VALUE).checked_sub(u128::from(trade_fee_rate))?; numerator - .checked_add(denominator)? - .checked_sub(1)? - .checked_div(denominator) + .checked_add(denominator)? + .checked_sub(1)? + .checked_div(denominator) } } } diff --git a/programs/cp-swap/src/instructions/admin/update_config.rs b/programs/cp-swap/src/instructions/admin/update_config.rs index 1ebc807..7fd900b 100644 --- a/programs/cp-swap/src/instructions/admin/update_config.rs +++ b/programs/cp-swap/src/instructions/admin/update_config.rs @@ -58,8 +58,8 @@ fn set_new_protocol_owner(amm_config: &mut Account, new_owner: Pubkey require_keys_neq!(new_owner, Pubkey::default()); #[cfg(feature = "enable-log")] msg!( - "amm_config, old_owner:{}, new_owner:{}", - amm_config.owner.to_string(), + "amm_config, old_protocol_owner:{}, new_owner:{}", + amm_config.protocol_owner.to_string(), new_owner.key().to_string() ); amm_config.protocol_owner = new_owner; diff --git a/programs/cp-swap/src/instructions/deposit.rs b/programs/cp-swap/src/instructions/deposit.rs index 7d0a3e0..35f38ae 100644 --- a/programs/cp-swap/src/instructions/deposit.rs +++ b/programs/cp-swap/src/instructions/deposit.rs @@ -77,7 +77,10 @@ pub struct Deposit<'info> { pub vault_1_mint: Box>, /// Lp token mint - #[account(address = pool_state.load()?.lp_mint @ ErrorCode::IncorrectLpMint)] + #[account( + mut, + address = pool_state.load()?.lp_mint @ ErrorCode::IncorrectLpMint) + ] pub lp_mint: Box>, } @@ -115,10 +118,6 @@ pub fn deposit( ) }; - if transfer_token_0_amount > maximum_token_0_amount { - return Err(ErrorCode::ExceededSlippage.into()); - } - let token_1_amount = u64::try_from(results.token_1_amount).unwrap(); let (transfer_token_1_amount, transfer_token_1_fee) = { let transfer_fee = get_transfer_inverse_fee(&ctx.accounts.vault_1_mint, token_1_amount)?; @@ -127,7 +126,22 @@ pub fn deposit( transfer_fee, ) }; - if transfer_token_1_amount > maximum_token_1_amount { + + #[cfg(feature = "enable-log")] + msg!( + "results.token_0_amount;{}, results.token_1_amount:{},transfer_token_0_amount:{},transfer_token_0_fee:{}, + transfer_token_1_amount:{},transfer_token_1_fee:{}", + results.token_0_amount, + results.token_1_amount, + transfer_token_0_amount, + transfer_token_0_fee, + transfer_token_1_amount, + transfer_token_1_fee + ); + + if transfer_token_0_amount > maximum_token_0_amount + || transfer_token_1_amount > maximum_token_1_amount + { return Err(ErrorCode::ExceededSlippage.into()); } diff --git a/programs/cp-swap/src/instructions/initialize.rs b/programs/cp-swap/src/instructions/initialize.rs index 0274e38..3432ddc 100644 --- a/programs/cp-swap/src/instructions/initialize.rs +++ b/programs/cp-swap/src/instructions/initialize.rs @@ -49,7 +49,7 @@ pub struct Initialize<'info> { )] pub pool_state: AccountLoader<'info, PoolState>, - /// Token_0 mint, the key must grater then token_1 mint. + /// Token_0 mint, the key must smaller then token_1 mint. #[account( constraint = token_0_mint.key() < token_1_mint.key(), mint::token_program = token_0_program, diff --git a/programs/cp-swap/src/instructions/mod.rs b/programs/cp-swap/src/instructions/mod.rs index c16f748..3ae3631 100644 --- a/programs/cp-swap/src/instructions/mod.rs +++ b/programs/cp-swap/src/instructions/mod.rs @@ -12,4 +12,4 @@ pub mod admin; pub use admin::*; pub mod swap_base_output; -pub use swap_base_output::*; \ No newline at end of file +pub use swap_base_output::*; diff --git a/programs/cp-swap/src/instructions/swap_base_input.rs b/programs/cp-swap/src/instructions/swap_base_input.rs index 61e3f09..e05bc65 100644 --- a/programs/cp-swap/src/instructions/swap_base_input.rs +++ b/programs/cp-swap/src/instructions/swap_base_input.rs @@ -83,6 +83,7 @@ pub fn swap_base_input(ctx: Context, amount_in: u64, minimum_amount_out: u let transfer_fee = get_transfer_fee(&ctx.accounts.input_token_mint, amount_in)?; // Take transfer fees into account for actual amount transferred in let actual_amount_in = amount_in.saturating_sub(transfer_fee); + require_gt!(actual_amount_in, 0); // Calculate the trade amounts let (trade_direction, total_input_token_amount, total_output_token_amount) = @@ -130,6 +131,14 @@ pub fn swap_base_input(ctx: Context, amount_in: u64, minimum_amount_out: u let constant_after = u128::from(result.new_swap_source_amount) .checked_mul(u128::from(result.new_swap_destination_amount)) .unwrap(); + #[cfg(feature = "enable-log")] + msg!( + "source_amount_swapped:{}, destination_amount_swapped:{},constant_before:{},constant_after:{}", + result.source_amount_swapped, + result.destination_amount_swapped, + constant_before, + constant_after + ); require_gte!(constant_after, constant_before); // Re-calculate the source amount swapped based on what the curve says @@ -147,6 +156,7 @@ pub fn swap_base_input(ctx: Context, amount_in: u64, minimum_amount_out: u let amount_out = u64::try_from(result.destination_amount_swapped).unwrap(); let transfer_fee = get_transfer_fee(&ctx.accounts.output_token_mint, amount_out)?; let amount_received = amount_out.checked_sub(transfer_fee).unwrap(); + require_gt!(amount_received, 0); if amount_received < minimum_amount_out { return Err(ErrorCode::ExceededSlippage.into()); } diff --git a/programs/cp-swap/src/instructions/swap_base_output.rs b/programs/cp-swap/src/instructions/swap_base_output.rs index d61bdd0..958bcf1 100644 --- a/programs/cp-swap/src/instructions/swap_base_output.rs +++ b/programs/cp-swap/src/instructions/swap_base_output.rs @@ -69,15 +69,25 @@ pub fn swap_base_output( let constant_after = u128::from(result.new_swap_source_amount) .checked_mul(u128::from(result.new_swap_destination_amount)) .unwrap(); + + #[cfg(feature = "enable-log")] + msg!( + "source_amount_swapped:{}, destination_amount_swapped:{},constant_before:{},constant_after:{}", + result.source_amount_swapped, + result.destination_amount_swapped, + constant_before, + constant_after + ); require_gte!(constant_after, constant_before); // Re-calculate the source amount swapped based on what the curve says let (input_transfer_amount, input_transfer_fee) = { let source_amount_swapped = u64::try_from(result.source_amount_swapped).unwrap(); + require_gt!(source_amount_swapped, 0); let transfer_fee = get_transfer_inverse_fee(&ctx.accounts.input_token_mint, source_amount_swapped)?; let input_transfer_amount = source_amount_swapped.checked_add(transfer_fee).unwrap(); - if input_transfer_amount < max_amount_in { + if input_transfer_amount > max_amount_in { return Err(ErrorCode::ExceededSlippage.into()); } (input_transfer_amount, transfer_fee) @@ -85,7 +95,6 @@ pub fn swap_base_output( let (output_transfer_amount, output_transfer_fee) = { let destination_amount_swapped = u64::try_from(result.destination_amount_swapped).unwrap(); - require_gte!(actual_amount_out, destination_amount_swapped); let output_transfer_fee = get_transfer_inverse_fee(&ctx.accounts.output_token_mint, destination_amount_swapped)?; (destination_amount_swapped, output_transfer_fee) diff --git a/programs/cp-swap/src/instructions/withdraw.rs b/programs/cp-swap/src/instructions/withdraw.rs index 49fddb5..50d8e5a 100644 --- a/programs/cp-swap/src/instructions/withdraw.rs +++ b/programs/cp-swap/src/instructions/withdraw.rs @@ -68,20 +68,23 @@ pub struct Withdraw<'info> { /// Token program 2022 pub token_program_2022: Program<'info, Token2022>, - /// The mint of token_0 vault + /// The mint of token_0 vault #[account( address = token_0_vault.mint )] pub vault_0_mint: Box>, - /// The mint of token_1 vault + /// The mint of token_1 vault #[account( address = token_1_vault.mint )] pub vault_1_mint: Box>, /// Pool lp token mint - #[account(address = pool_state.load()?.lp_mint @ ErrorCode::IncorrectLpMint)] + #[account( + mut, + address = pool_state.load()?.lp_mint @ ErrorCode::IncorrectLpMint) + ] pub lp_mint: Box>, /// memo program @@ -92,8 +95,8 @@ pub struct Withdraw<'info> { pub memo_program: UncheckedAccount<'info>, } -pub fn withdraw<>( - ctx: Context< Withdraw>, +pub fn withdraw( + ctx: Context, lp_token_amount: u64, minimum_token_0_amount: u64, minimum_token_1_amount: u64, @@ -104,56 +107,66 @@ pub fn withdraw<>( if !pool_state.get_status_by_bit(PoolStatusBitIndex::Withdraw) { return err!(ErrorCode::NotApproved); } - let (total_token_0_amount, total_token_1_amount) = - pool_state.vault_amount_without_fee( - ctx.accounts.token_0_vault.amount, - ctx.accounts.token_1_vault.amount, - ); + let (total_token_0_amount, total_token_1_amount) = pool_state.vault_amount_without_fee( + ctx.accounts.token_0_vault.amount, + ctx.accounts.token_1_vault.amount, + ); let results = CurveCalculator::lp_tokens_to_trading_tokens( u128::from(lp_token_amount), - u128::from(pool_state.lp_supply), - u128::from(total_token_0_amount), - u128::from(total_token_1_amount), + u128::from(pool_state.lp_supply), + u128::from(total_token_0_amount), + u128::from(total_token_1_amount), RoundDirection::Floor, ) .ok_or(ErrorCode::ZeroTradingTokens)?; let token_0_amount = u64::try_from(results.token_0_amount).unwrap(); let token_0_amount = std::cmp::min(ctx.accounts.token_0_vault.amount, token_0_amount); - let (receive_token_0_amount,token_0_transfer_fee) = { - let transfer_fee = get_transfer_fee( - &ctx.accounts.vault_0_mint, - token_0_amount, - )?; - (token_0_amount.checked_sub(transfer_fee).unwrap(),transfer_fee) + let (receive_token_0_amount, token_0_transfer_fee) = { + let transfer_fee = get_transfer_fee(&ctx.accounts.vault_0_mint, token_0_amount)?; + ( + token_0_amount.checked_sub(transfer_fee).unwrap(), + transfer_fee, + ) }; - if receive_token_0_amount < minimum_token_0_amount { - return Err(ErrorCode::ExceededSlippage.into()); - } let token_1_amount = u64::try_from(results.token_1_amount).unwrap(); let token_1_amount = std::cmp::min(ctx.accounts.token_1_vault.amount, token_1_amount); - let (receive_token_1_amount,token_1_transfer_fee) = { - let transfer_fee = get_transfer_fee( - &ctx.accounts.vault_1_mint, - token_1_amount, - )?; - (token_1_amount.checked_sub(transfer_fee).unwrap(),transfer_fee) + let (receive_token_1_amount, token_1_transfer_fee) = { + let transfer_fee = get_transfer_fee(&ctx.accounts.vault_1_mint, token_1_amount)?; + ( + token_1_amount.checked_sub(transfer_fee).unwrap(), + transfer_fee, + ) }; - if receive_token_1_amount < minimum_token_1_amount { + + #[cfg(feature = "enable-log")] + msg!( + "results.token_0_amount;{}, results.token_1_amount:{},receive_token_0_amount:{},token_0_transfer_fee:{}, + receive_token_1_amount:{},token_1_transfer_fee:{}", + results.token_0_amount, + results.token_1_amount, + receive_token_0_amount, + token_0_transfer_fee, + receive_token_1_amount, + token_1_transfer_fee + ); + + if receive_token_0_amount < minimum_token_0_amount + || receive_token_1_amount < minimum_token_1_amount + { return Err(ErrorCode::ExceededSlippage.into()); - } + } pool_state.lp_supply = pool_state.lp_supply.checked_sub(lp_token_amount).unwrap(); token_burn( - ctx.accounts.authority.to_account_info(), + ctx.accounts.owner.to_account_info(), ctx.accounts.token_program.to_account_info(), ctx.accounts.lp_mint.to_account_info(), ctx.accounts.owner_lp_token.to_account_info(), lp_token_amount, &[&[crate::AUTH_SEED.as_bytes(), &[pool_state.auth_bump]]], )?; - transfer_from_pool_vault_to_user( ctx.accounts.authority.to_account_info(), @@ -167,7 +180,7 @@ pub fn withdraw<>( }, token_0_amount, ctx.accounts.vault_0_mint.decimals, - &[&[crate::AUTH_SEED.as_bytes(), &[pool_state.auth_bump]]] + &[&[crate::AUTH_SEED.as_bytes(), &[pool_state.auth_bump]]], )?; transfer_from_pool_vault_to_user( @@ -182,7 +195,7 @@ pub fn withdraw<>( }, token_1_amount, ctx.accounts.vault_1_mint.decimals, - &[&[crate::AUTH_SEED.as_bytes(), &[pool_state.auth_bump]]] + &[&[crate::AUTH_SEED.as_bytes(), &[pool_state.auth_bump]]], )?; emit!(LpChangeEvent { @@ -190,8 +203,8 @@ pub fn withdraw<>( lp_amount: lp_token_amount, token_0_vault_before: total_token_0_amount, token_1_vault_before: total_token_1_amount, - token_0_amount:receive_token_0_amount, - token_1_amount:receive_token_1_amount, + token_0_amount: receive_token_0_amount, + token_1_amount: receive_token_1_amount, token_0_transfer_fee, token_1_transfer_fee, change_type: 1 diff --git a/programs/cp-swap/src/utils/math.rs b/programs/cp-swap/src/utils/math.rs index 41113d4..19210ba 100644 --- a/programs/cp-swap/src/utils/math.rs +++ b/programs/cp-swap/src/utils/math.rs @@ -9,3 +9,39 @@ construct_uint! { construct_uint! { pub struct U256(4); } + +pub trait CheckedCeilDiv: Sized { + /// Perform ceiling division + fn checked_ceil_div(&self, rhs: Self) -> Option<(Self, Self)>; +} + +impl CheckedCeilDiv for u128 { + fn checked_ceil_div(&self, mut rhs: Self) -> Option<(Self, Self)> { + let mut quotient = self.checked_div(rhs)?; + // Avoid dividing a small number by a big one and returning 1, and instead + // fail. + if quotient == 0 { + // return None; + if self.checked_mul(2 as u128)? >= rhs { + return Some((1, 0)); + } else { + return Some((0, 0)); + } + } + + // Ceiling the destination amount if there's any remainder, which will + // almost always be the case. + let remainder = self.checked_rem(rhs)?; + if remainder > 0 { + quotient = quotient.checked_add(1)?; + // calculate the minimum amount needed to get the dividend amount to + // avoid truncating too much + rhs = self.checked_div(quotient)?; + let remainder = self.checked_rem(quotient)?; + if remainder > 0 { + rhs = rhs.checked_add(1)?; + } + } + Some((quotient, rhs)) + } +} diff --git a/programs/cp-swap/src/utils/token.rs b/programs/cp-swap/src/utils/token.rs index 891a87a..6de1e99 100644 --- a/programs/cp-swap/src/utils/token.rs +++ b/programs/cp-swap/src/utils/token.rs @@ -7,7 +7,7 @@ use anchor_spl::{ spl_token_2022::{ self, extension::{ - transfer_fee::TransferFeeConfig, + transfer_fee::{TransferFeeConfig, MAX_FEE_BASIS_POINTS}, ExtensionType, StateWithExtensions, }, }, @@ -132,9 +132,16 @@ pub fn get_transfer_inverse_fee( let mint = StateWithExtensions::::unpack(&mint_data)?; let fee = if let Ok(transfer_fee_config) = mint.get_extension::() { - transfer_fee_config - .calculate_inverse_epoch_fee(Clock::get()?.epoch, post_fee_amount) - .unwrap() + let epoch = Clock::get()?.epoch; + + let transfer_fee = transfer_fee_config.get_epoch_fee(epoch); + if u16::from(transfer_fee.transfer_fee_basis_points) == MAX_FEE_BASIS_POINTS { + u64::from(transfer_fee.maximum_fee) + } else { + transfer_fee_config + .calculate_inverse_epoch_fee(epoch, post_fee_amount) + .unwrap() + } } else { 0 }; diff --git a/tests/deposit.test.ts b/tests/deposit.test.ts new file mode 100644 index 0000000..ca606d4 --- /dev/null +++ b/tests/deposit.test.ts @@ -0,0 +1,337 @@ +import * as anchor from "@coral-xyz/anchor"; +import { Program, BN } from "@coral-xyz/anchor"; +import { CpSwap } from "../target/types/cp_swap"; +import { + calculateFee, + calculatePreFeeAmount, + deposit, + getUserAndPoolVaultAmount, + setupDepositTest, +} from "./utils"; +import { assert } from "chai"; +import { MAX_FEE_BASIS_POINTS, TOKEN_PROGRAM_ID } from "@solana/spl-token"; + +describe("deposit test", () => { + anchor.setProvider(anchor.AnchorProvider.env()); + const owner = anchor.Wallet.local().payer; + + const program = anchor.workspace.CpSwap as Program; + + const confirmOptions = { + skipPreflight: true, + }; + + it("deposit test, add the same liquidity and check the correctness of the values with and without transfer fees", async () => { + /// deposit without fee + const { poolAddress, poolState } = await setupDepositTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 0, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(0), + }, + { transferFeeBasisPoints: 0, MaxFee: 0 } + ); + + const { + onwerToken0Account: ownerToken0AccountBefore, + onwerToken1Account: ownerToken1AccountBefore, + poolVault0TokenAccount: poolVault0TokenAccountBefore, + poolVault1TokenAccount: poolVault1TokenAccountBefore, + } = await getUserAndPoolVaultAmount( + owner.publicKey, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + poolState.token0Vault, + poolState.token1Vault + ); + + const liquidity = new BN(10000000000); + await deposit( + program, + owner, + poolState.ammConfig, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + liquidity, + new BN(10000000000), + new BN(20000000000), + confirmOptions + ); + const newPoolState = await program.account.poolState.fetch(poolAddress); + assert(newPoolState.lpSupply.eq(liquidity.add(poolState.lpSupply))); + + const { + onwerToken0Account: ownerToken0AccountAfter, + onwerToken1Account: ownerToken1AccountAfter, + poolVault0TokenAccount: poolVault0TokenAccountAfter, + poolVault1TokenAccount: poolVault1TokenAccountAfter, + } = await getUserAndPoolVaultAmount( + owner.publicKey, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + poolState.token0Vault, + poolState.token1Vault + ); + const input_token0_amount = + ownerToken0AccountBefore.amount - ownerToken0AccountAfter.amount; + const input_token1_amount = + ownerToken1AccountBefore.amount - ownerToken1AccountAfter.amount; + assert.equal( + poolVault0TokenAccountAfter.amount - poolVault0TokenAccountBefore.amount, + input_token0_amount + ); + assert.equal( + poolVault1TokenAccountAfter.amount - poolVault1TokenAccountBefore.amount, + input_token1_amount + ); + + /// deposit with fee + const transferFeeConfig = { + transferFeeBasisPoints: 100, + MaxFee: 50000000000, + }; // %10 + + // Ensure that the initialization state is the same with depsoit without fee + const { poolAddress: poolAddress2, poolState: poolState2 } = + await setupDepositTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 0, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(0), + }, + transferFeeConfig, + confirmOptions, + { + initAmount0: new BN( + calculatePreFeeAmount( + transferFeeConfig, + poolVault0TokenAccountBefore.amount, + poolState.token0Program + ).toString() + ), + initAmount1: new BN( + calculatePreFeeAmount( + transferFeeConfig, + poolVault1TokenAccountBefore.amount, + poolState.token1Program + ).toString() + ), + }, + { + token0Program: poolState.token0Program, + token1Program: poolState.token1Program, + } + ); + const { + onwerToken0Account: onwerToken0AccountBefore2, + onwerToken1Account: onwerToken1AccountBefore2, + poolVault0TokenAccount: poolVault0TokenAccountBefore2, + poolVault1TokenAccount: poolVault1TokenAccountBefore2, + } = await getUserAndPoolVaultAmount( + owner.publicKey, + poolState2.token0Mint, + poolState2.token0Program, + poolState2.token1Mint, + poolState2.token1Program, + poolState2.token0Vault, + poolState2.token1Vault + ); + // check vault init state + assert.equal( + poolVault0TokenAccountBefore2.amount, + poolVault0TokenAccountBefore.amount + ); + assert.equal( + poolVault1TokenAccountBefore2.amount, + poolVault1TokenAccountBefore.amount + ); + + await deposit( + program, + owner, + poolState2.ammConfig, + poolState2.token0Mint, + poolState2.token0Program, + poolState2.token1Mint, + poolState2.token1Program, + liquidity, + new BN(100000000000), + new BN(200000000000), + confirmOptions + ); + const newPoolState2 = await program.account.poolState.fetch(poolAddress2); + assert(newPoolState2.lpSupply.eq(liquidity.add(poolState2.lpSupply))); + + const { + onwerToken0Account: onwerToken0AccountAfter2, + onwerToken1Account: onwerToken1AccountAfter2, + poolVault0TokenAccount: poolVault0TokenAccountAfter2, + poolVault1TokenAccount: poolVault1TokenAccountAfter2, + } = await getUserAndPoolVaultAmount( + owner.publicKey, + poolState2.token0Mint, + poolState2.token0Program, + poolState2.token1Mint, + poolState2.token1Program, + poolState2.token0Vault, + poolState2.token1Vault + ); + + const input_token0_amount_with_fee = + onwerToken0AccountBefore2.amount - onwerToken0AccountAfter2.amount; + const input_token1_amount_with_fee = + onwerToken1AccountBefore2.amount - onwerToken1AccountAfter2.amount; + assert(input_token0_amount_with_fee >= input_token0_amount); + assert(input_token1_amount_with_fee >= input_token1_amount); + + assert.equal( + input_token0_amount_with_fee, + calculateFee( + transferFeeConfig, + input_token0_amount_with_fee, + poolState2.token0Program + ) + input_token0_amount + ); + assert.equal( + input_token1_amount_with_fee, + calculateFee( + transferFeeConfig, + input_token1_amount_with_fee, + poolState2.token1Program + ) + input_token1_amount + ); + + // Add the same liquidity, the amount increment of the pool vault will be the same as without fees. + assert.equal( + poolVault0TokenAccountAfter2.amount - + poolVault0TokenAccountBefore2.amount, + input_token0_amount + ); + assert.equal( + poolVault1TokenAccountAfter2.amount - + poolVault1TokenAccountBefore2.amount, + input_token1_amount + ); + + assert.equal( + poolVault0TokenAccountAfter.amount, + poolVault0TokenAccountAfter2.amount + ); + assert.equal( + poolVault1TokenAccountAfter.amount, + poolVault1TokenAccountAfter2.amount + ); + }); + + it("deposit test with 100% transferFeeConfig, reache maximum fee limit", async () => { + const transferFeeConfig = { + transferFeeBasisPoints: MAX_FEE_BASIS_POINTS, + MaxFee: 5000000000, + }; // %100 + + const { poolAddress, poolState } = await setupDepositTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 0, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(0), + }, + transferFeeConfig + ); + + const { + onwerToken0Account: ownerToken0AccountBefore, + onwerToken1Account: ownerToken1AccountBefore, + poolVault0TokenAccount: poolVault0TokenAccountBefore, + poolVault1TokenAccount: poolVault1TokenAccountBefore, + } = await getUserAndPoolVaultAmount( + owner.publicKey, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + poolState.token0Vault, + poolState.token1Vault + ); + + const liquidity = new BN(10000000000); + await deposit( + program, + owner, + poolState.ammConfig, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + liquidity, + new BN(10000000000), + new BN(20000000000), + confirmOptions + ); + const newPoolState = await program.account.poolState.fetch(poolAddress); + assert(newPoolState.lpSupply.eq(liquidity.add(poolState.lpSupply))); + + const { + onwerToken0Account: ownerToken0AccountAfter, + onwerToken1Account: ownerToken1AccountAfter, + poolVault0TokenAccount: poolVault0TokenAccountAfter, + poolVault1TokenAccount: poolVault1TokenAccountAfter, + } = await getUserAndPoolVaultAmount( + owner.publicKey, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + poolState.token0Vault, + poolState.token1Vault + ); + const input_token0_amount = + ownerToken0AccountBefore.amount - ownerToken0AccountAfter.amount; + const input_token1_amount = + ownerToken1AccountBefore.amount - ownerToken1AccountAfter.amount; + + if (poolState.token0Program.equals(TOKEN_PROGRAM_ID)) { + assert.equal( + poolVault0TokenAccountAfter.amount - + poolVault0TokenAccountBefore.amount, + input_token0_amount + ); + assert.equal( + poolVault1TokenAccountAfter.amount - + poolVault1TokenAccountBefore.amount, + input_token1_amount - BigInt(transferFeeConfig.MaxFee) + ); + } else { + assert.equal( + poolVault0TokenAccountAfter.amount - + poolVault0TokenAccountBefore.amount, + input_token0_amount - BigInt(transferFeeConfig.MaxFee) + ); + assert.equal( + poolVault1TokenAccountAfter.amount - + poolVault1TokenAccountBefore.amount, + input_token1_amount + ); + } + }); +}); diff --git a/tests/initialize.test.ts b/tests/initialize.test.ts new file mode 100644 index 0000000..851759b --- /dev/null +++ b/tests/initialize.test.ts @@ -0,0 +1,183 @@ +import * as anchor from "@coral-xyz/anchor"; +import { Program, BN } from "@coral-xyz/anchor"; +import { CpSwap } from "../target/types/cp_swap"; + +import { getAccount, TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { setupInitializeTest, initialize, calculateFee } from "./utils"; +import { assert } from "chai"; + +describe("initialize test", () => { + anchor.setProvider(anchor.AnchorProvider.env()); + const owner = anchor.Wallet.local().payer; + console.log("owner: ", owner.publicKey.toString()); + + const program = anchor.workspace.CpSwap as Program; + + const confirmOptions = { + skipPreflight: true, + }; + + it("create pool without fee", async () => { + const { configAddress, token0, token0Program, token1, token1Program } = + await setupInitializeTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 0, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(0), + }, + { transferFeeBasisPoints: 0, MaxFee: 0 }, + confirmOptions + ); + + const initAmount0 = new BN(10000000000); + const initAmount1 = new BN(10000000000); + const { poolAddress, poolState } = await initialize( + program, + owner, + configAddress, + token0, + token0Program, + token1, + token1Program, + confirmOptions, + { initAmount0, initAmount1 } + ); + let vault0 = await getAccount( + anchor.getProvider().connection, + poolState.token0Vault, + "processed", + poolState.token0Program + ); + assert.equal(vault0.amount.toString(), initAmount0.toString()); + + let vault1 = await getAccount( + anchor.getProvider().connection, + poolState.token1Vault, + "processed", + poolState.token1Program + ); + assert.equal(vault1.amount.toString(), initAmount1.toString()); + }); + + it("create pool with fee", async () => { + const { configAddress, token0, token0Program, token1, token1Program } = + await setupInitializeTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 1, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(100000000), + }, + { transferFeeBasisPoints: 0, MaxFee: 0 }, + confirmOptions + ); + + const initAmount0 = new BN(10000000000); + const initAmount1 = new BN(10000000000); + const { poolAddress, poolState } = await initialize( + program, + owner, + configAddress, + token0, + token0Program, + token1, + token1Program, + confirmOptions, + { initAmount0, initAmount1 } + ); + let vault0 = await getAccount( + anchor.getProvider().connection, + poolState.token0Vault, + "processed", + poolState.token0Program + ); + assert.equal(vault0.amount.toString(), initAmount0.toString()); + + let vault1 = await getAccount( + anchor.getProvider().connection, + poolState.token1Vault, + "processed", + poolState.token1Program + ); + assert.equal(vault1.amount.toString(), initAmount1.toString()); + }); + + it("create pool with token2022 mint has transfer fee", async () => { + const transferFeeConfig = { transferFeeBasisPoints: 100, MaxFee: 50000000 }; // %10 + const { configAddress, token0, token0Program, token1, token1Program } = + await setupInitializeTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 1, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(100000000), + }, + transferFeeConfig, + confirmOptions + ); + + const initAmount0 = new BN(10000000000); + const initAmount1 = new BN(10000000000); + const { poolAddress, poolState } = await initialize( + program, + owner, + configAddress, + token0, + token0Program, + token1, + token1Program, + confirmOptions, + { initAmount0, initAmount1 } + ); + let vault0 = await getAccount( + anchor.getProvider().connection, + poolState.token0Vault, + "processed", + poolState.token0Program + ); + if (token0Program == TOKEN_PROGRAM_ID) { + assert.equal(vault0.amount.toString(), initAmount0.toString()); + } else { + const total = + vault0.amount + + calculateFee( + transferFeeConfig, + BigInt(initAmount0.toString()), + poolState.token0Program + ); + assert(new BN(total.toString()).gte(initAmount0)); + } + + let vault1 = await getAccount( + anchor.getProvider().connection, + poolState.token1Vault, + "processed", + poolState.token1Program + ); + if (token1Program == TOKEN_PROGRAM_ID) { + assert.equal(vault1.amount.toString(), initAmount1.toString()); + } else { + const total = + vault1.amount + + calculateFee( + transferFeeConfig, + BigInt(initAmount1.toString()), + poolState.token1Program + ); + assert(new BN(total.toString()).gte(initAmount1)); + } + }); +}); diff --git a/tests/swap.test.ts b/tests/swap.test.ts new file mode 100644 index 0000000..802985a --- /dev/null +++ b/tests/swap.test.ts @@ -0,0 +1,193 @@ +import * as anchor from "@coral-xyz/anchor"; +import { Program, BN } from "@coral-xyz/anchor"; +import { CpSwap } from "../target/types/cp_swap"; +import { setupSwapTest, swap_base_input, swap_base_output } from "./utils"; +import { assert } from "chai"; +import { getAccount, getAssociatedTokenAddressSync } from "@solana/spl-token"; + +describe("swap test", () => { + anchor.setProvider(anchor.AnchorProvider.env()); + const owner = anchor.Wallet.local().payer; + + const program = anchor.workspace.CpSwap as Program; + + const confirmOptions = { + skipPreflight: true, + }; + + it("swap base input without transfer fee", async () => { + const { configAddress, poolAddress, poolState } = await setupSwapTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 0, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(0), + }, + { transferFeeBasisPoints: 0, MaxFee: 0 } + ); + const inputToken = poolState.token0Mint; + const inputTokenProgram = poolState.token0Program; + const inputTokenAccountAddr = getAssociatedTokenAddressSync( + inputToken, + owner.publicKey, + false, + inputTokenProgram + ); + const inputTokenAccountBefore = await getAccount( + anchor.getProvider().connection, + inputTokenAccountAddr, + "processed", + inputTokenProgram + ); + let amount_in = new BN(100000000); + await swap_base_input( + program, + owner, + configAddress, + inputToken, + inputTokenProgram, + poolState.token1Mint, + poolState.token1Program, + amount_in, + new BN(0) + ); + const inputTokenAccountAfter = await getAccount( + anchor.getProvider().connection, + inputTokenAccountAddr, + "processed", + inputTokenProgram + ); + assert.equal( + inputTokenAccountBefore.amount - inputTokenAccountAfter.amount, + BigInt(amount_in.toString()) + ); + }); + + it("swap base output without transfer fee", async () => { + const { configAddress, poolAddress, poolState } = await setupSwapTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 0, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(0), + }, + { transferFeeBasisPoints: 0, MaxFee: 0 } + ); + const inputToken = poolState.token0Mint; + const inputTokenProgram = poolState.token0Program; + const inputTokenAccountAddr = getAssociatedTokenAddressSync( + inputToken, + owner.publicKey, + false, + inputTokenProgram + ); + const outputToken = poolState.token1Mint; + const outputTokenProgram = poolState.token1Program; + const outputTokenAccountAddr = getAssociatedTokenAddressSync( + outputToken, + owner.publicKey, + false, + outputTokenProgram + ); + const outputTokenAccountBefore = await getAccount( + anchor.getProvider().connection, + outputTokenAccountAddr, + "processed", + outputTokenProgram + ); + let amount_out = new BN(100000000); + await swap_base_output( + program, + owner, + configAddress, + inputToken, + inputTokenProgram, + poolState.token1Mint, + poolState.token1Program, + amount_out, + new BN(10000000000000), + confirmOptions + ); + const outputTokenAccountAfter = await getAccount( + anchor.getProvider().connection, + outputTokenAccountAddr, + "processed", + outputTokenProgram + ); + assert.equal( + outputTokenAccountAfter.amount - outputTokenAccountBefore.amount, + BigInt(amount_out.toString()) + ); + }); + + it("swap base output with transfer fee", async () => { + const transferFeeConfig = { transferFeeBasisPoints: 5, MaxFee: 5000 }; // %5 + const { configAddress, poolAddress, poolState } = await setupSwapTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 0, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(0), + }, + transferFeeConfig + ); + + const inputToken = poolState.token0Mint; + const inputTokenProgram = poolState.token0Program; + const inputTokenAccountAddr = getAssociatedTokenAddressSync( + inputToken, + owner.publicKey, + false, + inputTokenProgram + ); + const outputToken = poolState.token1Mint; + const outputTokenProgram = poolState.token1Program; + const outputTokenAccountAddr = getAssociatedTokenAddressSync( + outputToken, + owner.publicKey, + false, + outputTokenProgram + ); + const outputTokenAccountBefore = await getAccount( + anchor.getProvider().connection, + outputTokenAccountAddr, + "processed", + outputTokenProgram + ); + let amount_out = new BN(100000000); + await swap_base_output( + program, + owner, + configAddress, + inputToken, + inputTokenProgram, + poolState.token1Mint, + poolState.token1Program, + amount_out, + new BN(10000000000000), + confirmOptions + ); + const outputTokenAccountAfter = await getAccount( + anchor.getProvider().connection, + outputTokenAccountAddr, + "processed", + outputTokenProgram + ); + assert.equal( + outputTokenAccountAfter.amount - outputTokenAccountBefore.amount, + BigInt(amount_out.toString()) + ); + }); +}); diff --git a/tests/utils/fee.ts b/tests/utils/fee.ts new file mode 100644 index 0000000..d023ca9 --- /dev/null +++ b/tests/utils/fee.ts @@ -0,0 +1,46 @@ +import { + MAX_FEE_BASIS_POINTS, + ONE_IN_BASIS_POINTS, + TOKEN_PROGRAM_ID, +} from "@solana/spl-token"; +import { PublicKey } from "@solana/web3.js"; + +export function calculateFee( + transferFeeConfig: { transferFeeBasisPoints: number; MaxFee: number }, + preFeeAmount: bigint, + tokenProgram: PublicKey +): bigint { + if (tokenProgram.equals(TOKEN_PROGRAM_ID)) { + return BigInt(0); + } + if (preFeeAmount === BigInt(0)) { + return BigInt(0); + } else { + const numerator = + preFeeAmount * BigInt(transferFeeConfig.transferFeeBasisPoints); + const rawFee = + (numerator + ONE_IN_BASIS_POINTS - BigInt(1)) / ONE_IN_BASIS_POINTS; + const fee = + rawFee > transferFeeConfig.MaxFee ? transferFeeConfig.MaxFee : rawFee; + return BigInt(fee); + } +} + +export function calculatePreFeeAmount( + transferFeeConfig: { transferFeeBasisPoints: number; MaxFee: number }, + postFeeAmount: bigint, + tokenProgram: PublicKey +) { + if ( + transferFeeConfig.transferFeeBasisPoints == 0 || + tokenProgram.equals(TOKEN_PROGRAM_ID) + ) { + return postFeeAmount; + } else { + let numerator = postFeeAmount * BigInt(MAX_FEE_BASIS_POINTS); + let denominator = + MAX_FEE_BASIS_POINTS - transferFeeConfig.transferFeeBasisPoints; + + return (numerator + BigInt(denominator) - BigInt(1)) / BigInt(denominator); + } +} diff --git a/tests/utils/index.ts b/tests/utils/index.ts new file mode 100644 index 0000000..2bbbc15 --- /dev/null +++ b/tests/utils/index.ts @@ -0,0 +1,5 @@ +export * from "./web3"; +export * from "./pda"; +export * from "./util"; +export * from "./fee"; +export * from "./instruction"; diff --git a/tests/utils/instruction.ts b/tests/utils/instruction.ts new file mode 100644 index 0000000..eeff76a --- /dev/null +++ b/tests/utils/instruction.ts @@ -0,0 +1,627 @@ +import { Program, BN } from "@coral-xyz/anchor"; +import { CpSwap } from "../../target/types/cp_swap"; +import { + Connection, + ConfirmOptions, + PublicKey, + Keypair, + Signer, + SystemProgram, + SYSVAR_RENT_PUBKEY, +} from "@solana/web3.js"; +import { + TOKEN_PROGRAM_ID, + TOKEN_2022_PROGRAM_ID, + getAssociatedTokenAddressSync, +} from "@solana/spl-token"; +import { + accountExist, + sendTransaction, + getAmmConfigAddress, + getAuthAddress, + getPoolAddress, + getPoolLpMintAddress, + getPoolVaultAddress, + createTokenMintAndAssociatedTokenAccount, +} from "./index"; + +import { ASSOCIATED_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/utils/token"; + +export async function setupInitializeTest( + program: Program, + connection: Connection, + owner: Signer, + config: { + config_index: number; + tradeFeeRate: BN; + protocolFeeRate: BN; + fundFeeRate: BN; + create_fee: BN; + }, + transferFeeConfig: { transferFeeBasisPoints: number; MaxFee: number } = { + transferFeeBasisPoints: 0, + MaxFee: 0, + }, + confirmOptions?: ConfirmOptions +) { + const [{ token0, token0Program }, { token1, token1Program }] = + await createTokenMintAndAssociatedTokenAccount( + connection, + owner, + new Keypair(), + transferFeeConfig + ); + const configAddress = await createAmmConfig( + program, + connection, + owner, + config.config_index, + config.tradeFeeRate, + config.protocolFeeRate, + config.fundFeeRate, + config.create_fee, + confirmOptions + ); + return { + configAddress, + token0, + token0Program, + token1, + token1Program, + }; +} + +export async function setupDepositTest( + program: Program, + connection: Connection, + owner: Signer, + config: { + config_index: number; + tradeFeeRate: BN; + protocolFeeRate: BN; + fundFeeRate: BN; + create_fee: BN; + }, + transferFeeConfig: { transferFeeBasisPoints: number; MaxFee: number } = { + transferFeeBasisPoints: 0, + MaxFee: 0, + }, + confirmOptions?: ConfirmOptions, + initAmount: { initAmount0: BN; initAmount1: BN } = { + initAmount0: new BN(10000000000), + initAmount1: new BN(20000000000), + }, + tokenProgramRequired?: { + token0Program: PublicKey; + token1Program: PublicKey; + } +) { + const configAddress = await createAmmConfig( + program, + connection, + owner, + config.config_index, + config.tradeFeeRate, + config.protocolFeeRate, + config.fundFeeRate, + config.create_fee, + confirmOptions + ); + + while (1) { + const [{ token0, token0Program }, { token1, token1Program }] = + await createTokenMintAndAssociatedTokenAccount( + connection, + owner, + new Keypair(), + transferFeeConfig + ); + + if (tokenProgramRequired != undefined) { + if ( + token0Program.equals(tokenProgramRequired.token0Program) && + token1Program.equals(tokenProgramRequired.token1Program) + ) { + return await initialize( + program, + owner, + configAddress, + token0, + token0Program, + token1, + token1Program, + confirmOptions, + initAmount + ); + } + } else { + return await initialize( + program, + owner, + configAddress, + token0, + token0Program, + token1, + token1Program, + confirmOptions, + initAmount + ); + } + } +} + +export async function setupSwapTest( + program: Program, + connection: Connection, + owner: Signer, + config: { + config_index: number; + tradeFeeRate: BN; + protocolFeeRate: BN; + fundFeeRate: BN; + create_fee: BN; + }, + transferFeeConfig: { transferFeeBasisPoints: number; MaxFee: number } = { + transferFeeBasisPoints: 0, + MaxFee: 0, + }, + confirmOptions?: ConfirmOptions +) { + const configAddress = await createAmmConfig( + program, + connection, + owner, + config.config_index, + config.tradeFeeRate, + config.protocolFeeRate, + config.fundFeeRate, + config.create_fee, + confirmOptions + ); + + const [{ token0, token0Program }, { token1, token1Program }] = + await createTokenMintAndAssociatedTokenAccount( + connection, + owner, + new Keypair(), + transferFeeConfig + ); + + const { poolAddress, poolState } = await initialize( + program, + owner, + configAddress, + token0, + token0Program, + token1, + token1Program, + confirmOptions + ); + + await deposit( + program, + owner, + poolState.ammConfig, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + new BN(10000000000), + new BN(100000000000), + new BN(100000000000), + confirmOptions + ); + return { configAddress, poolAddress, poolState }; +} + +export async function createAmmConfig( + program: Program, + connection: Connection, + owner: Signer, + config_index: number, + tradeFeeRate: BN, + protocolFeeRate: BN, + fundFeeRate: BN, + create_fee: BN, + confirmOptions?: ConfirmOptions +): Promise { + const [address, _] = await getAmmConfigAddress( + config_index, + program.programId + ); + if (await accountExist(connection, address)) { + return address; + } + + const ix = await program.methods + .createAmmConfig( + config_index, + tradeFeeRate, + protocolFeeRate, + fundFeeRate, + create_fee + ) + .accounts({ + owner: owner.publicKey, + ammConfig: address, + systemProgram: SystemProgram.programId, + }) + .instruction(); + + const tx = await sendTransaction(connection, [ix], [owner], confirmOptions); + console.log("init amm config tx: ", tx); + return address; +} + +export async function initialize( + program: Program, + creator: Signer, + configAddress: PublicKey, + token0: PublicKey, + token0Program: PublicKey, + token1: PublicKey, + token1Program: PublicKey, + confirmOptions?: ConfirmOptions, + initAmount: { initAmount0: BN; initAmount1: BN } = { + initAmount0: new BN(10000000000), + initAmount1: new BN(20000000000), + }, + createPoolFee = new PublicKey("DNXgeM9EiiaAbaWvwjHj9fQQLAX5ZsfHyvmYUNRAdNC8") +) { + const [auth] = await getAuthAddress(program.programId); + const [poolAddress] = await getPoolAddress( + configAddress, + token0, + token1, + program.programId + ); + const [lpMintAddress] = await getPoolLpMintAddress( + poolAddress, + program.programId + ); + const [vault0] = await getPoolVaultAddress( + poolAddress, + token0, + program.programId + ); + const [vault1] = await getPoolVaultAddress( + poolAddress, + token1, + program.programId + ); + const [creatorLpTokenAddress] = await PublicKey.findProgramAddress( + [ + creator.publicKey.toBuffer(), + TOKEN_PROGRAM_ID.toBuffer(), + lpMintAddress.toBuffer(), + ], + ASSOCIATED_PROGRAM_ID + ); + + const creatorToken0 = getAssociatedTokenAddressSync( + token0, + creator.publicKey, + false, + token0Program + ); + const creatorToken1 = getAssociatedTokenAddressSync( + token1, + creator.publicKey, + false, + token1Program + ); + await program.methods + .initialize(initAmount.initAmount0, initAmount.initAmount1, new BN(0)) + .accounts({ + creator: creator.publicKey, + ammConfig: configAddress, + authority: auth, + poolState: poolAddress, + token0Mint: token0, + token1Mint: token1, + lpMint: lpMintAddress, + creatorToken0, + creatorToken1, + creatorLpToken: creatorLpTokenAddress, + token0Vault: vault0, + token1Vault: vault1, + createPoolFee, + tokenProgram: TOKEN_PROGRAM_ID, + token0Program: token0Program, + token1Program: token1Program, + systemProgram: SystemProgram.programId, + rent: SYSVAR_RENT_PUBKEY, + }) + .rpc(confirmOptions); + const poolState = await program.account.poolState.fetch(poolAddress); + return { poolAddress, poolState }; +} + +export async function deposit( + program: Program, + owner: Signer, + configAddress: PublicKey, + token0: PublicKey, + token0Program: PublicKey, + token1: PublicKey, + token1Program: PublicKey, + lp_token_amount: BN, + maximum_token_0_amount: BN, + maximum_token_1_amount: BN, + confirmOptions?: ConfirmOptions +) { + const [auth] = await getAuthAddress(program.programId); + const [poolAddress] = await getPoolAddress( + configAddress, + token0, + token1, + program.programId + ); + + const [lpMintAddress] = await getPoolLpMintAddress( + poolAddress, + program.programId + ); + const [vault0] = await getPoolVaultAddress( + poolAddress, + token0, + program.programId + ); + const [vault1] = await getPoolVaultAddress( + poolAddress, + token1, + program.programId + ); + const [ownerLpToken] = await PublicKey.findProgramAddress( + [ + owner.publicKey.toBuffer(), + TOKEN_PROGRAM_ID.toBuffer(), + lpMintAddress.toBuffer(), + ], + ASSOCIATED_PROGRAM_ID + ); + + const onwerToken0 = getAssociatedTokenAddressSync( + token0, + owner.publicKey, + false, + token0Program + ); + const onwerToken1 = getAssociatedTokenAddressSync( + token1, + owner.publicKey, + false, + token1Program + ); + + const tx = await program.methods + .deposit(lp_token_amount, maximum_token_0_amount, maximum_token_1_amount) + .accounts({ + owner: owner.publicKey, + authority: auth, + poolState: poolAddress, + ownerLpToken, + token0Account: onwerToken0, + token1Account: onwerToken1, + token0Vault: vault0, + token1Vault: vault1, + tokenProgram: TOKEN_PROGRAM_ID, + tokenProgram2022: TOKEN_2022_PROGRAM_ID, + vault0Mint: token0, + vault1Mint: token1, + lpMint: lpMintAddress, + }) + .rpc(confirmOptions); + return tx; +} + +export async function withdraw( + program: Program, + owner: Signer, + configAddress: PublicKey, + token0: PublicKey, + token0Program: PublicKey, + token1: PublicKey, + token1Program: PublicKey, + lp_token_amount: BN, + minimum_token_0_amount: BN, + minimum_token_1_amount: BN, + confirmOptions?: ConfirmOptions +) { + const [auth] = await getAuthAddress(program.programId); + const [poolAddress] = await getPoolAddress( + configAddress, + token0, + token1, + program.programId + ); + + const [lpMintAddress] = await getPoolLpMintAddress( + poolAddress, + program.programId + ); + const [vault0] = await getPoolVaultAddress( + poolAddress, + token0, + program.programId + ); + const [vault1] = await getPoolVaultAddress( + poolAddress, + token1, + program.programId + ); + const [ownerLpToken] = await PublicKey.findProgramAddress( + [ + owner.publicKey.toBuffer(), + TOKEN_PROGRAM_ID.toBuffer(), + lpMintAddress.toBuffer(), + ], + ASSOCIATED_PROGRAM_ID + ); + + const onwerToken0 = getAssociatedTokenAddressSync( + token0, + owner.publicKey, + false, + token0Program + ); + const onwerToken1 = getAssociatedTokenAddressSync( + token1, + owner.publicKey, + false, + token1Program + ); + + const tx = await program.methods + .withdraw(lp_token_amount, minimum_token_0_amount, minimum_token_1_amount) + .accounts({ + owner: owner.publicKey, + authority: auth, + poolState: poolAddress, + ownerLpToken, + token0Account: onwerToken0, + token1Account: onwerToken1, + token0Vault: vault0, + token1Vault: vault1, + tokenProgram: TOKEN_PROGRAM_ID, + tokenProgram2022: TOKEN_2022_PROGRAM_ID, + vault0Mint: token0, + vault1Mint: token1, + lpMint: lpMintAddress, + memoProgram: new PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"), + }) + .rpc(confirmOptions) + .catch(); + + return tx; +} + +export async function swap_base_input( + program: Program, + owner: Signer, + configAddress: PublicKey, + inputToken: PublicKey, + inputTokenProgram: PublicKey, + outputToken: PublicKey, + outputTokenProgram: PublicKey, + amount_in: BN, + minimum_amount_out: BN, + confirmOptions?: ConfirmOptions +) { + const [auth] = await getAuthAddress(program.programId); + const [poolAddress] = await getPoolAddress( + configAddress, + inputToken, + outputToken, + program.programId + ); + + const [inputVault] = await getPoolVaultAddress( + poolAddress, + inputToken, + program.programId + ); + const [outputVault] = await getPoolVaultAddress( + poolAddress, + outputToken, + program.programId + ); + + const inputTokenAccount = getAssociatedTokenAddressSync( + inputToken, + owner.publicKey, + false, + inputTokenProgram + ); + const outputTokenAccount = getAssociatedTokenAddressSync( + outputToken, + owner.publicKey, + false, + outputTokenProgram + ); + + const tx = await program.methods + .swapBaseInput(amount_in, minimum_amount_out) + .accounts({ + payer: owner.publicKey, + authority: auth, + ammConfig: configAddress, + poolState: poolAddress, + inputTokenAccount, + outputTokenAccount, + inputVault, + outputVault, + inputTokenProgram: inputTokenProgram, + outputTokenProgram: outputTokenProgram, + inputTokenMint: inputToken, + outputTokenMint: outputToken, + }) + .rpc(confirmOptions); + + return tx; +} + +export async function swap_base_output( + program: Program, + owner: Signer, + configAddress: PublicKey, + inputToken: PublicKey, + inputTokenProgram: PublicKey, + outputToken: PublicKey, + outputTokenProgram: PublicKey, + amount_out_less_fee: BN, + max_amount_in: BN, + confirmOptions?: ConfirmOptions +) { + const [auth] = await getAuthAddress(program.programId); + const [poolAddress] = await getPoolAddress( + configAddress, + inputToken, + outputToken, + program.programId + ); + + const [inputVault] = await getPoolVaultAddress( + poolAddress, + inputToken, + program.programId + ); + const [outputVault] = await getPoolVaultAddress( + poolAddress, + outputToken, + program.programId + ); + + const inputTokenAccount = getAssociatedTokenAddressSync( + inputToken, + owner.publicKey, + false, + inputTokenProgram + ); + const outputTokenAccount = getAssociatedTokenAddressSync( + outputToken, + owner.publicKey, + false, + outputTokenProgram + ); + + const tx = await program.methods + .swapBaseOutput(amount_out_less_fee, max_amount_in) + .accounts({ + payer: owner.publicKey, + authority: auth, + ammConfig: configAddress, + poolState: poolAddress, + inputTokenAccount, + outputTokenAccount, + inputVault, + outputVault, + inputTokenProgram: inputTokenProgram, + outputTokenProgram: outputTokenProgram, + inputTokenMint: inputToken, + outputTokenMint: outputToken, + }) + .rpc(confirmOptions); + + return tx; +} diff --git a/tests/utils/pda.ts b/tests/utils/pda.ts new file mode 100644 index 0000000..78bb0c1 --- /dev/null +++ b/tests/utils/pda.ts @@ -0,0 +1,107 @@ +import * as anchor from "@coral-xyz/anchor"; +import { PublicKey } from "@solana/web3.js"; +export const AMM_CONFIG_SEED = Buffer.from(anchor.utils.bytes.utf8.encode("amm_config")); +export const POOL_SEED = Buffer.from(anchor.utils.bytes.utf8.encode("pool")); +export const POOL_VAULT_SEED = Buffer.from( + anchor.utils.bytes.utf8.encode("pool_vault") +); +export const POOL_AUTH_SEED = Buffer.from( + anchor.utils.bytes.utf8.encode("vault_and_lp_mint_auth_seed") +); +export const POOL_LPMINT_SEED = Buffer.from( + anchor.utils.bytes.utf8.encode("pool_lp_mint") +); +export const TICK_ARRAY_SEED = Buffer.from(anchor.utils.bytes.utf8.encode("tick_array")); + +export const OPERATION_SEED = Buffer.from(anchor.utils.bytes.utf8.encode("operation")); + +export function u16ToBytes(num: number) { + const arr = new ArrayBuffer(2) + const view = new DataView(arr) + view.setUint16(0, num, false) + return new Uint8Array(arr) +} + +export function i16ToBytes(num: number) { + const arr = new ArrayBuffer(2) + const view = new DataView(arr) + view.setInt16(0, num, false) + return new Uint8Array(arr) +} + +export function u32ToBytes(num: number) { + const arr = new ArrayBuffer(4) + const view = new DataView(arr) + view.setUint32(0, num, false) + return new Uint8Array(arr) +} + +export function i32ToBytes(num: number) { + const arr = new ArrayBuffer(4) + const view = new DataView(arr) + view.setInt32(0, num, false) + return new Uint8Array(arr) +} + +export async function getAmmConfigAddress( + index: number, + programId: PublicKey +): Promise<[PublicKey, number]> { + const [address, bump] = await PublicKey.findProgramAddress( + [AMM_CONFIG_SEED, u16ToBytes(index)], + programId + ); + return [address, bump]; +} + +export async function getAuthAddress( + programId: PublicKey +): Promise<[PublicKey, number]> { + const [address, bump] = await PublicKey.findProgramAddress( + [POOL_AUTH_SEED], + programId + ); + return [address, bump]; +} + +export async function getPoolAddress( + ammConfig: PublicKey, + tokenMint0: PublicKey, + tokenMint1: PublicKey, + programId: PublicKey +): Promise<[PublicKey, number]> { + const [address, bump] = await PublicKey.findProgramAddress( + [ + POOL_SEED, + ammConfig.toBuffer(), + tokenMint0.toBuffer(), + tokenMint1.toBuffer(), + ], + programId + ); + return [address, bump]; +} + +export async function getPoolVaultAddress( + pool: PublicKey, + vaultTokenMint: PublicKey, + programId: PublicKey +): Promise<[PublicKey, number]> { + const [address, bump] = await PublicKey.findProgramAddress( + [POOL_VAULT_SEED, pool.toBuffer(), vaultTokenMint.toBuffer()], + programId + ); + return [address, bump]; +} + + +export async function getPoolLpMintAddress( + pool: PublicKey, + programId: PublicKey +): Promise<[PublicKey, number]> { + const [address, bump] = await PublicKey.findProgramAddress( + [POOL_LPMINT_SEED, pool.toBuffer()], + programId + ); + return [address, bump]; +} \ No newline at end of file diff --git a/tests/utils/util.ts b/tests/utils/util.ts new file mode 100644 index 0000000..4aa9857 --- /dev/null +++ b/tests/utils/util.ts @@ -0,0 +1,266 @@ +import * as anchor from "@coral-xyz/anchor"; +import { web3 } from "@coral-xyz/anchor"; +import { + Connection, + PublicKey, + Keypair, + Signer, + TransactionInstruction, + SystemProgram, + Transaction, + sendAndConfirmTransaction, +} from "@solana/web3.js"; +import { + createMint, + TOKEN_PROGRAM_ID, + getOrCreateAssociatedTokenAccount, + mintTo, + TOKEN_2022_PROGRAM_ID, + getAssociatedTokenAddressSync, + ExtensionType, + getMintLen, + createInitializeTransferFeeConfigInstruction, + createInitializeMintInstruction, + getAccount, +} from "@solana/spl-token"; +import { sendTransaction } from "./index"; + +// create a token mint and a token2022 mint with transferFeeConfig +export async function createTokenMintAndAssociatedTokenAccount( + connection: Connection, + payer: Signer, + mintAuthority: Signer, + transferFeeConfig: { transferFeeBasisPoints: number; MaxFee: number } +) { + let ixs: TransactionInstruction[] = []; + ixs.push( + web3.SystemProgram.transfer({ + fromPubkey: payer.publicKey, + toPubkey: mintAuthority.publicKey, + lamports: web3.LAMPORTS_PER_SOL, + }) + ); + await sendTransaction(connection, ixs, [payer]); + + interface Token { + address: PublicKey; + program: PublicKey; + } + + let tokenArray: Token[] = []; + let token0 = await createMint( + connection, + mintAuthority, + mintAuthority.publicKey, + null, + 9 + ); + tokenArray.push({ address: token0, program: TOKEN_PROGRAM_ID }); + + let token1 = await createMintWithTransferFee( + connection, + payer, + mintAuthority, + Keypair.generate(), + transferFeeConfig + ); + + tokenArray.push({ address: token1, program: TOKEN_2022_PROGRAM_ID }); + + tokenArray.sort(function (x, y) { + if (x.address < y.address) { + return -1; + } + if (x.address > y.address) { + return 1; + } + return 0; + }); + + token0 = tokenArray[0].address; + token1 = tokenArray[1].address; + // console.log("Token 0", token0.toString()); + // console.log("Token 1", token1.toString()); + const token0Program = tokenArray[0].program; + const token1Program = tokenArray[1].program; + + const ownerToken0Account = await getOrCreateAssociatedTokenAccount( + connection, + payer, + token0, + payer.publicKey, + false, + "processed", + { skipPreflight: true }, + token0Program + ); + + await mintTo( + connection, + payer, + token0, + ownerToken0Account.address, + mintAuthority, + 100_000_000_000_000, + [], + { skipPreflight: true }, + token0Program + ); + + // console.log( + // "ownerToken0Account key: ", + // ownerToken0Account.address.toString() + // ); + + const ownerToken1Account = await getOrCreateAssociatedTokenAccount( + connection, + payer, + token1, + payer.publicKey, + false, + "processed", + { skipPreflight: true }, + token1Program + ); + // console.log( + // "ownerToken1Account key: ", + // ownerToken1Account.address.toString() + // ); + await mintTo( + connection, + payer, + token1, + ownerToken1Account.address, + mintAuthority, + 100_000_000_000_000, + [], + { skipPreflight: true }, + token1Program + ); + + return [ + { token0, token0Program }, + { token1, token1Program }, + ]; +} + +async function createMintWithTransferFee( + connection: Connection, + payer: Signer, + mintAuthority: Signer, + mintKeypair = Keypair.generate(), + transferFeeConfig: { transferFeeBasisPoints: number; MaxFee: number } +) { + const transferFeeConfigAuthority = Keypair.generate(); + const withdrawWithheldAuthority = Keypair.generate(); + + const extensions = [ExtensionType.TransferFeeConfig]; + + const mintLen = getMintLen(extensions); + const decimals = 9; + + const mintLamports = await connection.getMinimumBalanceForRentExemption( + mintLen + ); + const mintTransaction = new Transaction().add( + SystemProgram.createAccount({ + fromPubkey: payer.publicKey, + newAccountPubkey: mintKeypair.publicKey, + space: mintLen, + lamports: mintLamports, + programId: TOKEN_2022_PROGRAM_ID, + }), + createInitializeTransferFeeConfigInstruction( + mintKeypair.publicKey, + transferFeeConfigAuthority.publicKey, + withdrawWithheldAuthority.publicKey, + transferFeeConfig.transferFeeBasisPoints, + BigInt(transferFeeConfig.MaxFee), + TOKEN_2022_PROGRAM_ID + ), + createInitializeMintInstruction( + mintKeypair.publicKey, + decimals, + mintAuthority.publicKey, + null, + TOKEN_2022_PROGRAM_ID + ) + ); + await sendAndConfirmTransaction( + connection, + mintTransaction, + [payer, mintKeypair], + undefined + ); + + return mintKeypair.publicKey; +} + +export async function getUserAndPoolVaultAmount( + owner: PublicKey, + token0Mint: PublicKey, + token0Program: PublicKey, + token1Mint: PublicKey, + token1Program: PublicKey, + poolToken0Vault: PublicKey, + poolToken1Vault: PublicKey +) { + const onwerToken0AccountAddr = getAssociatedTokenAddressSync( + token0Mint, + owner, + false, + token0Program + ); + + const onwerToken1AccountAddr = getAssociatedTokenAddressSync( + token1Mint, + owner, + false, + token1Program + ); + + const onwerToken0Account = await getAccount( + anchor.getProvider().connection, + onwerToken0AccountAddr, + "processed", + token0Program + ); + + const onwerToken1Account = await getAccount( + anchor.getProvider().connection, + onwerToken1AccountAddr, + "processed", + token1Program + ); + + const poolVault0TokenAccount = await getAccount( + anchor.getProvider().connection, + poolToken0Vault, + "processed", + token0Program + ); + + const poolVault1TokenAccount = await getAccount( + anchor.getProvider().connection, + poolToken1Vault, + "processed", + token1Program + ); + return { + onwerToken0Account, + onwerToken1Account, + poolVault0TokenAccount, + poolVault1TokenAccount, + }; +} + +export function isEqual(amount1: bigint, amount2: bigint) { + if ( + BigInt(amount1) === BigInt(amount2) || + BigInt(amount1) - BigInt(amount2) === BigInt(1) || + BigInt(amount1) - BigInt(amount2) === BigInt(-1) + ) { + return true; + } + return false; +} diff --git a/tests/utils/web3.ts b/tests/utils/web3.ts new file mode 100644 index 0000000..73b53de --- /dev/null +++ b/tests/utils/web3.ts @@ -0,0 +1,65 @@ +import * as anchor from "@coral-xyz/anchor"; +import { + Connection, + Signer, + Transaction, + TransactionInstruction, + TransactionSignature, + ConfirmOptions, +} from "@solana/web3.js"; + +export async function accountExist( + connection: anchor.web3.Connection, + account: anchor.web3.PublicKey +) { + const info = await connection.getAccountInfo(account); + if (info == null || info.data.length == 0) { + return false; + } + return true; +} + +export async function sendTransaction( + connection: Connection, + ixs: TransactionInstruction[], + signers: Array, + options?: ConfirmOptions +): Promise { + const tx = new Transaction(); + for (var i = 0; i < ixs.length; i++) { + tx.add(ixs[i]); + } + + if (options == undefined) { + options = { + preflightCommitment: "confirmed", + commitment: "confirmed", + }; + } + + const sendOpt = options && { + skipPreflight: options.skipPreflight, + preflightCommitment: options.preflightCommitment || options.commitment, + }; + + tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash; + const signature = await connection.sendTransaction(tx, signers, sendOpt); + + const status = ( + await connection.confirmTransaction(signature, options.commitment) + ).value; + + if (status.err) { + throw new Error( + `Raw transaction ${signature} failed (${JSON.stringify(status)})` + ); + } + return signature; +} + +export async function getBlockTimestamp( + connection: Connection +): Promise { + let slot = await connection.getSlot(); + return await connection.getBlockTime(slot); +} diff --git a/tests/withdraw.test.ts b/tests/withdraw.test.ts new file mode 100644 index 0000000..7c5921e --- /dev/null +++ b/tests/withdraw.test.ts @@ -0,0 +1,161 @@ +import * as anchor from "@coral-xyz/anchor"; +import { Program, BN } from "@coral-xyz/anchor"; +import { CpSwap } from "../target/types/cp_swap"; +import { + deposit, + getUserAndPoolVaultAmount, + isEqual, + setupDepositTest, + withdraw, +} from "./utils"; +import { assert } from "chai"; + +describe("withdraw test", () => { + anchor.setProvider(anchor.AnchorProvider.env()); + const owner = anchor.Wallet.local().payer; + const program = anchor.workspace.CpSwap as Program; + + const confirmOptions = { + skipPreflight: true, + }; + + it("withdraw half of lp ", async () => { + const { poolAddress, poolState } = await setupDepositTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 0, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(0), + }, + { transferFeeBasisPoints: 0, MaxFee: 0 } + ); + const liquidity = new BN(10000000000); + await deposit( + program, + owner, + poolState.ammConfig, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + liquidity, + new BN(10000000000), + new BN(20000000000) + ); + + await withdraw( + program, + owner, + poolState.ammConfig, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + liquidity.divn(2), + new BN(10000000), + new BN(1000000), + confirmOptions + ); + const newPoolState = await program.account.poolState.fetch(poolAddress); + assert(newPoolState.lpSupply.eq(liquidity.divn(2).add(poolState.lpSupply))); + }); + + it("withdraw all lp ", async () => { + const { poolAddress, poolState } = await setupDepositTest( + program, + anchor.getProvider().connection, + owner, + { + config_index: 0, + tradeFeeRate: new BN(10), + protocolFeeRate: new BN(1000), + fundFeeRate: new BN(25000), + create_fee: new BN(0), + }, + { transferFeeBasisPoints: 0, MaxFee: 0 } + ); + const liquidity = new BN(10000000000); + const { + onwerToken0Account: ownerToken0AccountBefore, + onwerToken1Account: ownerToken1AccountBefore, + poolVault0TokenAccount: poolVault0TokenAccountBefore, + poolVault1TokenAccount: poolVault1TokenAccountBefore, + } = await getUserAndPoolVaultAmount( + owner.publicKey, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + poolState.token0Vault, + poolState.token1Vault + ); + + await deposit( + program, + owner, + poolState.ammConfig, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + liquidity, + new BN(10000000000), + new BN(20000000000) + ); + + await withdraw( + program, + owner, + poolState.ammConfig, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + liquidity, + new BN(10000000), + new BN(1000000), + confirmOptions + ); + + const newPoolState = await program.account.poolState.fetch(poolAddress); + assert(newPoolState.lpSupply.eq(poolState.lpSupply)); + + const { + onwerToken0Account: ownerToken0AccountAfter, + onwerToken1Account: ownerToken1AccountAfter, + poolVault0TokenAccount: poolVault0TokenAccountAfter, + poolVault1TokenAccount: poolVault1TokenAccountAfter, + } = await getUserAndPoolVaultAmount( + owner.publicKey, + poolState.token0Mint, + poolState.token0Program, + poolState.token1Mint, + poolState.token1Program, + poolState.token0Vault, + poolState.token1Vault + ); + + assert( + isEqual(ownerToken0AccountBefore.amount, ownerToken0AccountAfter.amount) + ); + assert( + isEqual(ownerToken1AccountBefore.amount, ownerToken1AccountAfter.amount) + ); + assert( + isEqual( + poolVault0TokenAccountBefore.amount, + poolVault0TokenAccountAfter.amount + ) + ); + assert( + isEqual( + poolVault1TokenAccountBefore.amount, + poolVault1TokenAccountAfter.amount + ) + ); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..558b83e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "commonjs", + "target": "es6", + "esModuleInterop": true + } + } + \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..30f05ea --- /dev/null +++ b/yarn.lock @@ -0,0 +1,2469 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 6 + cacheKey: 8 + +"@babel/runtime@npm:^7.17.2, @babel/runtime@npm:^7.23.4": + version: 7.23.9 + resolution: "@babel/runtime@npm:7.23.9" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 6bbebe8d27c0c2dd275d1ac197fc1a6c00e18dab68cc7aaff0adc3195b45862bae9c4cc58975629004b0213955b2ed91e99eccb3d9b39cabea246c657323d667 + languageName: node + linkType: hard + +"@coral-xyz/anchor@npm:^0.29.0": + version: 0.29.0 + resolution: "@coral-xyz/anchor@npm:0.29.0" + dependencies: + "@coral-xyz/borsh": ^0.29.0 + "@noble/hashes": ^1.3.1 + "@solana/web3.js": ^1.68.0 + bn.js: ^5.1.2 + bs58: ^4.0.1 + buffer-layout: ^1.2.2 + camelcase: ^6.3.0 + cross-fetch: ^3.1.5 + crypto-hash: ^1.3.0 + eventemitter3: ^4.0.7 + pako: ^2.0.3 + snake-case: ^3.0.4 + superstruct: ^0.15.4 + toml: ^3.0.0 + checksum: 10c4e6c5557653419683f5ae22ec47ac266b64e5b422d466885cf2dc7efa8f836239bdf321495d3e2b3ce03e766667c0e2192cc573fbd66bc12cc652f5146e10 + languageName: node + linkType: hard + +"@coral-xyz/borsh@npm:^0.29.0": + version: 0.29.0 + resolution: "@coral-xyz/borsh@npm:0.29.0" + dependencies: + bn.js: ^5.1.2 + buffer-layout: ^1.2.0 + peerDependencies: + "@solana/web3.js": ^1.68.0 + checksum: 37006c75cd012672adf48e10234062624634da2a9335e34b7ff30969f58aff78cc3073b66a3edc806b52f038469f0c477a5a3ed35aaa075f3cbd44d7133ac218 + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: ^5.1.2 + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: ^7.0.1 + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: ^8.1.0 + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 4a473b9b32a7d4d3cfb7a614226e555091ff0c5a29a1734c28c72a182c2f6699b26fc6b5c2131dfd841e86b185aea714c72201d7c98c2fba5f17709333a67aeb + languageName: node + linkType: hard + +"@noble/curves@npm:^1.2.0": + version: 1.3.0 + resolution: "@noble/curves@npm:1.3.0" + dependencies: + "@noble/hashes": 1.3.3 + checksum: b65342ee66c4a440eee2978524412eabba9a9efdd16d6370e15218c6a7d80bddf35e66bb57ed52c0dfd32cb9a717b439ab3a72db618f1a0066dfebe3fd12a421 + languageName: node + linkType: hard + +"@noble/hashes@npm:1.3.3, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:^1.3.2": + version: 1.3.3 + resolution: "@noble/hashes@npm:1.3.3" + checksum: 8a6496d1c0c64797339bc694ad06cdfaa0f9e56cd0c3f68ae3666cfb153a791a55deb0af9c653c7ed2db64d537aa3e3054629740d2f2338bb1dcb7ab60cd205b + languageName: node + linkType: hard + +"@npmcli/agent@npm:^2.0.0": + version: 2.2.1 + resolution: "@npmcli/agent@npm:2.2.1" + dependencies: + agent-base: ^7.1.0 + http-proxy-agent: ^7.0.0 + https-proxy-agent: ^7.0.1 + lru-cache: ^10.0.1 + socks-proxy-agent: ^8.0.1 + checksum: c69aca42dbba393f517bc5777ee872d38dc98ea0e5e93c1f6d62b82b8fecdc177a57ea045f07dda1a770c592384b2dd92a5e79e21e2a7cf51c9159466a8f9c9b + languageName: node + linkType: hard + +"@npmcli/fs@npm:^3.1.0": + version: 3.1.0 + resolution: "@npmcli/fs@npm:3.1.0" + dependencies: + semver: ^7.3.5 + checksum: a50a6818de5fc557d0b0e6f50ec780a7a02ab8ad07e5ac8b16bf519e0ad60a144ac64f97d05c443c3367235d337182e1d012bbac0eb8dbae8dc7b40b193efd0e + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f + languageName: node + linkType: hard + +"@solana/buffer-layout-utils@npm:^0.2.0": + version: 0.2.0 + resolution: "@solana/buffer-layout-utils@npm:0.2.0" + dependencies: + "@solana/buffer-layout": ^4.0.0 + "@solana/web3.js": ^1.32.0 + bigint-buffer: ^1.1.5 + bignumber.js: ^9.0.1 + checksum: 9284242245b18b49577195ba7548263850be865a4a2d183944fa01bb76382039db589aab8473698e9bb734b515ada9b4d70db0a72e341c5d567c59b83d6d0840 + languageName: node + linkType: hard + +"@solana/buffer-layout@npm:^4.0.0, @solana/buffer-layout@npm:^4.0.1": + version: 4.0.1 + resolution: "@solana/buffer-layout@npm:4.0.1" + dependencies: + buffer: ~6.0.3 + checksum: bf846888e813187243d4008a7a9f58b49d16cbd995b9d7f1b72898aa510ed77b1ce5e8468e7b2fd26dd81e557a4e74a666e21fccb95f123c1f740d41138bbacd + languageName: node + linkType: hard + +"@solana/codecs-core@npm:2.0.0-experimental.8618508": + version: 2.0.0-experimental.8618508 + resolution: "@solana/codecs-core@npm:2.0.0-experimental.8618508" + checksum: 3f16d037b0cb7347e87b94558cf90cb10c8e50c08856d057b2844dc9ae19a5721e04f03058fa4ad45f7529531f6c2678c0cb088c6711169951a11c1ef508da57 + languageName: node + linkType: hard + +"@solana/codecs-data-structures@npm:2.0.0-experimental.8618508": + version: 2.0.0-experimental.8618508 + resolution: "@solana/codecs-data-structures@npm:2.0.0-experimental.8618508" + dependencies: + "@solana/codecs-core": 2.0.0-experimental.8618508 + "@solana/codecs-numbers": 2.0.0-experimental.8618508 + checksum: 1a72f82cad338bb6153eb7687fef860dffa2d1701961fc529f5051007a029f302621e92a05a51ad1d23a3bc4aa1d02d517cac0f4b28e9819d91686e18becd07c + languageName: node + linkType: hard + +"@solana/codecs-numbers@npm:2.0.0-experimental.8618508": + version: 2.0.0-experimental.8618508 + resolution: "@solana/codecs-numbers@npm:2.0.0-experimental.8618508" + dependencies: + "@solana/codecs-core": 2.0.0-experimental.8618508 + checksum: 7c80fc0a2deb654fb5e43b8cc267f6105eab6d9e18afcef43374768c82fa088d58b4872adc608c74b0f54a9e0822f4ae49772137d436d323b2b327770d867df7 + languageName: node + linkType: hard + +"@solana/codecs-strings@npm:2.0.0-experimental.8618508": + version: 2.0.0-experimental.8618508 + resolution: "@solana/codecs-strings@npm:2.0.0-experimental.8618508" + dependencies: + "@solana/codecs-core": 2.0.0-experimental.8618508 + "@solana/codecs-numbers": 2.0.0-experimental.8618508 + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + checksum: 0186dbf1c6933ba451e0f5dc7be1092220d7a5551ee97ae09259d2b736d52273dbbda6dbf4bb847ed251fb1849399b4dc76889998d3bea1648c930b1c3ead895 + languageName: node + linkType: hard + +"@solana/options@npm:2.0.0-experimental.8618508": + version: 2.0.0-experimental.8618508 + resolution: "@solana/options@npm:2.0.0-experimental.8618508" + dependencies: + "@solana/codecs-core": 2.0.0-experimental.8618508 + "@solana/codecs-numbers": 2.0.0-experimental.8618508 + checksum: d260faec7a44d5c2e95edcea756fe5690bdc6685b2e4ee078226e74319eee6ab931aeedfb580b420e1c5987a1d28304898ed03cdcf6b19e253460a3101080c75 + languageName: node + linkType: hard + +"@solana/spl-token-metadata@npm:^0.1.2": + version: 0.1.2 + resolution: "@solana/spl-token-metadata@npm:0.1.2" + dependencies: + "@solana/codecs-core": 2.0.0-experimental.8618508 + "@solana/codecs-data-structures": 2.0.0-experimental.8618508 + "@solana/codecs-numbers": 2.0.0-experimental.8618508 + "@solana/codecs-strings": 2.0.0-experimental.8618508 + "@solana/options": 2.0.0-experimental.8618508 + "@solana/spl-type-length-value": 0.1.0 + peerDependencies: + "@solana/web3.js": ^1.87.6 + checksum: 9cd90aed86a2fcfa40cd209b61553641524c01d9888eb4a36f053315dfdc544aa66ad0e7a22d27a30d904648c0ec5c9db11791ac6fa87ec15a44322f7bf5077b + languageName: node + linkType: hard + +"@solana/spl-token@npm:^0.4.0": + version: 0.4.0 + resolution: "@solana/spl-token@npm:0.4.0" + dependencies: + "@solana/buffer-layout": ^4.0.0 + "@solana/buffer-layout-utils": ^0.2.0 + "@solana/spl-token-metadata": ^0.1.2 + buffer: ^6.0.3 + peerDependencies: + "@solana/web3.js": ^1.89.1 + checksum: 6f578ea2019f46b8ac87a696377d9c08e227227da4f623b1f4e6c0b25cc2d2dda55b1ef63b909ac39d83d75d630d106f61df03887f2abc7d69d477dbd106d0ad + languageName: node + linkType: hard + +"@solana/spl-type-length-value@npm:0.1.0": + version: 0.1.0 + resolution: "@solana/spl-type-length-value@npm:0.1.0" + dependencies: + buffer: ^6.0.3 + checksum: 9bea6d9638fd2093db4542b12ac657407950737bd00ed919448308df59bfeb9d97a96e471d7824ba4077daeb01bbb0cf9e410d412767555e49a5bfc6bfb9bc91 + languageName: node + linkType: hard + +"@solana/web3.js@npm:^1.32.0, @solana/web3.js@npm:^1.90.0": + version: 1.90.0 + resolution: "@solana/web3.js@npm:1.90.0" + dependencies: + "@babel/runtime": ^7.23.4 + "@noble/curves": ^1.2.0 + "@noble/hashes": ^1.3.2 + "@solana/buffer-layout": ^4.0.1 + agentkeepalive: ^4.5.0 + bigint-buffer: ^1.1.5 + bn.js: ^5.2.1 + borsh: ^0.7.0 + bs58: ^4.0.1 + buffer: 6.0.3 + fast-stable-stringify: ^1.0.0 + jayson: ^4.1.0 + node-fetch: ^2.7.0 + rpc-websockets: ^7.5.1 + superstruct: ^0.14.2 + checksum: 8ea1bb731b7d399285005e386d328e284d2884ebdf3e80c6c3845b2278248f12379e6a2765c3471f319d09061dabde1cf0a0e9b300e9537408c613713df52b70 + languageName: node + linkType: hard + +"@solana/web3.js@npm:^1.68.0": + version: 1.89.1 + resolution: "@solana/web3.js@npm:1.89.1" + dependencies: + "@babel/runtime": ^7.23.4 + "@noble/curves": ^1.2.0 + "@noble/hashes": ^1.3.2 + "@solana/buffer-layout": ^4.0.1 + agentkeepalive: ^4.5.0 + bigint-buffer: ^1.1.5 + bn.js: ^5.2.1 + borsh: ^0.7.0 + bs58: ^4.0.1 + buffer: 6.0.3 + fast-stable-stringify: ^1.0.0 + jayson: ^4.1.0 + node-fetch: ^2.7.0 + rpc-websockets: ^7.5.1 + superstruct: ^0.14.2 + checksum: 4c87fdefa4f750cbb308e6d41e74d2f4bb42a31b2fc8df195daa46fc26cbde4f2e1ed46b8308481d9372371b192d6f81a7c69315248e080e4f7fffc87a0d3087 + languageName: node + linkType: hard + +"@types/bn.js@npm:^5.1.0": + version: 5.1.5 + resolution: "@types/bn.js@npm:5.1.5" + dependencies: + "@types/node": "*" + checksum: c87b28c4af74545624f8a3dae5294b16aa190c222626e8d4b2e327b33b1a3f1eeb43e7a24d914a9774bca43d8cd6e1cb0325c1f4b3a244af6693a024e1d918e6 + languageName: node + linkType: hard + +"@types/chai@npm:^4.3.0": + version: 4.3.11 + resolution: "@types/chai@npm:4.3.11" + checksum: d0c05fe5d02b2e6bbca2bd4866a2ab20a59cf729bc04af0060e7a3277eaf2fb65651b90d4c74b0ebf1d152b4b1d49fa8e44143acef276a2bbaa7785fbe5642d3 + languageName: node + linkType: hard + +"@types/connect@npm:^3.4.33": + version: 3.4.38 + resolution: "@types/connect@npm:3.4.38" + dependencies: + "@types/node": "*" + checksum: 7eb1bc5342a9604facd57598a6c62621e244822442976c443efb84ff745246b10d06e8b309b6e80130026a396f19bf6793b7cecd7380169f369dac3bfc46fb99 + languageName: node + linkType: hard + +"@types/json5@npm:^0.0.29": + version: 0.0.29 + resolution: "@types/json5@npm:0.0.29" + checksum: e60b153664572116dfea673c5bda7778dbff150498f44f998e34b5886d8afc47f16799280e4b6e241c0472aef1bc36add771c569c68fc5125fc2ae519a3eb9ac + languageName: node + linkType: hard + +"@types/mocha@npm:^9.0.0": + version: 9.1.1 + resolution: "@types/mocha@npm:9.1.1" + checksum: 516077c0acd9806dc78317f88aaac0df5aaf0bdc2f63dfdadeabdf0b0137953b6ca65472e6ff7c30bc93ce4e0ae76eae70e8d46764b9a8eae4877a928b6ef49a + languageName: node + linkType: hard + +"@types/node@npm:*": + version: 20.11.16 + resolution: "@types/node@npm:20.11.16" + dependencies: + undici-types: ~5.26.4 + checksum: 51f0831c1219bf4698e7430aeb9892237bd851deeb25ce23c5bb0ceefcc77c3b114e48f4e98d9fc26def5a87ba9d8079f0281dd37bee691140a93f133812c152 + languageName: node + linkType: hard + +"@types/node@npm:^12.12.54": + version: 12.20.55 + resolution: "@types/node@npm:12.20.55" + checksum: e4f86785f4092706e0d3b0edff8dca5a13b45627e4b36700acd8dfe6ad53db71928c8dee914d4276c7fd3b6ccd829aa919811c9eb708a2c8e4c6eb3701178c37 + languageName: node + linkType: hard + +"@types/ws@npm:^7.4.4": + version: 7.4.7 + resolution: "@types/ws@npm:7.4.7" + dependencies: + "@types/node": "*" + checksum: b4c9b8ad209620c9b21e78314ce4ff07515c0cadab9af101c1651e7bfb992d7fd933bd8b9c99d110738fd6db523ed15f82f29f50b45510288da72e964dedb1a3 + languageName: node + linkType: hard + +"@ungap/promise-all-settled@npm:1.1.2": + version: 1.1.2 + resolution: "@ungap/promise-all-settled@npm:1.1.2" + checksum: 08d37fdfa23a6fe8139f1305313562ebad973f3fac01bcce2773b2bda5bcb0146dfdcf3cb6a722cf0a5f2ca0bc56a827eac8f1e7b3beddc548f654addf1fc34c + languageName: node + linkType: hard + +"JSONStream@npm:^1.3.5": + version: 1.3.5 + resolution: "JSONStream@npm:1.3.5" + dependencies: + jsonparse: ^1.2.0 + through: ">=2.2.7 <3" + bin: + JSONStream: ./bin.js + checksum: 2605fa124260c61bad38bb65eba30d2f72216a78e94d0ab19b11b4e0327d572b8d530c0c9cc3b0764f727ad26d39e00bf7ebad57781ca6368394d73169c59e46 + languageName: node + linkType: hard + +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 0e994ad2aa6575f94670d8a2149afe94465de9cedaaaac364e7fb43a40c3691c980ff74899f682f4ca58fa96b4cbd7421a015d3a6defe43a442117d7821a2f36 + languageName: node + linkType: hard + +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": + version: 7.1.0 + resolution: "agent-base@npm:7.1.0" + dependencies: + debug: ^4.3.4 + checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f + languageName: node + linkType: hard + +"agentkeepalive@npm:^4.5.0": + version: 4.5.0 + resolution: "agentkeepalive@npm:4.5.0" + dependencies: + humanize-ms: ^1.2.1 + checksum: 13278cd5b125e51eddd5079f04d6fe0914ac1b8b91c1f3db2c1822f99ac1a7457869068997784342fe455d59daaff22e14fb7b8c3da4e741896e7e31faf92481 + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: ^2.0.0 + indent-string: ^4.0.0 + checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 + languageName: node + linkType: hard + +"ansi-colors@npm:4.1.1": + version: 4.1.1 + resolution: "ansi-colors@npm:4.1.1" + checksum: 138d04a51076cb085da0a7e2d000c5c0bb09f6e772ed5c65c53cb118d37f6c5f1637506d7155fb5f330f0abcf6f12fa2e489ac3f8cdab9da393bf1bb4f9a32b0 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: ^2.0.1 + checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 + languageName: node + linkType: hard + +"anymatch@npm:~3.1.2": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" + dependencies: + normalize-path: ^3.0.0 + picomatch: ^2.0.4 + checksum: 3e044fd6d1d26545f235a9fe4d7a534e2029d8e59fa7fd9f2a6eb21230f6b5380ea1eaf55136e60cbf8e613544b3b766e7a6fa2102e2a3a117505466e3025dc2 + languageName: node + linkType: hard + +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: 83644b56493e89a254bae05702abf3a1101b4fa4d0ca31df1c9985275a5a5bd47b3c27b7fa0b71098d41114d8ca000e6ed90cad764b306f8a503665e4d517ced + languageName: node + linkType: hard + +"arrify@npm:^1.0.0": + version: 1.0.1 + resolution: "arrify@npm:1.0.1" + checksum: 745075dd4a4624ff0225c331dacb99be501a515d39bcb7c84d24660314a6ec28e68131b137e6f7e16318170842ce97538cd298fc4cd6b2cc798e0b957f2747e7 + languageName: node + linkType: hard + +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 + languageName: node + linkType: hard + +"base-x@npm:^3.0.2": + version: 3.0.9 + resolution: "base-x@npm:3.0.9" + dependencies: + safe-buffer: ^5.0.1 + checksum: 957101d6fd09e1903e846fd8f69fd7e5e3e50254383e61ab667c725866bec54e5ece5ba49ce385128ae48f9ec93a26567d1d5ebb91f4d56ef4a9cc0d5a5481e8 + languageName: node + linkType: hard + +"base64-js@npm:^1.3.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 + languageName: node + linkType: hard + +"bigint-buffer@npm:^1.1.5": + version: 1.1.5 + resolution: "bigint-buffer@npm:1.1.5" + dependencies: + bindings: ^1.3.0 + node-gyp: latest + checksum: d010c9f57758bcdaccb435d88b483ffcc95fe8bbc6e7fb3a44fb5221f29c894ffaf4a3c5a4a530e0e7d6608203c2cde9b79ee4f2386cd6d4462d1070bc8c9f4e + languageName: node + linkType: hard + +"bignumber.js@npm:^9.0.1": + version: 9.1.2 + resolution: "bignumber.js@npm:9.1.2" + checksum: 582c03af77ec9cb0ebd682a373ee6c66475db94a4325f92299621d544aa4bd45cb45fd60001610e94aef8ae98a0905fa538241d9638d4422d57abbeeac6fadaf + languageName: node + linkType: hard + +"binary-extensions@npm:^2.0.0": + version: 2.2.0 + resolution: "binary-extensions@npm:2.2.0" + checksum: ccd267956c58d2315f5d3ea6757cf09863c5fc703e50fbeb13a7dc849b812ef76e3cf9ca8f35a0c48498776a7478d7b4a0418e1e2b8cb9cb9731f2922aaad7f8 + languageName: node + linkType: hard + +"bindings@npm:^1.3.0": + version: 1.5.0 + resolution: "bindings@npm:1.5.0" + dependencies: + file-uri-to-path: 1.0.0 + checksum: 65b6b48095717c2e6105a021a7da4ea435aa8d3d3cd085cb9e85bcb6e5773cf318c4745c3f7c504412855940b585bdf9b918236612a1c7a7942491de176f1ae7 + languageName: node + linkType: hard + +"bn.js@npm:^5.1.2, bn.js@npm:^5.2.0, bn.js@npm:^5.2.1": + version: 5.2.1 + resolution: "bn.js@npm:5.2.1" + checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3 + languageName: node + linkType: hard + +"borsh@npm:^0.7.0": + version: 0.7.0 + resolution: "borsh@npm:0.7.0" + dependencies: + bn.js: ^5.2.0 + bs58: ^4.0.0 + text-encoding-utf-8: ^1.0.2 + checksum: e98bfb5f7cfb820819c2870b884dac58dd4b4ce6a86c286c8fbf5c9ca582e73a8c6094df67e81a28c418ff07a309c6b118b2e27fdfea83fd92b8100c741da0b5 + languageName: node + linkType: hard + +"brace-expansion@npm:^1.1.7": + version: 1.1.11 + resolution: "brace-expansion@npm:1.1.11" + dependencies: + balanced-match: ^1.0.0 + concat-map: 0.0.1 + checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: ^1.0.0 + checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 + languageName: node + linkType: hard + +"braces@npm:~3.0.2": + version: 3.0.2 + resolution: "braces@npm:3.0.2" + dependencies: + fill-range: ^7.0.1 + checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 + languageName: node + linkType: hard + +"browser-stdout@npm:1.3.1": + version: 1.3.1 + resolution: "browser-stdout@npm:1.3.1" + checksum: b717b19b25952dd6af483e368f9bcd6b14b87740c3d226c2977a65e84666ffd67000bddea7d911f111a9b6ddc822b234de42d52ab6507bce4119a4cc003ef7b3 + languageName: node + linkType: hard + +"bs58@npm:^4.0.0, bs58@npm:^4.0.1": + version: 4.0.1 + resolution: "bs58@npm:4.0.1" + dependencies: + base-x: ^3.0.2 + checksum: b3c5365bb9e0c561e1a82f1a2d809a1a692059fae016be233a6127ad2f50a6b986467c3a50669ce4c18929dcccb297c5909314dd347a25a68c21b68eb3e95ac2 + languageName: node + linkType: hard + +"buffer-from@npm:^1.0.0, buffer-from@npm:^1.1.0": + version: 1.1.2 + resolution: "buffer-from@npm:1.1.2" + checksum: 0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb + languageName: node + linkType: hard + +"buffer-layout@npm:^1.2.0, buffer-layout@npm:^1.2.2": + version: 1.2.2 + resolution: "buffer-layout@npm:1.2.2" + checksum: e5809ba275530bf4e52fd09558b7c2111fbda5b405124f581acf364261d9c154e271800271898cd40473f9bcbb42c31584efb04219bde549d3460ca4bafeaa07 + languageName: node + linkType: hard + +"buffer@npm:6.0.3, buffer@npm:^6.0.3, buffer@npm:~6.0.3": + version: 6.0.3 + resolution: "buffer@npm:6.0.3" + dependencies: + base64-js: ^1.3.1 + ieee754: ^1.2.1 + checksum: 5ad23293d9a731e4318e420025800b42bf0d264004c0286c8cc010af7a270c7a0f6522e84f54b9ad65cbd6db20b8badbfd8d2ebf4f80fa03dab093b89e68c3f9 + languageName: node + linkType: hard + +"bufferutil@npm:^4.0.1": + version: 4.0.8 + resolution: "bufferutil@npm:4.0.8" + dependencies: + node-gyp: latest + node-gyp-build: ^4.3.0 + checksum: 7e9a46f1867dca72fda350966eb468eca77f4d623407b0650913fadf73d5750d883147d6e5e21c56f9d3b0bdc35d5474e80a600b9f31ec781315b4d2469ef087 + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.2 + resolution: "cacache@npm:18.0.2" + dependencies: + "@npmcli/fs": ^3.1.0 + fs-minipass: ^3.0.0 + glob: ^10.2.2 + lru-cache: ^10.0.1 + minipass: ^7.0.3 + minipass-collect: ^2.0.1 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + p-map: ^4.0.0 + ssri: ^10.0.0 + tar: ^6.1.11 + unique-filename: ^3.0.0 + checksum: 0250df80e1ad0c828c956744850c5f742c24244e9deb5b7dc81bca90f8c10e011e132ecc58b64497cc1cad9a98968676147fb6575f4f94722f7619757b17a11b + languageName: node + linkType: hard + +"camelcase@npm:^6.0.0, camelcase@npm:^6.3.0": + version: 6.3.0 + resolution: "camelcase@npm:6.3.0" + checksum: 8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d + languageName: node + linkType: hard + +"chai@npm:^4.3.4": + version: 4.4.1 + resolution: "chai@npm:4.4.1" + dependencies: + assertion-error: ^1.1.0 + check-error: ^1.0.3 + deep-eql: ^4.1.3 + get-func-name: ^2.0.2 + loupe: ^2.3.6 + pathval: ^1.1.1 + type-detect: ^4.0.8 + checksum: 9ab84f36eb8e0b280c56c6c21ca4da5933132cd8a0c89c384f1497f77953640db0bc151edd47f81748240a9fab57b78f7d925edfeedc8e8fc98016d71f40c36e + languageName: node + linkType: hard + +"chalk@npm:^4.1.0": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: ^4.1.0 + supports-color: ^7.1.0 + checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc + languageName: node + linkType: hard + +"check-error@npm:^1.0.3": + version: 1.0.3 + resolution: "check-error@npm:1.0.3" + dependencies: + get-func-name: ^2.0.2 + checksum: e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399 + languageName: node + linkType: hard + +"chokidar@npm:3.5.3": + version: 3.5.3 + resolution: "chokidar@npm:3.5.3" + dependencies: + anymatch: ~3.1.2 + braces: ~3.0.2 + fsevents: ~2.3.2 + glob-parent: ~5.1.2 + is-binary-path: ~2.1.0 + is-glob: ~4.0.1 + normalize-path: ~3.0.0 + readdirp: ~3.6.0 + dependenciesMeta: + fsevents: + optional: true + checksum: b49fcde40176ba007ff361b198a2d35df60d9bb2a5aab228279eb810feae9294a6b4649ab15981304447afe1e6ffbf4788ad5db77235dc770ab777c6e771980c + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 + languageName: node + linkType: hard + +"cliui@npm:^7.0.2": + version: 7.0.4 + resolution: "cliui@npm:7.0.4" + dependencies: + string-width: ^4.2.0 + strip-ansi: ^6.0.0 + wrap-ansi: ^7.0.0 + checksum: ce2e8f578a4813806788ac399b9e866297740eecd4ad1823c27fd344d78b22c5f8597d548adbcc46f0573e43e21e751f39446c5a5e804a12aace402b7a315d7f + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: ~1.1.4 + checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 + languageName: node + linkType: hard + +"commander@npm:^2.20.3": + version: 2.20.3 + resolution: "commander@npm:2.20.3" + checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e + languageName: node + linkType: hard + +"concat-map@npm:0.0.1": + version: 0.0.1 + resolution: "concat-map@npm:0.0.1" + checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af + languageName: node + linkType: hard + +"cross-fetch@npm:^3.1.5": + version: 3.1.8 + resolution: "cross-fetch@npm:3.1.8" + dependencies: + node-fetch: ^2.6.12 + checksum: 78f993fa099eaaa041122ab037fe9503ecbbcb9daef234d1d2e0b9230a983f64d645d088c464e21a247b825a08dc444a6e7064adfa93536d3a9454b4745b3632 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: ^3.1.0 + shebang-command: ^2.0.0 + which: ^2.0.1 + checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 + languageName: node + linkType: hard + +"crypto-hash@npm:^1.3.0": + version: 1.3.0 + resolution: "crypto-hash@npm:1.3.0" + checksum: a3a507e0d2b18fbd2da8088a1c62d0c53c009a99bbfa6d851cac069734ffa546922fa51bdd776d006459701cdda873463e5059ece3431aca048fd99e7573d138 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.3.4": + version: 4.3.4 + resolution: "debug@npm:4.3.4" + dependencies: + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 + languageName: node + linkType: hard + +"debug@npm:4.3.3": + version: 4.3.3 + resolution: "debug@npm:4.3.3" + dependencies: + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 14472d56fe4a94dbcfaa6dbed2dd3849f1d72ba78104a1a328047bb564643ca49df0224c3a17fa63533fd11dd3d4c8636cd861191232a2c6735af00cc2d4de16 + languageName: node + linkType: hard + +"decamelize@npm:^4.0.0": + version: 4.0.0 + resolution: "decamelize@npm:4.0.0" + checksum: b7d09b82652c39eead4d6678bb578e3bebd848add894b76d0f6b395bc45b2d692fb88d977e7cfb93c4ed6c119b05a1347cef261174916c2e75c0a8ca57da1809 + languageName: node + linkType: hard + +"deep-eql@npm:^4.1.3": + version: 4.1.3 + resolution: "deep-eql@npm:4.1.3" + dependencies: + type-detect: ^4.0.0 + checksum: 7f6d30cb41c713973dc07eaadded848b2ab0b835e518a88b91bea72f34e08c4c71d167a722a6f302d3a6108f05afd8e6d7650689a84d5d29ec7fe6220420397f + languageName: node + linkType: hard + +"delay@npm:^5.0.0": + version: 5.0.0 + resolution: "delay@npm:5.0.0" + checksum: 62f151151ecfde0d9afbb8a6be37a6d103c4cb24f35a20ef3fe56f920b0d0d0bb02bc9c0a3084d0179ef669ca332b91155f2ee4d9854622cd2cdba5fc95285f9 + languageName: node + linkType: hard + +"diff@npm:5.0.0": + version: 5.0.0 + resolution: "diff@npm:5.0.0" + checksum: f19fe29284b633afdb2725c2a8bb7d25761ea54d321d8e67987ac851c5294be4afeab532bd84531e02583a3fe7f4014aa314a3eda84f5590e7a9e6b371ef3b46 + languageName: node + linkType: hard + +"diff@npm:^3.1.0": + version: 3.5.0 + resolution: "diff@npm:3.5.0" + checksum: 00842950a6551e26ce495bdbce11047e31667deea546527902661f25cc2e73358967ebc78cf86b1a9736ec3e14286433225f9970678155753a6291c3bca5227b + languageName: node + linkType: hard + +"dot-case@npm:^3.0.4": + version: 3.0.4 + resolution: "dot-case@npm:3.0.4" + dependencies: + no-case: ^3.0.4 + tslib: ^2.0.3 + checksum: a65e3519414856df0228b9f645332f974f2bf5433370f544a681122eab59e66038fc3349b4be1cdc47152779dac71a5864f1ccda2f745e767c46e9c6543b1169 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 7d00d7cd8e49b9afa762a813faac332dee781932d6f2c848dc348939c4253f1d4564341b7af1d041853bc3f32c2ef141b58e0a4d9862c17a7f08f68df1e0f1ed + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: ^0.6.2 + checksum: bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 65b5df55a8bab92229ab2b40dad3b387fad24613263d103a97f91c9fe43ceb21965cd3392b1ccb5d77088021e525c4e0481adb309625d0cb94ade1d1fb8dc17e + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 8b7b1be20d2de12d2255c0bc2ca638b7af5171142693299416e6a9339bd7d88fc8d7707d913d78e0993176005405a236b066b45666b27b797252c771156ace54 + languageName: node + linkType: hard + +"es6-promise@npm:^4.0.3": + version: 4.2.8 + resolution: "es6-promise@npm:4.2.8" + checksum: 95614a88873611cb9165a85d36afa7268af5c03a378b35ca7bda9508e1d4f1f6f19a788d4bc755b3fd37c8ebba40782018e02034564ff24c9d6fa37e959ad57d + languageName: node + linkType: hard + +"es6-promisify@npm:^5.0.0": + version: 5.0.0 + resolution: "es6-promisify@npm:5.0.0" + dependencies: + es6-promise: ^4.0.3 + checksum: fbed9d791598831413be84a5374eca8c24800ec71a16c1c528c43a98e2dadfb99331483d83ae6094ddb9b87e6f799a15d1553cebf756047e0865c753bc346b92 + languageName: node + linkType: hard + +"escalade@npm:^3.1.1": + version: 3.1.1 + resolution: "escalade@npm:3.1.1" + checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 + languageName: node + linkType: hard + +"escape-string-regexp@npm:4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: 98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 + languageName: node + linkType: hard + +"eventemitter3@npm:^4.0.7": + version: 4.0.7 + resolution: "eventemitter3@npm:4.0.7" + checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374 + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 3d21519a4f8207c99f7457287291316306255a328770d320b401114ec8481986e4e467e854cb9914dd965e0a1ca810a23ccb559c642c88f4c7f55c55778a9b48 + languageName: node + linkType: hard + +"eyes@npm:^0.1.8": + version: 0.1.8 + resolution: "eyes@npm:0.1.8" + checksum: c31703a92bf36ba75ee8d379ee7985c24ee6149f3a6175f44cec7a05b178c38bce9836d3ca48c9acb0329a960ac2c4b2ead4e60cdd4fe6e8c92cad7cd6913687 + languageName: node + linkType: hard + +"fast-stable-stringify@npm:^1.0.0": + version: 1.0.0 + resolution: "fast-stable-stringify@npm:1.0.0" + checksum: ef1203d246a7e8ac15e2bfbda0a89fa375947bccf9f7910be0ea759856dbe8ea5024a0d8cc2cceabe18a9cb67e95927b78bb6173a3ae37ec55a518cf36e5244b + languageName: node + linkType: hard + +"file-uri-to-path@npm:1.0.0": + version: 1.0.0 + resolution: "file-uri-to-path@npm:1.0.0" + checksum: b648580bdd893a008c92c7ecc96c3ee57a5e7b6c4c18a9a09b44fb5d36d79146f8e442578bc0e173dc027adf3987e254ba1dfd6e3ec998b7c282873010502144 + languageName: node + linkType: hard + +"fill-range@npm:^7.0.1": + version: 7.0.1 + resolution: "fill-range@npm:7.0.1" + dependencies: + to-regex-range: ^5.0.1 + checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 + languageName: node + linkType: hard + +"find-up@npm:5.0.0": + version: 5.0.0 + resolution: "find-up@npm:5.0.0" + dependencies: + locate-path: ^6.0.0 + path-exists: ^4.0.0 + checksum: 07955e357348f34660bde7920783204ff5a26ac2cafcaa28bace494027158a97b9f56faaf2d89a6106211a8174db650dd9f503f9c0d526b1202d5554a00b9095 + languageName: node + linkType: hard + +"flat@npm:^5.0.2": + version: 5.0.2 + resolution: "flat@npm:5.0.2" + bin: + flat: cli.js + checksum: 12a1536ac746db74881316a181499a78ef953632ddd28050b7a3a43c62ef5462e3357c8c29d76072bb635f147f7a9a1f0c02efef6b4be28f8db62ceb3d5c7f5d + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.1.1 + resolution: "foreground-child@npm:3.1.1" + dependencies: + cross-spawn: ^7.0.0 + signal-exit: ^4.0.1 + checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: ^3.0.0 + checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: ^7.0.3 + checksum: 8722a41109130851d979222d3ec88aabaceeaaf8f57b2a8f744ef8bd2d1ce95453b04a61daa0078822bc5cd21e008814f06fe6586f56fef511e71b8d2394d802 + languageName: node + linkType: hard + +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 + languageName: node + linkType: hard + +"fsevents@npm:~2.3.2": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: latest + checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@~2.3.2#~builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + +"get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: b9769a836d2a98c3ee734a88ba712e62703f1df31b94b784762c433c27a386dd6029ff55c2a920c392e33657d80191edbf18c61487e198844844516f843496b9 + languageName: node + linkType: hard + +"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b + languageName: node + linkType: hard + +"glob-parent@npm:~5.1.2": + version: 5.1.2 + resolution: "glob-parent@npm:5.1.2" + dependencies: + is-glob: ^4.0.1 + checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e + languageName: node + linkType: hard + +"glob@npm:7.2.0": + version: 7.2.0 + resolution: "glob@npm:7.2.0" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^3.0.4 + once: ^1.3.0 + path-is-absolute: ^1.0.0 + checksum: 78a8ea942331f08ed2e055cb5b9e40fe6f46f579d7fd3d694f3412fe5db23223d29b7fee1575440202e9a7ff9a72ab106a39fee39934c7bedafe5e5f8ae20134 + languageName: node + linkType: hard + +"glob@npm:^10.2.2, glob@npm:^10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.3.5 + minimatch: ^9.0.1 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + path-scurry: ^1.10.1 + bin: + glob: dist/esm/bin.mjs + checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 + languageName: node + linkType: hard + +"graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 + languageName: node + linkType: hard + +"growl@npm:1.10.5": + version: 1.10.5 + resolution: "growl@npm:1.10.5" + checksum: 4b86685de6831cebcbb19f93870bea624afee61124b0a20c49017013987cd129e73a8c4baeca295728f41d21265e1f859d25ef36731b142ca59c655fea94bb1a + languageName: node + linkType: hard + +"has-flag@npm:^4.0.0": + version: 4.0.0 + resolution: "has-flag@npm:4.0.0" + checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad + languageName: node + linkType: hard + +"he@npm:1.2.0": + version: 1.2.0 + resolution: "he@npm:1.2.0" + bin: + he: bin/he + checksum: 3d4d6babccccd79c5c5a3f929a68af33360d6445587d628087f39a965079d84f18ce9c3d3f917ee1e3978916fc833bb8b29377c3b403f919426f91bc6965e7a7 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: ^7.1.0 + debug: ^4.3.4 + checksum: 670858c8f8f3146db5889e1fa117630910101db601fff7d5a8aa637da0abedf68c899f03d3451cac2f83bcc4c3d2dabf339b3aa00ff8080571cceb02c3ce02f3 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.4 + resolution: "https-proxy-agent@npm:7.0.4" + dependencies: + agent-base: ^7.0.2 + debug: 4 + checksum: daaab857a967a2519ddc724f91edbbd388d766ff141b9025b629f92b9408fc83cee8a27e11a907aede392938e9c398e240d643e178408a59e4073539cde8cfe9 + languageName: node + linkType: hard + +"humanize-ms@npm:^1.2.1": + version: 1.2.1 + resolution: "humanize-ms@npm:1.2.1" + dependencies: + ms: ^2.0.0 + checksum: 9c7a74a2827f9294c009266c82031030eae811ca87b0da3dceb8d6071b9bde22c9f3daef0469c3c533cc67a97d8a167cd9fc0389350e5f415f61a79b171ded16 + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: ">= 2.1.2 < 3.0.0" + checksum: 3f60d47a5c8fc3313317edfd29a00a692cc87a19cac0159e2ce711d0ebc9019064108323b5e493625e25594f11c6236647d8e256fbe7a58f4a3b33b89e6d30bf + languageName: node + linkType: hard + +"ieee754@npm:^1.2.1": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 + languageName: node + linkType: hard + +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: ^1.3.0 + wrappy: 1 + checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd + languageName: node + linkType: hard + +"inherits@npm:2": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 + languageName: node + linkType: hard + +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: 1.1.0 + sprintf-js: ^1.1.3 + checksum: aa15f12cfd0ef5e38349744e3654bae649a34c3b10c77a674a167e99925d1549486c5b14730eebce9fea26f6db9d5e42097b00aa4f9f612e68c79121c71652dc + languageName: node + linkType: hard + +"is-binary-path@npm:~2.1.0": + version: 2.1.0 + resolution: "is-binary-path@npm:2.1.0" + dependencies: + binary-extensions: ^2.0.0 + checksum: 84192eb88cff70d320426f35ecd63c3d6d495da9d805b19bc65b518984b7c0760280e57dbf119b7e9be6b161784a5a673ab2c6abe83abb5198a432232ad5b35c + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 + languageName: node + linkType: hard + +"is-glob@npm:^4.0.1, is-glob@npm:~4.0.1": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: ^2.1.1 + checksum: d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4 + languageName: node + linkType: hard + +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 + languageName: node + linkType: hard + +"is-number@npm:^7.0.0": + version: 7.0.0 + resolution: "is-number@npm:7.0.0" + checksum: 456ac6f8e0f3111ed34668a624e45315201dff921e5ac181f8ec24923b99e9f32ca1a194912dc79d539c97d33dba17dc635202ff0b2cf98326f608323276d27a + languageName: node + linkType: hard + +"is-plain-obj@npm:^2.1.0": + version: 2.1.0 + resolution: "is-plain-obj@npm:2.1.0" + checksum: cec9100678b0a9fe0248a81743041ed990c2d4c99f893d935545cfbc42876cbe86d207f3b895700c690ad2fa520e568c44afc1605044b535a7820c1d40e38daa + languageName: node + linkType: hard + +"is-unicode-supported@npm:^0.1.0": + version: 0.1.0 + resolution: "is-unicode-supported@npm:0.1.0" + checksum: a2aab86ee7712f5c2f999180daaba5f361bdad1efadc9610ff5b8ab5495b86e4f627839d085c6530363c6d6d4ecbde340fb8e54bdb83da4ba8e0865ed5513c52 + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + +"isomorphic-ws@npm:^4.0.1": + version: 4.0.1 + resolution: "isomorphic-ws@npm:4.0.1" + peerDependencies: + ws: "*" + checksum: d7190eadefdc28bdb93d67b5f0c603385aaf87724fa2974abb382ac1ec9756ed2cfb27065cbe76122879c2d452e2982bc4314317f3d6c737ddda6c047328771a + languageName: node + linkType: hard + +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 57d43ad11eadc98cdfe7496612f6bbb5255ea69fe51ea431162db302c2a11011642f50cfad57288bd0aea78384a0612b16e131944ad8ecd09d619041c8531b54 + languageName: node + linkType: hard + +"jayson@npm:^4.1.0": + version: 4.1.0 + resolution: "jayson@npm:4.1.0" + dependencies: + "@types/connect": ^3.4.33 + "@types/node": ^12.12.54 + "@types/ws": ^7.4.4 + JSONStream: ^1.3.5 + commander: ^2.20.3 + delay: ^5.0.0 + es6-promisify: ^5.0.0 + eyes: ^0.1.8 + isomorphic-ws: ^4.0.1 + json-stringify-safe: ^5.0.1 + uuid: ^8.3.2 + ws: ^7.4.5 + bin: + jayson: bin/jayson.js + checksum: 86464322fbdc6db65d2bb4fc278cb6c86fad5c2a506065490d39459f09ba0d30f2b4fb740b33828a1424791419b6c8bd295dc54d361a4ad959bf70cc62b1ca7e + languageName: node + linkType: hard + +"js-yaml@npm:4.1.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" + dependencies: + argparse: ^2.0.1 + bin: + js-yaml: bin/js-yaml.js + checksum: c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a + languageName: node + linkType: hard + +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965 + languageName: node + linkType: hard + +"json-stringify-safe@npm:^5.0.1": + version: 5.0.1 + resolution: "json-stringify-safe@npm:5.0.1" + checksum: 48ec0adad5280b8a96bb93f4563aa1667fd7a36334f79149abd42446d0989f2ddc58274b479f4819f1f00617957e6344c886c55d05a4e15ebb4ab931e4a6a8ee + languageName: node + linkType: hard + +"json5@npm:^1.0.2": + version: 1.0.2 + resolution: "json5@npm:1.0.2" + dependencies: + minimist: ^1.2.0 + bin: + json5: lib/cli.js + checksum: 866458a8c58a95a49bef3adba929c625e82532bcff1fe93f01d29cb02cac7c3fe1f4b79951b7792c2da9de0b32871a8401a6e3c5b36778ad852bf5b8a61165d7 + languageName: node + linkType: hard + +"jsonparse@npm:^1.2.0": + version: 1.3.1 + resolution: "jsonparse@npm:1.3.1" + checksum: 6514a7be4674ebf407afca0eda3ba284b69b07f9958a8d3113ef1005f7ec610860c312be067e450c569aab8b89635e332cee3696789c750692bb60daba627f4d + languageName: node + linkType: hard + +"locate-path@npm:^6.0.0": + version: 6.0.0 + resolution: "locate-path@npm:6.0.0" + dependencies: + p-locate: ^5.0.0 + checksum: 72eb661788a0368c099a184c59d2fee760b3831c9c1c33955e8a19ae4a21b4116e53fa736dc086cdeb9fce9f7cc508f2f92d2d3aae516f133e16a2bb59a39f5a + languageName: node + linkType: hard + +"log-symbols@npm:4.1.0": + version: 4.1.0 + resolution: "log-symbols@npm:4.1.0" + dependencies: + chalk: ^4.1.0 + is-unicode-supported: ^0.1.0 + checksum: fce1497b3135a0198803f9f07464165e9eb83ed02ceb2273930a6f8a508951178d8cf4f0378e9d28300a2ed2bc49050995d2bd5f53ab716bb15ac84d58c6ef74 + languageName: node + linkType: hard + +"loupe@npm:^2.3.6": + version: 2.3.7 + resolution: "loupe@npm:2.3.7" + dependencies: + get-func-name: ^2.0.1 + checksum: 96c058ec7167598e238bb7fb9def2f9339215e97d6685d9c1e3e4bdb33d14600e11fe7a812cf0c003dfb73ca2df374f146280b2287cae9e8d989e9d7a69a203b + languageName: node + linkType: hard + +"lower-case@npm:^2.0.2": + version: 2.0.2 + resolution: "lower-case@npm:2.0.2" + dependencies: + tslib: ^2.0.3 + checksum: 83a0a5f159ad7614bee8bf976b96275f3954335a84fad2696927f609ddae902802c4f3312d86668722e668bef41400254807e1d3a7f2e8c3eede79691aa1f010 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.2.0 + resolution: "lru-cache@npm:10.2.0" + checksum: eee7ddda4a7475deac51ac81d7dd78709095c6fa46e8350dc2d22462559a1faa3b81ed931d5464b13d48cbd7e08b46100b6f768c76833912bc444b99c37e25db + languageName: node + linkType: hard + +"lru-cache@npm:^6.0.0": + version: 6.0.0 + resolution: "lru-cache@npm:6.0.0" + dependencies: + yallist: ^4.0.0 + checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 + languageName: node + linkType: hard + +"make-error@npm:^1.1.1": + version: 1.3.6 + resolution: "make-error@npm:1.3.6" + checksum: b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^13.0.0": + version: 13.0.0 + resolution: "make-fetch-happen@npm:13.0.0" + dependencies: + "@npmcli/agent": ^2.0.0 + cacache: ^18.0.0 + http-cache-semantics: ^4.1.1 + is-lambda: ^1.0.1 + minipass: ^7.0.2 + minipass-fetch: ^3.0.0 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + negotiator: ^0.6.3 + promise-retry: ^2.0.1 + ssri: ^10.0.0 + checksum: 7c7a6d381ce919dd83af398b66459a10e2fe8f4504f340d1d090d3fa3d1b0c93750220e1d898114c64467223504bd258612ba83efbc16f31b075cd56de24b4af + languageName: node + linkType: hard + +"minimatch@npm:4.2.1": + version: 4.2.1 + resolution: "minimatch@npm:4.2.1" + dependencies: + brace-expansion: ^1.1.7 + checksum: 2b1514e3d0f29a549912f0db7ae7b82c5cab4a8f2dd0369f1c6451a325b3f12b2cf473c95873b6157bb8df183d6cf6db82ff03614b6adaaf1d7e055beccdfd01 + languageName: node + linkType: hard + +"minimatch@npm:^3.0.4": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" + dependencies: + brace-expansion: ^1.1.7 + checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a + languageName: node + linkType: hard + +"minimatch@npm:^9.0.1": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" + dependencies: + brace-expansion: ^2.0.1 + checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 + languageName: node + linkType: hard + +"minimist@npm:^1.2.0, minimist@npm:^1.2.6": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: ^7.0.3 + checksum: b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 + languageName: node + linkType: hard + +"minipass-fetch@npm:^3.0.0": + version: 3.0.4 + resolution: "minipass-fetch@npm:3.0.4" + dependencies: + encoding: ^0.1.13 + minipass: ^7.0.3 + minipass-sized: ^1.0.3 + minizlib: ^2.1.2 + dependenciesMeta: + encoding: + optional: true + checksum: af7aad15d5c128ab1ebe52e043bdf7d62c3c6f0cecb9285b40d7b395e1375b45dcdfd40e63e93d26a0e8249c9efd5c325c65575aceee192883970ff8cb11364a + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: ^3.0.0 + checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: ^3.0.0 + checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: ^3.0.0 + checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: ^4.0.0 + checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: 425dab288738853fded43da3314a0b5c035844d6f3097a8e3b5b29b328da8f3c1af6fc70618b32c29ff906284cf6406b6841376f21caaadd0793c1d5a6a620ea + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": + version: 7.0.4 + resolution: "minipass@npm:7.0.4" + checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: ^3.0.0 + yallist: ^4.0.0 + checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 + languageName: node + linkType: hard + +"mkdirp@npm:^0.5.1": + version: 0.5.6 + resolution: "mkdirp@npm:0.5.6" + dependencies: + minimist: ^1.2.6 + bin: + mkdirp: bin/cmd.js + checksum: 0c91b721bb12c3f9af4b77ebf73604baf350e64d80df91754dc509491ae93bf238581e59c7188360cec7cb62fc4100959245a42cfe01834efedc5e9d068376c2 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f + languageName: node + linkType: hard + +"mocha@npm:^9.0.3": + version: 9.2.2 + resolution: "mocha@npm:9.2.2" + dependencies: + "@ungap/promise-all-settled": 1.1.2 + ansi-colors: 4.1.1 + browser-stdout: 1.3.1 + chokidar: 3.5.3 + debug: 4.3.3 + diff: 5.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 7.2.0 + growl: 1.10.5 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 4.2.1 + ms: 2.1.3 + nanoid: 3.3.1 + serialize-javascript: 6.0.0 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + which: 2.0.2 + workerpool: 6.2.0 + yargs: 16.2.0 + yargs-parser: 20.2.4 + yargs-unparser: 2.0.0 + bin: + _mocha: bin/_mocha + mocha: bin/mocha + checksum: 4d5ca4ce33fc66627e63acdf09a634e2358c9a00f61de7788b1091b6aad430da04f97f9ecb82d56dc034b623cb833b65576136fd010d77679c03fcea5bc1e12d + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f + languageName: node + linkType: hard + +"ms@npm:2.1.3, ms@npm:^2.0.0": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d + languageName: node + linkType: hard + +"nanoid@npm:3.3.1": + version: 3.3.1 + resolution: "nanoid@npm:3.3.1" + bin: + nanoid: bin/nanoid.cjs + checksum: 4ef0969e1bbe866fc223eb32276cbccb0961900bfe79104fa5abe34361979dead8d0e061410a5c03bc3d47455685adf32c09d6f27790f4a6898fb51f7df7ec86 + languageName: node + linkType: hard + +"negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 + languageName: node + linkType: hard + +"no-case@npm:^3.0.4": + version: 3.0.4 + resolution: "no-case@npm:3.0.4" + dependencies: + lower-case: ^2.0.2 + tslib: ^2.0.3 + checksum: 0b2ebc113dfcf737d48dde49cfebf3ad2d82a8c3188e7100c6f375e30eafbef9e9124aadc3becef237b042fd5eb0aad2fd78669c20972d045bbe7fea8ba0be5c + languageName: node + linkType: hard + +"node-fetch@npm:^2.6.12, node-fetch@npm:^2.7.0": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: ^5.0.0 + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: d76d2f5edb451a3f05b15115ec89fc6be39de37c6089f1b6368df03b91e1633fd379a7e01b7ab05089a25034b2023d959b47e59759cb38d88341b2459e89d6e5 + languageName: node + linkType: hard + +"node-gyp-build@npm:^4.3.0": + version: 4.8.0 + resolution: "node-gyp-build@npm:4.8.0" + bin: + node-gyp-build: bin.js + node-gyp-build-optional: optional.js + node-gyp-build-test: build-test.js + checksum: b82a56f866034b559dd3ed1ad04f55b04ae381b22ec2affe74b488d1582473ca6e7f85fccf52da085812d3de2b0bf23109e752a57709ac7b9963951c710fea40 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.0.1 + resolution: "node-gyp@npm:10.0.1" + dependencies: + env-paths: ^2.2.0 + exponential-backoff: ^3.1.1 + glob: ^10.3.10 + graceful-fs: ^4.2.6 + make-fetch-happen: ^13.0.0 + nopt: ^7.0.0 + proc-log: ^3.0.0 + semver: ^7.3.5 + tar: ^6.1.2 + which: ^4.0.0 + bin: + node-gyp: bin/node-gyp.js + checksum: 60a74e66d364903ce02049966303a57f898521d139860ac82744a5fdd9f7b7b3b61f75f284f3bfe6e6add3b8f1871ce305a1d41f775c7482de837b50c792223f + languageName: node + linkType: hard + +"nopt@npm:^7.0.0": + version: 7.2.0 + resolution: "nopt@npm:7.2.0" + dependencies: + abbrev: ^2.0.0 + bin: + nopt: bin/nopt.js + checksum: a9c0f57fb8cb9cc82ae47192ca2b7ef00e199b9480eed202482c962d61b59a7fbe7541920b2a5839a97b42ee39e288c0aed770e38057a608d7f579389dfde410 + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: 88eeb4da891e10b1318c4b2476b6e2ecbeb5ff97d946815ffea7794c31a89017c70d7f34b3c2ebf23ef4e9fc9fb99f7dffe36da22011b5b5c6ffa34f4873ec20 + languageName: node + linkType: hard + +"once@npm:^1.3.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: 1 + checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 + languageName: node + linkType: hard + +"p-limit@npm:^3.0.2": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: ^0.1.0 + checksum: 7c3690c4dbf62ef625671e20b7bdf1cbc9534e83352a2780f165b0d3ceba21907e77ad63401708145ca4e25bfc51636588d89a8c0aeb715e6c37d1c066430360 + languageName: node + linkType: hard + +"p-locate@npm:^5.0.0": + version: 5.0.0 + resolution: "p-locate@npm:5.0.0" + dependencies: + p-limit: ^3.0.2 + checksum: 1623088f36cf1cbca58e9b61c4e62bf0c60a07af5ae1ca99a720837356b5b6c5ba3eb1b2127e47a06865fee59dd0453cad7cc844cda9d5a62ac1a5a51b7c86d3 + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: ^3.0.0 + checksum: cb0ab21ec0f32ddffd31dfc250e3afa61e103ef43d957cc45497afe37513634589316de4eb88abdfd969fe6410c22c0b93ab24328833b8eb1ccc087fc0442a1c + languageName: node + linkType: hard + +"pako@npm:^2.0.3": + version: 2.1.0 + resolution: "pako@npm:2.1.0" + checksum: 71666548644c9a4d056bcaba849ca6fd7242c6cf1af0646d3346f3079a1c7f4a66ffec6f7369ee0dc88f61926c10d6ab05da3e1fca44b83551839e89edd75a3e + languageName: node + linkType: hard + +"path-exists@npm:^4.0.0": + version: 4.0.0 + resolution: "path-exists@npm:4.0.0" + checksum: 505807199dfb7c50737b057dd8d351b82c033029ab94cb10a657609e00c1bc53b951cfdbccab8de04c5584d5eff31128ce6afd3db79281874a5ef2adbba55ed1 + languageName: node + linkType: hard + +"path-is-absolute@npm:^1.0.0": + version: 1.0.1 + resolution: "path-is-absolute@npm:1.0.1" + checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 + languageName: node + linkType: hard + +"path-scurry@npm:^1.10.1": + version: 1.10.1 + resolution: "path-scurry@npm:1.10.1" + dependencies: + lru-cache: ^9.1.1 || ^10.0.0 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 + languageName: node + linkType: hard + +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: 090e3147716647fb7fb5b4b8c8e5b55e5d0a6086d085b6cd23f3d3c01fcf0ff56fd3cc22f2f4a033bd2e46ed55d61ed8379e123b42afe7d531a2a5fc8bb556d6 + languageName: node + linkType: hard + +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1": + version: 2.3.1 + resolution: "picomatch@npm:2.3.1" + checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf + languageName: node + linkType: hard + +"prettier@npm:^2.6.2": + version: 2.8.8 + resolution: "prettier@npm:2.8.8" + bin: + prettier: bin-prettier.js + checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8 + languageName: node + linkType: hard + +"proc-log@npm:^3.0.0": + version: 3.0.0 + resolution: "proc-log@npm:3.0.0" + checksum: 02b64e1b3919e63df06f836b98d3af002b5cd92655cab18b5746e37374bfb73e03b84fe305454614b34c25b485cc687a9eebdccf0242cda8fda2475dd2c97e02 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: ^2.0.2 + retry: ^0.12.0 + checksum: f96a3f6d90b92b568a26f71e966cbbc0f63ab85ea6ff6c81284dc869b41510e6cdef99b6b65f9030f0db422bf7c96652a3fff9f2e8fb4a0f069d8f4430359429 + languageName: node + linkType: hard + +"randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: ^5.1.0 + checksum: d779499376bd4cbb435ef3ab9a957006c8682f343f14089ed5f27764e4645114196e75b7f6abf1cbd84fd247c0cb0651698444df8c9bf30e62120fbbc52269d6 + languageName: node + linkType: hard + +"readdirp@npm:~3.6.0": + version: 3.6.0 + resolution: "readdirp@npm:3.6.0" + dependencies: + picomatch: ^2.2.1 + checksum: 1ced032e6e45670b6d7352d71d21ce7edf7b9b928494dcaba6f11fba63180d9da6cd7061ebc34175ffda6ff529f481818c962952004d273178acd70f7059b320 + languageName: node + linkType: hard + +"regenerator-runtime@npm:^0.14.0": + version: 0.14.1 + resolution: "regenerator-runtime@npm:0.14.1" + checksum: 9f57c93277b5585d3c83b0cf76be47b473ae8c6d9142a46ce8b0291a04bb2cf902059f0f8445dcabb3fb7378e5fe4bb4ea1e008876343d42e46d3b484534ce38 + languageName: node + linkType: hard + +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: fb47e70bf0001fdeabdc0429d431863e9475e7e43ea5f94ad86503d918423c1543361cc5166d713eaa7029dd7a3d34775af04764bebff99ef413111a5af18c80 + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 623bd7d2e5119467ba66202d733ec3c2e2e26568074923bc0585b6b99db14f357e79bdedb63cab56cec47491c4a0da7e6021a7465ca6dc4f481d3898fdd3158c + languageName: node + linkType: hard + +"root-workspace-0b6124@workspace:.": + version: 0.0.0-use.local + resolution: "root-workspace-0b6124@workspace:." + dependencies: + "@coral-xyz/anchor": ^0.29.0 + "@solana/spl-token": ^0.4.0 + "@solana/web3.js": ^1.90.0 + "@types/bn.js": ^5.1.0 + "@types/chai": ^4.3.0 + "@types/mocha": ^9.0.0 + chai: ^4.3.4 + mocha: ^9.0.3 + prettier: ^2.6.2 + ts-mocha: ^10.0.0 + typescript: ^4.3.5 + languageName: unknown + linkType: soft + +"rpc-websockets@npm:^7.5.1": + version: 7.9.0 + resolution: "rpc-websockets@npm:7.9.0" + dependencies: + "@babel/runtime": ^7.17.2 + bufferutil: ^4.0.1 + eventemitter3: ^4.0.7 + utf-8-validate: ^5.0.2 + uuid: ^8.3.2 + ws: ^8.5.0 + dependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: c3ddd79ea7cf63b7a6a8d32356c7f9b363e41f26a6a8bbe889f9d2c5267811d492e194340fbad1a21ecfa457d5d1f253af3357a94d0118f66fcdea1fd9236adc + languageName: node + linkType: hard + +"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 + languageName: node + linkType: hard + +"semver@npm:^7.3.5": + version: 7.6.0 + resolution: "semver@npm:7.6.0" + dependencies: + lru-cache: ^6.0.0 + bin: + semver: bin/semver.js + checksum: 7427f05b70786c696640edc29fdd4bc33b2acf3bbe1740b955029044f80575fc664e1a512e4113c3af21e767154a94b4aa214bf6cd6e42a1f6dba5914e0b208c + languageName: node + linkType: hard + +"serialize-javascript@npm:6.0.0": + version: 6.0.0 + resolution: "serialize-javascript@npm:6.0.0" + dependencies: + randombytes: ^2.1.0 + checksum: 56f90b562a1bdc92e55afb3e657c6397c01a902c588c0fe3d4c490efdcc97dcd2a3074ba12df9e94630f33a5ce5b76a74784a7041294628a6f4306e0ec84bf93 + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: ^3.0.0 + checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: b5167a7142c1da704c0e3af85c402002b597081dd9575031a90b4f229ca5678e9a36e8a374f1814c8156a725d17008ae3bde63b92f9cfd132526379e580bec8b + languageName: node + linkType: hard + +"snake-case@npm:^3.0.4": + version: 3.0.4 + resolution: "snake-case@npm:3.0.4" + dependencies: + dot-case: ^3.0.4 + tslib: ^2.0.3 + checksum: 0a7a79900bbb36f8aaa922cf111702a3647ac6165736d5dc96d3ef367efc50465cac70c53cd172c382b022dac72ec91710608e5393de71f76d7142e6fd80e8a3 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.1": + version: 8.0.2 + resolution: "socks-proxy-agent@npm:8.0.2" + dependencies: + agent-base: ^7.0.2 + debug: ^4.3.4 + socks: ^2.7.1 + checksum: 4fb165df08f1f380881dcd887b3cdfdc1aba3797c76c1e9f51d29048be6e494c5b06d68e7aea2e23df4572428f27a3ec22b3d7c75c570c5346507433899a4b6d + languageName: node + linkType: hard + +"socks@npm:^2.7.1": + version: 2.8.0 + resolution: "socks@npm:2.8.0" + dependencies: + ip-address: ^9.0.5 + smart-buffer: ^4.2.0 + checksum: b245081650c5fc112f0e10d2ee3976f5665d2191b9f86b181edd3c875d53d84a94bc173752d5be2651a450e3ef799fe7ec405dba3165890c08d9ac0b4ec1a487 + languageName: node + linkType: hard + +"source-map-support@npm:^0.5.6": + version: 0.5.21 + resolution: "source-map-support@npm:0.5.21" + dependencies: + buffer-from: ^1.0.0 + source-map: ^0.6.0 + checksum: 43e98d700d79af1d36f859bdb7318e601dfc918c7ba2e98456118ebc4c4872b327773e5a1df09b0524e9e5063bb18f0934538eace60cca2710d1fa687645d137 + languageName: node + linkType: hard + +"source-map@npm:^0.6.0": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 + languageName: node + linkType: hard + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.5 + resolution: "ssri@npm:10.0.5" + dependencies: + minipass: ^7.0.3 + checksum: 0a31b65f21872dea1ed3f7c200d7bc1c1b91c15e419deca14f282508ba917cbb342c08a6814c7f68ca4ca4116dd1a85da2bbf39227480e50125a1ceffeecb750 + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: ^8.0.0 + is-fullwidth-code-point: ^3.0.0 + strip-ansi: ^6.0.1 + checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: ^0.2.0 + emoji-regex: ^9.2.2 + strip-ansi: ^7.0.1 + checksum: 7369deaa29f21dda9a438686154b62c2c5f661f8dda60449088f9f980196f7908fc39fdd1803e3e01541970287cf5deae336798337e9319a7055af89dafa7193 + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: ^5.0.1 + checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: ^6.0.1 + checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d + languageName: node + linkType: hard + +"strip-bom@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-bom@npm:3.0.0" + checksum: 8d50ff27b7ebe5ecc78f1fe1e00fcdff7af014e73cf724b46fb81ef889eeb1015fc5184b64e81a2efe002180f3ba431bdd77e300da5c6685d702780fbf0c8d5b + languageName: node + linkType: hard + +"strip-json-comments@npm:3.1.1": + version: 3.1.1 + resolution: "strip-json-comments@npm:3.1.1" + checksum: 492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 + languageName: node + linkType: hard + +"superstruct@npm:^0.14.2": + version: 0.14.2 + resolution: "superstruct@npm:0.14.2" + checksum: c5c4840f432da82125b923ec45faca5113217e83ae416e314d80eae012b8bb603d2e745025d173450758d116348820bc7028157f8c9a72b6beae879f94b837c0 + languageName: node + linkType: hard + +"superstruct@npm:^0.15.4": + version: 0.15.5 + resolution: "superstruct@npm:0.15.5" + checksum: 6d1f5249fee789424b7178fa0a1ffb2ace629c5480c39505885bd8c0046a4ff8b267569a3442fa53b8c560a7ba6599cf3f8af94225aebeb2cf6023f7dd911050 + languageName: node + linkType: hard + +"supports-color@npm:8.1.1": + version: 8.1.1 + resolution: "supports-color@npm:8.1.1" + dependencies: + has-flag: ^4.0.0 + checksum: c052193a7e43c6cdc741eb7f378df605636e01ad434badf7324f17fb60c69a880d8d8fcdcb562cf94c2350e57b937d7425ab5b8326c67c2adc48f7c87c1db406 + languageName: node + linkType: hard + +"supports-color@npm:^7.1.0": + version: 7.2.0 + resolution: "supports-color@npm:7.2.0" + dependencies: + has-flag: ^4.0.0 + checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.1.2": + version: 6.2.0 + resolution: "tar@npm:6.2.0" + dependencies: + chownr: ^2.0.0 + fs-minipass: ^2.0.0 + minipass: ^5.0.0 + minizlib: ^2.1.1 + mkdirp: ^1.0.3 + yallist: ^4.0.0 + checksum: db4d9fe74a2082c3a5016630092c54c8375ff3b280186938cfd104f2e089c4fd9bad58688ef6be9cf186a889671bf355c7cda38f09bbf60604b281715ca57f5c + languageName: node + linkType: hard + +"text-encoding-utf-8@npm:^1.0.2": + version: 1.0.2 + resolution: "text-encoding-utf-8@npm:1.0.2" + checksum: ec4c15d50e738c5dba7327ad432ebf0725ec75d4d69c0bd55609254c5a3bc5341272d7003691084a0a73d60d981c8eb0e87603676fdb6f3fed60f4c9192309f9 + languageName: node + linkType: hard + +"through@npm:>=2.2.7 <3": + version: 2.3.8 + resolution: "through@npm:2.3.8" + checksum: a38c3e059853c494af95d50c072b83f8b676a9ba2818dcc5b108ef252230735c54e0185437618596c790bbba8fcdaef5b290405981ffa09dce67b1f1bf190cbd + languageName: node + linkType: hard + +"to-regex-range@npm:^5.0.1": + version: 5.0.1 + resolution: "to-regex-range@npm:5.0.1" + dependencies: + is-number: ^7.0.0 + checksum: f76fa01b3d5be85db6a2a143e24df9f60dd047d151062d0ba3df62953f2f697b16fe5dad9b0ac6191c7efc7b1d9dcaa4b768174b7b29da89d4428e64bc0a20ed + languageName: node + linkType: hard + +"toml@npm:^3.0.0": + version: 3.0.0 + resolution: "toml@npm:3.0.0" + checksum: 5d7f1d8413ad7780e9bdecce8ea4c3f5130dd53b0a4f2e90b93340979a137739879d7b9ce2ce05c938b8cc828897fe9e95085197342a1377dd8850bf5125f15f + languageName: node + linkType: hard + +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 726321c5eaf41b5002e17ffbd1fb7245999a073e8979085dacd47c4b4e8068ff5777142fc6726d6ca1fd2ff16921b48788b87225cbc57c72636f6efa8efbffe3 + languageName: node + linkType: hard + +"ts-mocha@npm:^10.0.0": + version: 10.0.0 + resolution: "ts-mocha@npm:10.0.0" + dependencies: + ts-node: 7.0.1 + tsconfig-paths: ^3.5.0 + peerDependencies: + mocha: ^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X + dependenciesMeta: + tsconfig-paths: + optional: true + bin: + ts-mocha: bin/ts-mocha + checksum: b11f2a8ceecf195b0db724da429159982fef12e4357088fe900289223587217e8c126ead7929679edd58bf19ad96c5da5911535d26f535386632e18fbff10c40 + languageName: node + linkType: hard + +"ts-node@npm:7.0.1": + version: 7.0.1 + resolution: "ts-node@npm:7.0.1" + dependencies: + arrify: ^1.0.0 + buffer-from: ^1.1.0 + diff: ^3.1.0 + make-error: ^1.1.1 + minimist: ^1.2.0 + mkdirp: ^0.5.1 + source-map-support: ^0.5.6 + yn: ^2.0.0 + bin: + ts-node: dist/bin.js + checksum: 07ed6ea1805361828737a767cfd6c57ea6e267ee8679282afb933610af02405e1a87c1f2aea1d38ed8e66b34fcbf6272b6021ab95d78849105d2e57fc283870b + languageName: node + linkType: hard + +"tsconfig-paths@npm:^3.5.0": + version: 3.15.0 + resolution: "tsconfig-paths@npm:3.15.0" + dependencies: + "@types/json5": ^0.0.29 + json5: ^1.0.2 + minimist: ^1.2.6 + strip-bom: ^3.0.0 + checksum: 59f35407a390d9482b320451f52a411a256a130ff0e7543d18c6f20afab29ac19fbe55c360a93d6476213cc335a4d76ce90f67df54c4e9037f7d240920832201 + languageName: node + linkType: hard + +"tslib@npm:^2.0.3": + version: 2.6.2 + resolution: "tslib@npm:2.6.2" + checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad + languageName: node + linkType: hard + +"type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": + version: 4.0.8 + resolution: "type-detect@npm:4.0.8" + checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15 + languageName: node + linkType: hard + +"typescript@npm:^4.3.5": + version: 4.9.5 + resolution: "typescript@npm:4.9.5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db + languageName: node + linkType: hard + +"typescript@patch:typescript@^4.3.5#~builtin": + version: 4.9.5 + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=d73830" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 + languageName: node + linkType: hard + +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 + languageName: node + linkType: hard + +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: ^4.0.0 + checksum: 8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: ^0.1.4 + checksum: 0884b58365af59f89739e6f71e3feacb5b1b41f2df2d842d0757933620e6de08eff347d27e9d499b43c40476cbaf7988638d3acb2ffbcb9d35fd035591adfd15 + languageName: node + linkType: hard + +"utf-8-validate@npm:^5.0.2": + version: 5.0.10 + resolution: "utf-8-validate@npm:5.0.10" + dependencies: + node-gyp: latest + node-gyp-build: ^4.3.0 + checksum: 5579350a023c66a2326752b6c8804cc7b39dcd251bb088241da38db994b8d78352e388dcc24ad398ab98385ba3c5ffcadb6b5b14b2637e43f767869055e46ba6 + languageName: node + linkType: hard + +"uuid@npm:^8.3.2": + version: 8.3.2 + resolution: "uuid@npm:8.3.2" + bin: + uuid: dist/bin/uuid + checksum: 5575a8a75c13120e2f10e6ddc801b2c7ed7d8f3c8ac22c7ed0c7b2ba6383ec0abda88c905085d630e251719e0777045ae3236f04c812184b7c765f63a70e58df + languageName: node + linkType: hard + +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: c92a0a6ab95314bde9c32e1d0a6dfac83b578f8fa5f21e675bc2706ed6981bc26b7eb7e6a1fab158e5ce4adf9caa4a0aee49a52505d4d13c7be545f15021b17c + languageName: node + linkType: hard + +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: ~0.0.3 + webidl-conversions: ^3.0.0 + checksum: b8daed4ad3356cc4899048a15b2c143a9aed0dfae1f611ebd55073310c7b910f522ad75d727346ad64203d7e6c79ef25eafd465f4d12775ca44b90fa82ed9e2c + languageName: node + linkType: hard + +"which@npm:2.0.2, which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: ^2.0.0 + bin: + node-which: ./bin/node-which + checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 + languageName: node + linkType: hard + +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: ^3.1.1 + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + languageName: node + linkType: hard + +"workerpool@npm:6.2.0": + version: 6.2.0 + resolution: "workerpool@npm:6.2.0" + checksum: 3493b4f0ef979a23d2c1583d7ef85f62fc9463cc02f82829d3e7e663b517f8ae9707da0249b382e46ac58986deb0ca2232ee1081713741211bda9254b429c9bb + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: ^4.0.0 + string-width: ^4.1.0 + strip-ansi: ^6.0.0 + checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: ^6.1.0 + string-width: ^5.0.1 + strip-ansi: ^7.0.1 + checksum: 371733296dc2d616900ce15a0049dca0ef67597d6394c57347ba334393599e800bab03c41d4d45221b6bc967b8c453ec3ae4749eff3894202d16800fdfe0e238 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 + languageName: node + linkType: hard + +"ws@npm:^7.4.5": + version: 7.5.9 + resolution: "ws@npm:7.5.9" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: c3c100a181b731f40b7f2fddf004aa023f79d64f489706a28bc23ff88e87f6a64b3c6651fbec3a84a53960b75159574d7a7385709847a62ddb7ad6af76f49138 + languageName: node + linkType: hard + +"ws@npm:^8.5.0": + version: 8.16.0 + resolution: "ws@npm:8.16.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: feb3eecd2bae82fa8a8beef800290ce437d8b8063bdc69712725f21aef77c49cb2ff45c6e5e7fce622248f9c7abaee506bae0a9064067ffd6935460c7357321b + languageName: node + linkType: hard + +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 54f0fb95621ee60898a38c572c515659e51cc9d9f787fb109cef6fde4befbe1c4602dc999d30110feee37456ad0f1660fa2edcfde6a9a740f86a290999550d30 + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 + languageName: node + linkType: hard + +"yargs-parser@npm:20.2.4": + version: 20.2.4 + resolution: "yargs-parser@npm:20.2.4" + checksum: d251998a374b2743a20271c2fd752b9fbef24eb881d53a3b99a7caa5e8227fcafd9abf1f345ac5de46435821be25ec12189a11030c12ee6481fef6863ed8b924 + languageName: node + linkType: hard + +"yargs-parser@npm:^20.2.2": + version: 20.2.9 + resolution: "yargs-parser@npm:20.2.9" + checksum: 8bb69015f2b0ff9e17b2c8e6bfe224ab463dd00ca211eece72a4cd8a906224d2703fb8a326d36fdd0e68701e201b2a60ed7cf81ce0fd9b3799f9fe7745977ae3 + languageName: node + linkType: hard + +"yargs-unparser@npm:2.0.0": + version: 2.0.0 + resolution: "yargs-unparser@npm:2.0.0" + dependencies: + camelcase: ^6.0.0 + decamelize: ^4.0.0 + flat: ^5.0.2 + is-plain-obj: ^2.1.0 + checksum: 68f9a542c6927c3768c2f16c28f71b19008710abd6b8f8efbac6dcce26bbb68ab6503bed1d5994bdbc2df9a5c87c161110c1dfe04c6a3fe5c6ad1b0e15d9a8a3 + languageName: node + linkType: hard + +"yargs@npm:16.2.0": + version: 16.2.0 + resolution: "yargs@npm:16.2.0" + dependencies: + cliui: ^7.0.2 + escalade: ^3.1.1 + get-caller-file: ^2.0.5 + require-directory: ^2.1.1 + string-width: ^4.2.0 + y18n: ^5.0.5 + yargs-parser: ^20.2.2 + checksum: b14afbb51e3251a204d81937c86a7e9d4bdbf9a2bcee38226c900d00f522969ab675703bee2a6f99f8e20103f608382936034e64d921b74df82b63c07c5e8f59 + languageName: node + linkType: hard + +"yn@npm:^2.0.0": + version: 2.0.0 + resolution: "yn@npm:2.0.0" + checksum: 9d49527cb3e9a0948cc057223810bf30607bf04b9ff7666cc1681a6501d660b60d90000c16f9e29311b0f28d8a06222ada565ccdca5f1049cdfefb1908217572 + languageName: node + linkType: hard + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 + languageName: node + linkType: hard