Added tests

This commit is contained in:
Ralfs 2021-05-24 20:30:37 +03:00
parent ed129179de
commit 1323c352ac
7 changed files with 1318 additions and 43 deletions

1
.env.example Normal file
View File

@ -0,0 +1 @@
AGGREGATOR_PATH=~/solana-flux-aggregator

1
.gitignore vendored
View File

@ -13,6 +13,7 @@
# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local

View File

@ -21,7 +21,7 @@
"clean": "rm -rf lib",
"prepare": "run-s clean build",
"shell": "node -e \"$(< shell)\" -i --experimental-repl-await",
"test": "run-s test:unit test:lint test:build",
"test": "mocha -r ts-node/register tests/Stateless.test.ts --timeout 0",
"test:build": "run-s build",
"test:lint": "eslint src",
"test:unit": "jest",
@ -32,7 +32,7 @@
"@types/bn.js": "^4.11.6",
"@types/chai": "^4.2.14",
"@types/jest": "^26.0.9",
"@types/mocha": "^8.2.0",
"@types/mocha": "^8.2.2",
"@typescript-eslint/eslint-plugin": "^4.6.0",
"@typescript-eslint/parser": "^4.6.0",
"babel-eslint": "^10.0.3",
@ -55,13 +55,16 @@
"trailingComma": "all"
},
"dependencies": {
"@project-serum/common": "^0.0.1-beta.3",
"@project-serum/serum": "^0.13.20",
"@project-serum/sol-wallet-adapter": "^0.1.4",
"@solana/spl-token": "^0.0.13",
"@solana/web3.js": "^0.90.0",
"@solana/spl-token": "0.0.13",
"@solana/web3.js": "^0.95.0",
"bn.js": "^5.1.2",
"borsh": "https://github.com/defactojob/borsh-js#field-mapper",
"buffer-layout": "^1.2.0"
"buffer-layout": "^1.2.0",
"dotenv": "^10.0.0",
"mocha": "^8.4.0"
},
"browserslist": [
">0.2%",

452
tests/Stateless.test.ts Normal file
View File

@ -0,0 +1,452 @@
import { MangoClient, MangoGroup, MarginAccount } from '../src/client';
import { findLargestTokenAccountForOwner } from '../src/utils';
import IDS from '../src/ids.json';
import { Account, Connection, PublicKey } from '@solana/web3.js';
import { Market } from '@project-serum/serum';
import { expect } from 'chai';
import { spawn } from 'child_process';
import { blob, struct, u8, nu64 } from 'buffer-layout';
import { sleep } from '../src/utils';
import dotenv from 'dotenv';
dotenv.config()
if (!process.env.AGGREGATOR_PATH) {
console.info("You have not set the AGGREGATOR_PATH in .env, some tests will fail");
}
import {
_sendTransaction,
createWalletAndRequestAirdrop,
createMangoGroupSymbolMappings,
createTokenAccountWithBalance,
getOwnedTokenAccounts,
getAndDecodeBidsAndAsksForOwner,
performSingleDepositOrWithdrawal,
getAndDecodeBidsAndAsks,
getOrderSizeAndPrice,
extractInfoFromLogs,
prettyPrintOwnerKeys
} from './test_utils';
console.log = function () {}; // NOTE: Disable all unnecessary logging
let cluster = "devnet";
const client = new MangoClient();
const clusterIds = IDS[cluster];
const mangoProgramId = new PublicKey(clusterIds.mango_program_id);
const dexProgramId = new PublicKey(clusterIds.dex_program_id);
let connection = new Connection(IDS.cluster_urls[cluster], 'singleGossip');
let mainnetCluster = "mainnet-beta";
const mainnetClusterIds = IDS[mainnetCluster];
const mainnetMangoProgramId = new PublicKey(mainnetClusterIds.mango_program_id);
const mainnetDexProgramId = new PublicKey(mainnetClusterIds.dex_program_id);
let mainnetConnection = new Connection(IDS.cluster_urls[mainnetCluster], 'singleGossip');
function chunkOrders(orders: any[], chunkSize: number) {
return orders.reduce((resultArray: any[], item, index) => {
const chunkIndex = Math.floor(index/chunkSize)
if(!resultArray[chunkIndex]) {
resultArray[chunkIndex] = []
}
resultArray[chunkIndex].push(item)
return resultArray;
}, []);
}
async function initAccountsWithBalances(neededBalances: number[]) {
const owner = await createWalletAndRequestAirdrop(connection, 5);
const mangoGroupTokenMappings = await createMangoGroupSymbolMappings(connection, mangoGroupIds);
await Promise.all(neededBalances.map(async (x, i) => {
if (x > 0) {
const baseSymbol = mangoGroupSymbols[i];
await createTokenAccountWithBalance(connection, owner, baseSymbol, mangoGroupTokenMappings, clusterIds.faucets, x);
}
}));
prettyPrintOwnerKeys(owner, "Account");
}
async function getSpotMarketDetails(mangoGroupSpotMarket: any): Promise<any> {
const [spotMarketSymbol, spotMarketAddress] = mangoGroupSpotMarket;
const [baseSymbol, quoteSymbol] = spotMarketSymbol.split('/');
const spotMarket = await Market.load(connection, new PublicKey(spotMarketAddress), { skipPreflight: true, commitment: 'singleGossip'}, dexProgramId);
return { spotMarket, baseSymbol, quoteSymbol };
}
async function requestPriceChange(mangoGroup: MangoGroup, requiredPrice: number, baseSymbol: string) {
let prices = await mangoGroup.getPrices(connection);
while (prices[0].toFixed(2) !== requiredPrice.toFixed(2)) {
console.info("Running oracle to change price");
await performPriceChange(Math.round( requiredPrice * 1e2 ) / 1e2, baseSymbol.toLowerCase());
console.info("Finished running oracle to change price");
try {
prices = await mangoGroup.getPrices(connection);
} catch (e) {
console.info("Error, trying to reset connection");
connection = new Connection(IDS.cluster_urls[cluster], 'singleGossip');
prices = await mangoGroup.getPrices(connection);
}
}
return prices;
}
function performPriceChange(requiredPrice: number, baseSymbol: string): Promise<void> {
return new Promise(function(resolve, _){
const priceChangerOracle = spawn('yarn', ['solink', 'oracle', (requiredPrice * 100).toString()], {cwd: process.env.AGGREGATOR_PATH});
priceChangerOracle.stdout.on("data", data => {
if (data.includes(`Submit OK {"aggregator":"${baseSymbol}:usd"`)) {
priceChangerOracle.kill();
resolve();
}
});
})
}
async function cleanOrderBook(mangoGroupSpotMarket: any) {
console.info("Cleaning order book, this will take a while...");
const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk);
const mangoGroupTokenMappings = await createMangoGroupSymbolMappings(connection, mangoGroupIds);
const { spotMarket, baseSymbol, quoteSymbol } = await getSpotMarketDetails(mangoGroupSpotMarket);
let bna = await getAndDecodeBidsAndAsks(connection, spotMarket);
let allAsks: any[] = [...bna.askOrderBook].map(x => ({ price: x.price, size: x.size })).reverse();
let allBids: any[] = [...bna.bidOrderBook].map(x => ({ price: x.price, size: x.size })).reverse();
if (allAsks.length || allBids.length) {
const owner = await createWalletAndRequestAirdrop(connection, 5);
try {
const marginAccountPk = await client.initMarginAccount(connection, mangoProgramId, mangoGroup, owner);
let marginAccount = await client.getMarginAccount(connection, marginAccountPk, dexProgramId);
const amountNeededToClearAsks: number = Math.ceil(allAsks.reduce((acc, ask) => acc + (ask.price * ask.size), 0) + 10);
await createTokenAccountWithBalance(connection, owner, quoteSymbol, mangoGroupTokenMappings, clusterIds.faucets, amountNeededToClearAsks);
await performSingleDepositOrWithdrawal(connection, owner, client, mangoGroup, mangoProgramId, quoteSymbol, mangoGroupTokenMappings, marginAccount, 'deposit', amountNeededToClearAsks);
const chunkedAsks = chunkOrders(allAsks, 15);
for (let ask of chunkedAsks) {
marginAccount = await client.getMarginAccount(connection, marginAccountPk, dexProgramId);
const price: number = Math.max(...ask.map((x: any) => x.price));
const size: number = ask.reduce(( a: any, b: any ) => a + b.size, 0);
const roundedSize = Math.round( size * 1e2 ) / 1e2;
await client.placeAndSettle(connection, mangoProgramId, mangoGroup, marginAccount, spotMarket, owner, 'buy', price, roundedSize);
}
const amountNeededToClearBids: number = Math.ceil(allBids.reduce((acc, bid) => acc + (bid.size), 0) + 10);
await createTokenAccountWithBalance(connection, owner, baseSymbol, mangoGroupTokenMappings, clusterIds.faucets, amountNeededToClearBids);
await performSingleDepositOrWithdrawal(connection, owner, client, mangoGroup, mangoProgramId, baseSymbol, mangoGroupTokenMappings, marginAccount, 'deposit', amountNeededToClearBids);
const chunkedBids = chunkOrders(allBids, 15);
for (let bid of chunkedBids) {
marginAccount = await client.getMarginAccount(connection, marginAccountPk, dexProgramId);
const price: number = Math.min(...bid.map((x: any) => x.price));
const size: number = bid.reduce(( a: any, b: any ) => a + b.size, 0);
const roundedSize = Math.round( size * 1e2 ) / 1e2;
await client.placeAndSettle(connection, mangoProgramId, mangoGroup, marginAccount, spotMarket, owner, 'sell', price, roundedSize);
}
bna = await getAndDecodeBidsAndAsks(connection, spotMarket);
allAsks = [...bna.askOrderBook].map(x => ({ price: x.price, size: x.size }));
allBids = [...bna.bidOrderBook].map(x => ({ price: x.price, size: x.size }));
expect(allAsks).to.be.empty;
expect(allBids).to.be.empty;
prettyPrintOwnerKeys(owner, "Cleaner");
} catch (error) {
throw new Error(`
Test Error: ${error.message},
${prettyPrintOwnerKeys(owner, "Cleaner")}
`);
}
}
}
async function placeNOrdersAfterLimit(mangoGroupSpotMarket: any, marketIndex: number, orderQuantityAfter: number) {
let openOrdersForOwner: any[];
const orderQuantity = 128; // Max orders
const buyerOwner = await createWalletAndRequestAirdrop(connection, 5);
prettyPrintOwnerKeys(buyerOwner, "Buyer");
const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk);
const mangoGroupTokenMappings = await createMangoGroupSymbolMappings(connection, mangoGroupIds);
const buyerMarginAccountPk = await client.initMarginAccount(connection, mangoProgramId, mangoGroup, buyerOwner);
let buyerMarginAccount = await client.getMarginAccount(connection, buyerMarginAccountPk, dexProgramId);
const { spotMarket, baseSymbol, quoteSymbol } = await getSpotMarketDetails(mangoGroupSpotMarket);
const baseSymbolIndex = mangoGroupSymbols.findIndex(x => x === baseSymbol);
const quoteSymbolIndex = mangoGroupSymbols.findIndex(x => x === quoteSymbol);
const [orderSize, orderPrice, _] = await getOrderSizeAndPrice(connection, spotMarket, mangoGroupTokenMappings, baseSymbol, quoteSymbol, 'buy');
const neededQuoteAmount = orderPrice * orderSize;
const neededBaseAmountForAllTrades = orderSize * orderQuantity;
const neededQuoteAmountForAllTrades = neededQuoteAmount * orderQuantity;
console.info("neededQuoteAmountForAllTrades:", neededQuoteAmountForAllTrades);
await createTokenAccountWithBalance(connection, buyerOwner, baseSymbol, mangoGroupTokenMappings, clusterIds.faucets, neededQuoteAmountForAllTrades);
await performSingleDepositOrWithdrawal(connection, buyerOwner, client, mangoGroup, mangoProgramId, baseSymbol, mangoGroupTokenMappings, buyerMarginAccount, 'deposit', neededQuoteAmountForAllTrades);
await requestPriceChange(mangoGroup, orderPrice, baseSymbol);
for (let i = 0; i < orderQuantity; i++) {
console.info(`Placing a buy order of ${orderSize} ${baseSymbol} for ${orderPrice} ${quoteSymbol} = ~${neededQuoteAmount} ${quoteSymbol} - ${i + 1}/${orderQuantity}`);
buyerMarginAccount = await client.getMarginAccount(connection, buyerMarginAccount.publicKey, dexProgramId);
await client.placeAndSettle(connection, mangoProgramId, mangoGroup, buyerMarginAccount, spotMarket, buyerOwner, 'buy', orderPrice, orderSize);
}
buyerMarginAccount = await client.getMarginAccount(connection, buyerMarginAccount.publicKey, dexProgramId);
openOrdersForOwner = await getAndDecodeBidsAndAsksForOwner(connection, spotMarket, buyerMarginAccount.openOrdersAccounts[marketIndex]);
// TODO: this should be a for loop of cancellations
// NOTE: Maybe trying cancelling last order not first
expect(openOrdersForOwner).to.be.an('array').and.to.have.lengthOf(128);
await client.cancelOrder(connection, mangoProgramId, mangoGroup, buyerMarginAccount, buyerOwner, spotMarket, openOrdersForOwner[0]);
buyerMarginAccount = await client.getMarginAccount(connection, buyerMarginAccount.publicKey, dexProgramId);
openOrdersForOwner = await getAndDecodeBidsAndAsksForOwner(connection, spotMarket, buyerMarginAccount.openOrdersAccounts[marketIndex]);
expect(openOrdersForOwner).to.be.an('array').and.to.have.lengthOf(127);
for (let i = 0; i < orderQuantityAfter; i++) {
console.info(`Placing a buy order of ${orderSize} ${baseSymbol} for ${orderPrice} ${quoteSymbol} = ~${neededQuoteAmount} ${quoteSymbol} - ${i + 1}/${orderQuantityAfter}`);
buyerMarginAccount = await client.getMarginAccount(connection, buyerMarginAccount.publicKey, dexProgramId);
await client.placeAndSettle(connection, mangoProgramId, mangoGroup, buyerMarginAccount, spotMarket, buyerOwner, 'buy', orderPrice, orderSize);
}
expect(openOrdersForOwner).to.be.an('array').and.to.have.lengthOf(128);
}
async function stressTestMatchOrder(mangoGroupSpotMarket: any, orderQuantity: number): Promise<void> {
let bna: any, allAsks: any[], allBids: any[];
const sellerOwner = await createWalletAndRequestAirdrop(connection, 5);
prettyPrintOwnerKeys(sellerOwner, "Seller");
const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk);
const mangoGroupTokenMappings = await createMangoGroupSymbolMappings(connection, mangoGroupIds);
const sellerMarginAccountPk = await client.initMarginAccount(connection, mangoProgramId, mangoGroup, sellerOwner);
let sellerMarginAccount = await client.getMarginAccount(connection, sellerMarginAccountPk, dexProgramId);
const { spotMarket, baseSymbol, quoteSymbol } = await getSpotMarketDetails(mangoGroupSpotMarket);
const [orderSize, orderPrice, _] = await getOrderSizeAndPrice(connection, spotMarket, mangoGroupTokenMappings, baseSymbol, quoteSymbol, 'sell');
const neededQuoteAmount = orderPrice * orderSize;
const neededBaseAmountForAllTrades = orderSize * orderQuantity;
const neededQuoteAmountForAllTrades = neededQuoteAmount * orderQuantity;
await createTokenAccountWithBalance(connection, sellerOwner, baseSymbol, mangoGroupTokenMappings, clusterIds.faucets, neededBaseAmountForAllTrades);
await performSingleDepositOrWithdrawal(connection, sellerOwner, client, mangoGroup, mangoProgramId, baseSymbol, mangoGroupTokenMappings, sellerMarginAccount, 'deposit', neededBaseAmountForAllTrades);
for (let i = 0; i < orderQuantity; i++) {
console.info(`Placing a sell order of ${orderSize} ${baseSymbol} for ${orderPrice} ${quoteSymbol} = ~${neededQuoteAmount} USD - ${i + 1}/${orderQuantity}`);
sellerMarginAccount = await client.getMarginAccount(connection, sellerMarginAccountPk, dexProgramId);
await client.placeAndSettle(connection, mangoProgramId, mangoGroup, sellerMarginAccount, spotMarket, sellerOwner, 'sell', orderPrice, orderSize);
}
bna = await getAndDecodeBidsAndAsks(connection, spotMarket);
allAsks = [...bna.askOrderBook].map(x => ({ price: x.price, size: x.size }));
allBids = [...bna.bidOrderBook].map(x => ({ price: x.price, size: x.size }));
const buyerOwner = await createWalletAndRequestAirdrop(connection, 5);
prettyPrintOwnerKeys(buyerOwner, "Buyer");
const buyerMarginAccountPk = await client.initMarginAccount(connection, mangoProgramId, mangoGroup, buyerOwner);
const buyerMarginAccount = await client.getMarginAccount(connection, buyerMarginAccountPk, dexProgramId);
await createTokenAccountWithBalance(connection, buyerOwner, quoteSymbol, mangoGroupTokenMappings, clusterIds.faucets, neededQuoteAmountForAllTrades);
await performSingleDepositOrWithdrawal(connection, buyerOwner, client, mangoGroup, mangoProgramId, quoteSymbol, mangoGroupTokenMappings, buyerMarginAccount, 'deposit', neededQuoteAmountForAllTrades);
console.info(`Placing a buy order of ${neededBaseAmountForAllTrades} ${baseSymbol} for ${orderPrice} ${quoteSymbol} = ~${neededQuoteAmountForAllTrades} ${quoteSymbol}`);
const buyTxHash = await client.placeAndSettle(connection, mangoProgramId, mangoGroup, buyerMarginAccount, spotMarket, buyerOwner, 'buy', orderPrice, neededBaseAmountForAllTrades);
console.info("buyTxHash:", buyTxHash);
await connection.confirmTransaction(buyTxHash, 'finalized');
const buyConfirmedTx: any = await connection.getConfirmedTransaction(buyTxHash);
const buyTxLogInfo = extractInfoFromLogs(buyConfirmedTx);
console.info("Buy txLogInfo:", buyTxLogInfo);
bna = await getAndDecodeBidsAndAsks(connection, spotMarket);
allAsks = [...bna.askOrderBook].map(x => ({ price: x.price, size: x.size }));
allBids = [...bna.bidOrderBook].map(x => ({ price: x.price, size: x.size }));
expect(allAsks).to.be.empty;
expect(allBids).to.be.empty;
}
async function stressTestLiquidation(mangoGroupSpotMarket: any, orderQuantity: number, shouldPartialLiquidate: boolean = false) {
let bna: any, allAsks: any[], allBids: any[], prices: number[];
let leverageCoefficient = 15;
const liqeeOwner = await createWalletAndRequestAirdrop(connection, 5);
prettyPrintOwnerKeys(liqeeOwner, "Liqee");
const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk);
const mangoGroupTokenMappings = await createMangoGroupSymbolMappings(connection, mangoGroupIds);
const liqeeMarginAccountPk = await client.initMarginAccount(connection, mangoProgramId, mangoGroup, liqeeOwner);
let liqeeMarginAccount = await client.getMarginAccount(connection, liqeeMarginAccountPk, dexProgramId);
const { spotMarket, baseSymbol, quoteSymbol } = await getSpotMarketDetails(mangoGroupSpotMarket);
const baseSymbolIndex = mangoGroupSymbols.findIndex(x => x === baseSymbol);
const quoteSymbolIndex = mangoGroupSymbols.findIndex(x => x === quoteSymbol);
const [orderSize, orderPrice, _] = await getOrderSizeAndPrice(connection, spotMarket, mangoGroupTokenMappings, baseSymbol, quoteSymbol, 'buy');
const neededQuoteAmount = orderPrice * orderSize;
const neededBaseAmountForAllTrades = orderSize * orderQuantity;
const neededQuoteAmountForAllTrades = neededQuoteAmount * orderQuantity;
console.info("neededBaseAmountForAllTrades:", neededBaseAmountForAllTrades);
await createTokenAccountWithBalance(connection, liqeeOwner, baseSymbol, mangoGroupTokenMappings, clusterIds.faucets, neededBaseAmountForAllTrades);
await performSingleDepositOrWithdrawal(connection, liqeeOwner, client, mangoGroup, mangoProgramId, baseSymbol, mangoGroupTokenMappings, liqeeMarginAccount, 'deposit', neededBaseAmountForAllTrades);
prices = await requestPriceChange(mangoGroup, orderPrice, baseSymbol);
for (let i = 0; i < orderQuantity; i++) {
console.info(`Placing a buy order of ${orderSize} ${baseSymbol} for ${orderPrice} ${quoteSymbol} = ~${neededQuoteAmount} ${quoteSymbol} - ${i + 1}/${orderQuantity}`);
liqeeMarginAccount = await client.getMarginAccount(connection, liqeeMarginAccountPk, dexProgramId);
await client.placeAndSettle(connection, mangoProgramId, mangoGroup, liqeeMarginAccount, spotMarket, liqeeOwner, 'buy', orderPrice, orderSize);
}
liqeeMarginAccount = await client.getMarginAccount(connection, liqeeMarginAccountPk, dexProgramId);
console.info("collRatio before price change:", liqeeMarginAccount.getCollateralRatio(mangoGroup, prices));
prices = await requestPriceChange(mangoGroup, orderPrice / leverageCoefficient, baseSymbol);
console.info("collRatio after price change:", liqeeMarginAccount.getCollateralRatio(mangoGroup, prices));
const liqorOwner = await createWalletAndRequestAirdrop(connection, 5);
prettyPrintOwnerKeys(liqeeOwner, "Liqor");
for (let mangoGroupSymbol of mangoGroupSymbols) {
const requiredBalance = (mangoGroupSymbol === quoteSymbol) ? neededQuoteAmountForAllTrades : 0;
await createTokenAccountWithBalance(connection, liqorOwner, mangoGroupSymbol, mangoGroupTokenMappings, clusterIds.faucets, requiredBalance);
}
const tokenWallets = (await Promise.all(
mangoGroup.tokens.map(
(mint) => findLargestTokenAccountForOwner(connection, liqorOwner.publicKey, mint).then(
(response) => response.publicKey
)
)
));
let liquidationTxHash: string;
if (shouldPartialLiquidate) {
liquidationTxHash = await client.partialLiquidate(connection, mangoProgramId, mangoGroup, liqeeMarginAccount, liqorOwner, tokenWallets[quoteSymbolIndex], tokenWallets[baseSymbolIndex], quoteSymbolIndex, baseSymbolIndex, neededQuoteAmountForAllTrades);
} else {
const depositQuantities = new Array(tokenWallets.length).fill(0);
depositQuantities[quoteSymbolIndex] = neededQuoteAmountForAllTrades;
liquidationTxHash = await client.liquidate(connection, mangoProgramId, mangoGroup, liqeeMarginAccount, liqorOwner, tokenWallets, depositQuantities);
}
console.info("liquidationTxHash:", liquidationTxHash);
await connection.confirmTransaction(liquidationTxHash, 'finalized');
const liquidationConfirmedTx: any = await connection.getConfirmedTransaction(liquidationTxHash);
const liquidationTxLogInfo = extractInfoFromLogs(liquidationConfirmedTx);
console.info("Liquidation txLogInfo:", liquidationTxLogInfo);
}
const mangoGroupName = 'BTC_ETH_SOL_SRM_USDC';
const mangoGroupSymbols = mangoGroupName.split('_');
const mangoGroupIds = clusterIds.mango_groups[mangoGroupName];
const mangoGroupSpotMarkets: [string, string][] = Object.entries(mangoGroupIds.spot_market_symbols);
const mangoGroupPk = new PublicKey(mangoGroupIds.mango_group_pk);
const mangoGroupSpotMarket = mangoGroupSpotMarkets[0]; //BTC/USDC
// const mangoGroupSpotMarket = mangoGroupSpotMarkets[1]; //ETH/USDC
// const mangoGroupSpotMarket = mangoGroupSpotMarkets[2]; //SOL/USDC
// const mangoGroupSpotMarket = mangoGroupSpotMarkets[3]; //SRM/USDC
describe('Log stuff', async() => {
// it('should log token decimals', async() => {
// const MINT_LAYOUT = struct([blob(44), u8('decimals'), blob(37)]);
// const mainnetTokensToTest = [
// ['BTC', '9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E'],
// ['ETH', '2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk'],
// ['SOL', 'So11111111111111111111111111111111111111112'],
// ['SRM', 'SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt'],
// ['USDT', 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'],
// ['USDC', 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'],
// ];
// const devnetTokensToTest = [
// ['BTC', 'bypQzRBaSDWiKhoAw3hNkf35eF3z3AZCU8Sxks6mTPP'],
// ['ETH', 'ErWGBLBQMwdyC4H3MR8ef6pFK6gyHAyBxy4o1mHoqKzm'],
// ['SOL', 'So11111111111111111111111111111111111111112'],
// ['SRM', '9FbAMDvXqNjPqZSYt4EWTguJuDrGkfvwr3gSFpiSbX9S'],
// ['USDT', '7KBVenLz5WNH4PA5MdGkJNpDDyNKnBQTwnz1UqJv9GUm'],
// ['USDC', 'H6hy7Ykzc43EuGivv7VVuUKNpKgUoFAfUY3wdPr4UyRX'],
// ];
// for (let [tokenName, tokenMint] of mainnetTokensToTest) {
// const data: any = await mainnetConnection.getAccountInfo(new PublicKey(tokenMint));
// const info = MINT_LAYOUT.decode(data.data);
// console.info(`Mainnet ${tokenName} decimals: ${info.decimals}`);
// }
// for (let [tokenName, tokenMint] of devnetTokensToTest) {
// const data: any = await connection.getAccountInfo(new PublicKey(tokenMint));
// const info = MINT_LAYOUT.decode(data.data);
// console.info(`Devnet ${tokenName} decimals: ${info.decimals}`);
// };
// });
// it('should log lotSizes', async() => {
// const mainnetSpotMarketsToTest = [
// ['BTC/USDC', 'A8YFbxQYFVqKZaoYJLLUVcQiWP7G2MeEgW5wsAQgMvFw'],
// ['ETH/USDC', '4tSvZvnbyzHXLMTiFonMyxZoHmFqau1XArcRCVHLZ5gX'],
// ['SOL/USDC', '9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT'],
// ['SRM/USDC', 'ByRys5tuUWDgL73G8JBAEfkdFf8JWBzPBDHsBVQ5vbQA'],
// ];
// for (let [spotMarketName, spotMarketAddress] of mainnetSpotMarketsToTest) {
// const spotMarket = await Market.load(mainnetConnection, new PublicKey(spotMarketAddress), { skipPreflight: true, commitment: 'singleGossip'}, mainnetDexProgramId);
// console.info(`Mainnet ${spotMarketName} base/quote lotSizes: ${spotMarket['_decoded'].baseLotSize.toString()}/${spotMarket['_decoded'].quoteLotSize.toString()}`);
// }
// })
// it ('should log order', async() => {
// const { spotMarket } = await getSpotMarketDetails(mangoGroupSpotMarket);
// let bna = await getAndDecodeBidsAndAsks(connection, spotMarket);
// let allAsks: any[] = [...bna.askOrderBook].map(x => ({ price: x.price, size: x.size })).reverse();
// let allBids: any[] = [...bna.bidOrderBook].map(x => ({ price: x.price, size: x.size })).reverse();
// console.info(allAsks);
// console.info(allBids);
// })
})
describe('create account with test money', async() => {
it('should create an account with test money', async() => {
await initAccountsWithBalances([50, 50, 50, 1000, 100000]);
});
});
describe('stress test order limits', async() => {
// before(async () => {
// await cleanOrderBook(mangoGroupSpotMarket);
// });
// it('should be able to place 129th order after cancelling one', async() => {
// await placeNOrdersAfterLimit(mangoGroupSpotMarket, 0, 1);
// });
});
describe('stress testing matching orders', async() => {
// before(async () => {
// await cleanOrderBook(mangoGroupSpotMarket);
// });
// it('should match 1 order at a single price', async() => {
// await stressTestMatchOrder(mangoGroupSpotMarket, 1);
// });
// it('should match 10 orders at a single price', async() => {
// await stressTestMatchOrder(mangoGroupSpotMarket, 10);
// });
// it('should match 20 orders at a single price', async() => {
// await stressTestMatchOrder(mangoGroupSpotMarket, 20);
// });
// it('should match 25 orders at a single price', async() => {
// await stressTestMatchOrder(mangoGroupSpotMarket, 25);
// });
});
describe('stress testing liquidation', async() => {
// before(async () => {
// await cleanOrderBook(mangoGroupSpotMarket);
// });
// it('should liquidate an account with 1 open order', async() => {
// await stressTestLiquidation(mangoGroupSpotMarket, 1);
// });
// it('should liquidate an account with 10 open orders', async() => {
// await stressTestLiquidation(mangoGroupSpotMarket, 10);
// });
// it('should liquidate an account with 20 open orders', async() => {
// await stressTestLiquidation(mangoGroupSpotMarket, 20);
// });
// it('should liquidate an account with 25 open orders', async() => {
// await stressTestLiquidation(mangoGroupSpotMarket, 25);
// });
// it('should liquidate an account with 128 open orders', async() => {
// await stressTestLiquidation(mangoGroupSpotMarket, 128);
// });
});
describe('stress testing partial liquidation', async() => {
// before(async () => {
// await cleanOrderBook(mangoGroupSpotMarket);
// });
// it('should partially liquidate an account with 1 open order', async() => {
// await stressTestLiquidation(mangoGroupSpotMarket, 1, true);
// });
// it('should partially liquidate an account with 10 open orders', async() => {
// await stressTestLiquidation(mangoGroupSpotMarket, 10, true);
// });
// it('should partially liquidate an account with 20 open orders', async() => {
// await stressTestLiquidation(mangoGroupSpotMarket, 20, true);
// });
// it('should partially liquidate an account with 25 open orders', async() => {
// await stressTestLiquidation(mangoGroupSpotMarket, 25, true);
// });
// it('should partially liquidate an account with 128 open orders', async() => {
// await stressTestLiquidation(mangoGroupSpotMarket, 128, true);
// });
});

444
tests/test_utils.ts Normal file
View File

@ -0,0 +1,444 @@
import { MangoClient, MangoGroup, MarginAccount } from '../src/client';
import { Account, Connection, PublicKey, SystemProgram, Transaction, TransactionInstruction, TransactionSignature, TransferParams } from '@solana/web3.js';
import { Market, TokenInstructions, OpenOrders, Orderbook } from '@project-serum/serum';
import { token } from '@project-serum/common';
import { u64, NATIVE_MINT } from "@solana/spl-token";
import { sleep } from '../src/utils';
import fs from 'fs';
console.log = function () {}; // NOTE: Disable all unnecessary logging
const FAUCET_PROGRAM_ID = new PublicKey(
"4bXpkKSV8swHSnwqtzuboGPaPDeEgAn4Vt8GfarV5rZt"
);
const getPDA = () => {
return PublicKey.findProgramAddress([Buffer.from("faucet")], FAUCET_PROGRAM_ID);
}
export async function _sendTransaction (
connection: Connection,
transaction: Transaction,
signers: Account[],
): Promise<TransactionSignature> {
const signature = await connection.sendTransaction(transaction, signers);
try {
await connection.confirmTransaction(signature);
} catch (e) {
console.info("Error while confirming, trying again");
await connection.confirmTransaction(signature);
}
return signature;
}
export async function createTokenAccountInstrs (
connection: Connection,
newAccountPubkey: PublicKey,
mint: PublicKey,
ownerPk: PublicKey,
lamports?: number,
): Promise<TransactionInstruction[]> {
if (lamports === undefined) lamports = await connection.getMinimumBalanceForRentExemption(165);
return [
SystemProgram.createAccount({
fromPubkey: ownerPk,
newAccountPubkey,
space: 165,
lamports,
programId: TokenInstructions.TOKEN_PROGRAM_ID,
}),
TokenInstructions.initializeAccount({
account: newAccountPubkey,
mint,
owner: ownerPk,
}),
];
}
export async function createWrappedNativeAccount (
connection: Connection,
owner: Account,
amount: number
): Promise<PublicKey> {
// Allocate memory for the account
const balanceNeeded = await connection.getMinimumBalanceForRentExemption(165);
const newAccount = new Account();
const tx = new Transaction();
tx.add(SystemProgram.createAccount({
fromPubkey: owner.publicKey,
newAccountPubkey: newAccount.publicKey,
lamports: balanceNeeded,
space: 165,
programId: TokenInstructions.TOKEN_PROGRAM_ID,
})); // Send lamports to it (these will be wrapped into native tokens by the token program)
tx.add(SystemProgram.transfer({
fromPubkey: owner.publicKey,
toPubkey: newAccount.publicKey,
lamports: amount
})); // Assign the new account to the native token mint.
// the account will be initialized with a balance equal to the native token balance.
// (i.e. amount)
tx.add(TokenInstructions.initializeAccount({
account: newAccount.publicKey,
mint: NATIVE_MINT,
owner: owner.publicKey,
}));
const signers = [owner, newAccount];
const signerPks = signers.map(x => x.publicKey);
tx.setSigners(...signerPks);
await _sendTransaction(connection, tx, signers);
return newAccount.publicKey;
}
export async function createTokenAccount (
connection: Connection,
mint: PublicKey,
owner: Account
): Promise<PublicKey> {
const newAccount = new Account();
const tx = new Transaction();
const signers = [owner, newAccount];
const signerPks = signers.map(x => x.publicKey);
tx.add(...(await createTokenAccountInstrs(connection, newAccount.publicKey, mint, owner.publicKey)));
tx.setSigners(...signerPks);
await _sendTransaction(connection, tx, signers);
return newAccount.publicKey;
}
export async function createWalletAndRequestAirdrop(
connection: Connection,
amount: number
): Promise<Account> {
console.info("Creating a new wallet");
const owner = new Account();
if (amount < 1) throw new Error("SOL is needed for gas fees so at least 1 SOL is required");
await airdropSol(connection, owner, amount);
return owner;
}
export async function createMangoGroupSymbolMappings (
connection: Connection,
mangoGroupIds: any,
): Promise<any> {
const mangoGroupTokenMappings = {};
const mangoGroupSymbols: [string, string][] = Object.entries(mangoGroupIds.symbols);
for (let [tokenName, tokenMint] of mangoGroupSymbols) {
const tokenSupply = await connection.getTokenSupply(new PublicKey(tokenMint));
mangoGroupTokenMappings[tokenMint] = { tokenMint: new PublicKey(tokenMint), tokenName, decimals: tokenSupply.value.decimals };
}
return mangoGroupTokenMappings;
}
export async function getOwnedTokenAccounts(
connection: Connection,
owner: Account,
): Promise<any[]> {
const ownedTokenAccounts = await token.getOwnedTokenAccounts(connection, owner.publicKey);
return ownedTokenAccounts;
}
export async function updateMarginTokenAccountsAndDeposits(
connection: Connection,
owner: Account,
client: MangoClient,
mangoGroup: MangoGroup,
marginAccountPk: PublicKey | null,
state: any,
dexProgramId: PublicKey,
): Promise<void>{
state.ownedTokenAccounts = await token.getOwnedTokenAccounts(connection, owner.publicKey);
state.marginAccount = (marginAccountPk) ? await client.getMarginAccount(connection, marginAccountPk, dexProgramId) : null;
state.deposits = (state.marginAccount) ? state.marginAccount.getDeposits(mangoGroup) : [];
}
export async function buildAirdropTokensIx(
amount: u64,
tokenMintPublicKey: PublicKey,
destinationAccountPubkey: PublicKey,
faucetPubkey: PublicKey
) {
const pubkeyNonce = await getPDA();
const keys = [
{ pubkey: pubkeyNonce[0], isSigner: false, isWritable: false },
{ pubkey: tokenMintPublicKey, isSigner: false, isWritable: true },
{ pubkey: destinationAccountPubkey, isSigner: false, isWritable: true },
{ pubkey: TokenInstructions.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: faucetPubkey, isSigner: false, isWritable: false }
];
return new TransactionInstruction({
programId: FAUCET_PROGRAM_ID,
data: Buffer.from([1, ...amount.toArray("le", 8)]),
keys
});
};
export async function airdropTokens(
connection: Connection,
feePayerAccount: Account,
faucetAddress: string,
tokenDestinationPublicKey: PublicKey,
mint: PublicKey,
amount: u64
) {
const faucetPubkey = new PublicKey(faucetAddress);
const ix = await buildAirdropTokensIx(amount, mint, tokenDestinationPublicKey, faucetPubkey);
const tx = new Transaction();
tx.add(ix);
const signers = [feePayerAccount];
await _sendTransaction(connection, tx, signers);
return tokenDestinationPublicKey.toBase58();
};
export async function airdropToken(
connection: Connection,
owner: Account,
tokenName: string,
mangoGroupTokenMappings: any,
faucetIds: any,
amount: number
): Promise<void> {
if (tokenName !== 'SOL') throw new Error('This airdrop is function is not meant for SOL');
const ownedTokenAccounts = await token.getOwnedTokenAccounts(connection, owner.publicKey);
const tokenMapping: any = Object.values(mangoGroupTokenMappings).find((x: any) => x.tokenName === tokenName);
const { tokenMint, decimals } = tokenMapping;
const ownedTokenAccount = ownedTokenAccounts.find((x: any) => x.account.mint.equals(tokenMint));
if (!ownedTokenAccount) throw new Error(`Token account doesn't exist for ${tokenName}`);
const multiplier = Math.pow(10, decimals);
await airdropTokens(connection, owner, faucetIds[tokenName], ownedTokenAccount.publicKey, tokenMint, new u64(amount * multiplier));
}
export async function airdropSol(
connection: Connection,
owner: Account,
amount: number
): Promise<void> {
const roundedSolAmount = Math.round(amount);
console.info(`Requesting ${roundedSolAmount} SOL`);
const generousAccount = [115,98,128,18,66,112,147,244,46,244,118,106,91,202,56,83,58,71,89,226,32,177,177,240,189,23,209,176,138,119,130,140,6,149,55,70,215,34,108,133,225,117,38,141,74,246,232,76,176,10,207,221,68,179,115,158,106,133,35,30,4,177,124,5];
const backupAcc = new Account(generousAccount);
const tx = new Transaction();
tx.add(SystemProgram.transfer({fromPubkey: backupAcc.publicKey, lamports: roundedSolAmount * 1e9, toPubkey: owner.publicKey}));
const signers = [backupAcc];
const signerPks = signers.map(x => x.publicKey);
tx.setSigners(...signerPks);
await _sendTransaction(connection, tx, signers);
}
export async function airdropMangoGroupTokens(
connection: Connection,
owner: Account,
mangoGroup: MangoGroup,
mangoGroupTokenMappings: any,
ownedTokenAccounts: any,
faucetIds: any
): Promise<void> {
(await Promise.all(
mangoGroup.tokens.map(async (mint: PublicKey) => {
const {tokenName, decimals} = mangoGroupTokenMappings[mint.toString()];
if (tokenName) {
const ownedTokenAccount = ownedTokenAccounts.find((x: any) => x.account.mint.equals(mint));
if (tokenName !== 'SOL') {
const multiplier = Math.pow(10, decimals);
await airdropTokens(connection, owner, faucetIds[tokenName], ownedTokenAccount.publicKey, mint, new u64(100 * multiplier));
}
}
})
));
}
export async function createTokenAccountWithBalance(
connection: Connection,
owner: Account,
tokenName: string,
mangoGroupTokenMappings: any,
faucetIds: any,
amount: number
) {
const tokenMapping: any = Object.values(mangoGroupTokenMappings).find((x: any) => x.tokenName === tokenName);
const { tokenMint, decimals } = tokenMapping;
const multiplier = Math.pow(10, decimals);
const processedAmount = amount * multiplier;
if (tokenName === 'SOL') {
await airdropSol(connection, owner, amount);
await createWrappedNativeAccount(connection, owner, processedAmount);
} else {
await createTokenAccount(connection, tokenMint, owner);
if (amount > 0) {
const ownedTokenAccounts = await token.getOwnedTokenAccounts(connection, owner.publicKey);
const ownedTokenAccount = ownedTokenAccounts.find((x: any) => x.account.mint.equals(tokenMint));
if (!ownedTokenAccount) throw new Error(`Token account doesn't exist for ${tokenName}`);
await airdropTokens(connection, owner, faucetIds[tokenName], ownedTokenAccount.publicKey, tokenMint, new u64(processedAmount));
}
}
}
export async function createTokenAccountsForMangoGroupTokens (
connection: Connection,
owner: Account,
mangoGroup: MangoGroup,
mangoGroupTokenMappings: any,
) {
(await Promise.all(
mangoGroup.tokens.map(async (mint: PublicKey) => {
const {tokenName} = mangoGroupTokenMappings[mint.toString()];
if (tokenName) {
if (tokenName === 'SOL') {
await createWrappedNativeAccount(connection, owner, 100 * 1e9);
} else {
await createTokenAccount(connection, mint, owner);
}
}
})
));
}
export async function performSingleDepositOrWithdrawal (
connection: Connection,
owner: Account,
client: MangoClient,
mangoGroup: MangoGroup,
mangoProgramId: PublicKey,
tokenName: string,
mangoGroupTokenMappings: any,
marginAccount: any,
type: string,
amount: number
) {
const tokenMapping: any = Object.values(mangoGroupTokenMappings).find((x: any) => x.tokenName === tokenName);
const { tokenMint } = tokenMapping;
const ownedTokenAccounts = await token.getOwnedTokenAccounts(connection, owner.publicKey);
const ownedTokenAccount = ownedTokenAccounts.find((x: any) => x.account.mint.equals(tokenMint));
if (!ownedTokenAccount) throw new Error(`Token account doesn't exist for ${tokenName}`);
if (type === 'deposit') {
await client.deposit(connection, mangoProgramId, mangoGroup, marginAccount, owner, tokenMint, ownedTokenAccount.publicKey, Number(amount));
} else if (type === 'withdraw') {
await client.withdraw(connection, mangoProgramId, mangoGroup, marginAccount, owner, tokenMint, ownedTokenAccount.publicKey, Number(amount));
}
}
export async function performDepositOrWithdrawal (
connection: Connection,
owner: Account,
client: MangoClient,
mangoGroup: MangoGroup,
mangoProgramId: PublicKey,
state: any,
type: string,
amount: number
) {
(await Promise.all(
mangoGroup.tokens.map(async (mint: PublicKey) => {
const ownedTokenAccount = state.ownedTokenAccounts.find((x: any) => x.account.mint.equals(mint));
if (type === 'deposit') {
await client.deposit(connection, mangoProgramId, mangoGroup, state.marginAccount, owner, mint, ownedTokenAccount.publicKey, Number(amount));
} else if (type === 'withdraw') {
await client.withdraw(connection, mangoProgramId, mangoGroup, state.marginAccount, owner, mint, ownedTokenAccount.publicKey, Number(amount));
}
})
));
}
export async function getAndDecodeBidsAndAsks (
connection: Connection,
spotMarket: Market
): Promise<any> {
const bidData = (await connection.getAccountInfo(spotMarket['_decoded'].bids))?.data;
const bidOrderBook = bidData ? Orderbook.decode(spotMarket, Buffer.from(bidData)): [];
const askData = (await connection.getAccountInfo(spotMarket['_decoded'].asks))?.data;
const askOrderBook = askData ? Orderbook.decode(spotMarket, Buffer.from(askData)): [];
return {bidOrderBook, askOrderBook};
}
export async function getAndDecodeBidsAndAsksForOwner (
connection: Connection,
spotMarket: Market,
openOrdersAccount: OpenOrders | undefined,
): Promise<any> {
if (!openOrdersAccount) throw new Error(`openOrdersAccount not found`);
const { bidOrderBook, askOrderBook } = await getAndDecodeBidsAndAsks(connection, spotMarket);
const openOrdersForOwner = [...bidOrderBook, ...askOrderBook].filter((o) =>
o.openOrdersAddress.equals(openOrdersAccount.address)
)
return openOrdersForOwner;
}
export async function getBidOrAskPriceEdge(
connection: Connection,
spotMarket: Market,
bidOrAsk: string,
maxOrMin: string
): Promise<number>{
const { bidOrderBook, askOrderBook } = await getAndDecodeBidsAndAsks(connection, spotMarket);
const [orderBookSide, orderBookOtherSide] = (bidOrAsk === 'bid' ? [bidOrderBook, askOrderBook] : [askOrderBook, bidOrderBook]);
const orderBookSidePrices: number[] = [...orderBookSide].map(x => x.price);
if (!orderBookSidePrices.length) {
// NOTE: This is a very arbitrary error prevention mechanism if one or both sides of the order book are empty
const orderBookOtherSidePrices: number[] = [...orderBookOtherSide].map(x => x.price);
if (bidOrAsk === 'bid') {
orderBookSidePrices.push(orderBookOtherSidePrices.length ? Math.min(...orderBookOtherSidePrices) / 2 : 10); // TODO: Maybe have a default value
} else {
orderBookSidePrices.push(orderBookOtherSidePrices.length ? Math.max(...orderBookOtherSidePrices) + 10 : 10); // TODO: Maybe have a default value
}
}
if (maxOrMin === 'min') {
return Math.min(...orderBookSidePrices);
} else {
return Math.max(...orderBookSidePrices);
}
}
export async function getOrderSizeAndPrice(
connection: Connection,
spotMarket: Market,
mangoGroupTokenMappings: any,
baseSymbol: string,
quoteSymbol: string,
side: string
): Promise<number[]>{
// NOTE: Always use minOrderSize
const tokenMapping: any = Object.values(mangoGroupTokenMappings).find((x: any) => x.tokenName === baseSymbol);
const { decimals } = tokenMapping;
const [stepSize, orderSize] = (decimals === 6) ? [0.01, 1] : [10, 0.01];
const edge = (side === 'buy') ? ['bid', 'max'] : ['ask', 'min'];
const orderPrice: number = Math.max(await getBidOrAskPriceEdge(connection, spotMarket, edge[0], edge[1]), stepSize);
return [orderSize, orderPrice, stepSize];
}
export function extractInfoFromLogs(
confirmedTx: any
): any {
if (!confirmedTx) throw new Error(`Couldn't find confirmed transaction`);
let invocationCount: number = 0;
let invocationComputeUnits: any[] = [];
const logMessages = confirmedTx.meta.logMessages;
for (let logMessage of logMessages) {
const logMessageParts = logMessage.split(' ');
if (logMessageParts.length === 4) {
if (logMessageParts[2] === 'invoke' && (/(\[[0-9]*\])/g).test(logMessageParts[3])) {
invocationCount += 1;
}
} else if (logMessageParts.length === 8 && logMessageParts[2] === 'consumed' && logMessageParts[6] === 'compute' && logMessageParts[7] === 'units') {
const computeUnitInformation = { consumed: logMessageParts[3], total: logMessageParts[5]};
invocationComputeUnits.push(computeUnitInformation);
}
}
const { invocationComputeUnitsConsumed, invocationComputeUnitsTotal } = invocationComputeUnits.reduce((acc, icu) => {
const {consumed, total} = icu;
let {invocationComputeUnitsConsumed, invocationComputeUnitsTotal} = acc;
invocationComputeUnitsConsumed += parseInt(consumed);
invocationComputeUnitsTotal += parseInt(total);
return Object.assign(acc, { invocationComputeUnitsConsumed, invocationComputeUnitsTotal });
}, {invocationComputeUnitsConsumed: 0, invocationComputeUnitsTotal: 0});
return { invocationCount, invocationComputeUnitsConsumed, invocationComputeUnitsTotal, invocationComputeUnits };
}
export function prettyPrintOwnerKeys(
owner: Account,
name: string
): void {
console.info("============");
console.info(`${name}'s wallet's public key: ${owner.publicKey.toString()}`);
console.info("============");
console.info(`${name}'s wallet's secret, to import in Sollet: \n [${owner.secretKey.toString()}]`);
console.info("============");
}

View File

@ -12,6 +12,6 @@
"sourceMap": true,
"jsx": "react"
},
"include": ["./src/**/*"],
"exclude": ["./src/**/*.test.js", "node_modules", "**/node_modules"]
"include": ["./tests/**/*", "./src/**/*"],
"exclude": ["./tests/**/*.test.js", "./src/**/*.test.js", "node_modules", "**/node_modules"]
}

446
yarn.lock
View File

@ -267,7 +267,14 @@
dependencies:
"@babel/helper-plugin-utils" "^7.12.13"
"@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.3.1":
"@babel/runtime@^7.10.5":
version "7.13.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.7.tgz#d494e39d198ee9ca04f4dcb76d25d9d7a1dc961a"
integrity sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1":
version "7.14.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
@ -541,6 +548,15 @@
"@nodelib/fs.scandir" "2.1.4"
fastq "^1.6.0"
"@project-serum/common@^0.0.1-beta.3":
version "0.0.1-beta.3"
resolved "https://registry.yarnpkg.com/@project-serum/common/-/common-0.0.1-beta.3.tgz#53586eaff9d9fd7e8938b1e12080c935b8b6ad07"
integrity sha512-gnQE/eUydTtto5okCgLWj1M97R9RRPJqnhKklikYI7jP/pnNhDmngSXC/dmfzED2GXSJEIKNIlxVw1k+E2Aw3w==
dependencies:
"@project-serum/serum" "^0.13.21"
bn.js "^5.1.2"
superstruct "0.8.3"
"@project-serum/serum@^0.13.20":
version "0.13.34"
resolved "https://registry.yarnpkg.com/@project-serum/serum/-/serum-0.13.34.tgz#c76477c27e14d975afa38b6c352b3abe92af6e52"
@ -550,6 +566,15 @@
bn.js "^5.1.2"
buffer-layout "^1.2.0"
"@project-serum/serum@^0.13.21":
version "0.13.37"
resolved "https://registry.yarnpkg.com/@project-serum/serum/-/serum-0.13.37.tgz#18cc2613a655a8e782e14c4d55a2707a79fbc625"
integrity sha512-Bt7D/0P0M1b+xyygCU9z1p7Pec6vontzy4Q92TgIg33/J1qiAR/899HXGlr7oho/NntGNwIlbEU22nqsWWuAiA==
dependencies:
"@solana/web3.js" "^0.90.0"
bn.js "^5.1.2"
buffer-layout "^1.2.0"
"@project-serum/sol-wallet-adapter@^0.1.4":
version "0.1.8"
resolved "https://registry.yarnpkg.com/@project-serum/sol-wallet-adapter/-/sol-wallet-adapter-0.1.8.tgz#90c6c1da793d32ed4ba3c67c5702a5bc804ef197"
@ -572,7 +597,7 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
"@solana/spl-token@^0.0.13":
"@solana/spl-token@0.0.13":
version "0.0.13"
resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.0.13.tgz#5e0b235b1f8b34643280401dbfddeb34d13d1acd"
integrity sha512-WT8M9V/hxURR5jLbhr3zgwVsgcY6m8UhHtK045w7o+jx8FJ9MKARkj387WBFU7mKiFq0k8jw/8YL7XmnIUuH8Q==
@ -630,6 +655,25 @@
tweetnacl "^1.0.0"
ws "^7.0.0"
"@solana/web3.js@^0.95.0":
version "0.95.0"
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-0.95.0.tgz#c028c800bf078bec90945240370df51026f8bdab"
integrity sha512-jdjAESYTChAYI1aZwH1RggcoT22BxdB9tDKBOt2Iw9SSpZ1Bb81ydrP+7eksE1AwQj6lpzrgtVt2d3sFosqupQ==
dependencies:
"@babel/runtime" "^7.12.5"
bn.js "^5.0.0"
bs58 "^4.0.1"
buffer "6.0.1"
buffer-layout "^1.2.0"
crypto-hash "^1.2.2"
jayson "^3.4.4"
js-sha3 "^0.8.0"
node-fetch "^2.6.1"
rpc-websockets "^7.4.2"
secp256k1 "^4.0.2"
superstruct "^0.14.2"
tweetnacl "^1.0.0"
"@tsconfig/node10@^1.0.0":
version "1.0.7"
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.7.tgz#1eb1de36c73478a2479cc661ef5af1c16d86d606"
@ -740,20 +784,20 @@
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.169.tgz#83c217688f07a4d9ef8f28a3ebd1d318f6ff4cbb"
integrity sha512-DvmZHoHTFJ8zhVYwCLWbQ7uAbYQEk52Ev2/ZiQ7Y7gQGeV9pjBqjnQpECMHfKS1rCYAhMI7LHVxwyZLZinJgdw==
"@types/mocha@^8.2.0":
"@types/mocha@^8.2.2":
version "8.2.2"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.2.tgz#91daa226eb8c2ff261e6a8cbf8c7304641e095e0"
integrity sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==
"@types/node@*":
version "15.0.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.0.3.tgz#ee09fcaac513576474c327da5818d421b98db88a"
integrity sha512-/WbxFeBU+0F79z9RdEOXH4CsDga+ibi5M8uEYr91u3CkT/pdWcV8MCook+4wDPnZBexRdwWS+PiVZ2xJviAzcQ==
version "15.0.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.0.2.tgz#51e9c0920d1b45936ea04341aa3e2e58d339fb67"
integrity sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==
"@types/node@^12.12.54":
version "12.20.13"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.13.tgz#e743bae112bd779ac9650f907197dd2caa7f0364"
integrity sha512-1x8W5OpxPq+T85OUsHRP6BqXeosKmeXRtjoF39STcdf/UWLqUsoehstZKOi0CunhVqHG17AyZgpj20eRVooK6A==
version "12.20.12"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.12.tgz#fd9c1c2cfab536a2383ed1ef70f94adea743a226"
integrity sha512-KQZ1al2hKOONAs2MFv+yTQP1LkDWMrRJ9YCVRalXltOfXsBmH5IownLxQaiq0lnAHwAViLnh2aTYqrPcRGEbgg==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@ -862,6 +906,11 @@
"@typescript-eslint/types" "4.23.0"
eslint-visitor-keys "^2.0.0"
"@ungap/promise-all-settled@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
JSONStream@^1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
@ -923,7 +972,7 @@ ajv@^8.0.1:
require-from-string "^2.0.2"
uri-js "^4.2.2"
ansi-colors@^4.1.1:
ansi-colors@4.1.1, ansi-colors@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
@ -935,6 +984,11 @@ ansi-escapes@^4.2.1:
dependencies:
type-fest "^0.21.3"
ansi-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
ansi-regex@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
@ -967,7 +1021,7 @@ anymatch@^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
anymatch@^3.0.3:
anymatch@^3.0.3, anymatch@~3.1.1:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
@ -987,6 +1041,11 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
arr-diff@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
@ -1181,16 +1240,26 @@ bcrypt-pbkdf@^1.0.0:
dependencies:
tweetnacl "^0.14.3"
binary-extensions@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
bn.js@^4.11.9:
version "4.12.0"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
bn.js@^5.0.0, bn.js@^5.1.2:
bn.js@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
bn.js@^5.1.2:
version "5.1.3"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
boolbase@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
@ -1229,7 +1298,7 @@ braces@^2.3.1:
split-string "^3.0.2"
to-regex "^3.0.1"
braces@^3.0.1:
braces@^3.0.1, braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
@ -1246,6 +1315,11 @@ browser-process-hrtime@^1.0.0:
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
browser-stdout@1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
browserslist@^4.14.5:
version "4.16.6"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2"
@ -1288,6 +1362,14 @@ buffer-layout@^1.2.0:
resolved "https://registry.yarnpkg.com/buffer-layout/-/buffer-layout-1.2.1.tgz#17b6db7abea303cab35eebd77919b89de026297d"
integrity sha512-RUTGEYG1vX0Zp1dStQFl8yeU/LEBPXVtHwzzDbPWkE5zq+Prt9fkFLKNiwmaeHg6BBiRMcQAgj4cynazO6eekw==
buffer@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.1.tgz#3cbea8c1463e5a0779e30b66d4c88c6ffa182ac2"
integrity sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ==
dependencies:
base64-js "^1.3.1"
ieee754 "^1.2.1"
buffer@^5.4.3:
version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
@ -1427,6 +1509,21 @@ cheerio@0.22.0:
lodash.reject "^4.4.0"
lodash.some "^4.4.0"
chokidar@3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
dependencies:
anymatch "~3.1.1"
braces "~3.0.2"
glob-parent "~5.1.0"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.5.0"
optionalDependencies:
fsevents "~2.3.1"
ci-info@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
@ -1461,6 +1558,15 @@ cliui@^6.0.0:
strip-ansi "^6.0.0"
wrap-ansi "^6.2.0"
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.0"
wrap-ansi "^7.0.0"
clone@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
@ -1642,6 +1748,13 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
debug@4.3.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
dependencies:
ms "2.1.2"
debug@^2.2.0, debug@^2.3.3:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@ -1649,18 +1762,16 @@ debug@^2.2.0, debug@^2.3.3:
dependencies:
ms "2.0.0"
debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
dependencies:
ms "2.1.2"
decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
decamelize@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837"
integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
decimal.js@^10.2.1:
version "10.2.1"
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3"
@ -1739,6 +1850,11 @@ diff-sequences@^26.6.2:
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1"
integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==
diff@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
diff@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
@ -1819,6 +1935,11 @@ dotenv@8.2.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
dotenv@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
ecc-jsbn@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
@ -1934,6 +2055,11 @@ escalade@^3.1.1:
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
escape-string-regexp@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
@ -2264,6 +2390,14 @@ fill-range@^7.0.1:
dependencies:
to-regex-range "^5.0.1"
find-up@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
dependencies:
locate-path "^6.0.0"
path-exists "^4.0.0"
find-up@^4.0.0, find-up@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
@ -2280,6 +2414,11 @@ flat-cache@^3.0.4:
flatted "^3.1.0"
rimraf "^3.0.2"
flat@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
flatted@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
@ -2325,7 +2464,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
fsevents@^2.1.2:
fsevents@^2.1.2, fsevents@~2.3.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@ -2345,7 +2484,7 @@ gensync@^1.0.0-beta.2:
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
get-caller-file@^2.0.1:
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
@ -2405,13 +2544,25 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
glob-parent@^5.0.0, glob-parent@^5.1.0:
glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
glob@7.1.6:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
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"
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
version "7.1.7"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
@ -2460,6 +2611,11 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.4:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
growl@1.10.5:
version "1.10.5"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@ -2544,6 +2700,11 @@ hash.js@^1.0.0, hash.js@^1.0.3:
inherits "^2.0.3"
minimalistic-assert "^1.0.1"
he@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
hmac-drbg@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@ -2676,6 +2837,13 @@ is-bigint@^1.0.1:
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.2.tgz#ffb381442503235ad245ea89e45b3dbff040ee5a"
integrity sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
dependencies:
binary-extensions "^2.0.0"
is-boolean-object@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.1.tgz#3c0878f035cb821228d350d2e1e36719716a3de8"
@ -2776,6 +2944,11 @@ is-extglob@^2.1.1:
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
is-fullwidth-code-point@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
@ -2786,7 +2959,7 @@ is-generator-fn@^2.0.0:
resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
is-glob@^4.0.0, is-glob@^4.0.1:
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
@ -2815,6 +2988,11 @@ is-number@^7.0.0:
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-plain-obj@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@ -2942,7 +3120,7 @@ istanbul-reports@^3.0.2:
html-escaper "^2.0.0"
istanbul-lib-report "^3.0.0"
jayson@^3.0.1:
jayson@^3.0.1, jayson@^3.4.4:
version "3.6.2"
resolved "https://registry.yarnpkg.com/jayson/-/jayson-3.6.2.tgz#e551e25abf2efe333051a6ed88b10f08c5288f50"
integrity sha512-hbl+x2xH6FT7nckw+Pq3lKOIJaMBKOgNJEVfvloDBWB8iSfzn/1U2igj1A5rplqNMFN/OnnaTNw8qPKVmoq83Q==
@ -3332,11 +3510,23 @@ jest@^26.6.3:
import-local "^3.0.2"
jest-cli "^26.6.3"
js-sha3@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f"
integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==
dependencies:
argparse "^2.0.1"
js-yaml@^3.13.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
@ -3545,6 +3735,13 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
locate-path@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
dependencies:
p-locate "^5.0.0"
lodash.assignin@^4.0.9:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2"
@ -3620,6 +3817,13 @@ lodash@4.x, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21,
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920"
integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==
dependencies:
chalk "^4.0.0"
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@ -3727,7 +3931,7 @@ minimalistic-crypto-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
minimatch@^3.0.4:
minimatch@3.0.4, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@ -3752,6 +3956,37 @@ mkdirp@1.0.4, mkdirp@1.x:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
mocha@^8.4.0:
version "8.4.0"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.4.0.tgz#677be88bf15980a3cae03a73e10a0fc3997f0cff"
integrity sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==
dependencies:
"@ungap/promise-all-settled" "1.1.2"
ansi-colors "4.1.1"
browser-stdout "1.3.1"
chokidar "3.5.1"
debug "4.3.1"
diff "5.0.0"
escape-string-regexp "4.0.0"
find-up "5.0.0"
glob "7.1.6"
growl "1.10.5"
he "1.2.0"
js-yaml "4.0.0"
log-symbols "4.0.0"
minimatch "3.0.4"
ms "2.1.3"
nanoid "3.1.20"
serialize-javascript "5.0.1"
strip-json-comments "3.1.1"
supports-color "8.1.1"
which "2.0.2"
wide-align "1.1.3"
workerpool "6.1.0"
yargs "16.2.0"
yargs-parser "20.2.4"
yargs-unparser "2.0.0"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@ -3762,6 +3997,11 @@ ms@2.1.2:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
ms@2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
mz@^2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
@ -3771,6 +4011,11 @@ mz@^2.7.0:
object-assign "^4.0.1"
thenify-all "^1.0.0"
nanoid@3.1.20:
version "3.1.20"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@ -3803,7 +4048,7 @@ node-addon-api@^2.0.0:
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
node-fetch@^2.2.0:
node-fetch@^2.2.0, node-fetch@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
@ -3857,7 +4102,7 @@ normalize-path@^2.1.1:
dependencies:
remove-trailing-separator "^1.0.1"
normalize-path@^3.0.0:
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
@ -4011,6 +4256,13 @@ p-limit@^2.2.0:
dependencies:
p-try "^2.0.0"
p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
dependencies:
yocto-queue "^0.1.0"
p-locate@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
@ -4018,6 +4270,13 @@ p-locate@^4.1.0:
dependencies:
p-limit "^2.2.0"
p-locate@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
dependencies:
p-limit "^3.0.2"
p-try@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
@ -4205,6 +4464,13 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
dependencies:
safe-buffer "^5.1.0"
react-is@^17.0.1:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
@ -4247,6 +4513,13 @@ readable-stream@^3.1.1:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readdirp@~3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
dependencies:
picomatch "^2.2.1"
regenerator-runtime@^0.13.4:
version "0.13.7"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
@ -4411,7 +4684,7 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@ -4481,6 +4754,13 @@ semver@^6.0.0, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
serialize-javascript@5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4"
integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==
dependencies:
randombytes "^2.1.0"
set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
@ -4704,6 +4984,14 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
"string-width@^1.0.2 || 2":
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
dependencies:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
string-width@^4.1.0, string-width@^4.2.0:
version "4.2.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"
@ -4745,6 +5033,13 @@ string_decoder@^1.1.1:
dependencies:
safe-buffer "~5.2.0"
strip-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
dependencies:
ansi-regex "^3.0.0"
strip-ansi@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
@ -4772,11 +5067,24 @@ strip-final-newline@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
superstruct@0.8.3:
version "0.8.3"
resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.8.3.tgz#fb4d8901aca3bf9f79afab1bbab7a7f335cc4ef2"
integrity sha512-LbtbFpktW1FcwxVIJlxdk7bCyBq/GzOx2FSFLRLTUhWIA1gHkYPIl3aXRG5mBdGZtnPNT6t+4eEcLDCMOuBHww==
dependencies:
kind-of "^6.0.2"
tiny-invariant "^1.0.6"
superstruct@^0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.14.2.tgz#0dbcdf3d83676588828f1cf5ed35cda02f59025b"
integrity sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==
superstruct@^0.8.3:
version "0.8.4"
resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.8.4.tgz#478a19649f6b02c6319c02044db6a1f5863c391f"
@ -4785,6 +5093,13 @@ superstruct@^0.8.3:
kind-of "^6.0.2"
tiny-invariant "^1.0.6"
supports-color@8.1.1:
version "8.1.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
dependencies:
has-flag "^4.0.0"
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@ -5230,6 +5545,13 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
which@2.0.2, which@^2.0.1, which@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
dependencies:
isexe "^2.0.0"
which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
@ -5237,18 +5559,23 @@ which@^1.2.9:
dependencies:
isexe "^2.0.0"
which@^2.0.1, which@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
wide-align@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
dependencies:
isexe "^2.0.0"
string-width "^1.0.2 || 2"
word-wrap@^1.2.3, word-wrap@~1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
workerpool@6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.0.tgz#a8e038b4c94569596852de7a8ea4228eefdeb37b"
integrity sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==
wrap-ansi@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
@ -5258,6 +5585,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
@ -5293,12 +5629,22 @@ y18n@^4.0.0:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
y18n@^5.0.5:
version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yargs-parser@20.x:
yargs-parser@20.2.4:
version "20.2.4"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==
yargs-parser@20.x, yargs-parser@^20.2.2:
version "20.2.7"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a"
integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==
@ -5311,6 +5657,29 @@ yargs-parser@^18.1.2:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-unparser@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb"
integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==
dependencies:
camelcase "^6.0.0"
decamelize "^4.0.0"
flat "^5.0.2"
is-plain-obj "^2.1.0"
yargs@16.2.0:
version "16.2.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
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"
yargs@^15.4.1:
version "15.4.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
@ -5332,3 +5701,8 @@ yn@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==