├── programs └── meteora-cpi │ ├── Xargo.toml │ ├── Cargo.toml │ └── src │ ├── utils.rs │ └── lib.rs ├── .gitignore ├── .prettierignore ├── .env ├── Cargo.toml ├── tsconfig.json ├── Anchor.toml ├── migrations └── deploy.ts ├── tests └── meteora-cpi.ts ├── package.json ├── lib └── dlmm │ ├── helpers │ ├── lbPair.ts │ ├── derive.ts │ ├── u64xu64_math.ts │ ├── index.ts │ ├── fee.ts │ ├── math.ts │ ├── binArray.ts │ ├── weightToAmounts.ts │ ├── strategy.ts │ └── weight.ts │ ├── error.ts │ ├── constants │ └── index.ts │ └── types │ └── index.ts ├── cli ├── helper.ts └── token-swap.ts └── yarn.lock /programs/meteora-cpi/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | **/*.rs.bk 5 | node_modules 6 | test-ledger 7 | .yarn 8 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | node_modules 5 | dist 6 | build 7 | test-ledger 8 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=../key/uu.json 2 | RPC=https://winter-solitary-season.solana-mainnet.quiknode.pro/d2ee96d2cb6cee59753c48ac22a264609c39b287 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist", 4 | "types": ["mocha", "chai"], 5 | "typeRoots": ["./node_modules/@types"], 6 | "module": "commonjs", 7 | "target": "ESNext", 8 | "moduleResolution": "node", 9 | "esModuleInterop": true, 10 | "resolveJsonModule": true, 11 | "noImplicitAny": false, 12 | "skipLibCheck": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | resolution = true 5 | skip-lint = false 6 | 7 | [programs.mainnet] 8 | meteora_cpi = "GUESbdzbRfwNuajJn27WpAiMoG8qif8rtLP13Pjy3Cza" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "mainnet" 15 | wallet = "../key/uu.json" 16 | 17 | [scripts] 18 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 19 | -------------------------------------------------------------------------------- /migrations/deploy.ts: -------------------------------------------------------------------------------- 1 | // Migrations are an early feature. Currently, they're nothing more than this 2 | // single deploy script that's invoked from the CLI, injecting a provider 3 | // configured from the workspace's Anchor.toml. 4 | 5 | const anchor = require("@coral-xyz/anchor"); 6 | 7 | module.exports = async function (provider) { 8 | // Configure client to use the provider. 9 | anchor.setProvider(provider); 10 | 11 | // Add your deploy script here. 12 | }; 13 | -------------------------------------------------------------------------------- /programs/meteora-cpi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "meteora-cpi" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "meteora_cpi" 10 | 11 | [features] 12 | default = [] 13 | cpi = ["no-entrypoint"] 14 | no-entrypoint = [] 15 | no-idl = [] 16 | no-log-ix-name = [] 17 | idl-build = ["anchor-lang/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = "0.30.0" 21 | anchor-spl = "0.30.0" 22 | -------------------------------------------------------------------------------- /tests/meteora-cpi.ts: -------------------------------------------------------------------------------- 1 | import * as anchor from "@coral-xyz/anchor"; 2 | import { Program } from "@coral-xyz/anchor"; 3 | import { MeteoraCpi } from "../target/types/meteora_cpi"; 4 | 5 | describe("meteora-cpi", () => { 6 | // Configure the client to use the local cluster. 7 | anchor.setProvider(anchor.AnchorProvider.env()); 8 | 9 | const program = anchor.workspace.MeteoraCpi as Program; 10 | 11 | it("Is initialized!", async () => { 12 | // Add your test here. 13 | const tx = await program.methods.initialize().rpc(); 14 | console.log("Your transaction signature", tx); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 4 | "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 5 | }, 6 | "dependencies": { 7 | "@coral-xyz/anchor": "^0.30.0", 8 | "@project-serum/serum": "^0.13.65", 9 | "@raydium-io/raydium-sdk": "^1.3.1-beta.48", 10 | "@solana/spl-token": "^0.4.6", 11 | "@solana/web3.js": "^1.90.0", 12 | "anchor28": "npm:@coral-xyz/anchor@^0.28.0", 13 | "dotenv": "^16.4.5", 14 | "gaussian": "^1.3.0", 15 | "typescript": "^5.0.4" 16 | }, 17 | "devDependencies": { 18 | "@types/bn.js": "^5.1.0", 19 | "@types/chai": "^4.3.0", 20 | "@types/gaussian": "^1.2.0", 21 | "@types/mocha": "^9.0.0", 22 | "chai": "^4.3.4", 23 | "mocha": "^9.0.3", 24 | "prettier": "^2.6.2", 25 | "ts-mocha": "^10.0.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /programs/meteora-cpi/src/utils.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | pub const METEORA_PROGRAM_KEY: &str = "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"; 4 | 5 | #[derive(AnchorSerialize, AnchorDeserialize)] 6 | struct CpiArgs { 7 | amount_in: u64, 8 | min_amount_out: u64 9 | } 10 | 11 | pub fn get_ix_data(amount_in: u64, min_amount_out: u64) -> Vec { 12 | let hash = get_function_hash("global", "swap"); 13 | let mut buf: Vec = vec![]; 14 | buf.extend_from_slice(&hash); 15 | let args = CpiArgs { amount_in, min_amount_out }; 16 | args.serialize(&mut buf).unwrap(); 17 | buf 18 | } 19 | 20 | fn get_function_hash(namespace: &str, name: &str) -> [u8; 8] { 21 | let preimage = format!("{}:{}", namespace, name); 22 | let mut sighash = [0u8; 8]; 23 | sighash.copy_from_slice( 24 | &anchor_lang::solana_program::hash::hash(preimage.as_bytes()).to_bytes() 25 | [..8], 26 | ); 27 | sighash 28 | } -------------------------------------------------------------------------------- /lib/dlmm/helpers/lbPair.ts: -------------------------------------------------------------------------------- 1 | import { AnchorProvider, Program } from "anchor28"; 2 | import { Cluster, Connection, PublicKey } from "@solana/web3.js"; 3 | import { IDL } from "../idl"; 4 | import { LBCLMM_PROGRAM_IDS } from "../constants"; 5 | 6 | /** 7 | * It fetches the pool account from the AMM program, and returns the mint addresses for the two tokens 8 | * @param {Connection} connection - Connection - The connection to the Solana cluster 9 | * @param {string} poolAddress - The address of the pool account. 10 | * @returns The tokenAMint and tokenBMint addresses for the pool. 11 | */ 12 | export async function getTokensMintFromPoolAddress( 13 | connection: Connection, 14 | poolAddress: string, 15 | opt?: { 16 | cluster?: Cluster; 17 | } 18 | ) { 19 | const provider = new AnchorProvider( 20 | connection, 21 | {} as any, 22 | AnchorProvider.defaultOptions() 23 | ); 24 | const program = new Program( 25 | IDL, 26 | LBCLMM_PROGRAM_IDS[opt?.cluster ?? "mainnet-beta"], 27 | provider 28 | ); 29 | 30 | const poolAccount = await program.account.lbPair.fetchNullable( 31 | new PublicKey(poolAddress) 32 | ); 33 | 34 | if (!poolAccount) throw new Error("Pool account not found"); 35 | 36 | return { 37 | tokenXMint: poolAccount.tokenXMint, 38 | tokenYMint: poolAccount.tokenYMint, 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /lib/dlmm/error.ts: -------------------------------------------------------------------------------- 1 | import { IDL } from "./idl"; 2 | import { AnchorError, ProgramError } from "anchor28"; 3 | import { LBCLMM_PROGRAM_IDS } from "./constants"; 4 | 5 | type Codes = (typeof IDL.errors)[number]["code"]; 6 | 7 | export class DLMMError extends Error { 8 | public errorCode: number; 9 | public errorName: string; 10 | public errorMessage: string; 11 | 12 | constructor(error: object | Codes) { 13 | let _errorCode = 0; 14 | let _errorName = "Something went wrong"; 15 | let _errorMessage = "Something went wrong"; 16 | 17 | if (error instanceof Error) { 18 | const anchorError = AnchorError.parse( 19 | JSON.parse(JSON.stringify(error)).logs as string[] 20 | ); 21 | 22 | if ( 23 | anchorError?.program.toBase58() === LBCLMM_PROGRAM_IDS["mainnet-beta"] 24 | ) { 25 | _errorCode = anchorError.error.errorCode.number; 26 | _errorName = anchorError.error.errorCode.code; 27 | _errorMessage = anchorError.error.errorMessage; 28 | } 29 | } else { 30 | const idlError = IDL.errors.find((err) => err.code === error); 31 | 32 | if (idlError) { 33 | _errorCode = idlError.code; 34 | _errorName = idlError.name; 35 | _errorMessage = idlError.msg; 36 | } 37 | } 38 | 39 | super(_errorMessage); 40 | 41 | this.errorCode = _errorCode; 42 | this.errorName = _errorName; 43 | this.errorMessage = _errorMessage; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/dlmm/constants/index.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from "@solana/web3.js"; 2 | import { IDL } from "../idl"; 3 | import { BN } from "anchor28"; 4 | 5 | export const LBCLMM_PROGRAM_IDS = { 6 | devnet: "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo", 7 | localhost: "LbVRzDTvBDEcrthxfZ4RL6yiq3uZw8bS6MwtdY6UhFQ", 8 | "mainnet-beta": "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo", 9 | }; 10 | 11 | export const ADMIN = { 12 | devnet: "6WaLrrRfReGKBYUSkmx2K6AuT21ida4j8at2SUiZdXu8", 13 | localhost: "bossj3JvwiNK7pvjr149DqdtJxf2gdygbcmEPTkb2F1", 14 | }; 15 | 16 | export enum Network { 17 | MAINNET = "mainnet-beta", 18 | TESTNET = "testnet", 19 | DEVNET = "devnet", 20 | LOCAL = "localhost", 21 | } 22 | 23 | export const BASIS_POINT_MAX = 10000; 24 | export const SCALE_OFFSET = 64; 25 | export const SCALE = new BN(1).shln(SCALE_OFFSET); 26 | 27 | export const FEE_PRECISION = new BN(1_000_000_000); 28 | export const MAX_FEE_RATE = new BN(100_000_000); 29 | export const BIN_ARRAY_FEE = 0.07054656; 30 | export const POSITION_FEE = 0.0565152; 31 | 32 | const CONSTANTS = Object.entries(IDL.constants); 33 | 34 | export const MAX_BIN_ARRAY_SIZE = new BN( 35 | CONSTANTS.find(([k, v]) => v.name == "MAX_BIN_PER_ARRAY")?.[1].value ?? 0 36 | ); 37 | export const MAX_BIN_PER_POSITION = new BN( 38 | CONSTANTS.find(([k, v]) => v.name == "MAX_BIN_PER_POSITION")?.[1].value ?? 0 39 | ); 40 | export const BIN_ARRAY_BITMAP_SIZE = new BN( 41 | CONSTANTS.find(([k, v]) => v.name == "BIN_ARRAY_BITMAP_SIZE")?.[1].value ?? 0 42 | ); 43 | export const EXTENSION_BINARRAY_BITMAP_SIZE = new BN( 44 | CONSTANTS.find(([k, v]) => v.name == "EXTENSION_BINARRAY_BITMAP_SIZE")?.[1] 45 | .value ?? 0 46 | ); 47 | 48 | export const SIMULATION_USER = new PublicKey( 49 | "HrY9qR5TiB2xPzzvbBu5KrBorMfYGQXh9osXydz4jy9s" 50 | ); 51 | 52 | export const PRECISION = 18446744073709551616; 53 | 54 | export const MAX_CLAIM_ALL_ALLOWED = 3; 55 | 56 | export const MAX_BIN_LENGTH_ALLOWED_IN_ONE_TX = 26; 57 | export const MAX_BIN_PER_TX = 69; 58 | 59 | export const MAX_ACTIVE_BIN_SLIPPAGE = 3; 60 | -------------------------------------------------------------------------------- /cli/helper.ts: -------------------------------------------------------------------------------- 1 | import * as anchor from "@coral-xyz/anchor"; 2 | import { Program, Wallet, AnchorProvider } from "@coral-xyz/anchor"; 3 | import { MeteoraCpi } from "../target/types/meteora_cpi"; 4 | import fs from "fs"; 5 | import { 6 | PublicKey, 7 | Keypair, 8 | Connection, 9 | Transaction, 10 | ConnectionConfig, 11 | } from "@solana/web3.js"; 12 | import { 13 | ASSOCIATED_TOKEN_PROGRAM_ID, 14 | TOKEN_PROGRAM_ID, 15 | } from "@solana/spl-token"; 16 | import { LBCLMM_PROGRAM_IDS } from "../lib/dlmm/constants"; 17 | 18 | require("dotenv").config(); 19 | 20 | const VAULT_SEED = "vault-authority"; 21 | 22 | export const JLP_ADDRESS = new PublicKey("27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4"); 23 | export const USDC_ADDRESS = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); 24 | export const METEORA_PROGRAM = new PublicKey(LBCLMM_PROGRAM_IDS["mainnet-beta"]); 25 | 26 | const walletKeypair = Keypair.fromSecretKey( 27 | Uint8Array.from( 28 | JSON.parse(fs.readFileSync(process.env.PRIVATE_KEY || "", "utf-8")) 29 | ), 30 | { skipValidation: true } 31 | ); 32 | 33 | export const wallet = new Wallet(walletKeypair); 34 | 35 | const config: ConnectionConfig = { 36 | commitment: "confirmed", 37 | disableRetryOnRateLimit: false, 38 | confirmTransactionInitialTimeout: 60000, 39 | }; 40 | 41 | export const connection = new Connection(process.env.RPC, config); 42 | export const provider = new AnchorProvider(connection, wallet, { 43 | commitment: "confirmed", 44 | }); 45 | anchor.setProvider(provider); 46 | export const program = anchor.workspace.MeteoraCpi as Program; 47 | 48 | console.log("rpc: ", process.env.RPC); 49 | console.log("user: ", wallet.publicKey.toBase58()); 50 | console.log("program: ", program.programId.toBase58()); 51 | 52 | const findVault = (): PublicKey => { 53 | return PublicKey.findProgramAddressSync( 54 | [Buffer.from(VAULT_SEED)], 55 | program.programId 56 | )[0]; 57 | }; 58 | export const vault = findVault(); 59 | console.log("vault: ", vault.toBase58()); 60 | 61 | export const findAssociatedTokenAddress = ( 62 | walletAddress: PublicKey, 63 | tokenMintAddress: PublicKey 64 | ): PublicKey => { 65 | return PublicKey.findProgramAddressSync( 66 | [ 67 | walletAddress.toBuffer(), 68 | TOKEN_PROGRAM_ID.toBuffer(), 69 | tokenMintAddress.toBuffer(), 70 | ], 71 | ASSOCIATED_TOKEN_PROGRAM_ID 72 | )[0]; 73 | }; 74 | 75 | export const execTx = async (transaction: Transaction) => { 76 | // Execute the transaction 77 | 78 | const rawTransaction = transaction.serialize(); 79 | 80 | const result = await connection.simulateTransaction(transaction as Transaction); 81 | console.log('simulate result'); 82 | console.log(result); 83 | 84 | if (result.value.err) { 85 | console.log(result.value.err); 86 | console.log(result.value.returnData); 87 | return; 88 | } 89 | 90 | const txid = await connection.sendRawTransaction(rawTransaction, { 91 | skipPreflight: true, 92 | maxRetries: 2, 93 | preflightCommitment: "processed", 94 | }); 95 | console.log(`https://solscan.io/tx/${txid}`); 96 | 97 | const confirmed = await connection.confirmTransaction(txid, "confirmed"); 98 | 99 | console.log("err ", confirmed.value.err); 100 | }; 101 | -------------------------------------------------------------------------------- /cli/token-swap.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { DLMM } from "../lib/dlmm"; 3 | import { 4 | vault, 5 | wallet, 6 | connection, 7 | execTx, 8 | program, 9 | findAssociatedTokenAddress, 10 | METEORA_PROGRAM, 11 | JLP_ADDRESS, 12 | USDC_ADDRESS, 13 | } from "./helper"; 14 | import { 15 | PublicKey, 16 | Transaction, 17 | ComputeBudgetProgram, 18 | AccountMeta, 19 | } from "@solana/web3.js"; 20 | import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes"; 21 | import { LbPairAccount } from "../lib/dlmm/types"; 22 | import { findProgramAddress } from "@raydium-io/raydium-sdk"; 23 | 24 | const main = async () => { 25 | 26 | const lbPairs = await DLMM.getLbPairsForTokens(connection, JLP_ADDRESS, USDC_ADDRESS); 27 | 28 | const tokenAmounts = await Promise.all( 29 | lbPairs.map(async (lbPair) => await connection.getTokenAccountBalance(lbPair.account.reserveX)) 30 | ); 31 | 32 | const maxIndex = tokenAmounts.reduce((maxIdx, current, idx, arr) => { 33 | const currentValue = current.value.uiAmount; 34 | const maxValue = arr[maxIdx].value.uiAmount; 35 | 36 | if (currentValue === null) return maxIdx; 37 | if (maxValue === null || currentValue > maxValue) return idx; 38 | 39 | return maxIdx; 40 | }, 0); 41 | 42 | await tokenSwap(lbPairs[maxIndex]); 43 | }; 44 | 45 | const tokenSwap = async (lbPair: LbPairAccount) => { 46 | 47 | const dlmmPool = await DLMM.create(connection, lbPair.publicKey, { 48 | cluster: "mainnet-beta", 49 | }); 50 | 51 | // Swap quote 52 | const swapYtoX = true; 53 | const binArrayAccounts = await dlmmPool.getBinArrayForSwap(swapYtoX); 54 | 55 | const swapQuote = dlmmPool.swapQuote( 56 | new BN(1_000_000), 57 | swapYtoX, 58 | new BN(10), 59 | binArrayAccounts 60 | ); 61 | 62 | const { tokenXMint, tokenYMint, reserveX, reserveY, oracle } = lbPair.account; 63 | 64 | const userTokenIn = findAssociatedTokenAddress(vault, tokenYMint); 65 | const userTokenOut = findAssociatedTokenAddress(vault, tokenXMint); 66 | const eventAuthority = findProgramAddress([Buffer.from("__event_authority")], METEORA_PROGRAM).publicKey; 67 | 68 | console.log("tokenIn: ", tokenYMint.toBase58()); 69 | console.log("tokenOut: ", tokenXMint.toBase58()); 70 | console.log("userTokenIn: ", userTokenIn.toBase58()); 71 | console.log("userTokenOut: ", userTokenOut.toBase58()); 72 | 73 | const binArrays: AccountMeta[] = swapQuote.binArraysPubkey.map((pubkey) => { 74 | return { 75 | isSigner: false, 76 | isWritable: true, 77 | pubkey, 78 | }; 79 | }); 80 | 81 | const transaction = new Transaction(); 82 | 83 | transaction 84 | .add(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1000000 })) 85 | .add(ComputeBudgetProgram.setComputeUnitLimit({ units: 100000 })) 86 | .add( 87 | await program.methods 88 | .tokenSwap() 89 | .accounts({ 90 | lbPair: lbPair.publicKey, 91 | reserveX, 92 | reserveY, 93 | userTokenIn, 94 | userTokenOut, 95 | tokenXMint, 96 | tokenYMint, 97 | oracle, 98 | meteoraProgram: METEORA_PROGRAM, 99 | eventAuthority 100 | }) 101 | .remainingAccounts(binArrays) 102 | .transaction() 103 | ); 104 | 105 | const blockhash = await connection.getLatestBlockhash(); 106 | transaction.recentBlockhash = blockhash.blockhash; 107 | transaction.feePayer = wallet.publicKey; 108 | const signedTx = await wallet.signTransaction(transaction); 109 | 110 | try { 111 | // send and confirm the transaction 112 | await execTx(signedTx); 113 | } catch (e) { 114 | console.log(e); 115 | } 116 | }; 117 | 118 | main(); 119 | -------------------------------------------------------------------------------- /lib/dlmm/helpers/derive.ts: -------------------------------------------------------------------------------- 1 | import { BN } from "anchor28"; 2 | import { Connection, PublicKey } from "@solana/web3.js"; 3 | import { DLMM } from ".."; 4 | 5 | /** private */ 6 | function sortTokenMints(tokenX: PublicKey, tokenY: PublicKey) { 7 | const [minKey, maxKey] = 8 | tokenX.toBuffer().compare(tokenY.toBuffer()) == 1 9 | ? [tokenY, tokenX] 10 | : [tokenX, tokenY]; 11 | return [minKey, maxKey]; 12 | } 13 | /** private */ 14 | 15 | /** 16 | * 17 | * @deprecated Use derivePresetParameter2 18 | */ 19 | export function derivePresetParameter(binStep: BN, programId: PublicKey) { 20 | return PublicKey.findProgramAddressSync( 21 | [ 22 | Buffer.from("preset_parameter"), 23 | new Uint8Array(binStep.toArrayLike(Buffer, "le", 2)), 24 | ], 25 | programId 26 | ); 27 | } 28 | 29 | export function derivePresetParameter2( 30 | binStep: BN, 31 | baseFactor: BN, 32 | programId: PublicKey 33 | ) { 34 | return PublicKey.findProgramAddressSync( 35 | [ 36 | Buffer.from("preset_parameter"), 37 | new Uint8Array(binStep.toArrayLike(Buffer, "le", 2)), 38 | new Uint8Array(baseFactor.toArrayLike(Buffer, "le", 2)), 39 | ], 40 | programId 41 | ); 42 | } 43 | 44 | export function deriveLbPair2( 45 | tokenX: PublicKey, 46 | tokenY: PublicKey, 47 | binStep: BN, 48 | baseFactor: BN, 49 | programId: PublicKey 50 | ) { 51 | const [minKey, maxKey] = sortTokenMints(tokenX, tokenY); 52 | return PublicKey.findProgramAddressSync( 53 | [ 54 | minKey.toBuffer(), 55 | maxKey.toBuffer(), 56 | new Uint8Array(binStep.toArrayLike(Buffer, "le", 2)), 57 | new Uint8Array(baseFactor.toArrayLike(Buffer, "le", 2)), 58 | ], 59 | programId 60 | ); 61 | } 62 | 63 | /** 64 | * 65 | * @deprecated Use deriveLbPair2 66 | */ 67 | 68 | export function deriveLbPair( 69 | tokenX: PublicKey, 70 | tokenY: PublicKey, 71 | binStep: BN, 72 | programId: PublicKey 73 | ) { 74 | const [minKey, maxKey] = sortTokenMints(tokenX, tokenY); 75 | return PublicKey.findProgramAddressSync( 76 | [ 77 | minKey.toBuffer(), 78 | maxKey.toBuffer(), 79 | new Uint8Array(binStep.toArrayLike(Buffer, "le", 2)), 80 | ], 81 | programId 82 | ); 83 | } 84 | 85 | export function derivePermissionLbPair( 86 | baseKey: PublicKey, 87 | tokenX: PublicKey, 88 | tokenY: PublicKey, 89 | binStep: BN, 90 | programId: PublicKey 91 | ) { 92 | const [minKey, maxKey] = sortTokenMints(tokenX, tokenY); 93 | return PublicKey.findProgramAddressSync( 94 | [ 95 | baseKey.toBuffer(), 96 | minKey.toBuffer(), 97 | maxKey.toBuffer(), 98 | new Uint8Array(binStep.toArrayLike(Buffer, "le", 2)), 99 | ], 100 | programId 101 | ); 102 | } 103 | 104 | export function deriveOracle(lbPair: PublicKey, programId: PublicKey) { 105 | return PublicKey.findProgramAddressSync( 106 | [Buffer.from("oracle"), lbPair.toBytes()], 107 | programId 108 | ); 109 | } 110 | 111 | export function derivePosition( 112 | lbPair: PublicKey, 113 | base: PublicKey, 114 | lowerBinId: BN, 115 | width: BN, 116 | programId: PublicKey 117 | ) { 118 | let lowerBinIdBytes: Uint8Array; 119 | if (lowerBinId.isNeg()) { 120 | lowerBinIdBytes = new Uint8Array( 121 | lowerBinId.toTwos(32).toArrayLike(Buffer, "le", 4) 122 | ); 123 | } else { 124 | lowerBinIdBytes = new Uint8Array(lowerBinId.toArrayLike(Buffer, "le", 4)); 125 | } 126 | return PublicKey.findProgramAddressSync( 127 | [ 128 | Buffer.from("position"), 129 | lbPair.toBuffer(), 130 | base.toBuffer(), 131 | lowerBinIdBytes, 132 | new Uint8Array(width.toBuffer("le", 4)), 133 | ], 134 | programId 135 | ); 136 | } 137 | 138 | export function deriveBinArray( 139 | lbPair: PublicKey, 140 | index: BN, 141 | programId: PublicKey 142 | ) { 143 | let binArrayBytes: Uint8Array; 144 | if (index.isNeg()) { 145 | binArrayBytes = new Uint8Array( 146 | index.toTwos(64).toArrayLike(Buffer, "le", 8) 147 | ); 148 | } else { 149 | binArrayBytes = new Uint8Array(index.toArrayLike(Buffer, "le", 8)); 150 | } 151 | return PublicKey.findProgramAddressSync( 152 | [Buffer.from("bin_array"), lbPair.toBytes(), binArrayBytes], 153 | programId 154 | ); 155 | } 156 | 157 | export function deriveReserve( 158 | token: PublicKey, 159 | lbPair: PublicKey, 160 | programId: PublicKey 161 | ) { 162 | return PublicKey.findProgramAddressSync( 163 | [lbPair.toBuffer(), token.toBuffer()], 164 | programId 165 | ); 166 | } 167 | -------------------------------------------------------------------------------- /lib/dlmm/helpers/u64xu64_math.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { SCALE_OFFSET } from "../constants"; 3 | 4 | const MAX_EXPONENTIAL = new BN(0x80000); 5 | 6 | export const ONE = new BN(1).shln(SCALE_OFFSET); 7 | const MAX = new BN(2).pow(new BN(128)).sub(new BN(1)); 8 | 9 | export function pow(base: BN, exp: BN): BN { 10 | let invert = exp.isNeg(); 11 | 12 | if (exp.isZero()) { 13 | return ONE; 14 | } 15 | 16 | exp = invert ? exp.abs() : exp; 17 | 18 | if (exp.gt(MAX_EXPONENTIAL)) { 19 | return new BN(0); 20 | } 21 | 22 | let squaredBase = base; 23 | let result = ONE; 24 | 25 | if (squaredBase.gte(result)) { 26 | squaredBase = MAX.div(squaredBase); 27 | invert = !invert; 28 | } 29 | 30 | if (!exp.and(new BN(0x1)).isZero()) { 31 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 32 | } 33 | 34 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 35 | 36 | if (!exp.and(new BN(0x2)).isZero()) { 37 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 38 | } 39 | 40 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 41 | 42 | if (!exp.and(new BN(0x4)).isZero()) { 43 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 44 | } 45 | 46 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 47 | 48 | if (!exp.and(new BN(0x8)).isZero()) { 49 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 50 | } 51 | 52 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 53 | 54 | if (!exp.and(new BN(0x10)).isZero()) { 55 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 56 | } 57 | 58 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 59 | 60 | if (!exp.and(new BN(0x20)).isZero()) { 61 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 62 | } 63 | 64 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 65 | 66 | if (!exp.and(new BN(0x40)).isZero()) { 67 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 68 | } 69 | 70 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 71 | 72 | if (!exp.and(new BN(0x80)).isZero()) { 73 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 74 | } 75 | 76 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 77 | 78 | if (!exp.and(new BN(0x100)).isZero()) { 79 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 80 | } 81 | 82 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 83 | 84 | if (!exp.and(new BN(0x200)).isZero()) { 85 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 86 | } 87 | 88 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 89 | 90 | if (!exp.and(new BN(0x400)).isZero()) { 91 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 92 | } 93 | 94 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 95 | 96 | if (!exp.and(new BN(0x800)).isZero()) { 97 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 98 | } 99 | 100 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 101 | 102 | if (!exp.and(new BN(0x1000)).isZero()) { 103 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 104 | } 105 | 106 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 107 | 108 | if (!exp.and(new BN(0x2000)).isZero()) { 109 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 110 | } 111 | 112 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 113 | 114 | if (!exp.and(new BN(0x4000)).isZero()) { 115 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 116 | } 117 | 118 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 119 | 120 | if (!exp.and(new BN(0x8000)).isZero()) { 121 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 122 | } 123 | 124 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 125 | 126 | if (!exp.and(new BN(0x10000)).isZero()) { 127 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 128 | } 129 | 130 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 131 | 132 | if (!exp.and(new BN(0x20000)).isZero()) { 133 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 134 | } 135 | 136 | squaredBase = squaredBase.mul(squaredBase).shrn(SCALE_OFFSET); 137 | 138 | if (!exp.and(new BN(0x40000)).isZero()) { 139 | result = result.mul(squaredBase).shrn(SCALE_OFFSET); 140 | } 141 | 142 | if (result.isZero()) { 143 | return new BN(0); 144 | } 145 | 146 | if (invert) { 147 | result = MAX.div(result); 148 | } 149 | 150 | return result; 151 | } 152 | -------------------------------------------------------------------------------- /programs/meteora-cpi/src/lib.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::{ 2 | prelude::*, 3 | solana_program::{ 4 | instruction::Instruction, 5 | program::invoke_signed 6 | } 7 | }; 8 | use anchor_spl::token::Token; 9 | use std::str::FromStr; 10 | 11 | pub mod utils; 12 | use utils::*; 13 | 14 | declare_id!("43cXKeawG2C13yMH4NzgfXPMaRVPEggQm1aqsKxoSJia"); 15 | 16 | pub const VAULT_SEED: &[u8] = b"vault-authority"; 17 | 18 | const AMOUNT_IN: u64 = 100_000; 19 | const MIN_AMOUNT_OUT: u64 = 0; 20 | 21 | #[program] 22 | pub mod meteora_cpi { 23 | 24 | use super::*; 25 | 26 | pub fn token_swap<'a, 'b, 'c, 'info>(ctx: Context<'a, 'b, 'c, 'info, TokenSwap<'info>>) -> Result<()> { 27 | msg!("yo, this is microgift"); 28 | 29 | let vault_bump = ctx.bumps.vault.to_le_bytes(); 30 | let signer_seeds: &[&[&[u8]]] = &[ 31 | &[VAULT_SEED, vault_bump.as_ref()] 32 | ]; 33 | 34 | msg!("Swap on Meteora"); 35 | 36 | let meteora_program_id: Pubkey = Pubkey::from_str(METEORA_PROGRAM_KEY).unwrap(); 37 | 38 | let mut accounts: Vec = vec![ 39 | AccountMeta::new(ctx.accounts.lb_pair.key(), false), 40 | AccountMeta::new_readonly(ctx.accounts.meteora_program.key(), false), 41 | AccountMeta::new(ctx.accounts.reserve_x.key(), false), 42 | AccountMeta::new(ctx.accounts.reserve_y.key(), false), 43 | AccountMeta::new(ctx.accounts.user_token_in.key(), false), 44 | AccountMeta::new(ctx.accounts.user_token_out.key(), false), 45 | AccountMeta::new_readonly(ctx.accounts.token_x_mint.key(), false), 46 | AccountMeta::new_readonly(ctx.accounts.token_y_mint.key(), false), 47 | AccountMeta::new(ctx.accounts.oracle.key(), false), 48 | AccountMeta::new(ctx.accounts.meteora_program.key(), false), 49 | AccountMeta::new_readonly(ctx.accounts.vault.key(), true), 50 | AccountMeta::new_readonly(ctx.accounts.token_program.key(), false), 51 | AccountMeta::new_readonly(ctx.accounts.token_program.key(), false), 52 | AccountMeta::new_readonly(ctx.accounts.event_authority.key(), false), 53 | AccountMeta::new_readonly(ctx.accounts.meteora_program.key(), false) 54 | ]; 55 | accounts.extend( 56 | ctx.remaining_accounts.iter().map(|acc| AccountMeta { 57 | pubkey: *acc.key, 58 | is_signer: false, 59 | is_writable: true 60 | }) 61 | ); 62 | 63 | let data = get_ix_data(AMOUNT_IN, MIN_AMOUNT_OUT); 64 | 65 | let instruction = Instruction { 66 | program_id: meteora_program_id, 67 | accounts, 68 | data 69 | }; 70 | 71 | let mut account_infos: Vec> = vec![ 72 | ctx.accounts.lb_pair.to_account_info(), 73 | ctx.accounts.reserve_x.to_account_info(), 74 | ctx.accounts.reserve_y.to_account_info(), 75 | ctx.accounts.user_token_in.to_account_info(), 76 | ctx.accounts.user_token_out.to_account_info(), 77 | ctx.accounts.token_x_mint.to_account_info(), 78 | ctx.accounts.token_y_mint.to_account_info(), 79 | ctx.accounts.oracle.to_account_info(), 80 | ctx.accounts.vault.to_account_info(), 81 | ctx.accounts.token_program.to_account_info(), 82 | ctx.accounts.meteora_program.to_account_info(), 83 | ctx.accounts.event_authority.to_account_info() 84 | ]; 85 | 86 | account_infos.extend_from_slice(ctx.remaining_accounts); 87 | 88 | 89 | invoke_signed(&instruction, &account_infos, signer_seeds)?; 90 | 91 | Ok(()) 92 | } 93 | } 94 | 95 | #[derive(Accounts)] 96 | pub struct TokenSwap<'info> { 97 | 98 | #[account( 99 | seeds = [VAULT_SEED], 100 | bump 101 | )] 102 | /// CHECK: This is not dangerous because we don't read or write from this account 103 | pub vault: AccountInfo<'info>, 104 | 105 | #[account(mut)] 106 | /// CHECK: 107 | pub meteora_program: AccountInfo<'info>, 108 | pub token_program: Program<'info, Token>, 109 | pub system_program: Program<'info, System>, 110 | 111 | #[account(mut)] 112 | /// CHECK: will be checked on meteora 113 | pub lb_pair: AccountInfo<'info>, 114 | 115 | #[account(mut)] 116 | /// CHECK: 117 | pub reserve_x: AccountInfo<'info>, 118 | 119 | #[account(mut)] 120 | /// CHECK: 121 | pub reserve_y: AccountInfo<'info>, 122 | 123 | #[account(mut)] 124 | /// CHECK: 125 | pub user_token_in: AccountInfo<'info>, 126 | #[account(mut)] 127 | /// CHECK: 128 | pub user_token_out: AccountInfo<'info>, 129 | 130 | /// CHECK: 131 | pub token_x_mint: AccountInfo<'info>, 132 | /// CHECK: 133 | pub token_y_mint: AccountInfo<'info>, 134 | 135 | #[account(mut)] 136 | /// CHECK: 137 | pub oracle: AccountInfo<'info>, 138 | 139 | /// CHECK: 140 | pub event_authority: AccountInfo<'info> 141 | } 142 | 143 | 144 | -------------------------------------------------------------------------------- /lib/dlmm/helpers/index.ts: -------------------------------------------------------------------------------- 1 | import { BN, EventParser } from "anchor28"; 2 | import { 3 | NATIVE_MINT, 4 | TOKEN_PROGRAM_ID, 5 | TokenAccountNotFoundError, 6 | TokenInvalidAccountOwnerError, 7 | createAssociatedTokenAccountInstruction, 8 | createCloseAccountInstruction, 9 | getAccount, 10 | getAssociatedTokenAddressSync, 11 | getMint, 12 | } from "@solana/spl-token"; 13 | import { SCALE_OFFSET } from "../constants"; 14 | import { 15 | ComputeBudgetProgram, 16 | Connection, 17 | PublicKey, 18 | SystemProgram, 19 | TransactionInstruction, 20 | } from "@solana/web3.js"; 21 | import { Bin, ClmmProgram, GetOrCreateATAResponse } from "../types"; 22 | import { Rounding, mulShr, shlDiv } from "./math"; 23 | 24 | export * from "./derive"; 25 | export * from "./binArray"; 26 | export * from "./weight"; 27 | export * from "./fee"; 28 | export * from "./weightToAmounts"; 29 | export * from "./strategy"; 30 | export * from "./lbPair"; 31 | 32 | export function chunks(array: T[], size: number): T[][] { 33 | return Array.apply(0, new Array(Math.ceil(array.length / size))).map( 34 | (_, index) => array.slice(index * size, (index + 1) * size) 35 | ); 36 | } 37 | 38 | export async function chunkedFetchMultiplePoolAccount( 39 | program: ClmmProgram, 40 | pks: PublicKey[], 41 | chunkSize: number = 100 42 | ) { 43 | const accounts = ( 44 | await Promise.all( 45 | chunks(pks, chunkSize).map((chunk) => 46 | program.account.lbPair.fetchMultiple(chunk) 47 | ) 48 | ) 49 | ).flat(); 50 | 51 | return accounts.filter(Boolean); 52 | } 53 | 54 | export async function chunkedFetchMultipleBinArrayBitmapExtensionAccount( 55 | program: ClmmProgram, 56 | pks: PublicKey[], 57 | chunkSize: number = 100 58 | ) { 59 | const accounts = ( 60 | await Promise.all( 61 | chunks(pks, chunkSize).map((chunk) => 62 | program.account.binArrayBitmapExtension.fetchMultiple(chunk) 63 | ) 64 | ) 65 | ).flat(); 66 | 67 | return accounts; 68 | } 69 | 70 | export function getOutAmount(bin: Bin, inAmount: BN, swapForY: boolean) { 71 | return swapForY 72 | ? mulShr(inAmount, bin.price, SCALE_OFFSET, Rounding.Down) 73 | : shlDiv(inAmount, bin.price, SCALE_OFFSET, Rounding.Down); 74 | } 75 | 76 | export async function getTokenDecimals(conn: Connection, mint: PublicKey) { 77 | const token = await getMint(conn, mint); 78 | return await token.decimals; 79 | } 80 | 81 | export const getOrCreateATAInstruction = async ( 82 | connection: Connection, 83 | tokenMint: PublicKey, 84 | owner: PublicKey, 85 | payer: PublicKey = owner, 86 | allowOwnerOffCurve = true 87 | ): Promise => { 88 | const toAccount = getAssociatedTokenAddressSync( 89 | tokenMint, 90 | owner, 91 | allowOwnerOffCurve 92 | ); 93 | 94 | try { 95 | await getAccount(connection, toAccount); 96 | 97 | return { ataPubKey: toAccount, ix: undefined }; 98 | } catch (e) { 99 | if ( 100 | e instanceof TokenAccountNotFoundError || 101 | e instanceof TokenInvalidAccountOwnerError 102 | ) { 103 | const ix = createAssociatedTokenAccountInstruction( 104 | payer, 105 | toAccount, 106 | owner, 107 | tokenMint 108 | ); 109 | 110 | return { ataPubKey: toAccount, ix }; 111 | } else { 112 | /* handle error */ 113 | console.error("Error::getOrCreateATAInstruction", e); 114 | throw e; 115 | } 116 | } 117 | }; 118 | 119 | export async function getTokenBalance( 120 | conn: Connection, 121 | tokenAccount: PublicKey 122 | ): Promise { 123 | const acc = await getAccount(conn, tokenAccount); 124 | return acc.amount; 125 | } 126 | 127 | export const parseLogs = (eventParser: EventParser, logs: string[]) => { 128 | if (!logs.length) throw new Error("No logs found"); 129 | 130 | for (const event of eventParser?.parseLogs(logs)) { 131 | return event.data as T; 132 | } 133 | 134 | throw new Error("No events found"); 135 | }; 136 | 137 | export const wrapSOLInstruction = ( 138 | from: PublicKey, 139 | to: PublicKey, 140 | amount: bigint 141 | ): TransactionInstruction[] => { 142 | return [ 143 | SystemProgram.transfer({ 144 | fromPubkey: from, 145 | toPubkey: to, 146 | lamports: amount, 147 | }), 148 | new TransactionInstruction({ 149 | keys: [ 150 | { 151 | pubkey: to, 152 | isSigner: false, 153 | isWritable: true, 154 | }, 155 | ], 156 | data: Buffer.from(new Uint8Array([17])), 157 | programId: TOKEN_PROGRAM_ID, 158 | }), 159 | ]; 160 | }; 161 | 162 | export const unwrapSOLInstruction = async ( 163 | owner: PublicKey, 164 | allowOwnerOffCurve = true 165 | ) => { 166 | const wSolATAAccount = getAssociatedTokenAddressSync( 167 | NATIVE_MINT, 168 | owner, 169 | allowOwnerOffCurve 170 | ); 171 | if (wSolATAAccount) { 172 | const closedWrappedSolInstruction = createCloseAccountInstruction( 173 | wSolATAAccount, 174 | owner, 175 | owner, 176 | [], 177 | TOKEN_PROGRAM_ID 178 | ); 179 | return closedWrappedSolInstruction; 180 | } 181 | return null; 182 | }; 183 | 184 | export async function chunkedGetMultipleAccountInfos( 185 | connection: Connection, 186 | pks: PublicKey[], 187 | chunkSize: number = 100 188 | ) { 189 | const accountInfos = ( 190 | await Promise.all( 191 | chunks(pks, chunkSize).map((chunk) => 192 | connection.getMultipleAccountsInfo(chunk) 193 | ) 194 | ) 195 | ).flat(); 196 | 197 | return accountInfos; 198 | } 199 | 200 | export const computeBudgetIx = () => { 201 | return ComputeBudgetProgram.setComputeUnitLimit({ 202 | units: 1_400_000, 203 | }); 204 | }; 205 | -------------------------------------------------------------------------------- /lib/dlmm/helpers/fee.ts: -------------------------------------------------------------------------------- 1 | import { BN } from "anchor28"; 2 | import { 3 | BASIS_POINT_MAX, 4 | FEE_PRECISION, 5 | MAX_FEE_RATE, 6 | SCALE_OFFSET, 7 | } from "../constants"; 8 | import { Bin, sParameters, vParameters } from "../types"; 9 | import { Rounding, mulShr, shlDiv } from "./math"; 10 | import { getOutAmount } from "."; 11 | 12 | export function getBaseFee(binStep: number, sParameter: sParameters) { 13 | return new BN(sParameter.baseFactor).mul(new BN(binStep)).mul(new BN(10)); 14 | } 15 | 16 | export function getVariableFee( 17 | binStep: number, 18 | sParameter: sParameters, 19 | vParameter: vParameters 20 | ) { 21 | if (sParameter.variableFeeControl > 0) { 22 | const square_vfa_bin = new BN(vParameter.volatilityAccumulator) 23 | .mul(new BN(binStep)) 24 | .pow(new BN(2)); 25 | const v_fee = new BN(sParameter.variableFeeControl).mul(square_vfa_bin); 26 | 27 | return v_fee.add(new BN(99_999_999_999)).div(new BN(100_000_000_000)); 28 | } 29 | return new BN(0); 30 | } 31 | 32 | export function getTotalFee( 33 | binStep: number, 34 | sParameter: sParameters, 35 | vParameter: vParameters 36 | ) { 37 | const totalFee = getBaseFee(binStep, sParameter).add( 38 | getVariableFee(binStep, sParameter, vParameter) 39 | ); 40 | return totalFee.gt(MAX_FEE_RATE) ? MAX_FEE_RATE : totalFee; 41 | } 42 | 43 | export function computeFee( 44 | binStep: number, 45 | sParameter: sParameters, 46 | vParameter: vParameters, 47 | inAmount: BN 48 | ) { 49 | const totalFee = getTotalFee(binStep, sParameter, vParameter); 50 | const denominator = FEE_PRECISION.sub(totalFee); 51 | 52 | return inAmount 53 | .mul(totalFee) 54 | .add(denominator) 55 | .sub(new BN(1)) 56 | .div(denominator); 57 | } 58 | 59 | export function computeFeeFromAmount( 60 | binStep: number, 61 | sParameter: sParameters, 62 | vParameter: vParameters, 63 | inAmountWithFees: BN 64 | ) { 65 | const totalFee = getTotalFee(binStep, sParameter, vParameter); 66 | return inAmountWithFees 67 | .mul(totalFee) 68 | .add(FEE_PRECISION.sub(new BN(1))) 69 | .div(FEE_PRECISION); 70 | } 71 | 72 | export function computeProtocolFee(feeAmount: BN, sParameter: sParameters) { 73 | return feeAmount 74 | .mul(new BN(sParameter.protocolShare)) 75 | .div(new BN(BASIS_POINT_MAX)); 76 | } 77 | 78 | export function swapQuoteAtBinWithCap( 79 | bin: Bin, 80 | binStep: number, 81 | sParameter: sParameters, 82 | vParameter: vParameters, 83 | inAmount: BN, 84 | swapForY: boolean, 85 | remainingCap: BN, 86 | ): { 87 | isReachCap: boolean, 88 | amountIn: BN; 89 | amountOut: BN; 90 | fee: BN; 91 | protocolFee: BN; 92 | } { 93 | let maxAmountOut: BN; 94 | if (swapForY) { 95 | maxAmountOut = bin.amountY; 96 | } else { 97 | maxAmountOut = bin.amountX; 98 | } 99 | 100 | if (maxAmountOut.lt(remainingCap)) { 101 | const { amountIn, amountOut, fee, protocolFee } = swapQuoteAtBin( 102 | bin, 103 | binStep, 104 | sParameter, 105 | vParameter, 106 | inAmount, 107 | swapForY 108 | ); 109 | return { 110 | isReachCap: false, 111 | amountIn, 112 | amountOut, 113 | fee, 114 | protocolFee 115 | } 116 | } 117 | let amountInWithCap = getAmountIn(remainingCap, bin.price, swapForY); 118 | let actualAmountIn = inAmount.gt(amountInWithCap) ? amountInWithCap : inAmount; 119 | const { amountIn, amountOut, fee, protocolFee } = swapQuoteAtBin( 120 | bin, 121 | binStep, 122 | sParameter, 123 | vParameter, 124 | actualAmountIn, 125 | swapForY 126 | ); 127 | return { 128 | isReachCap: true, 129 | amountIn, 130 | amountOut, 131 | fee, 132 | protocolFee 133 | } 134 | } 135 | 136 | export function swapQuoteAtBin( 137 | bin: Bin, 138 | binStep: number, 139 | sParameter: sParameters, 140 | vParameter: vParameters, 141 | inAmount: BN, 142 | swapForY: boolean 143 | ): { 144 | amountIn: BN; 145 | amountOut: BN; 146 | fee: BN; 147 | protocolFee: BN; 148 | } { 149 | if (swapForY && bin.amountY.isZero()) { 150 | return { 151 | amountIn: new BN(0), 152 | amountOut: new BN(0), 153 | fee: new BN(0), 154 | protocolFee: new BN(0), 155 | }; 156 | } 157 | 158 | if (!swapForY && bin.amountX.isZero()) { 159 | return { 160 | amountIn: new BN(0), 161 | amountOut: new BN(0), 162 | fee: new BN(0), 163 | protocolFee: new BN(0), 164 | }; 165 | } 166 | 167 | let maxAmountOut: BN; 168 | let maxAmountIn: BN; 169 | 170 | if (swapForY) { 171 | maxAmountOut = bin.amountY; 172 | maxAmountIn = shlDiv(bin.amountY, bin.price, SCALE_OFFSET, Rounding.Up); 173 | } else { 174 | maxAmountOut = bin.amountX; 175 | maxAmountIn = mulShr(bin.amountX, bin.price, SCALE_OFFSET, Rounding.Up); 176 | } 177 | 178 | const maxFee = computeFee(binStep, sParameter, vParameter, maxAmountIn); 179 | maxAmountIn = maxAmountIn.add(maxFee); 180 | 181 | let amountInWithFees: BN; 182 | let amountOut: BN; 183 | let fee: BN; 184 | let protocolFee: BN; 185 | 186 | if (inAmount.gt(maxAmountIn)) { 187 | amountInWithFees = maxAmountIn; 188 | amountOut = maxAmountOut; 189 | fee = maxFee; 190 | protocolFee = computeProtocolFee(maxFee, sParameter); 191 | } else { 192 | fee = computeFeeFromAmount(binStep, sParameter, vParameter, inAmount); 193 | const amountInAfterFee = inAmount.sub(fee); 194 | const computedOutAmount = getOutAmount(bin, amountInAfterFee, swapForY); 195 | 196 | amountOut = computedOutAmount.gt(maxAmountOut) 197 | ? maxAmountOut 198 | : computedOutAmount; 199 | protocolFee = computeProtocolFee(fee, sParameter); 200 | amountInWithFees = inAmount; 201 | } 202 | 203 | return { 204 | amountIn: amountInWithFees, 205 | amountOut, 206 | fee, 207 | protocolFee, 208 | }; 209 | } 210 | 211 | 212 | function getAmountIn(amountOut: BN, price: BN, swapForY: Boolean): BN { 213 | if (swapForY) { 214 | return shlDiv(amountOut, price, SCALE_OFFSET, Rounding.Down); 215 | } else { 216 | return mulShr(amountOut, price, SCALE_OFFSET, Rounding.Down); 217 | } 218 | } -------------------------------------------------------------------------------- /lib/dlmm/types/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BN, 3 | IdlAccounts, 4 | IdlTypes, 5 | Program, 6 | ProgramAccount, 7 | } from "anchor28"; 8 | import { LbClmm } from "../idl"; 9 | import { PublicKey, TransactionInstruction } from "@solana/web3.js"; 10 | import Decimal from "decimal.js"; 11 | 12 | export interface FeeInfo { 13 | baseFeeRatePercentage: Decimal; 14 | maxFeeRatePercentage: Decimal; 15 | protocolFeePercentage: Decimal; 16 | } 17 | 18 | export interface BinAndAmount { 19 | binId: number; 20 | xAmountBpsOfTotal: BN; 21 | yAmountBpsOfTotal: BN; 22 | } 23 | 24 | export interface TokenReserve { 25 | publicKey: PublicKey; 26 | reserve: PublicKey; 27 | amount: bigint; 28 | decimal: number; 29 | } 30 | 31 | export type ClmmProgram = Program; 32 | 33 | export type LbPair = IdlAccounts["lbPair"]; 34 | export type LbPairAccount = ProgramAccount["lbPair"]>; 35 | 36 | export type Bin = IdlTypes["Bin"]; 37 | export type BinArray = IdlAccounts["binArray"]; 38 | export type BinArrayAccount = ProgramAccount["binArray"]>; 39 | 40 | export type Position = IdlAccounts["position"]; 41 | export type PositionV2 = IdlAccounts["positionV2"]; 42 | 43 | export type vParameters = IdlAccounts["lbPair"]["vParameters"]; 44 | export type sParameters = IdlAccounts["lbPair"]["parameters"]; 45 | 46 | export type InitPermissionPairIx = IdlTypes["InitPermissionPairIx"]; 47 | 48 | export type BinLiquidityDistribution = 49 | IdlTypes["BinLiquidityDistribution"]; 50 | export type BinLiquidityReduction = IdlTypes["BinLiquidityReduction"]; 51 | 52 | export type BinArrayBitmapExtensionAccount = ProgramAccount< 53 | IdlAccounts["binArrayBitmapExtension"] 54 | >; 55 | export type BinArrayBitmapExtension = 56 | IdlAccounts["binArrayBitmapExtension"]; 57 | 58 | export type LiquidityParameterByWeight = 59 | IdlTypes["LiquidityParameterByWeight"]; 60 | export type LiquidityOneSideParameter = 61 | IdlTypes["LiquidityOneSideParameter"]; 62 | 63 | export type LiquidityParameterByStrategy = 64 | IdlTypes["LiquidityParameterByStrategy"]; 65 | export type LiquidityParameterByStrategyOneSide = 66 | IdlTypes["LiquidityParameterByStrategyOneSide"]; 67 | 68 | export type ProgramStrategyParameter = IdlTypes["StrategyParameters"]; 69 | export type ProgramStrategyType = IdlTypes["StrategyType"]; 70 | 71 | export type CompressedBinDepositAmount = 72 | IdlTypes["CompressedBinDepositAmount"]; 73 | export type CompressedBinDepositAmounts = CompressedBinDepositAmount[]; 74 | 75 | export interface LbPosition { 76 | publicKey: PublicKey; 77 | positionData: PositionData; 78 | version: PositionVersion; 79 | } 80 | 81 | export interface PositionInfo { 82 | publicKey: PublicKey; 83 | lbPair: LbPair; 84 | tokenX: TokenReserve; 85 | tokenY: TokenReserve; 86 | lbPairPositionsData: Array; 87 | } 88 | 89 | export interface FeeInfo { 90 | baseFeeRatePercentage: Decimal; 91 | maxFeeRatePercentage: Decimal; 92 | protocolFeePercentage: Decimal; 93 | } 94 | 95 | export interface EmissionRate { 96 | rewardOne: Decimal; 97 | rewardTwo: Decimal; 98 | } 99 | 100 | export interface SwapFee { 101 | feeX: BN; 102 | feeY: BN; 103 | } 104 | 105 | export interface LMRewards { 106 | rewardOne: BN; 107 | rewardTwo: BN; 108 | } 109 | 110 | export enum PositionVersion { 111 | V1, 112 | V2, 113 | } 114 | 115 | export enum PairType { 116 | Permissionless, 117 | Permissioned, 118 | } 119 | 120 | export const Strategy = { 121 | SpotOneSide: { spotOneSide: {} }, 122 | CurveOneSide: { curveOneSide: {} }, 123 | BidAskOneSide: { bidAskOneSide: {} }, 124 | SpotBalanced: { spotBalanced: {} }, 125 | CurveBalanced: { curveBalanced: {} }, 126 | BidAskBalanced: { bidAskBalanced: {} }, 127 | SpotImBalanced: { spotImBalanced: {} }, 128 | CurveImBalanced: { curveImBalanced: {} }, 129 | BidAskImBalanced: { bidAskImBalanced: {} }, 130 | }; 131 | 132 | export enum StrategyType { 133 | SpotOneSide, 134 | CurveOneSide, 135 | BidAskOneSide, 136 | SpotImBalanced, 137 | CurveImBalanced, 138 | BidAskImBalanced, 139 | SpotBalanced, 140 | CurveBalanced, 141 | BidAskBalanced, 142 | } 143 | 144 | export interface StrategyParameters { 145 | maxBinId: number; 146 | minBinId: number; 147 | strategyType: StrategyType; 148 | } 149 | 150 | export interface TQuoteCreatePositionParams { 151 | strategy: StrategyParameters; 152 | } 153 | 154 | export interface TInitializePositionAndAddLiquidityParams { 155 | positionPubKey: PublicKey; 156 | totalXAmount: BN; 157 | totalYAmount: BN; 158 | xYAmountDistribution: BinAndAmount[]; 159 | user: PublicKey; 160 | slippage?: number; 161 | } 162 | 163 | export interface TInitializePositionAndAddLiquidityParamsByStrategy { 164 | positionPubKey: PublicKey; 165 | totalXAmount: BN; 166 | totalYAmount: BN; 167 | strategy: StrategyParameters; 168 | user: PublicKey; 169 | slippage?: number; 170 | } 171 | 172 | export interface BinLiquidity { 173 | binId: number; 174 | xAmount: BN; 175 | yAmount: BN; 176 | supply: BN; 177 | version: number; 178 | price: string; 179 | pricePerToken: string; 180 | } 181 | 182 | export interface SwapQuote { 183 | consumedInAmount: BN; 184 | outAmount: BN; 185 | fee: BN; 186 | protocolFee: BN; 187 | minOutAmount: BN; 188 | priceImpact: Decimal; 189 | binArraysPubkey: any[]; 190 | } 191 | 192 | export interface IAccountsCache { 193 | binArrays: Map; 194 | lbPair: LbPair; 195 | } 196 | 197 | export interface PositionBinData { 198 | binId: number; 199 | price: string; 200 | pricePerToken: string; 201 | binXAmount: string; 202 | binYAmount: string; 203 | binLiquidity: string; 204 | positionLiquidity: string; 205 | positionXAmount: string; 206 | positionYAmount: string; 207 | } 208 | 209 | export interface PositionData { 210 | totalXAmount: string; 211 | totalYAmount: string; 212 | positionBinData: PositionBinData[]; 213 | lastUpdatedAt: BN; 214 | upperBinId: number; 215 | lowerBinId: number; 216 | feeX: BN; 217 | feeY: BN; 218 | rewardOne: BN; 219 | rewardTwo: BN; 220 | feeOwner: PublicKey; 221 | totalClaimedFeeXAmount: BN; 222 | totalClaimedFeeYAmount: BN; 223 | } 224 | 225 | export interface SwapParams { 226 | /** 227 | * mint of in token 228 | */ 229 | inToken: PublicKey; 230 | /** 231 | * mint of out token 232 | */ 233 | outToken: PublicKey; 234 | /** 235 | * in token amount 236 | */ 237 | inAmount: BN; 238 | /** 239 | * minimum out with slippage 240 | */ 241 | minOutAmount: BN; 242 | /** 243 | * desired lbPair to swap against 244 | */ 245 | lbPair: PublicKey; 246 | /** 247 | * user 248 | */ 249 | user: PublicKey; 250 | binArraysPubkey: PublicKey[]; 251 | } 252 | 253 | export interface GetOrCreateATAResponse { 254 | ataPubKey: PublicKey; 255 | ix?: TransactionInstruction; 256 | } 257 | 258 | export enum BitmapType { 259 | U1024, 260 | U512, 261 | } 262 | 263 | export interface SeedLiquidityResponse { 264 | initializeBinArraysAndPositionIxs: TransactionInstruction[][]; 265 | addLiquidityIxs: TransactionInstruction[][]; 266 | } 267 | -------------------------------------------------------------------------------- /lib/dlmm/helpers/math.ts: -------------------------------------------------------------------------------- 1 | import { BN } from "anchor28"; 2 | import { 3 | BASIS_POINT_MAX, 4 | MAX_BIN_PER_POSITION, 5 | SCALE_OFFSET, 6 | } from "../constants"; 7 | import Decimal from "decimal.js"; 8 | import { ONE, pow } from "./u64xu64_math"; 9 | import { DLMM } from ".."; 10 | import { getPriceOfBinByBinId } from "./weight"; 11 | 12 | export enum Rounding { 13 | Up, 14 | Down, 15 | } 16 | 17 | export function mulShr(x: BN, y: BN, offset: number, rounding: Rounding) { 18 | const denominator = new BN(1).shln(offset); 19 | return mulDiv(x, y, denominator, rounding); 20 | } 21 | 22 | export function shlDiv(x: BN, y: BN, offset: number, rounding: Rounding) { 23 | const scale = new BN(1).shln(offset); 24 | return mulDiv(x, scale, y, rounding); 25 | } 26 | 27 | export function mulDiv(x: BN, y: BN, denominator: BN, rounding: Rounding) { 28 | const { div, mod } = x.mul(y).divmod(denominator); 29 | 30 | if (rounding == Rounding.Up && !mod.isZero()) { 31 | return div.add(new BN(1)); 32 | } 33 | return div; 34 | } 35 | 36 | export function computeBaseFactorFromFeeBps(binStep: BN, feeBps: BN) { 37 | const U16_MAX = 65535; 38 | const computedBaseFactor = 39 | (feeBps.toNumber() * BASIS_POINT_MAX) / binStep.toNumber(); 40 | 41 | // Sanity check 42 | const computedBaseFactorFloor = Math.floor(computedBaseFactor); 43 | if (computedBaseFactor != computedBaseFactorFloor) { 44 | if (computedBaseFactorFloor >= U16_MAX) { 45 | throw "base factor for the give fee bps overflow u16"; 46 | } 47 | 48 | if (computedBaseFactorFloor == 0) { 49 | throw "base factor for the give fee bps underflow"; 50 | } 51 | 52 | if (computedBaseFactor % 1 != 0) { 53 | throw "couldn't compute base factor for the exact fee bps"; 54 | } 55 | } 56 | 57 | return new BN(computedBaseFactor); 58 | } 59 | 60 | export function getQPriceFromId(binId: BN, binStep: BN): BN { 61 | const bps = binStep.shln(SCALE_OFFSET).div(new BN(BASIS_POINT_MAX)); 62 | const base = ONE.add(bps); 63 | return pow(base, binId); 64 | } 65 | 66 | export function findSwappableMinMaxBinId(binStep: BN) { 67 | const base = 1 + binStep.toNumber() / BASIS_POINT_MAX; 68 | const maxQPriceSupported = new Decimal("18446744073709551615"); 69 | const n = maxQPriceSupported.log(10).div(new Decimal(base).log(10)).floor(); 70 | 71 | let minBinId = new BN(n.neg().toString()); 72 | let maxBinId = new BN(n.toString()); 73 | 74 | let minQPrice = new BN(1); 75 | let maxQPrice = new BN("340282366920938463463374607431768211455"); 76 | 77 | while (true) { 78 | const qPrice = getQPriceFromId(minBinId, binStep); 79 | if (qPrice.gt(minQPrice) && !qPrice.isZero()) { 80 | break; 81 | } else { 82 | minBinId = minBinId.add(new BN(1)); 83 | } 84 | } 85 | 86 | while (true) { 87 | const qPrice = getQPriceFromId(maxBinId, binStep); 88 | if (qPrice.lt(maxQPrice) && !qPrice.isZero()) { 89 | break; 90 | } else { 91 | maxBinId = maxBinId.sub(new BN(1)); 92 | } 93 | } 94 | 95 | return { 96 | minBinId, 97 | maxBinId, 98 | }; 99 | } 100 | 101 | export function getC( 102 | amount: BN, 103 | binStep: number, 104 | binId: BN, 105 | baseTokenDecimal: number, 106 | quoteTokenDecimal: number, 107 | minPrice: Decimal, 108 | maxPrice: Decimal, 109 | k: number 110 | ) { 111 | const currentPricePerLamport = new Decimal(1 + binStep / 10000).pow( 112 | binId.toNumber() 113 | ); 114 | const currentPricePerToken = currentPricePerLamport.mul( 115 | new Decimal(10 ** (baseTokenDecimal - quoteTokenDecimal)) 116 | ); 117 | const priceRange = maxPrice.sub(minPrice); 118 | const currentPriceDeltaFromMin = currentPricePerToken.sub( 119 | new Decimal(minPrice) 120 | ); 121 | 122 | const c = new Decimal(amount.toString()).mul( 123 | currentPriceDeltaFromMin.div(priceRange).pow(k) 124 | ); 125 | 126 | return c.floor(); 127 | } 128 | 129 | export function distributeAmountToCompressedBinsByRatio( 130 | compressedBinAmount: Map, 131 | uncompressedAmount: BN, 132 | multiplier: BN, 133 | binCapAmount: BN 134 | ) { 135 | const newCompressedBinAmount = new Map(); 136 | let totalCompressedAmount = new BN(0); 137 | 138 | for (const compressedAmount of compressedBinAmount.values()) { 139 | totalCompressedAmount = totalCompressedAmount.add(compressedAmount); 140 | } 141 | 142 | let totalDepositedAmount = new BN(0); 143 | 144 | for (const [binId, compressedAmount] of compressedBinAmount.entries()) { 145 | const depositAmount = compressedAmount 146 | .mul(uncompressedAmount) 147 | .div(totalCompressedAmount); 148 | 149 | let compressedDepositAmount = depositAmount.div(multiplier); 150 | 151 | let newCompressedAmount = compressedAmount.add(compressedDepositAmount); 152 | if (newCompressedAmount.gt(binCapAmount)) { 153 | compressedDepositAmount = compressedDepositAmount.sub( 154 | newCompressedAmount.sub(binCapAmount) 155 | ); 156 | newCompressedAmount = binCapAmount; 157 | } 158 | newCompressedBinAmount.set(binId, newCompressedAmount); 159 | 160 | totalDepositedAmount = totalDepositedAmount.add( 161 | compressedDepositAmount.mul(multiplier) 162 | ); 163 | } 164 | 165 | const loss = uncompressedAmount.sub(totalDepositedAmount); 166 | 167 | return { 168 | newCompressedBinAmount, 169 | loss, 170 | }; 171 | } 172 | 173 | export function getPositionCount(minBinId: BN, maxBinId: BN) { 174 | const binDelta = maxBinId.sub(minBinId); 175 | const positionCount = binDelta.div(MAX_BIN_PER_POSITION); 176 | return positionCount.add(new BN(1)); 177 | } 178 | 179 | export function compressBinAmount(binAmount: Map, multiplier: BN) { 180 | const compressedBinAmount = new Map(); 181 | 182 | let totalAmount = new BN(0); 183 | let compressionLoss = new BN(0); 184 | 185 | for (const [binId, amount] of binAmount) { 186 | totalAmount = totalAmount.add(amount); 187 | const compressedAmount = amount.div(multiplier); 188 | 189 | compressedBinAmount.set(binId, compressedAmount); 190 | let loss = amount.sub(compressedAmount.mul(multiplier)); 191 | compressionLoss = compressionLoss.add(loss); 192 | } 193 | 194 | return { 195 | compressedBinAmount, 196 | compressionLoss, 197 | }; 198 | } 199 | 200 | export function generateAmountForBinRange( 201 | amount: BN, 202 | binStep: number, 203 | tokenXDecimal: number, 204 | tokenYDecimal: number, 205 | minBinId: BN, 206 | maxBinId: BN, 207 | k: number 208 | ) { 209 | const toTokenMultiplier = new Decimal(10 ** (tokenXDecimal - tokenYDecimal)); 210 | const minPrice = getPriceOfBinByBinId(minBinId.toNumber(), binStep).mul( 211 | toTokenMultiplier 212 | ); 213 | const maxPrice = getPriceOfBinByBinId(maxBinId.toNumber(), binStep).mul( 214 | toTokenMultiplier 215 | ); 216 | const binAmounts = new Map(); 217 | 218 | for (let i = minBinId.toNumber(); i < maxBinId.toNumber(); i++) { 219 | const binAmount = generateBinAmount( 220 | amount, 221 | binStep, 222 | new BN(i), 223 | tokenXDecimal, 224 | tokenYDecimal, 225 | minPrice, 226 | maxPrice, 227 | k 228 | ); 229 | 230 | binAmounts.set(i, binAmount); 231 | } 232 | 233 | return binAmounts; 234 | } 235 | 236 | export function generateBinAmount( 237 | amount: BN, 238 | binStep: number, 239 | binId: BN, 240 | tokenXDecimal: number, 241 | tokenYDecimal: number, 242 | minPrice: Decimal, 243 | maxPrice: Decimal, 244 | k: number 245 | ) { 246 | const c1 = getC( 247 | amount, 248 | binStep, 249 | binId.add(new BN(1)), 250 | tokenXDecimal, 251 | tokenYDecimal, 252 | minPrice, 253 | maxPrice, 254 | k 255 | ); 256 | 257 | const c0 = getC( 258 | amount, 259 | binStep, 260 | binId, 261 | tokenXDecimal, 262 | tokenYDecimal, 263 | minPrice, 264 | maxPrice, 265 | k 266 | ); 267 | 268 | return new BN(c1.sub(c0).floor().toString()); 269 | } 270 | -------------------------------------------------------------------------------- /lib/dlmm/helpers/binArray.ts: -------------------------------------------------------------------------------- 1 | import { BN } from "anchor28"; 2 | import { PublicKey } from "@solana/web3.js"; 3 | import { MAX_BIN_ARRAY_SIZE } from "../constants"; 4 | import { 5 | Bin, 6 | BinArray, 7 | BinArrayAccount, 8 | BinArrayBitmapExtension, 9 | BitmapType, 10 | LbPair, 11 | } from "../types"; 12 | import { 13 | EXTENSION_BINARRAY_BITMAP_SIZE, 14 | BIN_ARRAY_BITMAP_SIZE, 15 | } from "../constants"; 16 | 17 | /** private */ 18 | function internalBitmapRange() { 19 | const lowerBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.neg(); 20 | const upperBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.sub(new BN(1)); 21 | return [lowerBinArrayIndex, upperBinArrayIndex]; 22 | } 23 | 24 | function buildBitmapFromU64Arrays(u64Arrays: BN[], type: BitmapType) { 25 | const buffer = Buffer.concat( 26 | u64Arrays.map((b) => { 27 | return b.toArrayLike(Buffer, "le", 8); 28 | }) 29 | ); 30 | 31 | return new BN(buffer, "le"); 32 | } 33 | 34 | function bitmapTypeDetail(type: BitmapType) { 35 | if (type == BitmapType.U1024) { 36 | return { 37 | bits: 1024, 38 | bytes: 1024 / 8, 39 | }; 40 | } else { 41 | return { 42 | bits: 512, 43 | bytes: 512 / 8, 44 | }; 45 | } 46 | } 47 | 48 | function mostSignificantBit(number: BN, bitLength: number) { 49 | const highestIndex = bitLength - 1; 50 | if (number.isZero()) { 51 | return null; 52 | } 53 | 54 | for (let i = highestIndex; i >= 0; i--) { 55 | if (number.testn(i)) { 56 | return highestIndex - i; 57 | } 58 | } 59 | return null; 60 | } 61 | 62 | function leastSignificantBit(number: BN, bitLength: number) { 63 | if (number.isZero()) { 64 | return null; 65 | } 66 | for (let i = 0; i < bitLength; i++) { 67 | if (number.testn(i)) { 68 | return i; 69 | } 70 | } 71 | return null; 72 | } 73 | 74 | function extensionBitmapRange() { 75 | return [ 76 | BIN_ARRAY_BITMAP_SIZE.neg().mul( 77 | EXTENSION_BINARRAY_BITMAP_SIZE.add(new BN(1)) 78 | ), 79 | BIN_ARRAY_BITMAP_SIZE.mul( 80 | EXTENSION_BINARRAY_BITMAP_SIZE.add(new BN(1)) 81 | ).sub(new BN(1)), 82 | ]; 83 | } 84 | 85 | function findSetBit( 86 | startIndex: number, 87 | endIndex: number, 88 | binArrayBitmapExtension: BinArrayBitmapExtension 89 | ): number | null { 90 | const getBinArrayOffset = (binArrayIndex: BN) => { 91 | return binArrayIndex.gt(new BN(0)) 92 | ? binArrayIndex.mod(BIN_ARRAY_BITMAP_SIZE) 93 | : binArrayIndex.add(new BN(1)).neg().mod(BIN_ARRAY_BITMAP_SIZE); 94 | }; 95 | 96 | const getBitmapOffset = (binArrayIndex: BN) => { 97 | return binArrayIndex.gt(new BN(0)) 98 | ? binArrayIndex.div(BIN_ARRAY_BITMAP_SIZE).sub(new BN(1)) 99 | : binArrayIndex 100 | .add(new BN(1)) 101 | .neg() 102 | .div(BIN_ARRAY_BITMAP_SIZE) 103 | .sub(new BN(1)); 104 | }; 105 | 106 | if (startIndex <= endIndex) { 107 | for (let i = startIndex; i <= endIndex; i++) { 108 | const binArrayOffset = getBinArrayOffset(new BN(i)).toNumber(); 109 | const bitmapOffset = getBitmapOffset(new BN(i)).toNumber(); 110 | const bitmapChunks = 111 | i > 0 112 | ? binArrayBitmapExtension.positiveBinArrayBitmap[bitmapOffset] 113 | : binArrayBitmapExtension.negativeBinArrayBitmap[bitmapOffset]; 114 | const bitmap = buildBitmapFromU64Arrays(bitmapChunks, BitmapType.U512); 115 | if (bitmap.testn(binArrayOffset)) { 116 | return i; 117 | } 118 | } 119 | } else { 120 | for (let i = startIndex; i >= endIndex; i--) { 121 | const binArrayOffset = getBinArrayOffset(new BN(i)).toNumber(); 122 | const bitmapOffset = getBitmapOffset(new BN(i)).toNumber(); 123 | const bitmapChunks = 124 | i > 0 125 | ? binArrayBitmapExtension.positiveBinArrayBitmap[bitmapOffset] 126 | : binArrayBitmapExtension.negativeBinArrayBitmap[bitmapOffset]; 127 | const bitmap = buildBitmapFromU64Arrays(bitmapChunks, BitmapType.U512); 128 | if (bitmap.testn(binArrayOffset)) { 129 | return i; 130 | } 131 | } 132 | } 133 | 134 | return null; 135 | } 136 | /** private */ 137 | 138 | export function isOverflowDefaultBinArrayBitmap(binArrayIndex: BN) { 139 | const [minBinArrayIndex, maxBinArrayIndex] = internalBitmapRange(); 140 | return ( 141 | binArrayIndex.gt(maxBinArrayIndex) || binArrayIndex.lt(minBinArrayIndex) 142 | ); 143 | } 144 | 145 | export function deriveBinArrayBitmapExtension( 146 | lbPair: PublicKey, 147 | programId: PublicKey 148 | ) { 149 | return PublicKey.findProgramAddressSync( 150 | [Buffer.from("bitmap"), lbPair.toBytes()], 151 | programId 152 | ); 153 | } 154 | 155 | export function binIdToBinArrayIndex(binId: BN): BN { 156 | const { div: idx, mod } = binId.divmod(MAX_BIN_ARRAY_SIZE); 157 | return binId.isNeg() && !mod.isZero() ? idx.sub(new BN(1)) : idx; 158 | } 159 | 160 | export function getBinArrayLowerUpperBinId(binArrayIndex: BN) { 161 | const lowerBinId = binArrayIndex.mul(MAX_BIN_ARRAY_SIZE); 162 | const upperBinId = lowerBinId.add(MAX_BIN_ARRAY_SIZE).sub(new BN(1)); 163 | 164 | return [lowerBinId, upperBinId]; 165 | } 166 | 167 | export function isBinIdWithinBinArray(activeId: BN, binArrayIndex: BN) { 168 | const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId(binArrayIndex); 169 | return activeId.gte(lowerBinId) && activeId.lte(upperBinId); 170 | } 171 | 172 | export function getBinFromBinArray(binId: number, binArray: BinArray): Bin { 173 | const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId(binArray.index); 174 | 175 | let index = 0; 176 | if (binId > 0) { 177 | index = binId - lowerBinId.toNumber(); 178 | } else { 179 | const delta = upperBinId.toNumber() - binId; 180 | index = MAX_BIN_ARRAY_SIZE.toNumber() - delta - 1; 181 | } 182 | 183 | return binArray.bins[index]; 184 | } 185 | 186 | export function findNextBinArrayIndexWithLiquidity( 187 | swapForY: boolean, 188 | activeId: BN, 189 | lbPairState: LbPair, 190 | binArrayBitmapExtension: BinArrayBitmapExtension | null 191 | ): BN | null { 192 | const [lowerBinArrayIndex, upperBinArrayIndex] = internalBitmapRange(); 193 | let startBinArrayIndex = binIdToBinArrayIndex(activeId); 194 | 195 | while (true) { 196 | if (isOverflowDefaultBinArrayBitmap(startBinArrayIndex)) { 197 | if (binArrayBitmapExtension === null) { 198 | return null; 199 | } 200 | // When bin array index is negative, the MSB is smallest bin array index. 201 | 202 | const [minBinArrayIndex, maxBinArrayIndex] = extensionBitmapRange(); 203 | 204 | if (startBinArrayIndex.isNeg()) { 205 | if (swapForY) { 206 | const binArrayIndex = findSetBit( 207 | startBinArrayIndex.toNumber(), 208 | minBinArrayIndex.toNumber(), 209 | binArrayBitmapExtension 210 | ); 211 | 212 | if (binArrayIndex !== null) { 213 | return new BN(binArrayIndex); 214 | } else { 215 | return null; 216 | } 217 | } else { 218 | const binArrayIndex = findSetBit( 219 | startBinArrayIndex.toNumber(), 220 | BIN_ARRAY_BITMAP_SIZE.neg().sub(new BN(1)).toNumber(), 221 | binArrayBitmapExtension 222 | ); 223 | 224 | if (binArrayIndex !== null) { 225 | return new BN(binArrayIndex); 226 | } else { 227 | // Move to internal bitmap 228 | startBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.neg(); 229 | } 230 | } 231 | } else { 232 | if (swapForY) { 233 | const binArrayIndex = findSetBit( 234 | startBinArrayIndex.toNumber(), 235 | BIN_ARRAY_BITMAP_SIZE.toNumber(), 236 | binArrayBitmapExtension 237 | ); 238 | 239 | if (binArrayIndex !== null) { 240 | return new BN(binArrayIndex); 241 | } else { 242 | // Move to internal bitmap 243 | startBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.sub(new BN(1)); 244 | } 245 | } else { 246 | const binArrayIndex = findSetBit( 247 | startBinArrayIndex.toNumber(), 248 | maxBinArrayIndex.toNumber(), 249 | binArrayBitmapExtension 250 | ); 251 | 252 | if (binArrayIndex !== null) { 253 | return new BN(binArrayIndex); 254 | } else { 255 | return null; 256 | } 257 | } 258 | } 259 | } else { 260 | // Internal bitmap 261 | const bitmapType = BitmapType.U1024; 262 | const bitmapDetail = bitmapTypeDetail(bitmapType); 263 | const offset = startBinArrayIndex.add(BIN_ARRAY_BITMAP_SIZE); 264 | 265 | const bitmap = buildBitmapFromU64Arrays( 266 | lbPairState.binArrayBitmap, 267 | bitmapType 268 | ); 269 | 270 | if (swapForY) { 271 | const upperBitRange = new BN(bitmapDetail.bits - 1).sub(offset); 272 | const croppedBitmap = bitmap.shln(upperBitRange.toNumber()); 273 | 274 | const msb = mostSignificantBit(croppedBitmap, bitmapDetail.bits); 275 | 276 | if (msb !== null) { 277 | return startBinArrayIndex.sub(new BN(msb)); 278 | } else { 279 | // Move to extension 280 | startBinArrayIndex = lowerBinArrayIndex.sub(new BN(1)); 281 | } 282 | } else { 283 | const lowerBitRange = offset; 284 | const croppedBitmap = bitmap.shrn(lowerBitRange.toNumber()); 285 | const lsb = leastSignificantBit(croppedBitmap, bitmapDetail.bits); 286 | if (lsb !== null) { 287 | return startBinArrayIndex.add(new BN(lsb)); 288 | } else { 289 | // Move to extension 290 | startBinArrayIndex = upperBinArrayIndex.add(new BN(1)); 291 | } 292 | } 293 | } 294 | } 295 | } 296 | 297 | export function findNextBinArrayWithLiquidity( 298 | swapForY: boolean, 299 | activeBinId: BN, 300 | lbPairState: LbPair, 301 | binArrayBitmapExtension: BinArrayBitmapExtension | null, 302 | binArrays: BinArrayAccount[] 303 | ): BinArrayAccount | null { 304 | const nearestBinArrayIndexWithLiquidity = findNextBinArrayIndexWithLiquidity( 305 | swapForY, 306 | activeBinId, 307 | lbPairState, 308 | binArrayBitmapExtension 309 | ); 310 | 311 | if (nearestBinArrayIndexWithLiquidity == null) { 312 | return null; 313 | } 314 | 315 | const binArrayAccount = binArrays.find((ba) => 316 | ba.account.index.eq(nearestBinArrayIndexWithLiquidity) 317 | ); 318 | if (!binArrayAccount) { 319 | // Critical bug 320 | throw new Error("Bin array not found based on indexing"); 321 | } 322 | 323 | return binArrayAccount; 324 | } 325 | -------------------------------------------------------------------------------- /lib/dlmm/helpers/weightToAmounts.ts: -------------------------------------------------------------------------------- 1 | 2 | import Decimal from "decimal.js"; 3 | import { BN } from "anchor28"; 4 | import { getPriceOfBinByBinId } from "./weight"; 5 | 6 | export function toAmountBidSide( 7 | activeId: number, 8 | totalAmount: BN, 9 | distributions: { binId: number; weight: number }[], 10 | ): { 11 | binId: number, 12 | amount: BN 13 | }[] { 14 | // get sum of weight 15 | const totalWeight = distributions.reduce(function (sum, el) { 16 | return el.binId > activeId ? sum : sum.add(el.weight); // skip all ask side 17 | }, new Decimal(0)); 18 | 19 | if (totalWeight.cmp(new Decimal(0)) != 1) { 20 | throw Error("Invalid parameteres"); 21 | } 22 | return distributions.map((bin) => { 23 | if (bin.binId > activeId) { 24 | return { 25 | binId: bin.binId, 26 | amount: new BN(0), 27 | }; 28 | } else { 29 | return { 30 | binId: bin.binId, 31 | amount: new BN(new Decimal(totalAmount.toString()) 32 | .mul(new Decimal(bin.weight).div(totalWeight)) 33 | .floor().toString()), 34 | }; 35 | } 36 | }); 37 | } 38 | 39 | export function toAmountAskSide(activeId: number, 40 | binStep: number, 41 | totalAmount: BN, 42 | distributions: { binId: number; weight: number }[]): { 43 | binId: number, 44 | amount: BN 45 | }[] { 46 | // get sum of weight 47 | const totalWeight: Decimal = distributions.reduce(function (sum, el) { 48 | if (el.binId < activeId) { 49 | return sum; 50 | } else { 51 | const price = getPriceOfBinByBinId(el.binId, binStep); 52 | const weightPerPrice = new Decimal(el.weight).div(price); 53 | return sum.add(weightPerPrice); 54 | } 55 | }, new Decimal(0)); 56 | 57 | if (totalWeight.cmp(new Decimal(0)) != 1) { 58 | throw Error("Invalid parameteres"); 59 | } 60 | 61 | return distributions.map((bin) => { 62 | if (bin.binId < activeId) { 63 | return { 64 | binId: bin.binId, 65 | amount: new BN(0), 66 | }; 67 | } else { 68 | const price = getPriceOfBinByBinId(bin.binId, binStep); 69 | const weightPerPrice = new Decimal(bin.weight).div(price); 70 | return { 71 | binId: bin.binId, 72 | amount: new BN(new Decimal(totalAmount.toString()).mul(weightPerPrice).div(totalWeight).floor().toString()), 73 | }; 74 | } 75 | }) 76 | } 77 | 78 | export function toAmountBothSide( 79 | activeId: number, 80 | binStep: number, 81 | amountX: BN, 82 | amountY: BN, 83 | amountXInActiveBin: BN, 84 | amountYInActiveBin: BN, 85 | distributions: { binId: number; weight: number }[]): { 86 | binId: number, 87 | amountX: BN, 88 | amountY: BN 89 | }[] { 90 | 91 | const activeBins = distributions.filter((element) => { 92 | return element.binId === activeId; 93 | }); 94 | 95 | if (activeBins.length === 1) { 96 | const p0 = getPriceOfBinByBinId(activeId, binStep); 97 | let wx0 = new Decimal(0); 98 | let wy0 = new Decimal(0); 99 | const activeBin = activeBins[0]; 100 | if (amountXInActiveBin.isZero() && amountYInActiveBin.isZero()) { 101 | wx0 = new Decimal(activeBin.weight).div(p0.mul(new Decimal(2))); 102 | wy0 = new Decimal(activeBin.weight).div(new Decimal(2)); 103 | } else { 104 | let amountXInActiveBinDec = new Decimal(amountXInActiveBin.toString()); 105 | let amountYInActiveBinDec = new Decimal(amountYInActiveBin.toString()); 106 | 107 | if (!amountXInActiveBin.isZero()) { 108 | wx0 = new Decimal(activeBin.weight).div( 109 | p0.add(amountYInActiveBinDec.div(amountXInActiveBinDec)) 110 | ); 111 | } 112 | if (!amountYInActiveBin.isZero()) { 113 | wy0 = new Decimal(activeBin.weight).div( 114 | new Decimal(1).add( 115 | p0.mul(amountXInActiveBinDec).div(amountYInActiveBinDec) 116 | ) 117 | ); 118 | } 119 | } 120 | 121 | let totalWeightX = wx0; 122 | let totalWeightY = wy0; 123 | distributions.forEach((element) => { 124 | if (element.binId < activeId) { 125 | totalWeightY = totalWeightY.add(new Decimal(element.weight)); 126 | } 127 | if (element.binId > activeId) { 128 | let price = getPriceOfBinByBinId(element.binId, binStep); 129 | let weighPerPrice = new Decimal(element.weight).div(price); 130 | totalWeightX = totalWeightX.add(weighPerPrice); 131 | } 132 | }); 133 | const kx = new Decimal(amountX.toString()).div(totalWeightX); 134 | const ky = new Decimal(amountY.toString()).div(totalWeightY); 135 | let k = (kx.lessThan(ky) ? kx : ky); 136 | return distributions.map((bin) => { 137 | if (bin.binId < activeId) { 138 | const amount = k.mul(new Decimal(bin.weight)); 139 | return { 140 | binId: bin.binId, 141 | amountX: new BN(0), 142 | amountY: new BN(amount.floor().toString()), 143 | }; 144 | } 145 | if (bin.binId > activeId) { 146 | const price = getPriceOfBinByBinId(bin.binId, binStep); 147 | const weighPerPrice = new Decimal(bin.weight).div(price); 148 | const amount = k.mul(weighPerPrice); 149 | return { 150 | binId: bin.binId, 151 | amountX: new BN(amount.floor().toString()), 152 | amountY: new BN(0), 153 | }; 154 | } 155 | 156 | const amountXActiveBin = k.mul(wx0); 157 | const amountYActiveBin = k.mul(wy0); 158 | return { 159 | binId: bin.binId, 160 | amountX: new BN(amountXActiveBin.floor().toString()), 161 | amountY: new BN(amountYActiveBin.floor().toString()), 162 | }; 163 | }); 164 | } else { 165 | let totalWeightX = new Decimal(0); 166 | let totalWeightY = new Decimal(0); 167 | distributions.forEach((element) => { 168 | if (element.binId < activeId) { 169 | totalWeightY = totalWeightY.add(new Decimal(element.weight)); 170 | } else { 171 | let price = getPriceOfBinByBinId(element.binId, binStep); 172 | let weighPerPrice = new Decimal(element.weight).div(price); 173 | totalWeightX = totalWeightX.add(weighPerPrice); 174 | } 175 | }); 176 | 177 | let kx = new Decimal(amountX.toString()).div(totalWeightX); 178 | let ky = new Decimal(amountY.toString()).div(totalWeightY); 179 | let k = kx.lessThan(ky) ? kx : ky; 180 | 181 | return distributions.map((bin) => { 182 | if (bin.binId < activeId) { 183 | const amount = k.mul(new Decimal(bin.weight)); 184 | return { 185 | binId: bin.binId, 186 | amountX: new BN(0), 187 | amountY: new BN(amount.floor().toString()), 188 | }; 189 | } else { 190 | let price = getPriceOfBinByBinId(bin.binId, binStep); 191 | let weighPerPrice = new Decimal(bin.weight).div(price); 192 | const amount = k.mul(weighPerPrice); 193 | return { 194 | binId: bin.binId, 195 | amountX: new BN(amount.floor().toString()), 196 | amountY: new BN(0), 197 | }; 198 | } 199 | }); 200 | } 201 | } 202 | 203 | 204 | export function autoFillYByWeight( 205 | activeId: number, 206 | binStep: number, 207 | amountX: BN, 208 | amountXInActiveBin: BN, 209 | amountYInActiveBin: BN, 210 | distributions: { binId: number; weight: number }[]): BN { 211 | const activeBins = distributions.filter((element) => { 212 | return element.binId === activeId; 213 | }); 214 | 215 | if (activeBins.length === 1) { 216 | const p0 = getPriceOfBinByBinId(activeId, binStep); 217 | let wx0 = new Decimal(0); 218 | let wy0 = new Decimal(0); 219 | const activeBin = activeBins[0]; 220 | if (amountXInActiveBin.isZero() && amountYInActiveBin.isZero()) { 221 | wx0 = new Decimal(activeBin.weight).div(p0.mul(new Decimal(2))); 222 | wy0 = new Decimal(activeBin.weight).div(new Decimal(2)); 223 | } else { 224 | let amountXInActiveBinDec = new Decimal(amountXInActiveBin.toString()); 225 | let amountYInActiveBinDec = new Decimal(amountYInActiveBin.toString()); 226 | 227 | if (!amountXInActiveBin.isZero()) { 228 | wx0 = new Decimal(activeBin.weight).div( 229 | p0.add(amountYInActiveBinDec.div(amountXInActiveBinDec)) 230 | ); 231 | } 232 | if (!amountYInActiveBin.isZero()) { 233 | wy0 = new Decimal(activeBin.weight).div( 234 | new Decimal(1).add( 235 | p0.mul(amountXInActiveBinDec).div(amountYInActiveBinDec) 236 | ) 237 | ); 238 | } 239 | } 240 | 241 | let totalWeightX = wx0; 242 | let totalWeightY = wy0; 243 | distributions.forEach((element) => { 244 | if (element.binId < activeId) { 245 | totalWeightY = totalWeightY.add(new Decimal(element.weight)); 246 | } 247 | if (element.binId > activeId) { 248 | const price = getPriceOfBinByBinId(element.binId, binStep); 249 | const weighPerPrice = new Decimal(element.weight).div(price); 250 | totalWeightX = totalWeightX.add(weighPerPrice); 251 | } 252 | }); 253 | const kx = totalWeightX.isZero() ? new Decimal(1) : new Decimal(amountX.toString()).div(totalWeightX); 254 | const amountY = kx.mul(totalWeightY); 255 | return new BN(amountY.floor().toString()) 256 | } else { 257 | let totalWeightX = new Decimal(0); 258 | let totalWeightY = new Decimal(0); 259 | distributions.forEach((element) => { 260 | if (element.binId < activeId) { 261 | totalWeightY = totalWeightY.add(new Decimal(element.weight)); 262 | } else { 263 | const price = getPriceOfBinByBinId(element.binId, binStep); 264 | const weighPerPrice = new Decimal(element.weight).div(price); 265 | totalWeightX = totalWeightX.add(weighPerPrice); 266 | } 267 | }); 268 | const kx = totalWeightX.isZero() ? new Decimal(1) : new Decimal(amountX.toString()).div(totalWeightX); 269 | const amountY = kx.mul(totalWeightY); 270 | return new BN(amountY.floor().toString()) 271 | } 272 | } 273 | 274 | 275 | export function autoFillXByWeight( 276 | activeId: number, 277 | binStep: number, 278 | amountY: BN, 279 | amountXInActiveBin: BN, 280 | amountYInActiveBin: BN, 281 | distributions: { binId: number; weight: number }[]): BN { 282 | const activeBins = distributions.filter((element) => { 283 | return element.binId === activeId; 284 | }); 285 | 286 | if (activeBins.length === 1) { 287 | const p0 = getPriceOfBinByBinId(activeId, binStep); 288 | let wx0 = new Decimal(0); 289 | let wy0 = new Decimal(0); 290 | const activeBin = activeBins[0]; 291 | if (amountXInActiveBin.isZero() && amountYInActiveBin.isZero()) { 292 | wx0 = new Decimal(activeBin.weight).div(p0.mul(new Decimal(2))); 293 | wy0 = new Decimal(activeBin.weight).div(new Decimal(2)); 294 | } else { 295 | let amountXInActiveBinDec = new Decimal(amountXInActiveBin.toString()); 296 | let amountYInActiveBinDec = new Decimal(amountYInActiveBin.toString()); 297 | 298 | if (!amountXInActiveBin.isZero()) { 299 | wx0 = new Decimal(activeBin.weight).div( 300 | p0.add(amountYInActiveBinDec.div(amountXInActiveBinDec)) 301 | ); 302 | } 303 | if (!amountYInActiveBin.isZero()) { 304 | wy0 = new Decimal(activeBin.weight).div( 305 | new Decimal(1).add( 306 | p0.mul(amountXInActiveBinDec).div(amountYInActiveBinDec) 307 | ) 308 | ); 309 | } 310 | } 311 | 312 | let totalWeightX = wx0; 313 | let totalWeightY = wy0; 314 | distributions.forEach((element) => { 315 | if (element.binId < activeId) { 316 | totalWeightY = totalWeightY.add(new Decimal(element.weight)); 317 | } 318 | if (element.binId > activeId) { 319 | const price = getPriceOfBinByBinId(element.binId, binStep); 320 | const weighPerPrice = new Decimal(element.weight).div(price); 321 | totalWeightX = totalWeightX.add(weighPerPrice); 322 | } 323 | }); 324 | const ky = totalWeightY.isZero() ? new Decimal(1) : new Decimal(amountY.toString()).div(totalWeightY); 325 | const amountX = ky.mul(totalWeightX); 326 | return new BN(amountX.floor().toString()) 327 | } else { 328 | let totalWeightX = new Decimal(0); 329 | let totalWeightY = new Decimal(0); 330 | distributions.forEach((element) => { 331 | if (element.binId < activeId) { 332 | totalWeightY = totalWeightY.add(new Decimal(element.weight)); 333 | } else { 334 | const price = getPriceOfBinByBinId(element.binId, binStep); 335 | const weighPerPrice = new Decimal(element.weight).div(price); 336 | totalWeightX = totalWeightX.add(weighPerPrice); 337 | } 338 | }); 339 | const ky = totalWeightY.isZero() ? new Decimal(1) : new Decimal(amountY.toString()).div(totalWeightY); 340 | const amountX = ky.mul(totalWeightX); 341 | return new BN(amountX.floor().toString()) 342 | } 343 | } -------------------------------------------------------------------------------- /lib/dlmm/helpers/strategy.ts: -------------------------------------------------------------------------------- 1 | import { BN } from "anchor28"; 2 | import { StrategyType, StrategyParameters } from "../types"; 3 | import { autoFillXByWeight, autoFillYByWeight, toAmountAskSide, toAmountBidSide, toAmountBothSide } from "./weightToAmounts"; 4 | import Decimal from "decimal.js"; 5 | const DEFAULT_MAX_WEIGHT = 2000; 6 | const DEFAULT_MIN_WEIGHT = 200; 7 | 8 | function toWeightSpotBalanced( 9 | minBinId: number, 10 | maxBinId: number): { 11 | binId: number, 12 | weight: number 13 | }[] { 14 | let distributions = []; 15 | for (let i = minBinId; i <= maxBinId; i++) { 16 | distributions.push({ 17 | binId: i, 18 | weight: 1, 19 | }); 20 | } 21 | return distributions; 22 | } 23 | 24 | function toWeightDecendingOrder(minBinId: number, 25 | maxBinId: number): { 26 | binId: number, 27 | weight: number 28 | }[] { 29 | let distributions = []; 30 | for (let i = minBinId; i <= maxBinId; i++) { 31 | distributions.push({ 32 | binId: i, 33 | weight: maxBinId - i + 1, 34 | }); 35 | } 36 | return distributions; 37 | } 38 | 39 | function toWeightAscendingOrder(minBinId: number, 40 | maxBinId: number): { 41 | binId: number, 42 | weight: number 43 | }[] { 44 | let distributions = []; 45 | for (let i = minBinId; i <= maxBinId; i++) { 46 | distributions.push({ 47 | binId: i, 48 | weight: i - minBinId + 1, 49 | }); 50 | } 51 | return distributions; 52 | } 53 | 54 | 55 | 56 | function toWeightCurve( 57 | minBinId: number, 58 | maxBinId: number, 59 | activeId: number, 60 | ): { 61 | binId: number, 62 | weight: number 63 | }[] { 64 | if (activeId < minBinId || activeId > maxBinId) { 65 | throw "Invalid strategy params"; 66 | } 67 | let maxWeight = DEFAULT_MAX_WEIGHT; 68 | let minWeight = DEFAULT_MIN_WEIGHT; 69 | 70 | let diffWeight = maxWeight - minWeight; 71 | let diffMinWeight = activeId > minBinId ? Math.floor(diffWeight / (activeId - minBinId)) : 0; 72 | let diffMaxWeight = maxBinId > activeId ? Math.floor(diffWeight / (maxBinId - activeId)) : 0; 73 | 74 | let distributions = []; 75 | for (let i = minBinId; i <= maxBinId; i++) { 76 | if (i < activeId) { 77 | distributions.push({ 78 | binId: i, 79 | weight: maxWeight - (activeId - i) * diffMinWeight, 80 | }); 81 | } else if (i > activeId) { 82 | distributions.push({ 83 | binId: i, 84 | weight: maxWeight - (i - activeId) * diffMaxWeight, 85 | }); 86 | } else { 87 | distributions.push({ 88 | binId: i, 89 | weight: maxWeight, 90 | }); 91 | } 92 | } 93 | return distributions; 94 | } 95 | 96 | 97 | function toWeightBidAsk( 98 | minBinId: number, 99 | maxBinId: number, 100 | activeId: number, 101 | ): { 102 | binId: number, 103 | weight: number 104 | }[] { 105 | if (activeId < minBinId || activeId > maxBinId) { 106 | throw "Invalid strategy params"; 107 | } 108 | let maxWeight = DEFAULT_MAX_WEIGHT; 109 | let minWeight = DEFAULT_MIN_WEIGHT; 110 | 111 | let diffWeight = maxWeight - minWeight; 112 | let diffMinWeight = activeId > minBinId ? Math.floor(diffWeight / (activeId - minBinId)) : 0; 113 | let diffMaxWeight = maxBinId > activeId ? Math.floor(diffWeight / (maxBinId - activeId)) : 0; 114 | 115 | let distributions = []; 116 | for (let i = minBinId; i <= maxBinId; i++) { 117 | if (i < activeId) { 118 | distributions.push({ 119 | binId: i, 120 | weight: minWeight + (activeId - i) * diffMinWeight, 121 | }); 122 | } else if (i > activeId) { 123 | distributions.push({ 124 | binId: i, 125 | weight: minWeight + (i - activeId) * diffMaxWeight, 126 | }); 127 | } else { 128 | distributions.push({ 129 | binId: i, 130 | weight: minWeight, 131 | }); 132 | } 133 | } 134 | return distributions; 135 | } 136 | 137 | 138 | export function toAmountsOneSideByStrategy( 139 | activeId: number, 140 | binStep: number, 141 | minBinId: number, 142 | maxBinId: number, 143 | amount: BN, 144 | strategyType: StrategyType, 145 | depositForY: boolean, 146 | ): { 147 | binId: number, 148 | amount: BN 149 | }[] { 150 | let weights = []; 151 | switch (strategyType) { 152 | case StrategyType.SpotBalanced: 153 | case StrategyType.CurveBalanced: 154 | case StrategyType.BidAskBalanced: 155 | case StrategyType.SpotImBalanced: 156 | case StrategyType.CurveImBalanced: 157 | case StrategyType.BidAskImBalanced: 158 | { 159 | throw "Invalid Strategy Parameters"; 160 | } 161 | case StrategyType.SpotOneSide: { 162 | weights = toWeightSpotBalanced(minBinId, maxBinId); 163 | break; 164 | } 165 | case StrategyType.CurveOneSide: { 166 | if (depositForY) { 167 | weights = toWeightAscendingOrder(minBinId, maxBinId); 168 | } else { 169 | weights = toWeightDecendingOrder(minBinId, maxBinId); 170 | } 171 | break; 172 | } 173 | case StrategyType.BidAskOneSide: { 174 | if (depositForY) { 175 | weights = toWeightDecendingOrder(minBinId, maxBinId); 176 | } else { 177 | weights = toWeightAscendingOrder(minBinId, maxBinId); 178 | } 179 | break; 180 | } 181 | } 182 | if (depositForY) { 183 | return toAmountBidSide(activeId, amount, weights); 184 | } else { 185 | return toAmountAskSide(activeId, binStep, amount, weights); 186 | } 187 | } 188 | 189 | export function toAmountsBothSideByStrategy( 190 | activeId: number, 191 | binStep: number, 192 | minBinId: number, 193 | maxBinId: number, 194 | amountX: BN, 195 | amountY: BN, 196 | amountXInActiveBin: BN, 197 | amountYInActiveBin: BN, 198 | strategyType: StrategyType, 199 | ): { 200 | binId: number, 201 | amountX: BN, 202 | amountY: BN, 203 | }[] { 204 | switch (strategyType) { 205 | case StrategyType.SpotOneSide: 206 | case StrategyType.CurveOneSide: 207 | case StrategyType.BidAskOneSide: 208 | { 209 | throw "Invalid Strategy Parameters"; 210 | } 211 | case StrategyType.SpotImBalanced: { 212 | let amountsInBin = []; 213 | if (minBinId <= activeId) { 214 | let weights = toWeightSpotBalanced(minBinId, activeId); 215 | let amounts = 216 | toAmountBidSide(activeId, amountY, weights); 217 | 218 | for (let bin of amounts) { 219 | amountsInBin.push({ 220 | binId: bin.binId, 221 | amountX: new BN(0), 222 | amountY: bin.amount, 223 | }) 224 | } 225 | } 226 | if (activeId < maxBinId) { 227 | let weights = toWeightSpotBalanced(activeId + 1, maxBinId); 228 | let amounts = 229 | toAmountAskSide(activeId, binStep, amountX, weights); 230 | for (let bin of amounts) { 231 | amountsInBin.push({ 232 | binId: bin.binId, 233 | amountX: bin.amount, 234 | amountY: new BN(0), 235 | }) 236 | } 237 | } 238 | return amountsInBin; 239 | } 240 | case StrategyType.CurveImBalanced: { 241 | let amountsInBin = []; 242 | if (minBinId <= activeId) { 243 | let weights = toWeightAscendingOrder(minBinId, activeId); 244 | let amounts = 245 | toAmountBidSide(activeId, amountY, weights); 246 | 247 | for (let bin of amounts) { 248 | amountsInBin.push({ 249 | binId: bin.binId, 250 | amountX: new BN(0), 251 | amountY: bin.amount, 252 | }) 253 | } 254 | } 255 | if (activeId < maxBinId) { 256 | let weights = toWeightDecendingOrder(activeId + 1, maxBinId); 257 | let amounts = 258 | toAmountAskSide(activeId, binStep, amountX, weights); 259 | for (let bin of amounts) { 260 | amountsInBin.push({ 261 | binId: bin.binId, 262 | amountX: bin.amount, 263 | amountY: new BN(0), 264 | }) 265 | } 266 | } 267 | return amountsInBin; 268 | } 269 | case StrategyType.BidAskImBalanced: { 270 | let amountsInBin = []; 271 | if (minBinId <= activeId) { 272 | let weights = toWeightDecendingOrder(minBinId, activeId); 273 | let amounts = 274 | toAmountBidSide(activeId, amountY, weights); 275 | 276 | for (let bin of amounts) { 277 | amountsInBin.push({ 278 | binId: bin.binId, 279 | amountX: new BN(0), 280 | amountY: bin.amount, 281 | }) 282 | } 283 | } 284 | if (activeId < maxBinId) { 285 | let weights = toWeightAscendingOrder(activeId + 1, maxBinId); 286 | let amounts = 287 | toAmountAskSide(activeId, binStep, amountX, weights); 288 | for (let bin of amounts) { 289 | amountsInBin.push({ 290 | binId: bin.binId, 291 | amountX: bin.amount, 292 | amountY: new BN(0), 293 | }) 294 | } 295 | } 296 | return amountsInBin; 297 | } 298 | case StrategyType.SpotBalanced: { 299 | let weights = toWeightSpotBalanced(minBinId, maxBinId); 300 | return toAmountBothSide(activeId, binStep, amountX, amountY, amountXInActiveBin, amountYInActiveBin, weights); 301 | } 302 | case StrategyType.CurveBalanced: { 303 | let weights = toWeightCurve(minBinId, maxBinId, activeId); 304 | return toAmountBothSide(activeId, binStep, amountX, amountY, amountXInActiveBin, amountYInActiveBin, weights); 305 | } 306 | case StrategyType.BidAskBalanced: { 307 | let weights = toWeightBidAsk(minBinId, maxBinId, activeId); 308 | return toAmountBothSide(activeId, binStep, amountX, amountY, amountXInActiveBin, amountYInActiveBin, weights); 309 | } 310 | } 311 | } 312 | 313 | // only apply for 314 | export function autoFillYByStrategy( 315 | activeId: number, 316 | binStep: number, 317 | amountX: BN, 318 | amountXInActiveBin: BN, 319 | amountYInActiveBin: BN, 320 | minBinId: number, 321 | maxBinId: number, 322 | strategyType: StrategyType, 323 | ): BN { 324 | switch (strategyType) { 325 | case StrategyType.SpotOneSide: 326 | case StrategyType.CurveOneSide: 327 | case StrategyType.BidAskOneSide: 328 | 329 | case StrategyType.SpotImBalanced: 330 | case StrategyType.CurveImBalanced: 331 | case StrategyType.BidAskImBalanced: 332 | { 333 | throw "Invalid Strategy Parameters"; 334 | } 335 | case StrategyType.SpotBalanced: { 336 | let weights = toWeightSpotBalanced(minBinId, maxBinId); 337 | return autoFillYByWeight(activeId, binStep, amountX, amountXInActiveBin, amountYInActiveBin, weights); 338 | } 339 | case StrategyType.CurveBalanced: { 340 | let weights = toWeightCurve(minBinId, maxBinId, activeId); 341 | return autoFillYByWeight(activeId, binStep, amountX, amountXInActiveBin, amountYInActiveBin, weights); 342 | } 343 | case StrategyType.BidAskBalanced: { 344 | let weights = toWeightBidAsk(minBinId, maxBinId, activeId); 345 | return autoFillYByWeight(activeId, binStep, amountX, amountXInActiveBin, amountYInActiveBin, weights); 346 | } 347 | } 348 | } 349 | 350 | // only apply for balanced deposit 351 | export function autoFillXByStrategy( 352 | activeId: number, 353 | binStep: number, 354 | amountY: BN, 355 | amountXInActiveBin: BN, 356 | amountYInActiveBin: BN, 357 | minBinId: number, 358 | maxBinId: number, 359 | strategyType: StrategyType, 360 | ): BN { 361 | switch (strategyType) { 362 | case StrategyType.SpotOneSide: 363 | case StrategyType.CurveOneSide: 364 | case StrategyType.BidAskOneSide: 365 | 366 | case StrategyType.SpotImBalanced: 367 | case StrategyType.CurveImBalanced: 368 | case StrategyType.BidAskImBalanced: 369 | { 370 | throw "Invalid Strategy Parameters"; 371 | } 372 | case StrategyType.SpotBalanced: { 373 | let weights = toWeightSpotBalanced(minBinId, maxBinId); 374 | return autoFillXByWeight(activeId, binStep, amountY, amountXInActiveBin, amountYInActiveBin, weights); 375 | } 376 | case StrategyType.CurveBalanced: { 377 | let weights = toWeightCurve(minBinId, maxBinId, activeId); 378 | return autoFillXByWeight(activeId, binStep, amountY, amountXInActiveBin, amountYInActiveBin, weights); 379 | } 380 | case StrategyType.BidAskBalanced: { 381 | let weights = toWeightBidAsk(minBinId, maxBinId, activeId); 382 | return autoFillXByWeight(activeId, binStep, amountY, amountXInActiveBin, amountYInActiveBin, weights); 383 | } 384 | } 385 | } 386 | 387 | // this this function to convert correct type for program 388 | export function toStrategyParameters(strategyParameters: StrategyParameters) { 389 | const { 390 | maxBinId, 391 | minBinId, 392 | strategyType, 393 | } = strategyParameters; 394 | switch (strategyType) { 395 | case StrategyType.SpotOneSide: { 396 | return { 397 | minBinId, 398 | maxBinId, 399 | strategyType: { spotOneSide: {} }, 400 | parameteres: Buffer.from(new Array(64).fill(0)).toJSON().data, 401 | }; 402 | } 403 | case StrategyType.CurveOneSide: { 404 | return { 405 | minBinId, 406 | maxBinId, 407 | strategyType: { curveOneSide: {} }, 408 | parameteres: Buffer.from(new Array(64).fill(0)).toJSON().data, 409 | }; 410 | } 411 | case StrategyType.BidAskOneSide: { 412 | return { 413 | minBinId, 414 | maxBinId, 415 | strategyType: { bidAskOneSide: {} }, 416 | parameteres: Buffer.from(new Array(64).fill(0)).toJSON().data, 417 | }; 418 | } 419 | case StrategyType.SpotBalanced: { 420 | return { 421 | minBinId, 422 | maxBinId, 423 | strategyType: { spotBalanced: {} }, 424 | parameteres: Buffer.from(new Array(64).fill(0)).toJSON().data, 425 | }; 426 | } 427 | case StrategyType.CurveBalanced: { 428 | return { 429 | minBinId, 430 | maxBinId, 431 | strategyType: { curveBalanced: {} }, 432 | parameteres: Buffer.from(new Array(64).fill(0)).toJSON().data, 433 | }; 434 | } 435 | case StrategyType.BidAskBalanced: { 436 | return { 437 | minBinId, 438 | maxBinId, 439 | strategyType: { bidAskBalanced: {} }, 440 | parameteres: Buffer.from(new Array(64).fill(0)).toJSON().data, 441 | }; 442 | } 443 | 444 | case StrategyType.SpotImBalanced: { 445 | return { 446 | minBinId, 447 | maxBinId, 448 | strategyType: { spotImBalanced: {} }, 449 | parameteres: Buffer.from(new Array(64).fill(0)).toJSON().data, 450 | }; 451 | } 452 | case StrategyType.CurveImBalanced: { 453 | return { 454 | minBinId, 455 | maxBinId, 456 | strategyType: { curveImBalanced: {} }, 457 | parameteres: Buffer.from(new Array(64).fill(0)).toJSON().data, 458 | }; 459 | } 460 | case StrategyType.BidAskImBalanced: { 461 | return { 462 | minBinId, 463 | maxBinId, 464 | strategyType: { bidAskImBalanced: {} }, 465 | parameteres: Buffer.from(new Array(64).fill(0)).toJSON().data, 466 | }; 467 | } 468 | } 469 | } 470 | 471 | 472 | 473 | -------------------------------------------------------------------------------- /lib/dlmm/helpers/weight.ts: -------------------------------------------------------------------------------- 1 | import { BN } from "anchor28"; 2 | import gaussian, { Gaussian } from "gaussian"; 3 | import { BASIS_POINT_MAX } from "../constants"; 4 | import Decimal from "decimal.js"; 5 | import { toAmountAskSide, toAmountBidSide, toAmountBothSide } from "./weightToAmounts"; 6 | 7 | export function getPriceOfBinByBinId(binId: number, binStep: number): Decimal { 8 | const binStepNum = new Decimal(binStep).div(new Decimal(BASIS_POINT_MAX)); 9 | return new Decimal(1).add(new Decimal(binStepNum)).pow(new Decimal(binId)); 10 | } 11 | 12 | /// Build a gaussian distribution from the bins, with active bin as the mean. 13 | function buildGaussianFromBins(activeBin: number, binIds: number[]) { 14 | const smallestBin = Math.min(...binIds); 15 | const largestBin = Math.max(...binIds); 16 | 17 | // Define the Gaussian distribution. The mean will be active bin when active bin is within the bin ids. Else, use left or right most bin id as the mean. 18 | let mean = 0; 19 | const isAroundActiveBin = binIds.find((bid) => bid == activeBin); 20 | // The liquidity will be distributed surrounding active bin 21 | if (isAroundActiveBin) { 22 | mean = activeBin; 23 | } 24 | // The liquidity will be distributed to the right side of the active bin. 25 | else if (activeBin < smallestBin) { 26 | mean = smallestBin; 27 | } 28 | // The liquidity will be distributed to the left side of the active bin. 29 | else { 30 | mean = largestBin; 31 | } 32 | 33 | const TWO_STANDARD_DEVIATION = 4; 34 | const stdDev = (largestBin - smallestBin) / TWO_STANDARD_DEVIATION; 35 | const variance = Math.max(stdDev ** 2, 1); 36 | 37 | return gaussian(mean, variance); 38 | } 39 | 40 | /// Find the probability of the bin id over the gaussian. The probability ranged from 0 - 1 and will be used as liquidity allocation for that particular bin. 41 | function generateBinLiquidityAllocation( 42 | gaussian: Gaussian, 43 | binIds: number[], 44 | invert: boolean 45 | ) { 46 | const allocations = binIds.map((bid) => 47 | invert ? 1 / gaussian.pdf(bid) : gaussian.pdf(bid) 48 | ); 49 | const totalAllocations = allocations.reduce((acc, v) => acc + v, 0); 50 | // Gaussian impossible to cover 100%, normalized it to have total of 100% 51 | return allocations.map((a) => a / totalAllocations); 52 | } 53 | 54 | /// Convert liquidity allocation from 0..1 to 0..10000 bps unit. The sum of allocations must be 1. Return BPS and the loss after conversion. 55 | function computeAllocationBps(allocations: number[]): { 56 | bpsAllocations: BN[]; 57 | pLoss: BN; 58 | } { 59 | let totalAllocation = new BN(0); 60 | const bpsAllocations: BN[] = []; 61 | 62 | for (const allocation of allocations) { 63 | const allocBps = new BN(allocation * 10000); 64 | bpsAllocations.push(allocBps); 65 | totalAllocation = totalAllocation.add(allocBps); 66 | } 67 | 68 | const pLoss = new BN(10000).sub(totalAllocation); 69 | return { 70 | bpsAllocations, 71 | pLoss, 72 | }; 73 | } 74 | /** private */ 75 | 76 | export function toWeightDistribution( 77 | amountX: BN, 78 | amountY: BN, 79 | distributions: { 80 | binId: number; 81 | xAmountBpsOfTotal: BN; 82 | yAmountBpsOfTotal: BN; 83 | }[], 84 | binStep: number 85 | ): { binId: number; weight: number }[] { 86 | // get all quote amount 87 | let totalQuote = new BN(0); 88 | const precision = 1_000_000_000_000; 89 | const quoteDistributions = distributions.map((bin) => { 90 | const price = new BN( 91 | getPriceOfBinByBinId(bin.binId, binStep).mul(precision).floor().toString() 92 | ); 93 | const quoteValue = amountX 94 | .mul(new BN(bin.xAmountBpsOfTotal)) 95 | .mul(new BN(price)) 96 | .div(new BN(BASIS_POINT_MAX)) 97 | .div(new BN(precision)); 98 | const quoteAmount = quoteValue.add( 99 | amountY.mul(new BN(bin.yAmountBpsOfTotal)).div(new BN(BASIS_POINT_MAX)) 100 | ); 101 | totalQuote = totalQuote.add(quoteAmount); 102 | return { 103 | binId: bin.binId, 104 | quoteAmount, 105 | }; 106 | }); 107 | 108 | if (totalQuote.eq(new BN(0))) { 109 | return []; 110 | } 111 | 112 | const distributionWeights = quoteDistributions 113 | .map((bin) => { 114 | const weight = Math.floor( 115 | bin.quoteAmount.mul(new BN(65535)).div(totalQuote).toNumber() 116 | ); 117 | return { 118 | binId: bin.binId, 119 | weight, 120 | }; 121 | }) 122 | .filter((item) => item.weight > 0); 123 | 124 | return distributionWeights; 125 | } 126 | 127 | export function calculateSpotDistribution( 128 | activeBin: number, 129 | binIds: number[] 130 | ): { binId: number; xAmountBpsOfTotal: BN; yAmountBpsOfTotal: BN }[] { 131 | if (!binIds.includes(activeBin)) { 132 | const { div: dist, mod: rem } = new BN(10_000).divmod( 133 | new BN(binIds.length) 134 | ); 135 | const loss = rem.isZero() ? new BN(0) : new BN(1); 136 | 137 | const distributions = 138 | binIds[0] < activeBin 139 | ? binIds.map((binId) => ({ 140 | binId, 141 | xAmountBpsOfTotal: new BN(0), 142 | yAmountBpsOfTotal: dist, 143 | })) 144 | : binIds.map((binId) => ({ 145 | binId, 146 | xAmountBpsOfTotal: dist, 147 | yAmountBpsOfTotal: new BN(0), 148 | })); 149 | 150 | // Add the loss to the left most bin 151 | if (binIds[0] < activeBin) { 152 | distributions[0].yAmountBpsOfTotal.add(loss); 153 | } 154 | // Add the loss to the right most bin 155 | else { 156 | distributions[binIds.length - 1].xAmountBpsOfTotal.add(loss); 157 | } 158 | 159 | return distributions; 160 | } 161 | 162 | const binYCount = binIds.filter((binId) => binId < activeBin).length; 163 | const binXCount = binIds.filter((binId) => binId > activeBin).length; 164 | 165 | const totalYBinCapacity = binYCount + 0.5; 166 | const totalXBinCapacity = binXCount + 0.5; 167 | 168 | const yBinBps = new BN(10_000 / totalYBinCapacity); 169 | const yActiveBinBps = new BN(10_000).sub(yBinBps.mul(new BN(binYCount))); 170 | 171 | const xBinBps = new BN(10_000 / totalXBinCapacity); 172 | const xActiveBinBps = new BN(10_000).sub(xBinBps.mul(new BN(binXCount))); 173 | 174 | return binIds.map((binId) => { 175 | const isYBin = binId < activeBin; 176 | const isXBin = binId > activeBin; 177 | const isActiveBin = binId === activeBin; 178 | 179 | if (isYBin) { 180 | return { 181 | binId, 182 | xAmountBpsOfTotal: new BN(0), 183 | yAmountBpsOfTotal: yBinBps, 184 | }; 185 | } 186 | 187 | if (isXBin) { 188 | return { 189 | binId, 190 | xAmountBpsOfTotal: xBinBps, 191 | yAmountBpsOfTotal: new BN(0), 192 | }; 193 | } 194 | 195 | if (isActiveBin) { 196 | return { 197 | binId, 198 | xAmountBpsOfTotal: xActiveBinBps, 199 | yAmountBpsOfTotal: yActiveBinBps, 200 | }; 201 | } 202 | }); 203 | } 204 | 205 | export function calculateBidAskDistribution( 206 | activeBin: number, 207 | binIds: number[] 208 | ): { 209 | binId: number; 210 | xAmountBpsOfTotal: BN; 211 | yAmountBpsOfTotal: BN; 212 | }[] { 213 | const smallestBin = Math.min(...binIds); 214 | const largestBin = Math.max(...binIds); 215 | 216 | const rightOnly = activeBin < smallestBin; 217 | const leftOnly = activeBin > largestBin; 218 | 219 | const gaussian = buildGaussianFromBins(activeBin, binIds); 220 | const allocations = generateBinLiquidityAllocation(gaussian, binIds, true); 221 | 222 | // To the right of active bin, liquidity distribution consists of only token X. 223 | if (rightOnly) { 224 | const { bpsAllocations, pLoss } = computeAllocationBps(allocations); 225 | const binDistributions = binIds.map((bid, idx) => ({ 226 | binId: bid, 227 | xAmountBpsOfTotal: bpsAllocations[idx], 228 | yAmountBpsOfTotal: new BN(0), 229 | })); 230 | const idx = binDistributions.length - 1; 231 | binDistributions[idx].xAmountBpsOfTotal = 232 | binDistributions[idx].xAmountBpsOfTotal.add(pLoss); 233 | return binDistributions; 234 | } 235 | 236 | // To the left of active bin, liquidity distribution consists of only token Y. 237 | if (leftOnly) { 238 | const { bpsAllocations, pLoss } = computeAllocationBps(allocations); 239 | const binDistributions = binIds.map((bid, idx) => ({ 240 | binId: bid, 241 | xAmountBpsOfTotal: new BN(0), 242 | yAmountBpsOfTotal: bpsAllocations[idx], 243 | })); 244 | binDistributions[0].yAmountBpsOfTotal = 245 | binDistributions[0].yAmountBpsOfTotal.add(pLoss); 246 | return binDistributions; 247 | } 248 | 249 | // Find total X, and Y bps allocations for normalization. 250 | const [totalXAllocation, totalYAllocation] = allocations.reduce( 251 | ([xAcc, yAcc], allocation, idx) => { 252 | const binId = binIds[idx]; 253 | if (binId > activeBin) { 254 | return [xAcc + allocation, yAcc]; 255 | } else if (binId < activeBin) { 256 | return [xAcc, yAcc + allocation]; 257 | } else { 258 | const half = allocation / 2; 259 | return [xAcc + half, yAcc + half]; 260 | } 261 | }, 262 | [0, 0] 263 | ); 264 | 265 | // Normalize and convert to BPS 266 | const [normXAllocations, normYAllocations] = allocations.reduce<[BN[], BN[]]>( 267 | ([xAllocations, yAllocations], allocation, idx) => { 268 | const binId = binIds[idx]; 269 | if (binId > activeBin) { 270 | const distX = new BN((allocation * 10000) / totalXAllocation); 271 | xAllocations.push(distX); 272 | } 273 | if (binId < activeBin) { 274 | const distY = new BN((allocation * 10000) / totalYAllocation); 275 | yAllocations.push(distY); 276 | } 277 | if (binId == activeBin) { 278 | const half = allocation / 2; 279 | const distX = new BN((half * 10000) / totalXAllocation); 280 | const distY = new BN((half * 10000) / totalYAllocation); 281 | xAllocations.push(distX); 282 | yAllocations.push(distY); 283 | } 284 | return [xAllocations, yAllocations]; 285 | }, 286 | [[], []] 287 | ); 288 | 289 | const totalXNormAllocations = normXAllocations.reduce( 290 | (acc, v) => acc.add(v), 291 | new BN(0) 292 | ); 293 | const totalYNormAllocations = normYAllocations.reduce( 294 | (acc, v) => acc.add(v), 295 | new BN(0) 296 | ); 297 | 298 | const xPLoss = new BN(10000).sub(totalXNormAllocations); 299 | const yPLoss = new BN(10000).sub(totalYNormAllocations); 300 | 301 | const distributions = binIds.map((binId) => { 302 | if (binId === activeBin) { 303 | return { 304 | binId, 305 | xAmountBpsOfTotal: normXAllocations.shift(), 306 | yAmountBpsOfTotal: normYAllocations.shift(), 307 | }; 308 | } 309 | 310 | if (binId > activeBin) { 311 | return { 312 | binId, 313 | xAmountBpsOfTotal: normXAllocations.shift(), 314 | yAmountBpsOfTotal: new BN(0), 315 | }; 316 | } 317 | 318 | if (binId < activeBin) { 319 | return { 320 | binId, 321 | xAmountBpsOfTotal: new BN(0), 322 | yAmountBpsOfTotal: normYAllocations.shift(), 323 | }; 324 | } 325 | }); 326 | 327 | if (!yPLoss.isZero()) { 328 | distributions[0].yAmountBpsOfTotal = 329 | distributions[0].yAmountBpsOfTotal.add(yPLoss); 330 | } 331 | 332 | if (!xPLoss.isZero()) { 333 | const last = distributions.length - 1; 334 | distributions[last].xAmountBpsOfTotal = 335 | distributions[last].xAmountBpsOfTotal.add(xPLoss); 336 | } 337 | 338 | return distributions; 339 | } 340 | 341 | export function calculateNormalDistribution( 342 | activeBin: number, 343 | binIds: number[] 344 | ): { 345 | binId: number; 346 | xAmountBpsOfTotal: BN; 347 | yAmountBpsOfTotal: BN; 348 | }[] { 349 | const smallestBin = Math.min(...binIds); 350 | const largestBin = Math.max(...binIds); 351 | 352 | const rightOnly = activeBin < smallestBin; 353 | const leftOnly = activeBin > largestBin; 354 | 355 | const gaussian = buildGaussianFromBins(activeBin, binIds); 356 | const allocations = generateBinLiquidityAllocation(gaussian, binIds, false); 357 | 358 | // To the right of active bin, liquidity distribution consists of only token X. 359 | if (rightOnly) { 360 | const { bpsAllocations, pLoss } = computeAllocationBps(allocations); 361 | const binDistributions = binIds.map((bid, idx) => ({ 362 | binId: bid, 363 | xAmountBpsOfTotal: bpsAllocations[idx], 364 | yAmountBpsOfTotal: new BN(0), 365 | })); 366 | // When contains only X token, bin closest to active bin will be index 0. 367 | // Add back the precision loss 368 | binDistributions[0].xAmountBpsOfTotal = 369 | binDistributions[0].xAmountBpsOfTotal.add(pLoss); 370 | return binDistributions; 371 | } 372 | 373 | // To the left of active bin, liquidity distribution consists of only token Y. 374 | if (leftOnly) { 375 | const { bpsAllocations, pLoss } = computeAllocationBps(allocations); 376 | const binDistributions = binIds.map((bid, idx) => ({ 377 | binId: bid, 378 | xAmountBpsOfTotal: new BN(0), 379 | yAmountBpsOfTotal: bpsAllocations[idx], 380 | })); 381 | // When contains only Y token, bin closest to active bin will be last index. 382 | // Add back the precision loss 383 | const idx = binDistributions.length - 1; 384 | binDistributions[idx].yAmountBpsOfTotal = 385 | binDistributions[idx].yAmountBpsOfTotal.add(pLoss); 386 | return binDistributions; 387 | } 388 | 389 | // The liquidity distribution consists of token X and Y. Allocations from gaussian only says how much liquidity percentage per bin over the full bin range. 390 | // Normalize liquidity allocation percentage into X - 100%, Y - 100%. 391 | 392 | // Find total X, and Y bps allocations for normalization. 393 | const [totalXAllocation, totalYAllocation] = allocations.reduce( 394 | ([xAcc, yAcc], allocation, idx) => { 395 | const binId = binIds[idx]; 396 | if (binId > activeBin) { 397 | return [xAcc + allocation, yAcc]; 398 | } else if (binId < activeBin) { 399 | return [xAcc, yAcc + allocation]; 400 | } else { 401 | const half = allocation / 2; 402 | return [xAcc + half, yAcc + half]; 403 | } 404 | }, 405 | [0, 0] 406 | ); 407 | 408 | // Normalize and convert to BPS 409 | const [normXAllocations, normYAllocations] = allocations.reduce( 410 | ([xAllocations, yAllocations], allocation, idx) => { 411 | const binId = binIds[idx]; 412 | if (binId > activeBin) { 413 | const distX = new BN((allocation * 10000) / totalXAllocation); 414 | xAllocations.push(distX); 415 | } 416 | if (binId < activeBin) { 417 | const distY = new BN((allocation * 10000) / totalYAllocation); 418 | yAllocations.push(distY); 419 | } 420 | return [xAllocations, yAllocations]; 421 | }, 422 | [[], []] 423 | ); 424 | 425 | const normXActiveBinAllocation = normXAllocations.reduce( 426 | (maxBps, bps) => maxBps.sub(bps), 427 | new BN(10_000) 428 | ); 429 | const normYActiveBinAllocation = normYAllocations.reduce( 430 | (maxBps, bps) => maxBps.sub(bps), 431 | new BN(10_000) 432 | ); 433 | 434 | return binIds.map((binId) => { 435 | if (binId === activeBin) { 436 | return { 437 | binId, 438 | xAmountBpsOfTotal: normXActiveBinAllocation, 439 | yAmountBpsOfTotal: normYActiveBinAllocation, 440 | }; 441 | } 442 | 443 | if (binId > activeBin) { 444 | return { 445 | binId, 446 | xAmountBpsOfTotal: normXAllocations.shift(), 447 | yAmountBpsOfTotal: new BN(0), 448 | }; 449 | } 450 | 451 | if (binId < activeBin) { 452 | return { 453 | binId, 454 | xAmountBpsOfTotal: new BN(0), 455 | yAmountBpsOfTotal: normYAllocations.shift(), 456 | }; 457 | } 458 | }); 459 | } 460 | 461 | export function fromWeightDistributionToAmountOneSide( 462 | amount: BN, 463 | distributions: { binId: number; weight: number }[], 464 | binStep: number, 465 | activeId: number, 466 | depositForY: boolean, 467 | ): { binId: number; amount: BN }[] { 468 | if (depositForY) { 469 | return toAmountBidSide(activeId, amount, distributions); 470 | } else { 471 | return toAmountAskSide(activeId, binStep, amount, distributions); 472 | } 473 | } 474 | 475 | export function fromWeightDistributionToAmount( 476 | amountX: BN, 477 | amountY: BN, 478 | distributions: { binId: number; weight: number }[], 479 | binStep: number, 480 | activeId: number, 481 | amountXInActiveBin: BN, 482 | amountYInActiveBin: BN 483 | ): { binId: number; amountX: BN; amountY: BN }[] { 484 | // sort distribution 485 | var distributions = distributions.sort((n1, n2) => { 486 | return n1.binId - n2.binId; 487 | }); 488 | 489 | if (distributions.length == 0) { 490 | return []; 491 | } 492 | 493 | // only bid side 494 | if (activeId > distributions[distributions.length - 1].binId) { 495 | let amounts = toAmountBidSide(activeId, amountY, distributions); 496 | return amounts.map((bin) => { 497 | return { 498 | binId: bin.binId, 499 | amountX: new BN(0), 500 | amountY: new BN(bin.amount.toString()), 501 | }; 502 | }); 503 | } 504 | 505 | // only ask side 506 | if (activeId < distributions[0].binId) { 507 | let amounts = toAmountAskSide(activeId, binStep, amountX, distributions); 508 | return amounts.map((bin) => { 509 | return { 510 | binId: bin.binId, 511 | amountX: new BN(bin.amount.toString()), 512 | amountY: new BN(0), 513 | }; 514 | }); 515 | } 516 | return toAmountBothSide(activeId, binStep, amountX, amountY, amountXInActiveBin, amountYInActiveBin, distributions); 517 | } -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/runtime@^7.10.5": 6 | version "7.24.7" 7 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" 8 | integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== 9 | dependencies: 10 | regenerator-runtime "^0.14.0" 11 | 12 | "@babel/runtime@^7.24.6": 13 | version "7.24.6" 14 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.6.tgz#5b76eb89ad45e2e4a0a8db54c456251469a3358e" 15 | integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw== 16 | dependencies: 17 | regenerator-runtime "^0.14.0" 18 | 19 | "@coral-xyz/anchor@^0.30.0": 20 | version "0.30.0" 21 | resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.30.0.tgz#52acdba504b0008f1026d3a4bbbcb2d4feb5c69e" 22 | integrity sha512-qreDh5ztiRHVnCbJ+RS70NJ6aSTPBYDAgFeQ7Z5QvaT5DcDIhNyt4onOciVz2ieIE1XWePOJDDu9SbNvPGBkvQ== 23 | dependencies: 24 | "@coral-xyz/borsh" "^0.30.0" 25 | "@noble/hashes" "^1.3.1" 26 | "@solana/web3.js" "^1.68.0" 27 | bn.js "^5.1.2" 28 | bs58 "^4.0.1" 29 | buffer-layout "^1.2.2" 30 | camelcase "^6.3.0" 31 | cross-fetch "^3.1.5" 32 | crypto-hash "^1.3.0" 33 | eventemitter3 "^4.0.7" 34 | pako "^2.0.3" 35 | snake-case "^3.0.4" 36 | superstruct "^0.15.4" 37 | toml "^3.0.0" 38 | 39 | "@coral-xyz/borsh@^0.28.0": 40 | version "0.28.0" 41 | resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.28.0.tgz#fa368a2f2475bbf6f828f4657f40a52102e02b6d" 42 | integrity sha512-/u1VTzw7XooK7rqeD7JLUSwOyRSesPUk0U37BV9zK0axJc1q0nRbKFGFLYCQ16OtdOJTTwGfGp11Lx9B45bRCQ== 43 | dependencies: 44 | bn.js "^5.1.2" 45 | buffer-layout "^1.2.0" 46 | 47 | "@coral-xyz/borsh@^0.30.0": 48 | version "0.30.0" 49 | resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.30.0.tgz#3e6f23e944ef6c89f2c9cbead383358752ac5e73" 50 | integrity sha512-OrcV+7N10cChhgDRUxM4iEIuwxUHHs52XD85R8cFCUqE0vbLYrcoPPPs+VF6kZ9DhdJGVW2I6DHJOp5TykyZog== 51 | dependencies: 52 | bn.js "^5.1.2" 53 | buffer-layout "^1.2.0" 54 | 55 | "@noble/curves@^1.4.0": 56 | version "1.4.0" 57 | resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.0.tgz#f05771ef64da724997f69ee1261b2417a49522d6" 58 | integrity sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg== 59 | dependencies: 60 | "@noble/hashes" "1.4.0" 61 | 62 | "@noble/hashes@1.4.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0": 63 | version "1.4.0" 64 | resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" 65 | integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== 66 | 67 | "@project-serum/anchor@^0.11.1": 68 | version "0.11.1" 69 | resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.11.1.tgz#155bff2c70652eafdcfd5559c81a83bb19cec9ff" 70 | integrity sha512-oIdm4vTJkUy6GmE6JgqDAuQPKI7XM4TPJkjtoIzp69RZe0iAD9JP2XHx7lV1jLdYXeYHqDXfBt3zcq7W91K6PA== 71 | dependencies: 72 | "@project-serum/borsh" "^0.2.2" 73 | "@solana/web3.js" "^1.17.0" 74 | base64-js "^1.5.1" 75 | bn.js "^5.1.2" 76 | bs58 "^4.0.1" 77 | buffer-layout "^1.2.0" 78 | camelcase "^5.3.1" 79 | crypto-hash "^1.3.0" 80 | eventemitter3 "^4.0.7" 81 | find "^0.3.0" 82 | js-sha256 "^0.9.0" 83 | pako "^2.0.3" 84 | snake-case "^3.0.4" 85 | toml "^3.0.0" 86 | 87 | "@project-serum/borsh@^0.2.2": 88 | version "0.2.5" 89 | resolved "https://registry.yarnpkg.com/@project-serum/borsh/-/borsh-0.2.5.tgz#6059287aa624ecebbfc0edd35e4c28ff987d8663" 90 | integrity sha512-UmeUkUoKdQ7rhx6Leve1SssMR/Ghv8qrEiyywyxSWg7ooV7StdpPBhciiy5eB3T0qU1BXvdRNC8TdrkxK7WC5Q== 91 | dependencies: 92 | bn.js "^5.1.2" 93 | buffer-layout "^1.2.0" 94 | 95 | "@project-serum/serum@^0.13.65": 96 | version "0.13.65" 97 | resolved "https://registry.yarnpkg.com/@project-serum/serum/-/serum-0.13.65.tgz#6d3cf07912f13985765237f053cca716fe84b0b0" 98 | integrity sha512-BHRqsTqPSfFB5p+MgI2pjvMBAQtO8ibTK2fYY96boIFkCI3TTwXDt2gUmspeChKO2pqHr5aKevmexzAcXxrSRA== 99 | dependencies: 100 | "@project-serum/anchor" "^0.11.1" 101 | "@solana/spl-token" "^0.1.6" 102 | "@solana/web3.js" "^1.21.0" 103 | bn.js "^5.1.2" 104 | buffer-layout "^1.2.0" 105 | 106 | "@raydium-io/raydium-sdk@^1.3.1-beta.48": 107 | version "1.3.1-beta.52" 108 | resolved "https://registry.yarnpkg.com/@raydium-io/raydium-sdk/-/raydium-sdk-1.3.1-beta.52.tgz#1e1d45d9834bc6d92cfdd7ab4d0d78703205191c" 109 | integrity sha512-NnCIfmFLT5QZLjeMhAwEofNuzZEPAU7q2O0P0o67O1fsGdVq5HJgLL8bI6UMKX2d2Ed4MEz7ip2bSng2tHp+5w== 110 | dependencies: 111 | "@solana/buffer-layout" "^4.0.1" 112 | "@solana/spl-token" "^0.3.9" 113 | axios "^1.6.2" 114 | big.js "^6.2.1" 115 | bn.js "^5.2.1" 116 | decimal.js "^10.4.3" 117 | decimal.js-light "^2.5.1" 118 | fecha "^4.2.3" 119 | lodash "^4.17.21" 120 | toformat "^2.0.0" 121 | 122 | "@solana/buffer-layout-utils@^0.2.0": 123 | version "0.2.0" 124 | resolved "https://registry.yarnpkg.com/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz#b45a6cab3293a2eb7597cceb474f229889d875ca" 125 | integrity sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g== 126 | dependencies: 127 | "@solana/buffer-layout" "^4.0.0" 128 | "@solana/web3.js" "^1.32.0" 129 | bigint-buffer "^1.1.5" 130 | bignumber.js "^9.0.1" 131 | 132 | "@solana/buffer-layout@^4.0.0", "@solana/buffer-layout@^4.0.1": 133 | version "4.0.1" 134 | resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" 135 | integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== 136 | dependencies: 137 | buffer "~6.0.3" 138 | 139 | "@solana/codecs-core@2.0.0-preview.2": 140 | version "2.0.0-preview.2" 141 | resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-2.0.0-preview.2.tgz#689784d032fbc1fedbde40bb25d76cdcecf6553b" 142 | integrity sha512-gLhCJXieSCrAU7acUJjbXl+IbGnqovvxQLlimztPoGgfLQ1wFYu+XJswrEVQqknZYK1pgxpxH3rZ+OKFs0ndQg== 143 | dependencies: 144 | "@solana/errors" "2.0.0-preview.2" 145 | 146 | "@solana/codecs-data-structures@2.0.0-preview.2": 147 | version "2.0.0-preview.2" 148 | resolved "https://registry.yarnpkg.com/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-preview.2.tgz#e82cb1b6d154fa636cd5c8953ff3f32959cc0370" 149 | integrity sha512-Xf5vIfromOZo94Q8HbR04TbgTwzigqrKII0GjYr21K7rb3nba4hUW2ir8kguY7HWFBcjHGlU5x3MevKBOLp3Zg== 150 | dependencies: 151 | "@solana/codecs-core" "2.0.0-preview.2" 152 | "@solana/codecs-numbers" "2.0.0-preview.2" 153 | "@solana/errors" "2.0.0-preview.2" 154 | 155 | "@solana/codecs-numbers@2.0.0-preview.2": 156 | version "2.0.0-preview.2" 157 | resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-2.0.0-preview.2.tgz#56995c27396cd8ee3bae8bd055363891b630bbd0" 158 | integrity sha512-aLZnDTf43z4qOnpTcDsUVy1Ci9im1Md8thWipSWbE+WM9ojZAx528oAql+Cv8M8N+6ALKwgVRhPZkto6E59ARw== 159 | dependencies: 160 | "@solana/codecs-core" "2.0.0-preview.2" 161 | "@solana/errors" "2.0.0-preview.2" 162 | 163 | "@solana/codecs-strings@2.0.0-preview.2": 164 | version "2.0.0-preview.2" 165 | resolved "https://registry.yarnpkg.com/@solana/codecs-strings/-/codecs-strings-2.0.0-preview.2.tgz#8bd01a4e48614d5289d72d743c3e81305d445c46" 166 | integrity sha512-EgBwY+lIaHHgMJIqVOGHfIfpdmmUDNoNO/GAUGeFPf+q0dF+DtwhJPEMShhzh64X2MeCZcmSO6Kinx0Bvmmz2g== 167 | dependencies: 168 | "@solana/codecs-core" "2.0.0-preview.2" 169 | "@solana/codecs-numbers" "2.0.0-preview.2" 170 | "@solana/errors" "2.0.0-preview.2" 171 | 172 | "@solana/codecs@2.0.0-preview.2": 173 | version "2.0.0-preview.2" 174 | resolved "https://registry.yarnpkg.com/@solana/codecs/-/codecs-2.0.0-preview.2.tgz#d6615fec98f423166fb89409f9a4ad5b74c10935" 175 | integrity sha512-4HHzCD5+pOSmSB71X6w9ptweV48Zj1Vqhe732+pcAQ2cMNnN0gMPMdDq7j3YwaZDZ7yrILVV/3+HTnfT77t2yA== 176 | dependencies: 177 | "@solana/codecs-core" "2.0.0-preview.2" 178 | "@solana/codecs-data-structures" "2.0.0-preview.2" 179 | "@solana/codecs-numbers" "2.0.0-preview.2" 180 | "@solana/codecs-strings" "2.0.0-preview.2" 181 | "@solana/options" "2.0.0-preview.2" 182 | 183 | "@solana/errors@2.0.0-preview.2": 184 | version "2.0.0-preview.2" 185 | resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-2.0.0-preview.2.tgz#e0ea8b008c5c02528d5855bc1903e5e9bbec322e" 186 | integrity sha512-H2DZ1l3iYF5Rp5pPbJpmmtCauWeQXRJapkDg8epQ8BJ7cA2Ut/QEtC3CMmw/iMTcuS6uemFNLcWvlOfoQhvQuA== 187 | dependencies: 188 | chalk "^5.3.0" 189 | commander "^12.0.0" 190 | 191 | "@solana/options@2.0.0-preview.2": 192 | version "2.0.0-preview.2" 193 | resolved "https://registry.yarnpkg.com/@solana/options/-/options-2.0.0-preview.2.tgz#13ff008bf43a5056ef9a091dc7bb3f39321e867e" 194 | integrity sha512-FAHqEeH0cVsUOTzjl5OfUBw2cyT8d5Oekx4xcn5hn+NyPAfQJgM3CEThzgRD6Q/4mM5pVUnND3oK/Mt1RzSE/w== 195 | dependencies: 196 | "@solana/codecs-core" "2.0.0-preview.2" 197 | "@solana/codecs-numbers" "2.0.0-preview.2" 198 | 199 | "@solana/spl-token-group@^0.0.4": 200 | version "0.0.4" 201 | resolved "https://registry.yarnpkg.com/@solana/spl-token-group/-/spl-token-group-0.0.4.tgz#4f45d9526c96a33b9a1929a264d0aa21c7e38a2d" 202 | integrity sha512-7+80nrEMdUKlK37V6kOe024+T7J4nNss0F8LQ9OOPYdWCCfJmsGUzVx2W3oeizZR4IHM6N4yC9v1Xqwc3BTPWw== 203 | dependencies: 204 | "@solana/codecs" "2.0.0-preview.2" 205 | "@solana/spl-type-length-value" "0.1.0" 206 | 207 | "@solana/spl-token-metadata@^0.1.2", "@solana/spl-token-metadata@^0.1.4": 208 | version "0.1.4" 209 | resolved "https://registry.yarnpkg.com/@solana/spl-token-metadata/-/spl-token-metadata-0.1.4.tgz#5cdc3b857a8c4a6877df24e24a8648c4132d22ba" 210 | integrity sha512-N3gZ8DlW6NWDV28+vCCDJoTqaCZiF/jDUnk3o8GRkAFzHObiR60Bs1gXHBa8zCPdvOwiG6Z3dg5pg7+RW6XNsQ== 211 | dependencies: 212 | "@solana/codecs" "2.0.0-preview.2" 213 | "@solana/spl-type-length-value" "0.1.0" 214 | 215 | "@solana/spl-token@^0.1.6": 216 | version "0.1.8" 217 | resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.1.8.tgz#f06e746341ef8d04165e21fc7f555492a2a0faa6" 218 | integrity sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ== 219 | dependencies: 220 | "@babel/runtime" "^7.10.5" 221 | "@solana/web3.js" "^1.21.0" 222 | bn.js "^5.1.0" 223 | buffer "6.0.3" 224 | buffer-layout "^1.2.0" 225 | dotenv "10.0.0" 226 | 227 | "@solana/spl-token@^0.3.9": 228 | version "0.3.11" 229 | resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.11.tgz#cdc10f9472b29b39c8983c92592cadd06627fb9a" 230 | integrity sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ== 231 | dependencies: 232 | "@solana/buffer-layout" "^4.0.0" 233 | "@solana/buffer-layout-utils" "^0.2.0" 234 | "@solana/spl-token-metadata" "^0.1.2" 235 | buffer "^6.0.3" 236 | 237 | "@solana/spl-token@^0.4.6": 238 | version "0.4.6" 239 | resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.4.6.tgz#eb44e5080ea7b6fc976abcb39457223211bd9076" 240 | integrity sha512-1nCnUqfHVtdguFciVWaY/RKcQz1IF4b31jnKgAmjU9QVN1q7dRUkTEWJZgTYIEtsULjVnC9jRqlhgGN39WbKKA== 241 | dependencies: 242 | "@solana/buffer-layout" "^4.0.0" 243 | "@solana/buffer-layout-utils" "^0.2.0" 244 | "@solana/spl-token-group" "^0.0.4" 245 | "@solana/spl-token-metadata" "^0.1.4" 246 | buffer "^6.0.3" 247 | 248 | "@solana/spl-type-length-value@0.1.0": 249 | version "0.1.0" 250 | resolved "https://registry.yarnpkg.com/@solana/spl-type-length-value/-/spl-type-length-value-0.1.0.tgz#b5930cf6c6d8f50c7ff2a70463728a4637a2f26b" 251 | integrity sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA== 252 | dependencies: 253 | buffer "^6.0.3" 254 | 255 | "@solana/web3.js@^1.17.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.90.0": 256 | version "1.92.3" 257 | resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.92.3.tgz#8880b446c0ec30fc552e1d501bd8db2780a1f70c" 258 | integrity sha512-NVBWvb9zdJIAx6X+caXaIICCEQfQaQ8ygykCjJW4u2z/sIKcvPj3ZIIllnx0MWMc3IxGq15ozGYDOQIMbwUcHw== 259 | dependencies: 260 | "@babel/runtime" "^7.24.6" 261 | "@noble/curves" "^1.4.0" 262 | "@noble/hashes" "^1.4.0" 263 | "@solana/buffer-layout" "^4.0.1" 264 | agentkeepalive "^4.5.0" 265 | bigint-buffer "^1.1.5" 266 | bn.js "^5.2.1" 267 | borsh "^0.7.0" 268 | bs58 "^4.0.1" 269 | buffer "6.0.3" 270 | fast-stable-stringify "^1.0.0" 271 | jayson "^4.1.0" 272 | node-fetch "^2.7.0" 273 | rpc-websockets "^8.0.1" 274 | superstruct "^1.0.4" 275 | 276 | "@solana/web3.js@^1.32.0": 277 | version "1.92.2" 278 | resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.92.2.tgz#49760e887b31e309543668e81e1fa60f53a3e34e" 279 | integrity sha512-dk26IHhtKyBszzsSzAuh6Lj2Z6guGlmdzkBjsOTvMmU/BiZTs5riNb+3eq56zXNLK3qvaMHAvVQPGwi9Po6qZQ== 280 | dependencies: 281 | "@babel/runtime" "^7.24.6" 282 | "@noble/curves" "^1.4.0" 283 | "@noble/hashes" "^1.4.0" 284 | "@solana/buffer-layout" "^4.0.1" 285 | agentkeepalive "^4.5.0" 286 | bigint-buffer "^1.1.5" 287 | bn.js "^5.2.1" 288 | borsh "^0.7.0" 289 | bs58 "^4.0.1" 290 | buffer "6.0.3" 291 | fast-stable-stringify "^1.0.0" 292 | jayson "^4.1.0" 293 | node-fetch "^2.7.0" 294 | rpc-websockets "^7.11.1" 295 | superstruct "^1.0.4" 296 | 297 | "@solana/web3.js@^1.68.0": 298 | version "1.92.1" 299 | resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.92.1.tgz#0c0fef31bbb20590ea5dfb63a578e5dfc4a111f1" 300 | integrity sha512-72hytgOHfJLbvKT0+HRuFUhxxZpCnlo4zFDt37UHPel1DJbgqGOWo3xUf3VEPRWBvSRv0EH15g8MGatdj1PO9g== 301 | dependencies: 302 | "@babel/runtime" "^7.24.6" 303 | "@noble/curves" "^1.4.0" 304 | "@noble/hashes" "^1.4.0" 305 | "@solana/buffer-layout" "^4.0.1" 306 | agentkeepalive "^4.5.0" 307 | bigint-buffer "^1.1.5" 308 | bn.js "^5.2.1" 309 | borsh "^0.7.0" 310 | bs58 "^4.0.1" 311 | buffer "6.0.3" 312 | fast-stable-stringify "^1.0.0" 313 | jayson "^4.1.0" 314 | node-fetch "^2.7.0" 315 | rpc-websockets "^7.11.1" 316 | superstruct "^1.0.4" 317 | 318 | "@types/bn.js@^5.1.0": 319 | version "5.1.5" 320 | resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" 321 | integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== 322 | dependencies: 323 | "@types/node" "*" 324 | 325 | "@types/chai@^4.3.0": 326 | version "4.3.16" 327 | resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.16.tgz#b1572967f0b8b60bf3f87fe1d854a5604ea70c82" 328 | integrity sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ== 329 | 330 | "@types/connect@^3.4.33": 331 | version "3.4.38" 332 | resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" 333 | integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== 334 | dependencies: 335 | "@types/node" "*" 336 | 337 | "@types/gaussian@^1.2.0": 338 | version "1.2.2" 339 | resolved "https://registry.yarnpkg.com/@types/gaussian/-/gaussian-1.2.2.tgz#99b1a7fda58acb12b0941653b4f4c22e86b9df8b" 340 | integrity sha512-FLlJb9oGcoq0xVaAmn5ytZWeEO4M7nfudewzqL6FxUUYLR5FB+hEzSYAsuhX7H7M6Mw/Z0rLbIVbQkMqHlRS7g== 341 | 342 | "@types/json5@^0.0.29": 343 | version "0.0.29" 344 | resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" 345 | integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== 346 | 347 | "@types/mocha@^9.0.0": 348 | version "9.1.1" 349 | resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" 350 | integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== 351 | 352 | "@types/node@*": 353 | version "20.14.2" 354 | resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.2.tgz#a5f4d2bcb4b6a87bffcaa717718c5a0f208f4a18" 355 | integrity sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q== 356 | dependencies: 357 | undici-types "~5.26.4" 358 | 359 | "@types/node@^12.12.54": 360 | version "12.20.55" 361 | resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" 362 | integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== 363 | 364 | "@types/ws@^7.4.4": 365 | version "7.4.7" 366 | resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" 367 | integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== 368 | dependencies: 369 | "@types/node" "*" 370 | 371 | "@ungap/promise-all-settled@1.1.2": 372 | version "1.1.2" 373 | resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" 374 | integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== 375 | 376 | JSONStream@^1.3.5: 377 | version "1.3.5" 378 | resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" 379 | integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== 380 | dependencies: 381 | jsonparse "^1.2.0" 382 | through ">=2.2.7 <3" 383 | 384 | agentkeepalive@^4.5.0: 385 | version "4.5.0" 386 | resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" 387 | integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== 388 | dependencies: 389 | humanize-ms "^1.2.1" 390 | 391 | "anchor28@npm:@coral-xyz/anchor@^0.28.0": 392 | version "0.28.0" 393 | resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.28.0.tgz#8345c3c9186a91f095f704d7b90cd256f7e8b2dc" 394 | integrity sha512-kQ02Hv2ZqxtWP30WN1d4xxT4QqlOXYDxmEd3k/bbneqhV3X5QMO4LAtoUFs7otxyivOgoqam5Il5qx81FuI4vw== 395 | dependencies: 396 | "@coral-xyz/borsh" "^0.28.0" 397 | "@solana/web3.js" "^1.68.0" 398 | base64-js "^1.5.1" 399 | bn.js "^5.1.2" 400 | bs58 "^4.0.1" 401 | buffer-layout "^1.2.2" 402 | camelcase "^6.3.0" 403 | cross-fetch "^3.1.5" 404 | crypto-hash "^1.3.0" 405 | eventemitter3 "^4.0.7" 406 | js-sha256 "^0.9.0" 407 | pako "^2.0.3" 408 | snake-case "^3.0.4" 409 | superstruct "^0.15.4" 410 | toml "^3.0.0" 411 | 412 | ansi-colors@4.1.1: 413 | version "4.1.1" 414 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 415 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 416 | 417 | ansi-regex@^5.0.1: 418 | version "5.0.1" 419 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 420 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 421 | 422 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 423 | version "4.3.0" 424 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 425 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 426 | dependencies: 427 | color-convert "^2.0.1" 428 | 429 | anymatch@~3.1.2: 430 | version "3.1.3" 431 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 432 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 433 | dependencies: 434 | normalize-path "^3.0.0" 435 | picomatch "^2.0.4" 436 | 437 | argparse@^2.0.1: 438 | version "2.0.1" 439 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 440 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 441 | 442 | arrify@^1.0.0: 443 | version "1.0.1" 444 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" 445 | integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== 446 | 447 | assertion-error@^1.1.0: 448 | version "1.1.0" 449 | resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" 450 | integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== 451 | 452 | asynckit@^0.4.0: 453 | version "0.4.0" 454 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 455 | integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== 456 | 457 | axios@^1.6.2: 458 | version "1.7.2" 459 | resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" 460 | integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== 461 | dependencies: 462 | follow-redirects "^1.15.6" 463 | form-data "^4.0.0" 464 | proxy-from-env "^1.1.0" 465 | 466 | balanced-match@^1.0.0: 467 | version "1.0.2" 468 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 469 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 470 | 471 | base-x@^3.0.2: 472 | version "3.0.9" 473 | resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" 474 | integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== 475 | dependencies: 476 | safe-buffer "^5.0.1" 477 | 478 | base64-js@^1.3.1, base64-js@^1.5.1: 479 | version "1.5.1" 480 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 481 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 482 | 483 | big.js@^6.2.1: 484 | version "6.2.1" 485 | resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.2.1.tgz#7205ce763efb17c2e41f26f121c420c6a7c2744f" 486 | integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== 487 | 488 | bigint-buffer@^1.1.5: 489 | version "1.1.5" 490 | resolved "https://registry.yarnpkg.com/bigint-buffer/-/bigint-buffer-1.1.5.tgz#d038f31c8e4534c1f8d0015209bf34b4fa6dd442" 491 | integrity sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA== 492 | dependencies: 493 | bindings "^1.3.0" 494 | 495 | bignumber.js@^9.0.1: 496 | version "9.1.2" 497 | resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" 498 | integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== 499 | 500 | binary-extensions@^2.0.0: 501 | version "2.3.0" 502 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" 503 | integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== 504 | 505 | bindings@^1.3.0: 506 | version "1.5.0" 507 | resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" 508 | integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== 509 | dependencies: 510 | file-uri-to-path "1.0.0" 511 | 512 | bn.js@^5.1.0, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: 513 | version "5.2.1" 514 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" 515 | integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== 516 | 517 | borsh@^0.7.0: 518 | version "0.7.0" 519 | resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" 520 | integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== 521 | dependencies: 522 | bn.js "^5.2.0" 523 | bs58 "^4.0.0" 524 | text-encoding-utf-8 "^1.0.2" 525 | 526 | brace-expansion@^1.1.7: 527 | version "1.1.11" 528 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 529 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 530 | dependencies: 531 | balanced-match "^1.0.0" 532 | concat-map "0.0.1" 533 | 534 | braces@~3.0.2: 535 | version "3.0.3" 536 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" 537 | integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 538 | dependencies: 539 | fill-range "^7.1.1" 540 | 541 | browser-stdout@1.3.1: 542 | version "1.3.1" 543 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 544 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 545 | 546 | bs58@^4.0.0, bs58@^4.0.1: 547 | version "4.0.1" 548 | resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" 549 | integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== 550 | dependencies: 551 | base-x "^3.0.2" 552 | 553 | buffer-from@^1.0.0, buffer-from@^1.1.0: 554 | version "1.1.2" 555 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" 556 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 557 | 558 | buffer-layout@^1.2.0, buffer-layout@^1.2.2: 559 | version "1.2.2" 560 | resolved "https://registry.yarnpkg.com/buffer-layout/-/buffer-layout-1.2.2.tgz#b9814e7c7235783085f9ca4966a0cfff112259d5" 561 | integrity sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA== 562 | 563 | buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: 564 | version "6.0.3" 565 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" 566 | integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== 567 | dependencies: 568 | base64-js "^1.3.1" 569 | ieee754 "^1.2.1" 570 | 571 | bufferutil@^4.0.1: 572 | version "4.0.8" 573 | resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.8.tgz#1de6a71092d65d7766c4d8a522b261a6e787e8ea" 574 | integrity sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw== 575 | dependencies: 576 | node-gyp-build "^4.3.0" 577 | 578 | camelcase@^5.3.1: 579 | version "5.3.1" 580 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" 581 | integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== 582 | 583 | camelcase@^6.0.0, camelcase@^6.3.0: 584 | version "6.3.0" 585 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" 586 | integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== 587 | 588 | chai@^4.3.4: 589 | version "4.4.1" 590 | resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" 591 | integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== 592 | dependencies: 593 | assertion-error "^1.1.0" 594 | check-error "^1.0.3" 595 | deep-eql "^4.1.3" 596 | get-func-name "^2.0.2" 597 | loupe "^2.3.6" 598 | pathval "^1.1.1" 599 | type-detect "^4.0.8" 600 | 601 | chalk@^4.1.0: 602 | version "4.1.2" 603 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 604 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 605 | dependencies: 606 | ansi-styles "^4.1.0" 607 | supports-color "^7.1.0" 608 | 609 | chalk@^5.3.0: 610 | version "5.3.0" 611 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" 612 | integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== 613 | 614 | check-error@^1.0.3: 615 | version "1.0.3" 616 | resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" 617 | integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== 618 | dependencies: 619 | get-func-name "^2.0.2" 620 | 621 | chokidar@3.5.3: 622 | version "3.5.3" 623 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 624 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 625 | dependencies: 626 | anymatch "~3.1.2" 627 | braces "~3.0.2" 628 | glob-parent "~5.1.2" 629 | is-binary-path "~2.1.0" 630 | is-glob "~4.0.1" 631 | normalize-path "~3.0.0" 632 | readdirp "~3.6.0" 633 | optionalDependencies: 634 | fsevents "~2.3.2" 635 | 636 | cliui@^7.0.2: 637 | version "7.0.4" 638 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 639 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 640 | dependencies: 641 | string-width "^4.2.0" 642 | strip-ansi "^6.0.0" 643 | wrap-ansi "^7.0.0" 644 | 645 | color-convert@^2.0.1: 646 | version "2.0.1" 647 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 648 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 649 | dependencies: 650 | color-name "~1.1.4" 651 | 652 | color-name@~1.1.4: 653 | version "1.1.4" 654 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 655 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 656 | 657 | combined-stream@^1.0.8: 658 | version "1.0.8" 659 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 660 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 661 | dependencies: 662 | delayed-stream "~1.0.0" 663 | 664 | commander@^12.0.0: 665 | version "12.1.0" 666 | resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" 667 | integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== 668 | 669 | commander@^2.20.3: 670 | version "2.20.3" 671 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 672 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 673 | 674 | concat-map@0.0.1: 675 | version "0.0.1" 676 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 677 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 678 | 679 | cross-fetch@^3.1.5: 680 | version "3.1.8" 681 | resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" 682 | integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== 683 | dependencies: 684 | node-fetch "^2.6.12" 685 | 686 | crypto-hash@^1.3.0: 687 | version "1.3.0" 688 | resolved "https://registry.yarnpkg.com/crypto-hash/-/crypto-hash-1.3.0.tgz#b402cb08f4529e9f4f09346c3e275942f845e247" 689 | integrity sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg== 690 | 691 | debug@4.3.3: 692 | version "4.3.3" 693 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" 694 | integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== 695 | dependencies: 696 | ms "2.1.2" 697 | 698 | decamelize@^4.0.0: 699 | version "4.0.0" 700 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 701 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 702 | 703 | decimal.js-light@^2.5.1: 704 | version "2.5.1" 705 | resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" 706 | integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== 707 | 708 | decimal.js@^10.4.3: 709 | version "10.4.3" 710 | resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" 711 | integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== 712 | 713 | deep-eql@^4.1.3: 714 | version "4.1.3" 715 | resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" 716 | integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== 717 | dependencies: 718 | type-detect "^4.0.0" 719 | 720 | delay@^5.0.0: 721 | version "5.0.0" 722 | resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" 723 | integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== 724 | 725 | delayed-stream@~1.0.0: 726 | version "1.0.0" 727 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 728 | integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== 729 | 730 | diff@5.0.0: 731 | version "5.0.0" 732 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" 733 | integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== 734 | 735 | diff@^3.1.0: 736 | version "3.5.0" 737 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" 738 | integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== 739 | 740 | dot-case@^3.0.4: 741 | version "3.0.4" 742 | resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" 743 | integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== 744 | dependencies: 745 | no-case "^3.0.4" 746 | tslib "^2.0.3" 747 | 748 | dotenv@10.0.0: 749 | version "10.0.0" 750 | resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" 751 | integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== 752 | 753 | dotenv@^16.4.5: 754 | version "16.4.5" 755 | resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" 756 | integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== 757 | 758 | emoji-regex@^8.0.0: 759 | version "8.0.0" 760 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 761 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 762 | 763 | es6-promise@^4.0.3: 764 | version "4.2.8" 765 | resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" 766 | integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== 767 | 768 | es6-promisify@^5.0.0: 769 | version "5.0.0" 770 | resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" 771 | integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== 772 | dependencies: 773 | es6-promise "^4.0.3" 774 | 775 | escalade@^3.1.1: 776 | version "3.1.2" 777 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" 778 | integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== 779 | 780 | escape-string-regexp@4.0.0: 781 | version "4.0.0" 782 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 783 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 784 | 785 | eventemitter3@^4.0.7: 786 | version "4.0.7" 787 | resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" 788 | integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== 789 | 790 | eyes@^0.1.8: 791 | version "0.1.8" 792 | resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" 793 | integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== 794 | 795 | fast-stable-stringify@^1.0.0: 796 | version "1.0.0" 797 | resolved "https://registry.yarnpkg.com/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz#5c5543462b22aeeefd36d05b34e51c78cb86d313" 798 | integrity sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag== 799 | 800 | fecha@^4.2.3: 801 | version "4.2.3" 802 | resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" 803 | integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== 804 | 805 | file-uri-to-path@1.0.0: 806 | version "1.0.0" 807 | resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" 808 | integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== 809 | 810 | fill-range@^7.1.1: 811 | version "7.1.1" 812 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" 813 | integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 814 | dependencies: 815 | to-regex-range "^5.0.1" 816 | 817 | find-up@5.0.0: 818 | version "5.0.0" 819 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 820 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 821 | dependencies: 822 | locate-path "^6.0.0" 823 | path-exists "^4.0.0" 824 | 825 | find@^0.3.0: 826 | version "0.3.0" 827 | resolved "https://registry.yarnpkg.com/find/-/find-0.3.0.tgz#4082e8fc8d8320f1a382b5e4f521b9bc50775cb8" 828 | integrity sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw== 829 | dependencies: 830 | traverse-chain "~0.1.0" 831 | 832 | flat@^5.0.2: 833 | version "5.0.2" 834 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 835 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 836 | 837 | follow-redirects@^1.15.6: 838 | version "1.15.6" 839 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" 840 | integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== 841 | 842 | form-data@^4.0.0: 843 | version "4.0.0" 844 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" 845 | integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== 846 | dependencies: 847 | asynckit "^0.4.0" 848 | combined-stream "^1.0.8" 849 | mime-types "^2.1.12" 850 | 851 | fs.realpath@^1.0.0: 852 | version "1.0.0" 853 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 854 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 855 | 856 | fsevents@~2.3.2: 857 | version "2.3.3" 858 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 859 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 860 | 861 | gaussian@^1.3.0: 862 | version "1.3.0" 863 | resolved "https://registry.yarnpkg.com/gaussian/-/gaussian-1.3.0.tgz#c550b01b59ca5ed2e54ca89b6584a359f167e5d5" 864 | integrity sha512-rYQ0ESfB+z0t7G95nHH80Zh7Pgg9A0FUYoZqV0yPec5WJZWKIHV2MPYpiJNy8oZAeVqyKwC10WXKSCnUQ5iDVg== 865 | 866 | get-caller-file@^2.0.5: 867 | version "2.0.5" 868 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 869 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 870 | 871 | get-func-name@^2.0.1, get-func-name@^2.0.2: 872 | version "2.0.2" 873 | resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" 874 | integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== 875 | 876 | glob-parent@~5.1.2: 877 | version "5.1.2" 878 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 879 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 880 | dependencies: 881 | is-glob "^4.0.1" 882 | 883 | glob@7.2.0: 884 | version "7.2.0" 885 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" 886 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== 887 | dependencies: 888 | fs.realpath "^1.0.0" 889 | inflight "^1.0.4" 890 | inherits "2" 891 | minimatch "^3.0.4" 892 | once "^1.3.0" 893 | path-is-absolute "^1.0.0" 894 | 895 | growl@1.10.5: 896 | version "1.10.5" 897 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" 898 | integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== 899 | 900 | has-flag@^4.0.0: 901 | version "4.0.0" 902 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 903 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 904 | 905 | he@1.2.0: 906 | version "1.2.0" 907 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 908 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 909 | 910 | humanize-ms@^1.2.1: 911 | version "1.2.1" 912 | resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" 913 | integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== 914 | dependencies: 915 | ms "^2.0.0" 916 | 917 | ieee754@^1.2.1: 918 | version "1.2.1" 919 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 920 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 921 | 922 | inflight@^1.0.4: 923 | version "1.0.6" 924 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 925 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 926 | dependencies: 927 | once "^1.3.0" 928 | wrappy "1" 929 | 930 | inherits@2: 931 | version "2.0.4" 932 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 933 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 934 | 935 | is-binary-path@~2.1.0: 936 | version "2.1.0" 937 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 938 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 939 | dependencies: 940 | binary-extensions "^2.0.0" 941 | 942 | is-extglob@^2.1.1: 943 | version "2.1.1" 944 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 945 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 946 | 947 | is-fullwidth-code-point@^3.0.0: 948 | version "3.0.0" 949 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 950 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 951 | 952 | is-glob@^4.0.1, is-glob@~4.0.1: 953 | version "4.0.3" 954 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 955 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 956 | dependencies: 957 | is-extglob "^2.1.1" 958 | 959 | is-number@^7.0.0: 960 | version "7.0.0" 961 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 962 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 963 | 964 | is-plain-obj@^2.1.0: 965 | version "2.1.0" 966 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 967 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 968 | 969 | is-unicode-supported@^0.1.0: 970 | version "0.1.0" 971 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 972 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 973 | 974 | isexe@^2.0.0: 975 | version "2.0.0" 976 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 977 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 978 | 979 | isomorphic-ws@^4.0.1: 980 | version "4.0.1" 981 | resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" 982 | integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== 983 | 984 | jayson@^4.1.0: 985 | version "4.1.0" 986 | resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.0.tgz#60dc946a85197317f2b1439d672a8b0a99cea2f9" 987 | integrity sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A== 988 | dependencies: 989 | "@types/connect" "^3.4.33" 990 | "@types/node" "^12.12.54" 991 | "@types/ws" "^7.4.4" 992 | JSONStream "^1.3.5" 993 | commander "^2.20.3" 994 | delay "^5.0.0" 995 | es6-promisify "^5.0.0" 996 | eyes "^0.1.8" 997 | isomorphic-ws "^4.0.1" 998 | json-stringify-safe "^5.0.1" 999 | uuid "^8.3.2" 1000 | ws "^7.4.5" 1001 | 1002 | js-sha256@^0.9.0: 1003 | version "0.9.0" 1004 | resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" 1005 | integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== 1006 | 1007 | js-yaml@4.1.0: 1008 | version "4.1.0" 1009 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 1010 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 1011 | dependencies: 1012 | argparse "^2.0.1" 1013 | 1014 | json-stringify-safe@^5.0.1: 1015 | version "5.0.1" 1016 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 1017 | integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== 1018 | 1019 | json5@^1.0.2: 1020 | version "1.0.2" 1021 | resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" 1022 | integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== 1023 | dependencies: 1024 | minimist "^1.2.0" 1025 | 1026 | jsonparse@^1.2.0: 1027 | version "1.3.1" 1028 | resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" 1029 | integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== 1030 | 1031 | locate-path@^6.0.0: 1032 | version "6.0.0" 1033 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 1034 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 1035 | dependencies: 1036 | p-locate "^5.0.0" 1037 | 1038 | lodash@^4.17.21: 1039 | version "4.17.21" 1040 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 1041 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 1042 | 1043 | log-symbols@4.1.0: 1044 | version "4.1.0" 1045 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 1046 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 1047 | dependencies: 1048 | chalk "^4.1.0" 1049 | is-unicode-supported "^0.1.0" 1050 | 1051 | loupe@^2.3.6: 1052 | version "2.3.7" 1053 | resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" 1054 | integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== 1055 | dependencies: 1056 | get-func-name "^2.0.1" 1057 | 1058 | lower-case@^2.0.2: 1059 | version "2.0.2" 1060 | resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" 1061 | integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== 1062 | dependencies: 1063 | tslib "^2.0.3" 1064 | 1065 | make-error@^1.1.1: 1066 | version "1.3.6" 1067 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" 1068 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 1069 | 1070 | mime-db@1.52.0: 1071 | version "1.52.0" 1072 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 1073 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 1074 | 1075 | mime-types@^2.1.12: 1076 | version "2.1.35" 1077 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 1078 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 1079 | dependencies: 1080 | mime-db "1.52.0" 1081 | 1082 | minimatch@4.2.1: 1083 | version "4.2.1" 1084 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" 1085 | integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== 1086 | dependencies: 1087 | brace-expansion "^1.1.7" 1088 | 1089 | minimatch@^3.0.4: 1090 | version "3.1.2" 1091 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 1092 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 1093 | dependencies: 1094 | brace-expansion "^1.1.7" 1095 | 1096 | minimist@^1.2.0, minimist@^1.2.6: 1097 | version "1.2.8" 1098 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" 1099 | integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 1100 | 1101 | mkdirp@^0.5.1: 1102 | version "0.5.6" 1103 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" 1104 | integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== 1105 | dependencies: 1106 | minimist "^1.2.6" 1107 | 1108 | mocha@^9.0.3: 1109 | version "9.2.2" 1110 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" 1111 | integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== 1112 | dependencies: 1113 | "@ungap/promise-all-settled" "1.1.2" 1114 | ansi-colors "4.1.1" 1115 | browser-stdout "1.3.1" 1116 | chokidar "3.5.3" 1117 | debug "4.3.3" 1118 | diff "5.0.0" 1119 | escape-string-regexp "4.0.0" 1120 | find-up "5.0.0" 1121 | glob "7.2.0" 1122 | growl "1.10.5" 1123 | he "1.2.0" 1124 | js-yaml "4.1.0" 1125 | log-symbols "4.1.0" 1126 | minimatch "4.2.1" 1127 | ms "2.1.3" 1128 | nanoid "3.3.1" 1129 | serialize-javascript "6.0.0" 1130 | strip-json-comments "3.1.1" 1131 | supports-color "8.1.1" 1132 | which "2.0.2" 1133 | workerpool "6.2.0" 1134 | yargs "16.2.0" 1135 | yargs-parser "20.2.4" 1136 | yargs-unparser "2.0.0" 1137 | 1138 | ms@2.1.2: 1139 | version "2.1.2" 1140 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 1141 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1142 | 1143 | ms@2.1.3, ms@^2.0.0: 1144 | version "2.1.3" 1145 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 1146 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 1147 | 1148 | nanoid@3.3.1: 1149 | version "3.3.1" 1150 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" 1151 | integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== 1152 | 1153 | no-case@^3.0.4: 1154 | version "3.0.4" 1155 | resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" 1156 | integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== 1157 | dependencies: 1158 | lower-case "^2.0.2" 1159 | tslib "^2.0.3" 1160 | 1161 | node-fetch@^2.6.12, node-fetch@^2.7.0: 1162 | version "2.7.0" 1163 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" 1164 | integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== 1165 | dependencies: 1166 | whatwg-url "^5.0.0" 1167 | 1168 | node-gyp-build@^4.3.0: 1169 | version "4.8.1" 1170 | resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.1.tgz#976d3ad905e71b76086f4f0b0d3637fe79b6cda5" 1171 | integrity sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw== 1172 | 1173 | normalize-path@^3.0.0, normalize-path@~3.0.0: 1174 | version "3.0.0" 1175 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 1176 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 1177 | 1178 | once@^1.3.0: 1179 | version "1.4.0" 1180 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1181 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 1182 | dependencies: 1183 | wrappy "1" 1184 | 1185 | p-limit@^3.0.2: 1186 | version "3.1.0" 1187 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 1188 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 1189 | dependencies: 1190 | yocto-queue "^0.1.0" 1191 | 1192 | p-locate@^5.0.0: 1193 | version "5.0.0" 1194 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 1195 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1196 | dependencies: 1197 | p-limit "^3.0.2" 1198 | 1199 | pako@^2.0.3: 1200 | version "2.1.0" 1201 | resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" 1202 | integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== 1203 | 1204 | path-exists@^4.0.0: 1205 | version "4.0.0" 1206 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1207 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1208 | 1209 | path-is-absolute@^1.0.0: 1210 | version "1.0.1" 1211 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1212 | integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 1213 | 1214 | pathval@^1.1.1: 1215 | version "1.1.1" 1216 | resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" 1217 | integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== 1218 | 1219 | picomatch@^2.0.4, picomatch@^2.2.1: 1220 | version "2.3.1" 1221 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 1222 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1223 | 1224 | prettier@^2.6.2: 1225 | version "2.8.8" 1226 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" 1227 | integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== 1228 | 1229 | proxy-from-env@^1.1.0: 1230 | version "1.1.0" 1231 | resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" 1232 | integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== 1233 | 1234 | randombytes@^2.1.0: 1235 | version "2.1.0" 1236 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 1237 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 1238 | dependencies: 1239 | safe-buffer "^5.1.0" 1240 | 1241 | readdirp@~3.6.0: 1242 | version "3.6.0" 1243 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 1244 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 1245 | dependencies: 1246 | picomatch "^2.2.1" 1247 | 1248 | regenerator-runtime@^0.14.0: 1249 | version "0.14.1" 1250 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" 1251 | integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== 1252 | 1253 | require-directory@^2.1.1: 1254 | version "2.1.1" 1255 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1256 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 1257 | 1258 | rpc-websockets@^7.11.1: 1259 | version "7.11.1" 1260 | resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.11.1.tgz#02d29aa6e561006b4a4c1e4769763948db8f4a62" 1261 | integrity sha512-ePm9GVlk1D1p1B35iU1AiAr9lMKUpSqU9wjYoUb9YaoabfLAcQ7DG6IfQvyam2nDJ0FOSB00AgEA4pGm/wSD5A== 1262 | dependencies: 1263 | eventemitter3 "^4.0.7" 1264 | uuid "^8.3.2" 1265 | ws "^8.5.0" 1266 | optionalDependencies: 1267 | bufferutil "^4.0.1" 1268 | utf-8-validate "^5.0.2" 1269 | 1270 | rpc-websockets@^8.0.1: 1271 | version "8.0.1" 1272 | resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-8.0.1.tgz#fa76db08badc0b2f5cd66b5496debd2c404c94b1" 1273 | integrity sha512-PptrPRK40uQvifq5sCcObmqInVcZXhy+RRrirzdE5KUPvDI47y1wPvfckD2QzqngOU9xaPW/dT+G+b+wj6M1MQ== 1274 | dependencies: 1275 | eventemitter3 "^4.0.7" 1276 | uuid "^8.3.2" 1277 | ws "^8.5.0" 1278 | optionalDependencies: 1279 | bufferutil "^4.0.1" 1280 | utf-8-validate "^5.0.2" 1281 | 1282 | safe-buffer@^5.0.1, safe-buffer@^5.1.0: 1283 | version "5.2.1" 1284 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1285 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1286 | 1287 | serialize-javascript@6.0.0: 1288 | version "6.0.0" 1289 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" 1290 | integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== 1291 | dependencies: 1292 | randombytes "^2.1.0" 1293 | 1294 | snake-case@^3.0.4: 1295 | version "3.0.4" 1296 | resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" 1297 | integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== 1298 | dependencies: 1299 | dot-case "^3.0.4" 1300 | tslib "^2.0.3" 1301 | 1302 | source-map-support@^0.5.6: 1303 | version "0.5.21" 1304 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" 1305 | integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== 1306 | dependencies: 1307 | buffer-from "^1.0.0" 1308 | source-map "^0.6.0" 1309 | 1310 | source-map@^0.6.0: 1311 | version "0.6.1" 1312 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1313 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1314 | 1315 | string-width@^4.1.0, string-width@^4.2.0: 1316 | version "4.2.3" 1317 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 1318 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 1319 | dependencies: 1320 | emoji-regex "^8.0.0" 1321 | is-fullwidth-code-point "^3.0.0" 1322 | strip-ansi "^6.0.1" 1323 | 1324 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 1325 | version "6.0.1" 1326 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1327 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1328 | dependencies: 1329 | ansi-regex "^5.0.1" 1330 | 1331 | strip-bom@^3.0.0: 1332 | version "3.0.0" 1333 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" 1334 | integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== 1335 | 1336 | strip-json-comments@3.1.1: 1337 | version "3.1.1" 1338 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1339 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1340 | 1341 | superstruct@^0.15.4: 1342 | version "0.15.5" 1343 | resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.15.5.tgz#0f0a8d3ce31313f0d84c6096cd4fa1bfdedc9dab" 1344 | integrity sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ== 1345 | 1346 | superstruct@^1.0.4: 1347 | version "1.0.4" 1348 | resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" 1349 | integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== 1350 | 1351 | supports-color@8.1.1: 1352 | version "8.1.1" 1353 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 1354 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 1355 | dependencies: 1356 | has-flag "^4.0.0" 1357 | 1358 | supports-color@^7.1.0: 1359 | version "7.2.0" 1360 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1361 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1362 | dependencies: 1363 | has-flag "^4.0.0" 1364 | 1365 | text-encoding-utf-8@^1.0.2: 1366 | version "1.0.2" 1367 | resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" 1368 | integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== 1369 | 1370 | "through@>=2.2.7 <3": 1371 | version "2.3.8" 1372 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1373 | integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== 1374 | 1375 | to-regex-range@^5.0.1: 1376 | version "5.0.1" 1377 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1378 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1379 | dependencies: 1380 | is-number "^7.0.0" 1381 | 1382 | toformat@^2.0.0: 1383 | version "2.0.0" 1384 | resolved "https://registry.yarnpkg.com/toformat/-/toformat-2.0.0.tgz#7a043fd2dfbe9021a4e36e508835ba32056739d8" 1385 | integrity sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ== 1386 | 1387 | toml@^3.0.0: 1388 | version "3.0.0" 1389 | resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" 1390 | integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== 1391 | 1392 | tr46@~0.0.3: 1393 | version "0.0.3" 1394 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 1395 | integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 1396 | 1397 | traverse-chain@~0.1.0: 1398 | version "0.1.0" 1399 | resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" 1400 | integrity sha512-up6Yvai4PYKhpNp5PkYtx50m3KbwQrqDwbuZP/ItyL64YEWHAvH6Md83LFLV/GRSk/BoUVwwgUzX6SOQSbsfAg== 1401 | 1402 | ts-mocha@^10.0.0: 1403 | version "10.0.0" 1404 | resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9" 1405 | integrity sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw== 1406 | dependencies: 1407 | ts-node "7.0.1" 1408 | optionalDependencies: 1409 | tsconfig-paths "^3.5.0" 1410 | 1411 | ts-node@7.0.1: 1412 | version "7.0.1" 1413 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" 1414 | integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== 1415 | dependencies: 1416 | arrify "^1.0.0" 1417 | buffer-from "^1.1.0" 1418 | diff "^3.1.0" 1419 | make-error "^1.1.1" 1420 | minimist "^1.2.0" 1421 | mkdirp "^0.5.1" 1422 | source-map-support "^0.5.6" 1423 | yn "^2.0.0" 1424 | 1425 | tsconfig-paths@^3.5.0: 1426 | version "3.15.0" 1427 | resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" 1428 | integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== 1429 | dependencies: 1430 | "@types/json5" "^0.0.29" 1431 | json5 "^1.0.2" 1432 | minimist "^1.2.6" 1433 | strip-bom "^3.0.0" 1434 | 1435 | tslib@^2.0.3: 1436 | version "2.6.3" 1437 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" 1438 | integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== 1439 | 1440 | type-detect@^4.0.0, type-detect@^4.0.8: 1441 | version "4.0.8" 1442 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" 1443 | integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== 1444 | 1445 | typescript@^5.0.4: 1446 | version "5.4.5" 1447 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" 1448 | integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== 1449 | 1450 | undici-types@~5.26.4: 1451 | version "5.26.5" 1452 | resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" 1453 | integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== 1454 | 1455 | utf-8-validate@^5.0.2: 1456 | version "5.0.10" 1457 | resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" 1458 | integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== 1459 | dependencies: 1460 | node-gyp-build "^4.3.0" 1461 | 1462 | uuid@^8.3.2: 1463 | version "8.3.2" 1464 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" 1465 | integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== 1466 | 1467 | webidl-conversions@^3.0.0: 1468 | version "3.0.1" 1469 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 1470 | integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 1471 | 1472 | whatwg-url@^5.0.0: 1473 | version "5.0.0" 1474 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 1475 | integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 1476 | dependencies: 1477 | tr46 "~0.0.3" 1478 | webidl-conversions "^3.0.0" 1479 | 1480 | which@2.0.2: 1481 | version "2.0.2" 1482 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1483 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1484 | dependencies: 1485 | isexe "^2.0.0" 1486 | 1487 | workerpool@6.2.0: 1488 | version "6.2.0" 1489 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" 1490 | integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== 1491 | 1492 | wrap-ansi@^7.0.0: 1493 | version "7.0.0" 1494 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1495 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1496 | dependencies: 1497 | ansi-styles "^4.0.0" 1498 | string-width "^4.1.0" 1499 | strip-ansi "^6.0.0" 1500 | 1501 | wrappy@1: 1502 | version "1.0.2" 1503 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1504 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 1505 | 1506 | ws@^7.4.5: 1507 | version "7.5.9" 1508 | resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" 1509 | integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== 1510 | 1511 | ws@^8.5.0: 1512 | version "8.17.0" 1513 | resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea" 1514 | integrity sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow== 1515 | 1516 | y18n@^5.0.5: 1517 | version "5.0.8" 1518 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 1519 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 1520 | 1521 | yargs-parser@20.2.4: 1522 | version "20.2.4" 1523 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" 1524 | integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== 1525 | 1526 | yargs-parser@^20.2.2: 1527 | version "20.2.9" 1528 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" 1529 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 1530 | 1531 | yargs-unparser@2.0.0: 1532 | version "2.0.0" 1533 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 1534 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 1535 | dependencies: 1536 | camelcase "^6.0.0" 1537 | decamelize "^4.0.0" 1538 | flat "^5.0.2" 1539 | is-plain-obj "^2.1.0" 1540 | 1541 | yargs@16.2.0: 1542 | version "16.2.0" 1543 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 1544 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 1545 | dependencies: 1546 | cliui "^7.0.2" 1547 | escalade "^3.1.1" 1548 | get-caller-file "^2.0.5" 1549 | require-directory "^2.1.1" 1550 | string-width "^4.2.0" 1551 | y18n "^5.0.5" 1552 | yargs-parser "^20.2.2" 1553 | 1554 | yn@^2.0.0: 1555 | version "2.0.0" 1556 | resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" 1557 | integrity sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ== 1558 | 1559 | yocto-queue@^0.1.0: 1560 | version "0.1.0" 1561 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 1562 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1563 | --------------------------------------------------------------------------------