├── 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 ├── README.md ├── 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solana Meteora CPI call 2 | 3 | This is repository for giving example of meteora(one of famous solana dex) cpi call. By token swap cpi call, it shows how to interat with meteora program. If you need to build some program that calls meteora program or if you face some difficulty for this project, then feel free to reach out of me[Telegram: https://t.me/DevCutup, Whatspp: https://wa.me/13137423660]. 4 | 5 | 6 | 7 | ## How to use it 8 | 9 | ```bash 10 | git clone https://github.com/cutupdev/Solana-Meteora-CPI-Call.git 11 | ``` 12 | 13 | ```bash 14 | cd ./Solana-Meteora-CPI-Call 15 | ``` 16 | 17 | ```bash 18 | npm run install 19 | ``` 20 | 21 | - To deploy program: 22 | ```bash 23 | anchor build 24 | ``` 25 | 26 | ```bash 27 | anchor deploy 28 | ``` 29 | 30 | 31 | 32 | ### Contact Information 33 | - Telegram: https://t.me/DevCutup 34 | - Whatsapp: https://wa.me/13137423660 35 | - Twitter: https://x.com/devcutup 36 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------