├── .gitignore ├── raydium ├── index.ts ├── ids.ts ├── layouts.ts ├── transactions.ts ├── instructions.ts └── infos.ts ├── README.md ├── package.json ├── saber ├── ids.ts ├── layouts.ts ├── index.ts ├── transactions.ts ├── instructions.ts └── infos.ts ├── index.ts ├── utils.ts ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /raydium/index.ts: -------------------------------------------------------------------------------- 1 | import { Connection, PublicKey, AccountInfo } from "@solana/web3.js"; 2 | import { parseV4PoolInfo } from "./infos"; 3 | 4 | export { swap } from "./transactions"; 5 | 6 | export async function getAmmPool(ammId: PublicKey, conn: Connection) { 7 | const account = (await conn.getAccountInfo(ammId)) as AccountInfo; 8 | const pool = parseV4PoolInfo(account.data, ammId); 9 | 10 | // Update amounts manually 11 | pool.updatePoolAmount(conn); 12 | return pool; 13 | } 14 | -------------------------------------------------------------------------------- /raydium/ids.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from "@solana/web3.js"; 2 | 3 | export const SBR_AMM_ID = new PublicKey( 4 | "5cmAS6Mj4pG2Vp9hhyu3kpK9yvC7P6ejh9HiobpTE6Jc" 5 | ); 6 | export const LIQUIDITY_POOL_PROGRAM_ID_V3 = new PublicKey( 7 | "27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv" 8 | ); 9 | export const LIQUIDITY_POOL_PROGRAM_ID_V4 = new PublicKey( 10 | "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" 11 | ); 12 | export const STAKE_PROGRAM_ID = new PublicKey( 13 | "EhhTKczWMGQt46ynNeRX1WfeagwwJd7ufHvCDjRxjo5Q" 14 | ); 15 | export const STAKE_PROGRAM_ID_V5 = new PublicKey( 16 | "9KEPoZmtHUrBbhWN1v1KWLMkkvwY6WLtAVUCPRtRjP4z" 17 | ); 18 | export const AMM_AUTHORITY = new PublicKey( 19 | "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1" 20 | ); 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # auto-compounding-bot 2 | 3 | ## prepare wallet 4 | 5 | ```bash 6 | $ sh -c "$(curl -sSfL https://release.solana.com/v1.9.8/install)" 7 | ... 8 | 9 | $ solana-keygen new 10 | ``` 11 | 12 | ## restore wallet from private key 13 | 14 | ```bash 15 | $ vim ~/.config/solana/solmeet-keypair-1.json 16 | # paste KeyPair as u8 array format inside and save 17 | # save and quit vim: esc -> :wq 18 | ``` 19 | 20 | ## connect to Mainnet-fork 21 | 22 | ```bash 23 | $ solana config set --url https://rpc-mainnet-fork.dappio.xyz 24 | $ solana config set --ws wss://rpc-mainnet-fork.dappio.xyz/ws 25 | $ solana config set --commitment processed 26 | $ solana airdrop 1 27 | ``` 28 | 29 | ## testing the script 30 | 31 | ```bash 32 | $ yarn 33 | $ yarn start 34 | ``` 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "auto-compounding-bot", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "./index.ts", 6 | "scripts": { 7 | "start": "ts-node ./index.ts" 8 | }, 9 | "dependencies": { 10 | "@project-serum/borsh": "^0.2.5", 11 | "@project-serum/serum": "^0.13.61", 12 | "@solana/buffer-layout": "^4.0.0", 13 | "@solana/spl-token": "^0.2.0", 14 | "@solana/web3.js": "^1.35.0", 15 | "bignumber.js": "^9.0.1", 16 | "buffer-layout": "^1.2.2", 17 | "js-sha256": "^0.9.0" 18 | }, 19 | "devDependencies": { 20 | "@project-serum/borsh": "^0.2.5", 21 | "@solana/web3.js": "^1.35.0", 22 | "@types/express": "^4.17.13", 23 | "@types/node": "^17.0.18", 24 | "buffer-layout": "^1.2.2", 25 | "ts-node": "^10.5.0", 26 | "typescript": "^4.5.5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /saber/ids.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from "@solana/web3.js"; 2 | 3 | export const SBR_MINT = new PublicKey( 4 | "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1" 5 | ); 6 | export const USDC_UST_POOL = new PublicKey( 7 | "KwnjUuZhTMTSGAaavkLEmSyfobY16JNH4poL9oeeEvE" 8 | ); 9 | export const ADMIN_KEY = new PublicKey( 10 | "H9XuKqszWYirDmXDQ12TZXGtxqUYYn4oi7FKzAm7RHGc" 11 | ); 12 | export const SWAP_PROGRAM_ID = new PublicKey( 13 | "SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ" 14 | ); 15 | export const SABER_WRAP_PROGRAM_ID = new PublicKey( 16 | "DecZY86MU5Gj7kppfUCEmd4LbXXuyZH1yHaP2NTqdiZB" 17 | ); 18 | export const SABER_QUARRY_REWARDER = new PublicKey( 19 | "rXhAofQCT7NN9TUqigyEAUzV1uLL4boeD8CRkNBSkYk" 20 | ); 21 | export const QURARRY_MINE_PROGRAM_ID = new PublicKey( 22 | "QMNeHCGYnLVDn1icRAfQZpjPLBNkfGbSKRB83G5d8KB" 23 | ); 24 | export const SABER_MINT_WRAPPER = new PublicKey( 25 | "EVVDA3ZiAjTizemLGXNUN3gb6cffQFEYkFjFZokPmUPz" 26 | ); 27 | export const QURARRY_MINT_WRAPPER = new PublicKey( 28 | "QMWoBmAyJLAsA1Lh9ugMTw2gciTihncciphzdNzdZYV" 29 | ); 30 | export const SABER_FARM_MINTER = new PublicKey( 31 | "GEoTC3gN12qHDniaDD7Zxvd5xtcZyEKkTPy42B44s82y" 32 | ); 33 | export const IOU_TOKEN_MINT = new PublicKey( 34 | "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u" 35 | ); 36 | export const CLAIM_FEE_TOKEN_ACCOUNT = new PublicKey( 37 | "4Snkea6wv3K6qzDTdyJiF2VTiLPmCoyHJCzAdkdTStBK" 38 | ); 39 | export const SABER_TOKEN_MINT = new PublicKey( 40 | "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1" 41 | ); 42 | export const MINTER_PROGRAM_ID = new PublicKey( 43 | "RDM23yr8pr1kEAmhnFpaabPny6C9UVcEcok3Py5v86X" 44 | ); 45 | export const DEPRECATED_POOLS = [ 46 | new PublicKey("LeekqF2NMKiFNtYD6qXJHZaHx4hUdj4UiPu4t8sz7uK"), 47 | new PublicKey("2jQoGQRixdcfuRPt9Zui7pk6ivnrQv79mf8h13Tyoa9K"), 48 | new PublicKey("SPaiZAYyJBQHaSjtxFBKtLtQiCuG328r1mTfmvvydR5"), 49 | new PublicKey("HoNG9Z4jsA1qtkZhDRYBc67LF2cbusZahjyxXtXdKZgR"), 50 | new PublicKey("4Fss9Dy3vAUBuQ4SyEZz4vcLxeQqoFLZjdXhEUr3wqz3"), 51 | ]; 52 | -------------------------------------------------------------------------------- /raydium/layouts.ts: -------------------------------------------------------------------------------- 1 | import { publicKey, struct, u8, u64, u128 } from "@project-serum/borsh"; 2 | 3 | export const SWAP_LAYOUT = struct([ 4 | u8("instruction"), 5 | u64("amountIn"), 6 | u64("minAmountOut"), 7 | ]); 8 | 9 | export const ADD_LIQUIDITY_LAYOUT = struct([ 10 | u8("instruction"), 11 | u64("maxCoinAmount"), 12 | u64("maxPcAmount"), 13 | u64("fixedFromCoin"), 14 | ]); 15 | 16 | export const REMOVE_LIQUIDITY_LAYOUT = struct([ 17 | u8("instruction"), 18 | u64("amount"), 19 | ]); 20 | 21 | export const AMM_INFO_LAYOUT_V4 = struct([ 22 | u64("status"), 23 | u64("nonce"), 24 | u64("orderNum"), 25 | u64("depth"), 26 | u64("coinDecimals"), 27 | u64("pcDecimals"), 28 | u64("state"), 29 | u64("resetFlag"), 30 | u64("minSize"), 31 | u64("volMaxCutRatio"), 32 | u64("amountWaveRatio"), 33 | u64("coinLotSize"), 34 | u64("pcLotSize"), 35 | u64("minPriceMultiplier"), 36 | u64("maxPriceMultiplier"), 37 | u64("systemDecimalsValue"), 38 | // Fees 39 | u64("minSeparateNumerator"), 40 | u64("minSeparateDenominator"), 41 | u64("tradeFeeNumerator"), 42 | u64("tradeFeeDenominator"), 43 | u64("pnlNumerator"), 44 | u64("pnlDenominator"), 45 | u64("swapFeeNumerator"), 46 | u64("swapFeeDenominator"), 47 | // OutPutData 48 | u64("needTakePnlCoin"), 49 | u64("needTakePnlPc"), 50 | u64("totalPnlPc"), 51 | u64("totalPnlCoin"), 52 | u128("poolTotalDepositPc"), 53 | u128("poolTotalDepositCoin"), 54 | u128("swapCoinInAmount"), 55 | u128("swapPcOutAmount"), 56 | u64("swapCoin2PcFee"), 57 | u128("swapPcInAmount"), 58 | u128("swapCoinOutAmount"), 59 | u64("swapPc2CoinFee"), 60 | publicKey("poolCoinTokenAccount"), 61 | publicKey("poolPcTokenAccount"), 62 | publicKey("coinMintAddress"), 63 | publicKey("pcMintAddress"), 64 | publicKey("lpMintAddress"), 65 | publicKey("ammOpenOrders"), 66 | publicKey("serumMarket"), 67 | publicKey("serumProgramId"), 68 | publicKey("ammTargetOrders"), 69 | publicKey("poolWithdrawQueue"), 70 | publicKey("poolTempLpTokenAccount"), 71 | publicKey("ammOwner"), 72 | publicKey("pnlOwner"), 73 | ]); 74 | -------------------------------------------------------------------------------- /saber/layouts.ts: -------------------------------------------------------------------------------- 1 | import { 2 | publicKey, 3 | struct, 4 | u64, 5 | u128, 6 | u8, 7 | u16, 8 | i64, 9 | bool, 10 | } from "@project-serum/borsh"; 11 | 12 | export const FARM_LAYOUT = struct([ 13 | publicKey("rewarderKey"), 14 | publicKey("tokenMintKey"), 15 | u8("bump"), 16 | u16("index"), 17 | u8("tokenMintDecimals"), 18 | i64("famineTs"), 19 | i64("lastUpdateTs"), 20 | u128("rewardsPerTokenStored"), 21 | u64("annualRewardsRate"), 22 | u64("rewardsShare"), 23 | u64("totalTokensDeposited"), 24 | u64("numMiners"), 25 | ]); 26 | 27 | export const MINER_LAYOUT = struct([ 28 | publicKey("farmKey"), 29 | publicKey("owner"), 30 | u8("bump"), 31 | publicKey("vault"), 32 | u64("rewardsEarned"), 33 | u128("rewardsPerTokenPaid"), 34 | u64("balance"), 35 | u64("index"), 36 | ]); 37 | 38 | export const SWAPINFO_LAYOUT = struct([ 39 | bool("isInitialized"), 40 | bool("isPaused"), 41 | u8("nonce"), 42 | u64("initialAmpFactor"), 43 | u64("targetAmpFactor"), 44 | i64("startRampTs"), 45 | i64("stopRampTs"), 46 | i64("futureAdminDeadline"), 47 | publicKey("futureAdminKey"), 48 | publicKey("adminKey"), 49 | publicKey("tokenAccountA"), 50 | publicKey("tokenAccountB"), 51 | publicKey("poolMint"), 52 | publicKey("mintA"), 53 | publicKey("mintB"), 54 | publicKey("adminFeeAccountA"), 55 | publicKey("adminFeeAccountB"), 56 | ]); 57 | 58 | export const WRAPINFO_LAYOUT = struct([ 59 | u8("decimal"), 60 | u64("multiplyer"), 61 | publicKey("underlyingWrappedTokenMint"), 62 | publicKey("underlyingTokenAccount"), 63 | publicKey("wrappedTokenMint"), 64 | ]); 65 | 66 | export const DEPOSIT_LAYPOUT = struct([ 67 | u8("instruction"), 68 | u64("AtokenAmount"), 69 | u64("BtokenAmount"), 70 | u64("minimalRecieve"), 71 | ]); 72 | 73 | export const WITHDRAW_LAYOUT = struct([ 74 | u8("instruction"), 75 | u64("LPtokenAmount"), 76 | u64("minimalRecieve"), 77 | ]); 78 | 79 | export const WRAP_LAYOUT = struct([u64("amount")]); 80 | 81 | export const UNWRAP_LAYOUT = struct([u64("amount")]); 82 | 83 | export const DEPOSIT_TO_FARM_LAYOUT = struct([u64("amount")]); 84 | 85 | export const CREATE_MINER_LAYOUT = struct([u64("amount")]); 86 | 87 | export const WITHDRAW_FROM_FARM_LAYOUT = struct([u64("amount")]); 88 | -------------------------------------------------------------------------------- /raydium/transactions.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { Market } from "@project-serum/serum"; 3 | import { NATIVE_MINT } from "@solana/spl-token"; 4 | import * as Token from "@solana/spl-token"; 5 | import { Connection, PublicKey, Transaction } from "@solana/web3.js"; 6 | import { PoolInfo } from "./infos"; 7 | import * as ixs from "./instructions"; 8 | import { 9 | AMM_AUTHORITY, 10 | LIQUIDITY_POOL_PROGRAM_ID_V3, 11 | LIQUIDITY_POOL_PROGRAM_ID_V4, 12 | } from "./ids"; 13 | import { 14 | createATAWithoutCheckIx, 15 | findAssociatedTokenAddress, 16 | wrapNative, 17 | } from "../utils"; 18 | 19 | export async function swap( 20 | pool: PoolInfo, 21 | fromMint: PublicKey, 22 | toMint: PublicKey, 23 | wallet: PublicKey, 24 | amountIn: BN, 25 | minAmountOut: BN, 26 | connection: Connection, 27 | fromTokenAccount?: PublicKey 28 | ): Promise { 29 | const tx = new Transaction(); 30 | const cleanUpTx = new Transaction(); 31 | if (fromTokenAccount) { 32 | fromTokenAccount = fromTokenAccount as PublicKey; 33 | } else { 34 | fromTokenAccount = await findAssociatedTokenAddress(wallet, fromMint); 35 | } 36 | const toTokenAccount = await findAssociatedTokenAddress(wallet, toMint); 37 | tx.add(await createATAWithoutCheckIx(wallet, toMint, wallet)); 38 | if (fromMint.toString() === NATIVE_MINT.toString()) { 39 | tx.add(await wrapNative(amountIn, wallet)); 40 | cleanUpTx.add( 41 | Token.createCloseAccountInstruction(fromTokenAccount, wallet, wallet, []) 42 | ); 43 | } 44 | if (toMint.toString() === NATIVE_MINT.toString()) { 45 | cleanUpTx.add( 46 | Token.createCloseAccountInstruction(toTokenAccount, wallet, wallet, []) 47 | ); 48 | } 49 | const serumMarket = await Market.load( 50 | connection, 51 | pool.serumMarket, 52 | undefined, 53 | pool.serumProgramId 54 | ); 55 | let programId = PublicKey.default; 56 | if (pool.version === 3) { 57 | programId = LIQUIDITY_POOL_PROGRAM_ID_V3; 58 | } else if (pool.version === 4) { 59 | programId = LIQUIDITY_POOL_PROGRAM_ID_V4; 60 | } 61 | const serumVaultSigner = await PublicKey.createProgramAddress( 62 | [ 63 | serumMarket.address.toBuffer(), 64 | serumMarket.decoded.vaultSignerNonce.toArrayLike(Buffer, "le", 8), 65 | ], 66 | serumMarket.programId 67 | ); 68 | const swapIxs = ixs.swapInstruction( 69 | programId, 70 | pool.infoPubkey, 71 | AMM_AUTHORITY, 72 | pool.ammOpenOrders, 73 | pool.ammTargetOrders, 74 | pool.poolCoinTokenAccount, 75 | pool.poolPcTokenAccount, 76 | pool.serumProgramId, 77 | pool.serumMarket, 78 | serumMarket.bidsAddress, 79 | serumMarket.asksAddress, 80 | new PublicKey(serumMarket.decoded.eventQueue), 81 | new PublicKey(serumMarket.decoded.baseVault), 82 | new PublicKey(serumMarket.decoded.quoteVault), 83 | serumVaultSigner, 84 | fromTokenAccount, 85 | toTokenAccount, 86 | wallet, 87 | amountIn, 88 | minAmountOut 89 | ); 90 | tx.add(swapIxs); 91 | tx.add(cleanUpTx); 92 | return tx; 93 | } 94 | -------------------------------------------------------------------------------- /saber/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Connection, 3 | MemcmpFilter, 4 | GetProgramAccountsConfig, 5 | DataSizeFilter, 6 | PublicKey, 7 | } from "@solana/web3.js"; 8 | import { 9 | ADMIN_KEY, 10 | DEPRECATED_POOLS, 11 | SABER_QUARRY_REWARDER, 12 | SWAP_PROGRAM_ID, 13 | } from "./ids"; 14 | import { 15 | SwapInfo, 16 | checkWrapped, 17 | getAllWrap, 18 | parseSwapInfoData, 19 | checkFarming, 20 | getAllFarms, 21 | } from "./infos"; 22 | 23 | export { FarmInfo, getAllMiners, defaultMiner } from "./infos"; 24 | export { claimRewardTx, createDepositTx, depositToFarm } from "./transactions"; 25 | 26 | export async function getAllSwaps(conn: Connection): Promise { 27 | const adminIdMemcmp: MemcmpFilter = { 28 | memcmp: { 29 | offset: 75, 30 | bytes: ADMIN_KEY.toString(), 31 | }, 32 | }; 33 | const sizeFilter: DataSizeFilter = { 34 | dataSize: 395, 35 | }; 36 | const filters = [sizeFilter]; 37 | const config: GetProgramAccountsConfig = { filters }; 38 | const allSaberAccount = await conn.getProgramAccounts( 39 | SWAP_PROGRAM_ID, 40 | config 41 | ); 42 | const infoArray: SwapInfo[] = []; 43 | const wrapInfoArray = await getAllWrap(conn); 44 | const allFarmInfo = await getAllFarms(conn, SABER_QUARRY_REWARDER); 45 | 46 | for (const account of allSaberAccount) { 47 | if (DEPRECATED_POOLS.includes(account.pubkey)) { 48 | continue; 49 | } 50 | const saberAccountInfo = await parseSwapInfoData( 51 | account.account.data, 52 | account.pubkey 53 | ); 54 | if (saberAccountInfo.isPaused) { 55 | continue; 56 | } 57 | const mintAwrapped = await checkWrapped( 58 | saberAccountInfo.mintA, 59 | wrapInfoArray 60 | ); 61 | saberAccountInfo.mintAWrapped = mintAwrapped[0]; 62 | if (mintAwrapped[0]) { 63 | saberAccountInfo.mintAWrapInfo = mintAwrapped[1]; 64 | } 65 | const mintBwrapped = await checkWrapped( 66 | saberAccountInfo.mintB, 67 | wrapInfoArray 68 | ); 69 | saberAccountInfo.mintBWrapped = mintBwrapped[0]; 70 | if (mintBwrapped[0]) { 71 | saberAccountInfo.mintBWrapInfo = mintBwrapped[1]; 72 | } 73 | const farmStarted = checkFarming(allFarmInfo, saberAccountInfo.poolMint); 74 | if (farmStarted[0]) { 75 | saberAccountInfo.isFarming = true; 76 | saberAccountInfo.farmingInfo = farmStarted[1]; 77 | } 78 | infoArray.push(saberAccountInfo); 79 | } 80 | return infoArray; 81 | } 82 | 83 | export async function getSwap( 84 | connection: Connection, 85 | swap: PublicKey 86 | ): Promise { 87 | const adminIdMemcmp: MemcmpFilter = { 88 | memcmp: { 89 | offset: 75, 90 | bytes: ADMIN_KEY.toString(), 91 | }, 92 | }; 93 | const sizeFilter: DataSizeFilter = { 94 | dataSize: 395, 95 | }; 96 | const filters = [adminIdMemcmp, sizeFilter]; 97 | 98 | const wrapInfoArray = await getAllWrap(connection); 99 | const allFarmInfo = await getAllFarms(connection, SABER_QUARRY_REWARDER); 100 | const saberAccount: any = await connection.getAccountInfo(swap); 101 | const saberAccountInfo = await parseSwapInfoData(saberAccount.data, swap); 102 | const mintAwrapped = await checkWrapped( 103 | saberAccountInfo.mintA, 104 | wrapInfoArray 105 | ); 106 | 107 | saberAccountInfo.mintAWrapped = mintAwrapped[0]; 108 | if (mintAwrapped[0]) { 109 | saberAccountInfo.mintAWrapInfo = mintAwrapped[1]; 110 | } 111 | const mintBwrapped = await checkWrapped( 112 | saberAccountInfo.mintB, 113 | wrapInfoArray 114 | ); 115 | saberAccountInfo.mintBWrapped = mintBwrapped[0]; 116 | if (mintBwrapped[0]) { 117 | saberAccountInfo.mintBWrapInfo = mintBwrapped[1]; 118 | } 119 | const farmStarted = checkFarming(allFarmInfo, saberAccountInfo.poolMint); 120 | if (farmStarted[0]) { 121 | saberAccountInfo.isFarming = true; 122 | saberAccountInfo.farmingInfo = farmStarted[1]; 123 | } 124 | saberAccountInfo.infoPublicKey = swap; 125 | 126 | return saberAccountInfo; 127 | } 128 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import os from "os"; 2 | import fs from "fs"; 3 | import BN from "bn.js"; 4 | import { Connection, Keypair } from "@solana/web3.js"; 5 | import * as raydium from "./raydium"; 6 | import { SBR_AMM_ID } from "./raydium/ids"; 7 | import * as saber from "./saber"; 8 | import { SBR_MINT, USDC_UST_POOL } from "./saber/ids"; 9 | import * as utils from "./utils"; 10 | 11 | // Load keypair 12 | const keyPairPath = `${os.homedir()}/.config/solana/solmeet-keypair-1.json`; 13 | const privateKeyUint8Array = JSON.parse(fs.readFileSync(keyPairPath, "utf-8")); 14 | const privateKey = Uint8Array.from(privateKeyUint8Array); 15 | const wallet = Keypair.fromSecretKey(privateKey); 16 | 17 | async function main() { 18 | const conn = new Connection("https://rpc-mainnet-fork.dappio.xyz", { 19 | wsEndpoint: "wss://rpc-mainnet-fork.dappio.xyz/ws", 20 | commitment: "processed", 21 | }); 22 | // const conn = new Connection("https://solana-api.tt-prod.net", { commitment: "processed", }); 23 | console.log("Fetching all Saber pools..."); 24 | const swaps = await saber.getAllSwaps(conn); 25 | console.log("Fetching all Saber miners..."); 26 | const miners = await saber.getAllMiners(conn, wallet.publicKey); 27 | console.log("Fetching Saber AMM pool on Raydium..."); 28 | const sbrAmm = await raydium.getAmmPool(SBR_AMM_ID, conn); 29 | 30 | // Claim all mining rewards 31 | console.log("Claiming all mining rewards..."); 32 | for (const miner of miners) { 33 | for (const swap of swaps) { 34 | if ( 35 | miner.farmKey.toString() === swap.farmingInfo?.infoPubkey.toString() 36 | ) { 37 | if (miner.balance.toNumber() > 0) { 38 | // Create claimRewardTx 39 | const claimRewardTx = await saber.claimRewardTx( 40 | swap.farmingInfo as saber.FarmInfo, 41 | wallet.publicKey, 42 | conn 43 | ); 44 | // Send Tx 45 | const result = await utils.signAndSendAll( 46 | claimRewardTx, 47 | conn, 48 | wallet 49 | ); 50 | console.log( 51 | miner.getUnclaimedRewards(swap), 52 | "SBR reward claimed. Tx:", 53 | result 54 | ); 55 | } 56 | } 57 | } 58 | } 59 | 60 | let tokenAccounts = await utils.getAllTokenAccount(wallet.publicKey, conn); 61 | let swapOutAmount = new BN(0); 62 | 63 | // Swap all SBR to USDC 64 | console.log("Swapping all SBR to USDC..."); 65 | for (const token of tokenAccounts) { 66 | if (token.mint === SBR_MINT && token.amount.cmpn(0)) { 67 | swapOutAmount = await ( 68 | await sbrAmm.calculateSwapOutAmount("coin", token.amount, conn) 69 | ).divn(0.98); 70 | if (!swapOutAmount.cmpn(1)) { 71 | break; 72 | } 73 | const swapIx = await raydium.swap( 74 | sbrAmm, 75 | token.mint, 76 | sbrAmm.pcMintAddress, 77 | wallet.publicKey, 78 | token.amount, 79 | new BN(0), 80 | conn 81 | ); 82 | const result = await utils.signAndSendAll(swapIx, conn, wallet); 83 | console.log( 84 | token.amount.toNumber() / 1000000, 85 | "SBR swapped. Tx:", 86 | result 87 | ); 88 | } 89 | } 90 | 91 | // Add all USDC swapped out to USDC-UST pool 92 | console.log("Adding all USDC swapped out to USDC-UST pool..."); 93 | for (const swap of swaps) { 94 | if (swap.infoPublicKey === USDC_UST_POOL) { 95 | const addLP = await saber.createDepositTx( 96 | swap, 97 | new BN(0), 98 | swapOutAmount, 99 | new BN(0), 100 | wallet.publicKey, 101 | conn 102 | ); 103 | const result = await utils.signAndSendAll(addLP, conn, wallet); 104 | console.log("LP reinvested. Tx:", result); 105 | } 106 | } 107 | 108 | // Deposit all LP to farming 109 | console.log("Depositing all LP to farming..."); 110 | tokenAccounts = await utils.getAllTokenAccount(wallet.publicKey, conn); 111 | for (const swap of swaps) { 112 | for (const token of tokenAccounts) { 113 | if ( 114 | token.mint.toString() === swap.poolMint.toString() && 115 | token.amount.cmpn(0) 116 | ) { 117 | // Create farmIx 118 | const farmIx = await saber.depositToFarm( 119 | swap.farmingInfo as saber.FarmInfo, 120 | wallet.publicKey, 121 | token.amount, 122 | conn 123 | ); 124 | // Send Tx 125 | const result = await utils.signAndSendAll(farmIx, conn, wallet); 126 | console.log("Farm deposited. Tx:", result); 127 | } 128 | } 129 | } 130 | } 131 | 132 | async function run() { 133 | try { 134 | main(); 135 | } catch (e) { 136 | console.error(e); 137 | } 138 | } 139 | 140 | run(); 141 | -------------------------------------------------------------------------------- /utils.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import * as sha256 from "js-sha256"; 3 | import { 4 | PublicKey, 5 | Transaction, 6 | TransactionInstruction, 7 | SystemProgram, 8 | Connection, 9 | SYSVAR_RENT_PUBKEY, 10 | Keypair, 11 | sendAndConfirmTransaction, 12 | } from "@solana/web3.js"; 13 | import { 14 | TOKEN_PROGRAM_ID, 15 | NATIVE_MINT, 16 | ASSOCIATED_TOKEN_PROGRAM_ID, 17 | } from "@solana/spl-token"; 18 | import { publicKey, struct, u64, u32, u8 } from "@project-serum/borsh"; 19 | 20 | const ATA_INIT_PROGRAM_ID = new PublicKey( 21 | "9tiP8yZcekzfGzSBmp7n9LaDHRjxP2w7wJj8tpPJtfG" 22 | ); 23 | 24 | const TOKEN_LAYOUT = struct([ 25 | publicKey("mint"), 26 | publicKey("owner"), 27 | u64("amount"), 28 | u32("delegateOption"), 29 | publicKey("delegate"), 30 | u8("state"), 31 | u32("isNativeOption"), 32 | u64("isNative"), 33 | u64("delegatedAmount"), 34 | u32("closeAuthorityOption"), 35 | publicKey("closeAuthority"), 36 | ]); 37 | 38 | const MINT_LAYOUT = struct([ 39 | u32("option"), 40 | publicKey("authority"), 41 | u64("amount"), 42 | u8("decimals"), 43 | ]); 44 | 45 | class TokenAccount { 46 | infoPubkey: PublicKey; 47 | mint: PublicKey; 48 | owner: PublicKey; 49 | amount: BN; 50 | constructor( 51 | infoPubkey: PublicKey, 52 | mint: PublicKey, 53 | owner: PublicKey, 54 | amount: BN 55 | ) { 56 | this.infoPubkey = infoPubkey; 57 | this.mint = mint; 58 | this.owner = owner; 59 | this.amount = new BN(amount); 60 | } 61 | } 62 | 63 | export async function checkTokenAccount( 64 | publickey: PublicKey, 65 | connection: Connection 66 | ): Promise { 67 | const accountInfo = await connection.getAccountInfo(publickey); 68 | return accountInfo?.owner.toString() === TOKEN_PROGRAM_ID.toString(); 69 | } 70 | 71 | export function parseTokenAccount( 72 | data: any, 73 | infoPubkey: PublicKey 74 | ): TokenAccount { 75 | const tokenAccountInfo = TOKEN_LAYOUT.decode(data); 76 | const { mint, owner, amount } = tokenAccountInfo; 77 | return new TokenAccount(infoPubkey, mint, owner, amount); 78 | } 79 | 80 | export async function getTokenAccount( 81 | connection: Connection, 82 | tokenAccountPubkey: PublicKey 83 | ): Promise { 84 | const accountInfo = await connection.getAccountInfo(tokenAccountPubkey); 85 | return parseTokenAccount(accountInfo?.data, tokenAccountPubkey); 86 | } 87 | 88 | export async function getAllTokenAccount( 89 | wallet: PublicKey, 90 | connection: Connection 91 | ): Promise { 92 | const tokenAccountInfos = await ( 93 | await connection.getTokenAccountsByOwner(wallet, { 94 | programId: TOKEN_PROGRAM_ID, 95 | }) 96 | ).value; 97 | const tokenAccounts = []; 98 | for (const info of tokenAccountInfos) { 99 | const tokenAccount = parseTokenAccount(info.account.data, info.pubkey); 100 | tokenAccounts.push(tokenAccount); 101 | } 102 | return tokenAccounts; 103 | } 104 | 105 | export async function getTokenAccountAmount( 106 | connection: Connection, 107 | tokenAccountPubkey: PublicKey 108 | ): Promise { 109 | const accountInfo = await connection.getAccountInfo(tokenAccountPubkey); 110 | const tokenAccountInfo = TOKEN_LAYOUT.decode(accountInfo?.data); 111 | return new BN(tokenAccountInfo.amount); 112 | } 113 | 114 | export async function getTokenSupply( 115 | connection: Connection, 116 | tokenMintPubkey: PublicKey 117 | ): Promise { 118 | const accountInfo = await connection.getAccountInfo(tokenMintPubkey); 119 | const mintAccountInfo = MINT_LAYOUT.decode(accountInfo?.data); 120 | return new BN(mintAccountInfo.amount); 121 | } 122 | 123 | export async function wrapNative( 124 | amount: BN, 125 | walletPublicKey: PublicKey 126 | ): Promise { 127 | const tx = new Transaction(); 128 | const destinationAta = await findAssociatedTokenAddress( 129 | walletPublicKey, 130 | NATIVE_MINT 131 | ); 132 | const createATA = await createATAWithoutCheckIx(walletPublicKey, NATIVE_MINT); 133 | tx.add(createATA); 134 | const transferPram = { 135 | fromPubkey: walletPublicKey, 136 | lamports: amount.toNumber(), 137 | toPubkey: destinationAta, 138 | }; 139 | const transferLamportIx = SystemProgram.transfer(transferPram); 140 | tx.add(transferLamportIx); 141 | const key = [{ pubkey: destinationAta, isSigner: false, isWritable: true }]; 142 | const dataString = "11"; 143 | const data = Buffer.from(dataString, "hex"); 144 | const syncNativeIx = new TransactionInstruction({ 145 | keys: key, 146 | programId: TOKEN_PROGRAM_ID, 147 | data, 148 | }); 149 | tx.add(syncNativeIx); 150 | return tx; 151 | } 152 | 153 | export async function findAssociatedTokenAddress( 154 | walletAddress: PublicKey, 155 | tokenMintAddress: PublicKey 156 | ): Promise { 157 | return ( 158 | await PublicKey.findProgramAddress( 159 | [ 160 | walletAddress.toBuffer(), 161 | TOKEN_PROGRAM_ID.toBuffer(), 162 | tokenMintAddress.toBuffer(), 163 | ], 164 | ASSOCIATED_TOKEN_PROGRAM_ID 165 | ) 166 | )[0]; 167 | } 168 | 169 | export async function createATAWithoutCheckIx( 170 | wallet: PublicKey, 171 | mint: PublicKey, 172 | payer?: PublicKey 173 | ): Promise { 174 | if (payer === undefined) { 175 | payer = wallet as PublicKey; 176 | } 177 | payer = payer as PublicKey; 178 | const ATA = await findAssociatedTokenAddress(wallet, mint); 179 | const keys = [ 180 | { pubkey: payer, isSigner: true, isWritable: true }, 181 | { pubkey: ATA, isSigner: false, isWritable: true }, 182 | { pubkey: wallet, isSigner: false, isWritable: true }, 183 | { pubkey: mint, isSigner: false, isWritable: false }, 184 | { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, 185 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 186 | { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, 187 | { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 188 | ]; 189 | return new TransactionInstruction({ 190 | keys, 191 | programId: ATA_INIT_PROGRAM_ID, 192 | }); 193 | } 194 | 195 | export function getAnchorInsByIdl(name: string): Buffer { 196 | const SIGHASH_GLOBAL_NAMESPACE = "global"; 197 | const preimage = `${SIGHASH_GLOBAL_NAMESPACE}:${name}`; 198 | const hash = sha256.sha256.digest(preimage); 199 | const data = Buffer.from(hash).slice(0, 8); 200 | return data; 201 | } 202 | 203 | export async function signAndSendAll( 204 | allTx: Transaction, 205 | connection: Connection, 206 | wallet: Keypair 207 | ): Promise { 208 | const walletPublicKey = wallet.publicKey; 209 | const tx = new Transaction(); 210 | tx.add(allTx); 211 | const recentBlockhash = (await connection.getLatestBlockhash()).blockhash; 212 | tx.recentBlockhash = recentBlockhash; 213 | tx.feePayer = walletPublicKey; 214 | const result = sendAndConfirmTransaction(connection, tx, [wallet]); 215 | return result; 216 | } 217 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ 22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | 26 | /* Modules */ 27 | "module": "commonjs", /* Specify what module code is generated. */ 28 | // "rootDir": "./", /* Specify the root folder within your source files. */ 29 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 30 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 31 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 32 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 33 | // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ 34 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 35 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 36 | // "resolveJsonModule": true, /* Enable importing .json files */ 37 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ 38 | 39 | /* JavaScript Support */ 40 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ 41 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 42 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ 43 | 44 | /* Emit */ 45 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 46 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 47 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 48 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 49 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ 50 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 51 | // "removeComments": true, /* Disable emitting comments. */ 52 | // "noEmit": true, /* Disable emitting files from a compilation. */ 53 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 54 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ 55 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 56 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 59 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 60 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 61 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 62 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ 63 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ 64 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 65 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ 66 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 67 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 68 | 69 | /* Interop Constraints */ 70 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 71 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 72 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ 73 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 74 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 75 | 76 | /* Type Checking */ 77 | "strict": true, /* Enable all strict type-checking options. */ 78 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ 79 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ 80 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 81 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ 82 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 83 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ 84 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ 85 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 86 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ 87 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ 88 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 89 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 90 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 91 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 92 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 93 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ 94 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 95 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 96 | 97 | /* Completeness */ 98 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 99 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /saber/transactions.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { NATIVE_MINT } from "@solana/spl-token"; 3 | import * as Token from "@solana/spl-token"; 4 | import { Connection, PublicKey, Transaction } from "@solana/web3.js"; 5 | import * as ins from "./instructions"; 6 | import { 7 | SwapInfo, 8 | WrapInfo, 9 | FarmInfo, 10 | getMinerKey, 11 | minerCreated, 12 | } from "./infos"; 13 | import { IOU_TOKEN_MINT, SABER_TOKEN_MINT } from "./ids"; 14 | import { 15 | checkTokenAccount, 16 | createATAWithoutCheckIx, 17 | findAssociatedTokenAddress, 18 | wrapNative, 19 | } from "../utils"; 20 | 21 | export async function createDepositTx( 22 | swapInfo: SwapInfo, 23 | AtokenAmount: BN, 24 | BtokenAmount: BN, 25 | minimalRecieve: BN, 26 | wallet: PublicKey, 27 | connection: Connection 28 | ) { 29 | const tx: Transaction = new Transaction(); 30 | const cleanupTx = new Transaction(); 31 | // check if Token A source account is created 32 | const AtokenSourceAccount = await findAssociatedTokenAddress( 33 | wallet, 34 | swapInfo.mintA 35 | ); 36 | const createAtokenAccount = await createATAWithoutCheckIx( 37 | wallet, 38 | swapInfo.mintA 39 | ); 40 | tx.add(createAtokenAccount); 41 | 42 | // check if Token B source account is created 43 | const BtokenSourceAccount = await findAssociatedTokenAddress( 44 | wallet, 45 | swapInfo.mintB 46 | ); 47 | const createBtokenAccount = await createATAWithoutCheckIx( 48 | wallet, 49 | swapInfo.mintB 50 | ); 51 | tx.add(createBtokenAccount); 52 | 53 | // check if LP Token account is created 54 | const LPtokenAccount = await findAssociatedTokenAddress( 55 | wallet, 56 | swapInfo.poolMint 57 | ); 58 | 59 | // if false add a create IX 60 | const createLPtokenAccount = await await createATAWithoutCheckIx( 61 | wallet, 62 | swapInfo.poolMint 63 | ); 64 | tx.add(createLPtokenAccount); 65 | 66 | // check Token A is wSol 67 | if (swapInfo.mintA.toString() === NATIVE_MINT.toString()) { 68 | // if true add a wrapNative IX 69 | const wrapNativeIns = await wrapNative(AtokenAmount, wallet); 70 | cleanupTx.add( 71 | Token.createCloseAccountInstruction( 72 | AtokenSourceAccount, 73 | wallet, 74 | wallet, 75 | [] 76 | ) 77 | ); 78 | tx.add(wrapNativeIns); 79 | } 80 | 81 | // check Token A is wSol 82 | if (swapInfo.mintB.toString() === NATIVE_MINT.toString()) { 83 | // if true add a wrapNative IX 84 | const wrapNativeIns = await wrapNative(BtokenAmount, wallet); 85 | cleanupTx.add( 86 | Token.createCloseAccountInstruction( 87 | BtokenSourceAccount, 88 | wallet, 89 | wallet, 90 | [] 91 | ) 92 | ); 93 | tx.add(wrapNativeIns); 94 | } 95 | 96 | // if Token A is wrapped 97 | if (swapInfo.mintAWrapped) { 98 | // check underlying tokan account is created 99 | const wrapMintAtokenAddress = await findAssociatedTokenAddress( 100 | wallet, 101 | swapInfo.mintAWrapInfo?.underlyingWrappedTokenMint as PublicKey 102 | ); 103 | const createAtokenAccount = await createATAWithoutCheckIx( 104 | wallet, 105 | swapInfo.mintAWrapInfo?.underlyingWrappedTokenMint as PublicKey 106 | ); 107 | tx.add(createAtokenAccount); 108 | 109 | const multiplyer = new BN(swapInfo.mintAWrapInfo?.multiplyer as BN); 110 | const wrapAIns = ins.wrapToken( 111 | swapInfo.mintAWrapInfo as WrapInfo, 112 | wallet, 113 | AtokenAmount.div(multiplyer), 114 | wrapMintAtokenAddress, 115 | AtokenSourceAccount 116 | ); 117 | 118 | tx.add(wrapAIns); 119 | } 120 | 121 | // if Token B is wrapped 122 | if (swapInfo.mintBWrapped === true) { 123 | // check underlying tokan account is created 124 | const wrapMintBtokenAddress = await findAssociatedTokenAddress( 125 | wallet, 126 | swapInfo.mintBWrapInfo?.underlyingWrappedTokenMint as PublicKey 127 | ); 128 | 129 | const createBtokenAccount = await createATAWithoutCheckIx( 130 | wallet, 131 | swapInfo.mintBWrapInfo?.underlyingWrappedTokenMint as PublicKey 132 | ); 133 | tx.add(createBtokenAccount); 134 | 135 | const multiplyer = new BN(swapInfo.mintBWrapInfo?.multiplyer as BN); 136 | const wrapBIns = ins.wrapToken( 137 | swapInfo.mintBWrapInfo as WrapInfo, 138 | wallet, 139 | BtokenAmount.div(multiplyer), 140 | wrapMintBtokenAddress, 141 | BtokenSourceAccount 142 | ); 143 | 144 | tx.add(wrapBIns); 145 | } 146 | 147 | const depositIns = ins.deposit( 148 | swapInfo, 149 | AtokenAmount, 150 | BtokenAmount, 151 | minimalRecieve, 152 | wallet, 153 | AtokenSourceAccount, 154 | BtokenSourceAccount, 155 | LPtokenAccount 156 | ); 157 | tx.add(depositIns); 158 | 159 | if (swapInfo.isFarming) { 160 | const farm = swapInfo.farmingInfo as FarmInfo; 161 | const depositToFarmIns = await depositToFarm( 162 | farm, 163 | wallet, 164 | minimalRecieve, 165 | connection 166 | ); 167 | tx.add(depositToFarmIns); 168 | } 169 | 170 | tx.add(cleanupTx); 171 | 172 | return tx; 173 | } 174 | 175 | export async function depositToFarm( 176 | farm: FarmInfo, 177 | wallet: PublicKey, 178 | amount: BN, 179 | connection: Connection 180 | ) { 181 | const tx = new Transaction(); 182 | const createMinerIx = await createMiner(farm, wallet, connection); 183 | tx.add(createMinerIx); 184 | const depositToFarm = await ins.depositToFarmIx(farm, wallet, amount); 185 | tx.add(depositToFarm); 186 | 187 | return tx; 188 | } 189 | 190 | export async function createMiner( 191 | farm: FarmInfo, 192 | wallet: PublicKey, 193 | connection: Connection 194 | ) { 195 | const tx = new Transaction(); 196 | const miner = await getMinerKey(wallet, farm.infoPubkey); 197 | const minerVault = await findAssociatedTokenAddress( 198 | miner[0], 199 | farm.tokenMintKey 200 | ); 201 | if (!(await minerCreated(wallet, farm, connection))) { 202 | const createAtaIx = await createATAWithoutCheckIx( 203 | miner[0], 204 | farm.tokenMintKey, 205 | wallet 206 | ); 207 | tx.add(createAtaIx); 208 | const createMinerIx = await ins.createMinerAccountIx( 209 | farm as FarmInfo, 210 | wallet 211 | ); 212 | tx.add(createMinerIx); 213 | } 214 | 215 | return tx; 216 | } 217 | 218 | export async function createWithdrawTx( 219 | swapInfo: SwapInfo, 220 | tokenType: string, 221 | farmTokenAmount: BN, 222 | LPtokenAmount: BN, 223 | minimalRecieve: BN, 224 | wallet: PublicKey, 225 | connection: Connection 226 | ) { 227 | const tx: Transaction = new Transaction(); 228 | const cleanupTx = new Transaction(); 229 | const LPtokenSourceAccount = await findAssociatedTokenAddress( 230 | wallet, 231 | swapInfo.poolMint 232 | ); 233 | let recieveTokenAccountMint = new PublicKey(0); 234 | 235 | if (tokenType === "A") { 236 | recieveTokenAccountMint = swapInfo.mintA; 237 | } else if (tokenType === "B") { 238 | recieveTokenAccountMint = swapInfo.mintB; 239 | } 240 | const createLPtokenAccount = await createATAWithoutCheckIx( 241 | wallet, 242 | swapInfo.poolMint 243 | ); 244 | tx.add(createLPtokenAccount); 245 | const recieveTokenAccount = await findAssociatedTokenAddress( 246 | wallet, 247 | recieveTokenAccountMint 248 | ); 249 | const createrecieveTokenAccount = await createATAWithoutCheckIx( 250 | wallet, 251 | recieveTokenAccountMint 252 | ); 253 | tx.add(createrecieveTokenAccount); 254 | 255 | if (swapInfo.isFarming) { 256 | const farm = swapInfo.farmingInfo as FarmInfo; 257 | const withdrawFromfram = await withdrawFromMiner( 258 | farm, 259 | wallet, 260 | farmTokenAmount 261 | ); 262 | tx.add(withdrawFromfram); 263 | LPtokenAmount = farmTokenAmount.add(LPtokenAmount); 264 | } 265 | 266 | if (!LPtokenAmount.eq(new BN(0))) { 267 | tx.add( 268 | ins.withdrawOne( 269 | swapInfo, 270 | tokenType, 271 | LPtokenAmount, 272 | minimalRecieve, 273 | wallet, 274 | LPtokenSourceAccount, 275 | recieveTokenAccount 276 | ) 277 | ); 278 | } 279 | 280 | if (tokenType === "A" && swapInfo.mintAWrapped) { 281 | const wrappedmint = swapInfo.mintAWrapInfo 282 | ?.underlyingWrappedTokenMint as PublicKey; 283 | const mintAUnderlyingTokenAccount = await findAssociatedTokenAddress( 284 | wallet, 285 | wrappedmint 286 | ); 287 | 288 | // if false add a create IX 289 | const createmMintAUnderlyingTokenIx = await await createATAWithoutCheckIx( 290 | wallet, 291 | wrappedmint 292 | ); 293 | tx.add(createmMintAUnderlyingTokenIx); 294 | 295 | tx.add( 296 | ins.unwrapToken( 297 | swapInfo.mintAWrapInfo as WrapInfo, 298 | wallet, 299 | recieveTokenAccount, 300 | mintAUnderlyingTokenAccount 301 | ) 302 | ); 303 | } else if (tokenType === "B" && swapInfo.mintBWrapped) { 304 | const wrappedmint = swapInfo.mintBWrapInfo 305 | ?.underlyingWrappedTokenMint as PublicKey; 306 | const mintBUnderlyingTokenAccount = await findAssociatedTokenAddress( 307 | wallet, 308 | wrappedmint 309 | ); 310 | const mintBUnderlyingTokenAccountCreated = await checkTokenAccount( 311 | mintBUnderlyingTokenAccount, 312 | connection 313 | ); 314 | 315 | if (!mintBUnderlyingTokenAccountCreated) { 316 | // if false add a create IX 317 | const createMintBUnderlyingTokenAccount = await createATAWithoutCheckIx( 318 | wallet, 319 | wrappedmint 320 | ); 321 | tx.add(createMintBUnderlyingTokenAccount); 322 | } 323 | tx.add( 324 | ins.unwrapToken( 325 | swapInfo.mintBWrapInfo as WrapInfo, 326 | wallet, 327 | recieveTokenAccount, 328 | mintBUnderlyingTokenAccount 329 | ) 330 | ); 331 | } 332 | 333 | if (recieveTokenAccountMint.toString() === NATIVE_MINT.toString()) { 334 | cleanupTx.add( 335 | Token.createCloseAccountInstruction( 336 | recieveTokenAccount, 337 | wallet, 338 | wallet, 339 | [] 340 | ) 341 | ); 342 | } 343 | tx.add(cleanupTx); 344 | 345 | return tx; 346 | } 347 | 348 | export async function withdrawFromMiner( 349 | farm: FarmInfo, 350 | wallet: PublicKey, 351 | amount: BN 352 | ): Promise { 353 | const tx = new Transaction(); 354 | 355 | if (!amount.eq(new BN(0))) { 356 | tx.add(await createATAWithoutCheckIx(wallet, farm.tokenMintKey)); 357 | 358 | const withdrawFromFarmIns = await ins.withdrawFromFarmIx( 359 | farm, 360 | wallet, 361 | amount 362 | ); 363 | tx.add(withdrawFromFarmIns); 364 | } 365 | 366 | return tx; 367 | } 368 | 369 | export async function claimRewardTx( 370 | farm: FarmInfo, 371 | wallet: PublicKey, 372 | conn: Connection 373 | ): Promise { 374 | const tx = new Transaction(); 375 | const createMinerIx = await createMiner(farm, wallet, conn); 376 | tx.add(createMinerIx); 377 | const iouTokenAccount = await findAssociatedTokenAddress( 378 | wallet, 379 | IOU_TOKEN_MINT 380 | ); 381 | tx.add(await createATAWithoutCheckIx(wallet, IOU_TOKEN_MINT)); 382 | 383 | const sbrTokenAccount = await findAssociatedTokenAddress( 384 | wallet, 385 | SABER_TOKEN_MINT 386 | ); 387 | tx.add(await createATAWithoutCheckIx(wallet, SABER_TOKEN_MINT)); 388 | 389 | tx.add(await ins.claimReward(farm, wallet)); 390 | tx.add( 391 | Token.createCloseAccountInstruction(iouTokenAccount, wallet, wallet, []) 392 | ); 393 | return tx; 394 | } 395 | -------------------------------------------------------------------------------- /raydium/instructions.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { PublicKey, TransactionInstruction } from "@solana/web3.js"; 3 | import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; 4 | import { 5 | ADD_LIQUIDITY_LAYOUT, 6 | REMOVE_LIQUIDITY_LAYOUT, 7 | SWAP_LAYOUT, 8 | } from "./layouts"; 9 | 10 | export function swapInstruction( 11 | programId: PublicKey, 12 | // amm 13 | ammId: PublicKey, 14 | ammAuthority: PublicKey, 15 | ammOpenOrders: PublicKey, 16 | ammTargetOrders: PublicKey, 17 | poolCoinTokenAccount: PublicKey, 18 | poolPcTokenAccount: PublicKey, 19 | // serum 20 | serumProgramId: PublicKey, 21 | serumMarket: PublicKey, 22 | serumBids: PublicKey, 23 | serumAsks: PublicKey, 24 | serumEventQueue: PublicKey, 25 | serumCoinVaultAccount: PublicKey, 26 | serumPcVaultAccount: PublicKey, 27 | serumVaultSigner: PublicKey, 28 | // user 29 | userSourceTokenAccount: PublicKey, 30 | userDestTokenAccount: PublicKey, 31 | userOwner: PublicKey, 32 | amountIn: BN, 33 | minAmountOut: BN 34 | ): TransactionInstruction { 35 | const keys = [ 36 | // spl token 37 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 38 | // amm 39 | { pubkey: ammId, isSigner: false, isWritable: true }, 40 | { pubkey: ammAuthority, isSigner: false, isWritable: false }, 41 | { pubkey: ammOpenOrders, isSigner: false, isWritable: true }, 42 | { pubkey: ammTargetOrders, isSigner: false, isWritable: true }, 43 | { pubkey: poolCoinTokenAccount, isSigner: false, isWritable: true }, 44 | { pubkey: poolPcTokenAccount, isSigner: false, isWritable: true }, 45 | // serum 46 | { pubkey: serumProgramId, isSigner: false, isWritable: false }, 47 | { pubkey: serumMarket, isSigner: false, isWritable: true }, 48 | { pubkey: serumBids, isSigner: false, isWritable: true }, 49 | { pubkey: serumAsks, isSigner: false, isWritable: true }, 50 | { pubkey: serumEventQueue, isSigner: false, isWritable: true }, 51 | { pubkey: serumCoinVaultAccount, isSigner: false, isWritable: true }, 52 | { pubkey: serumPcVaultAccount, isSigner: false, isWritable: true }, 53 | { pubkey: serumVaultSigner, isSigner: false, isWritable: false }, 54 | { pubkey: userSourceTokenAccount, isSigner: false, isWritable: true }, 55 | { pubkey: userDestTokenAccount, isSigner: false, isWritable: true }, 56 | { pubkey: userOwner, isSigner: true, isWritable: false }, 57 | ]; 58 | 59 | const data = Buffer.alloc(SWAP_LAYOUT.span); 60 | SWAP_LAYOUT.encode( 61 | { 62 | instruction: 9, 63 | amountIn, 64 | minAmountOut, 65 | }, 66 | data 67 | ); 68 | 69 | return new TransactionInstruction({ 70 | keys, 71 | programId, 72 | data, 73 | }); 74 | } 75 | 76 | export function addLiquidityInstruction( 77 | programId: PublicKey, 78 | // amm 79 | ammId: PublicKey, 80 | ammAuthority: PublicKey, 81 | ammOpenOrders: PublicKey, 82 | ammQuantities: PublicKey, 83 | lpMintAddress: PublicKey, 84 | poolCoinTokenAccount: PublicKey, 85 | poolPcTokenAccount: PublicKey, 86 | // serum 87 | serumMarket: PublicKey, 88 | // user 89 | userCoinTokenAccount: PublicKey, 90 | userPcTokenAccount: PublicKey, 91 | userLpTokenAccount: PublicKey, 92 | userOwner: PublicKey, 93 | maxCoinAmount: BN, 94 | maxPcAmount: BN, 95 | fixedFromCoin: BN 96 | ): TransactionInstruction { 97 | const keys = [ 98 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 99 | { pubkey: ammId, isSigner: false, isWritable: true }, 100 | { pubkey: ammAuthority, isSigner: false, isWritable: false }, 101 | { pubkey: ammOpenOrders, isSigner: false, isWritable: false }, 102 | { pubkey: ammQuantities, isSigner: false, isWritable: true }, 103 | { pubkey: lpMintAddress, isSigner: false, isWritable: true }, 104 | { pubkey: poolCoinTokenAccount, isSigner: false, isWritable: true }, 105 | { pubkey: poolPcTokenAccount, isSigner: false, isWritable: true }, 106 | { pubkey: serumMarket, isSigner: false, isWritable: false }, 107 | { pubkey: userCoinTokenAccount, isSigner: false, isWritable: true }, 108 | { pubkey: userPcTokenAccount, isSigner: false, isWritable: true }, 109 | { pubkey: userLpTokenAccount, isSigner: false, isWritable: true }, 110 | { pubkey: userOwner, isSigner: true, isWritable: false }, 111 | ]; 112 | 113 | const data = Buffer.alloc(ADD_LIQUIDITY_LAYOUT.span); 114 | ADD_LIQUIDITY_LAYOUT.encode( 115 | { 116 | instruction: 3, 117 | maxCoinAmount, 118 | maxPcAmount, 119 | fixedFromCoin, 120 | }, 121 | data 122 | ); 123 | 124 | return new TransactionInstruction({ 125 | keys, 126 | programId, 127 | data, 128 | }); 129 | } 130 | 131 | export function addLiquidityInstructionV4( 132 | programId: PublicKey, 133 | // amm 134 | ammId: PublicKey, 135 | ammAuthority: PublicKey, 136 | ammOpenOrders: PublicKey, 137 | ammTargetOrders: PublicKey, 138 | lpMintAddress: PublicKey, 139 | poolCoinTokenAccount: PublicKey, 140 | poolPcTokenAccount: PublicKey, 141 | // serum 142 | serumMarket: PublicKey, 143 | // user 144 | userCoinTokenAccount: PublicKey, 145 | userPcTokenAccount: PublicKey, 146 | userLpTokenAccount: PublicKey, 147 | userOwner: PublicKey, 148 | maxCoinAmount: BN, 149 | maxPcAmount: BN, 150 | fixedFromCoin: BN 151 | ): TransactionInstruction { 152 | const keys = [ 153 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 154 | { pubkey: ammId, isSigner: false, isWritable: true }, 155 | { pubkey: ammAuthority, isSigner: false, isWritable: false }, 156 | { pubkey: ammOpenOrders, isSigner: false, isWritable: false }, 157 | { pubkey: ammTargetOrders, isSigner: false, isWritable: true }, 158 | { pubkey: lpMintAddress, isSigner: false, isWritable: true }, 159 | { pubkey: poolCoinTokenAccount, isSigner: false, isWritable: true }, 160 | { pubkey: poolPcTokenAccount, isSigner: false, isWritable: true }, 161 | { pubkey: serumMarket, isSigner: false, isWritable: false }, 162 | { pubkey: userCoinTokenAccount, isSigner: false, isWritable: true }, 163 | { pubkey: userPcTokenAccount, isSigner: false, isWritable: true }, 164 | { pubkey: userLpTokenAccount, isSigner: false, isWritable: true }, 165 | { pubkey: userOwner, isSigner: true, isWritable: false }, 166 | ]; 167 | 168 | const data = Buffer.alloc(ADD_LIQUIDITY_LAYOUT.span); 169 | ADD_LIQUIDITY_LAYOUT.encode( 170 | { 171 | instruction: 3, 172 | maxCoinAmount, 173 | maxPcAmount, 174 | fixedFromCoin, 175 | }, 176 | data 177 | ); 178 | 179 | return new TransactionInstruction({ 180 | keys, 181 | programId, 182 | data, 183 | }); 184 | } 185 | 186 | export function removeLiquidityInstruction( 187 | programId: PublicKey, 188 | // amm 189 | ammId: PublicKey, 190 | ammAuthority: PublicKey, 191 | ammOpenOrders: PublicKey, 192 | ammQuantities: PublicKey, 193 | lpMintAddress: PublicKey, 194 | poolCoinTokenAccount: PublicKey, 195 | poolPcTokenAccount: PublicKey, 196 | poolWithdrawQueue: PublicKey, 197 | poolTempLpTokenAccount: PublicKey, 198 | // serum 199 | serumProgramId: PublicKey, 200 | serumMarket: PublicKey, 201 | serumCoinVaultAccount: PublicKey, 202 | serumPcVaultAccount: PublicKey, 203 | serumVaultSigner: PublicKey, 204 | // user 205 | userLpTokenAccount: PublicKey, 206 | userCoinTokenAccount: PublicKey, 207 | userPcTokenAccount: PublicKey, 208 | userOwner: PublicKey, 209 | amount: BN 210 | ): TransactionInstruction { 211 | const keys = [ 212 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 213 | { pubkey: ammId, isSigner: false, isWritable: true }, 214 | { pubkey: ammAuthority, isSigner: false, isWritable: false }, 215 | { pubkey: ammOpenOrders, isSigner: false, isWritable: true }, 216 | { pubkey: ammQuantities, isSigner: false, isWritable: true }, 217 | { pubkey: lpMintAddress, isSigner: false, isWritable: true }, 218 | { pubkey: poolCoinTokenAccount, isSigner: false, isWritable: true }, 219 | { pubkey: poolPcTokenAccount, isSigner: false, isWritable: true }, 220 | { pubkey: poolWithdrawQueue, isSigner: false, isWritable: true }, 221 | { pubkey: poolTempLpTokenAccount, isSigner: false, isWritable: true }, 222 | { pubkey: serumProgramId, isSigner: false, isWritable: false }, 223 | { pubkey: serumMarket, isSigner: false, isWritable: true }, 224 | { pubkey: serumCoinVaultAccount, isSigner: false, isWritable: true }, 225 | { pubkey: serumPcVaultAccount, isSigner: false, isWritable: true }, 226 | { pubkey: serumVaultSigner, isSigner: false, isWritable: false }, 227 | { pubkey: userLpTokenAccount, isSigner: false, isWritable: true }, 228 | { pubkey: userCoinTokenAccount, isSigner: false, isWritable: true }, 229 | { pubkey: userPcTokenAccount, isSigner: false, isWritable: true }, 230 | { pubkey: userOwner, isSigner: true, isWritable: false }, 231 | ]; 232 | 233 | const data = Buffer.alloc(REMOVE_LIQUIDITY_LAYOUT.span); 234 | REMOVE_LIQUIDITY_LAYOUT.encode( 235 | { 236 | instruction: 4, 237 | amount, 238 | }, 239 | data 240 | ); 241 | 242 | return new TransactionInstruction({ 243 | keys, 244 | programId, 245 | data, 246 | }); 247 | } 248 | 249 | export function removeLiquidityInstructionV4( 250 | programId: PublicKey, 251 | // amm 252 | ammId: PublicKey, 253 | ammAuthority: PublicKey, 254 | ammOpenOrders: PublicKey, 255 | ammTargetOrders: PublicKey, 256 | lpMintAddress: PublicKey, 257 | poolCoinTokenAccount: PublicKey, 258 | poolPcTokenAccount: PublicKey, 259 | poolWithdrawQueue: PublicKey, 260 | poolTempLpTokenAccount: PublicKey, 261 | // serum 262 | serumProgramId: PublicKey, 263 | serumMarket: PublicKey, 264 | serumCoinVaultAccount: PublicKey, 265 | serumPcVaultAccount: PublicKey, 266 | serumVaultSigner: PublicKey, 267 | // user 268 | userLpTokenAccount: PublicKey, 269 | userCoinTokenAccount: PublicKey, 270 | userPcTokenAccount: PublicKey, 271 | userOwner: PublicKey, 272 | amount: BN 273 | ): TransactionInstruction { 274 | const keys = [ 275 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 276 | { pubkey: ammId, isSigner: false, isWritable: true }, 277 | { pubkey: ammAuthority, isSigner: false, isWritable: false }, 278 | { pubkey: ammOpenOrders, isSigner: false, isWritable: true }, 279 | { pubkey: ammTargetOrders, isSigner: false, isWritable: true }, 280 | { pubkey: lpMintAddress, isSigner: false, isWritable: true }, 281 | { pubkey: poolCoinTokenAccount, isSigner: false, isWritable: true }, 282 | { pubkey: poolPcTokenAccount, isSigner: false, isWritable: true }, 283 | { pubkey: poolWithdrawQueue, isSigner: false, isWritable: true }, 284 | { pubkey: poolTempLpTokenAccount, isSigner: false, isWritable: true }, 285 | { pubkey: serumProgramId, isSigner: false, isWritable: false }, 286 | { pubkey: serumMarket, isSigner: false, isWritable: true }, 287 | { pubkey: serumCoinVaultAccount, isSigner: false, isWritable: true }, 288 | { pubkey: serumPcVaultAccount, isSigner: false, isWritable: true }, 289 | { pubkey: serumVaultSigner, isSigner: false, isWritable: false }, 290 | { pubkey: userLpTokenAccount, isSigner: false, isWritable: true }, 291 | { pubkey: userCoinTokenAccount, isSigner: false, isWritable: true }, 292 | { pubkey: userPcTokenAccount, isSigner: false, isWritable: true }, 293 | { pubkey: userOwner, isSigner: true, isWritable: false }, 294 | ]; 295 | 296 | const data = Buffer.alloc(REMOVE_LIQUIDITY_LAYOUT.span); 297 | REMOVE_LIQUIDITY_LAYOUT.encode( 298 | { 299 | instruction: 4, 300 | amount, 301 | }, 302 | data 303 | ); 304 | 305 | return new TransactionInstruction({ 306 | keys, 307 | programId, 308 | data, 309 | }); 310 | } 311 | -------------------------------------------------------------------------------- /raydium/infos.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { OpenOrders } from "@project-serum/serum"; 3 | import { Connection, PublicKey, AccountInfo } from "@solana/web3.js"; 4 | import { parseTokenAccount } from "../utils"; 5 | import { AMM_INFO_LAYOUT_V4 } from "./layouts"; 6 | 7 | export interface LiquidityPoolInfo { 8 | infoPubkey: PublicKey; 9 | version: number; 10 | status: BN; 11 | nonce: BN; 12 | orderNum: BN; 13 | depth: BN; 14 | coinDecimals: BN; 15 | pcDecimals: BN; 16 | state: BN; 17 | resetFlag: BN; 18 | minSize: BN; 19 | volMaxCutRatio: BN; 20 | amountWaveRatio: BN; 21 | coinLotSize: BN; 22 | pcLotSize: BN; 23 | minPriceMultiplier: BN; 24 | maxPriceMultiplier: BN; 25 | needTakePnlCoin: BN; 26 | needTakePnlPc: BN; 27 | totalPnlPc: BN; 28 | totalPnlCoin: BN; 29 | poolTotalDepositPc: BN; 30 | poolTotalDepositCoin: BN; 31 | systemDecimalsValue: BN; 32 | poolCoinTokenAccount: PublicKey; 33 | poolPcTokenAccount: PublicKey; 34 | coinMintAddress: PublicKey; 35 | pcMintAddress: PublicKey; 36 | lpMintAddress: PublicKey; 37 | ammOpenOrders: PublicKey; 38 | serumMarket: PublicKey; 39 | serumProgramId: PublicKey; 40 | ammTargetOrders: PublicKey; 41 | poolWithdrawQueue: PublicKey; 42 | poolTempLpTokenAccount: PublicKey; 43 | ammOwner: PublicKey; 44 | pnlOwner: PublicKey; 45 | coinAccountAmount?: BN; 46 | pcAccountAmount?: BN; 47 | srmTokenAccount?: PublicKey; 48 | ammQuantities?: PublicKey; 49 | } 50 | 51 | export class PoolInfo implements LiquidityPoolInfo { 52 | infoPubkey: PublicKey; 53 | version: number; 54 | status: BN; 55 | nonce: BN; 56 | orderNum: BN; 57 | depth: BN; 58 | coinDecimals: BN; 59 | pcDecimals: BN; 60 | state: BN; 61 | resetFlag: BN; 62 | minSize: BN; 63 | volMaxCutRatio: BN; 64 | amountWaveRatio: BN; 65 | coinLotSize: BN; 66 | pcLotSize: BN; 67 | minPriceMultiplier: BN; 68 | maxPriceMultiplier: BN; 69 | needTakePnlCoin: BN; 70 | needTakePnlPc: BN; 71 | totalPnlPc: BN; 72 | totalPnlCoin: BN; 73 | poolTotalDepositPc: BN; 74 | poolTotalDepositCoin: BN; 75 | systemDecimalsValue: BN; 76 | poolCoinTokenAccount: PublicKey; 77 | poolPcTokenAccount: PublicKey; 78 | coinMintAddress: PublicKey; 79 | pcMintAddress: PublicKey; 80 | lpMintAddress: PublicKey; 81 | ammOpenOrders: PublicKey; 82 | serumMarket: PublicKey; 83 | serumProgramId: PublicKey; 84 | ammTargetOrders: PublicKey; 85 | poolWithdrawQueue: PublicKey; 86 | poolTempLpTokenAccount: PublicKey; 87 | ammOwner: PublicKey; 88 | pnlOwner: PublicKey; 89 | coinAccountAmount?: BN; 90 | pcAccountAmount?: BN; 91 | ammOrderbaseTokenTotal?: BN; 92 | ammOrderquoteTokenTotal?: BN; 93 | srmTokenAccount?: PublicKey; 94 | ammQuantities?: PublicKey; 95 | constructor( 96 | infoPubkey: PublicKey, 97 | version: number, 98 | status: BN, 99 | nonce: BN, 100 | orderNum: BN, 101 | depth: BN, 102 | coinDecimals: BN, 103 | pcDecimals: BN, 104 | state: BN, 105 | resetFlag: BN, 106 | minSize: BN, 107 | volMaxCutRatio: BN, 108 | amountWaveRatio: BN, 109 | coinLotSize: BN, 110 | pcLotSize: BN, 111 | minPriceMultiplier: BN, 112 | maxPriceMultiplier: BN, 113 | needTakePnlCoin: BN, 114 | needTakePnlPc: BN, 115 | totalPnlPc: BN, 116 | totalPnlCoin: BN, 117 | poolTotalDepositPc: BN, 118 | poolTotalDepositCoin: BN, 119 | systemDecimalsValue: BN, 120 | poolCoinTokenAccount: PublicKey, 121 | poolPcTokenAccount: PublicKey, 122 | coinMintAddress: PublicKey, 123 | pcMintAddress: PublicKey, 124 | lpMintAddress: PublicKey, 125 | ammOpenOrders: PublicKey, 126 | serumMarket: PublicKey, 127 | serumProgramId: PublicKey, 128 | ammTargetOrders: PublicKey, 129 | poolWithdrawQueue: PublicKey, 130 | poolTempLpTokenAccount: PublicKey, 131 | ammOwner: PublicKey, 132 | pnlOwner: PublicKey, 133 | srmTokenAccount?: PublicKey, 134 | ammQuantities?: PublicKey 135 | ) { 136 | this.totalPnlPc = totalPnlPc; 137 | this.totalPnlCoin = totalPnlCoin; 138 | this.infoPubkey = infoPubkey; 139 | this.version = version; 140 | this.status = status; 141 | this.nonce = nonce; 142 | this.orderNum = orderNum; 143 | this.depth = depth; 144 | this.coinDecimals = coinDecimals; 145 | this.pcDecimals = pcDecimals; 146 | this.state = state; 147 | this.resetFlag = resetFlag; 148 | this.minSize = minSize; 149 | this.volMaxCutRatio = volMaxCutRatio; 150 | this.amountWaveRatio = amountWaveRatio; 151 | this.coinLotSize = coinLotSize; 152 | this.pcLotSize = pcLotSize; 153 | this.minPriceMultiplier = minPriceMultiplier; 154 | this.maxPriceMultiplier = maxPriceMultiplier; 155 | this.needTakePnlCoin = needTakePnlCoin; 156 | this.needTakePnlPc = needTakePnlPc; 157 | this.poolTotalDepositPc = poolTotalDepositPc; 158 | this.poolTotalDepositCoin = poolTotalDepositCoin; 159 | this.systemDecimalsValue = systemDecimalsValue; 160 | this.poolCoinTokenAccount = poolCoinTokenAccount; 161 | this.poolPcTokenAccount = poolPcTokenAccount; 162 | this.coinMintAddress = coinMintAddress; 163 | this.pcMintAddress = pcMintAddress; 164 | this.lpMintAddress = lpMintAddress; 165 | this.ammOpenOrders = ammOpenOrders; 166 | this.serumMarket = serumMarket; 167 | this.serumProgramId = serumProgramId; 168 | this.ammTargetOrders = ammTargetOrders; 169 | this.ammQuantities = ammQuantities; 170 | this.poolWithdrawQueue = poolWithdrawQueue; 171 | this.poolTempLpTokenAccount = poolTempLpTokenAccount; 172 | this.ammOwner = ammOwner; 173 | this.pnlOwner = pnlOwner; 174 | this.srmTokenAccount = srmTokenAccount; 175 | } 176 | async calculateSwapOutAmount( 177 | fromSide: string, 178 | amountIn: BN, 179 | connection: Connection 180 | ) { 181 | const pool = await this.updatePoolAmount(connection); 182 | if (fromSide === "coin") { 183 | const x1 = pool.coinAccountAmount 184 | ?.add(pool.ammOrderbaseTokenTotal as BN) 185 | .sub(pool.needTakePnlCoin) as BN; 186 | const y1 = pool.pcAccountAmount 187 | ?.add(pool.ammOrderquoteTokenTotal as BN) 188 | .sub(pool.needTakePnlPc) as BN; 189 | const k = x1.mul(y1); 190 | const x2 = x1.add(amountIn); 191 | const y2 = k.div(x2); 192 | const amountOut = y1.sub(y2); 193 | 194 | return amountOut; 195 | } else if (fromSide === "pc") { 196 | const x1 = pool.pcAccountAmount 197 | ?.add(pool.ammOrderquoteTokenTotal as BN) 198 | .sub(pool.needTakePnlPc) as BN; 199 | const y1 = pool.coinAccountAmount 200 | ?.add(pool.ammOrderbaseTokenTotal as BN) 201 | .sub(pool.needTakePnlCoin) as BN; 202 | const k = x1.mul(y1); 203 | const x2 = x1.add(amountIn); 204 | const y2 = k.div(x2); 205 | const amountOut = y1.sub(y2); 206 | 207 | return amountOut; 208 | } 209 | 210 | return new BN(0); 211 | } 212 | async updatePoolAmount(connection: Connection) { 213 | const accounts: PublicKey[] = []; 214 | accounts.push(this.poolPcTokenAccount); 215 | accounts.push(this.poolCoinTokenAccount); 216 | accounts.push(this.ammOpenOrders); 217 | const infos = (await connection.getMultipleAccountsInfo( 218 | accounts 219 | )) as AccountInfo[]; 220 | 221 | const pc = parseTokenAccount(infos[0].data, accounts[0]); 222 | this.pcAccountAmount = pc.amount; 223 | const coin = parseTokenAccount(infos[1].data, accounts[1]); 224 | this.coinAccountAmount = coin.amount; 225 | const ammOrder = OpenOrders.fromAccountInfo( 226 | accounts[2], 227 | infos[2], 228 | this.serumProgramId 229 | ); 230 | this.ammOrderquoteTokenTotal = ammOrder.quoteTokenTotal; 231 | this.ammOrderbaseTokenTotal = ammOrder.baseTokenTotal; 232 | return this; 233 | } 234 | } 235 | 236 | export function parseV4PoolInfo(data: any, infoPubkey: PublicKey) { 237 | const poolData = Buffer.from(data); 238 | const rawPoolData = AMM_INFO_LAYOUT_V4.decode(poolData); 239 | const { 240 | status, 241 | nonce, 242 | orderNum, 243 | depth, 244 | coinDecimals, 245 | pcDecimals, 246 | state, 247 | resetFlag, 248 | minSize, 249 | volMaxCutRatio, 250 | amountWaveRatio, 251 | coinLotSize, 252 | pcLotSize, 253 | minPriceMultiplier, 254 | maxPriceMultiplier, 255 | systemDecimalsValue, 256 | minSeparateNumerator, 257 | minSeparateDenominator, 258 | tradeFeeNumerator, 259 | tradeFeeDenominator, 260 | pnlNumerator, 261 | pnlDenominator, 262 | swapFeeNumerator, 263 | swapFeeDenominator, 264 | needTakePnlCoin, 265 | needTakePnlPc, 266 | totalPnlPc, 267 | totalPnlCoin, 268 | poolTotalDepositPc, 269 | poolTotalDepositCoin, 270 | swapCoinInAmount, 271 | swapPcOutAmount, 272 | swapCoin2PcFee, 273 | swapPcInAmount, 274 | swapCoinOutAmount, 275 | swapPc2CoinFee, 276 | poolCoinTokenAccount, 277 | poolPcTokenAccount, 278 | coinMintAddress, 279 | pcMintAddress, 280 | lpMintAddress, 281 | ammOpenOrders, 282 | serumMarket, 283 | serumProgramId, 284 | ammTargetOrders, 285 | poolWithdrawQueue, 286 | poolTempLpTokenAccount, 287 | ammOwner, 288 | pnlOwner, 289 | } = rawPoolData; 290 | return new PoolInfo( 291 | infoPubkey, 292 | 4, 293 | status, 294 | nonce, 295 | orderNum, 296 | depth, 297 | coinDecimals, 298 | pcDecimals, 299 | state, 300 | resetFlag, 301 | minSize, 302 | volMaxCutRatio, 303 | amountWaveRatio, 304 | coinLotSize, 305 | pcLotSize, 306 | minPriceMultiplier, 307 | maxPriceMultiplier, 308 | needTakePnlCoin, 309 | needTakePnlPc, 310 | totalPnlPc, 311 | totalPnlCoin, 312 | poolTotalDepositPc, 313 | poolTotalDepositCoin, 314 | systemDecimalsValue, 315 | poolCoinTokenAccount, 316 | poolPcTokenAccount, 317 | coinMintAddress, 318 | pcMintAddress, 319 | lpMintAddress, 320 | ammOpenOrders, 321 | serumMarket, 322 | serumProgramId, 323 | ammTargetOrders, 324 | poolWithdrawQueue, 325 | poolTempLpTokenAccount, 326 | ammOwner, 327 | pnlOwner 328 | ); 329 | } 330 | 331 | export async function updateAllTokenAmount( 332 | pools: PoolInfo[], 333 | connection: Connection 334 | ) { 335 | let accounts: PublicKey[] = []; 336 | let allAccountInfo: AccountInfo[] = []; 337 | for (const pool of pools) { 338 | accounts.push(pool.poolPcTokenAccount); 339 | accounts.push(pool.poolCoinTokenAccount); 340 | accounts.push(pool.ammOpenOrders); 341 | if (accounts.length > 96) { 342 | const infos = (await connection.getMultipleAccountsInfo( 343 | accounts 344 | )) as AccountInfo[]; 345 | allAccountInfo = allAccountInfo.concat(infos); 346 | accounts = []; 347 | } 348 | } 349 | const infos = (await connection.getMultipleAccountsInfo( 350 | accounts 351 | )) as AccountInfo[]; 352 | allAccountInfo = allAccountInfo.concat(infos); 353 | for (let index = 0; index < pools.length; index++) { 354 | const pc = parseTokenAccount( 355 | allAccountInfo[index * 3].data, 356 | pools[index].poolPcTokenAccount 357 | ); 358 | pools[index].pcAccountAmount = pc.amount; 359 | const coin = parseTokenAccount( 360 | allAccountInfo[index * 3 + 1].data, 361 | pools[index].poolCoinTokenAccount 362 | ); 363 | pools[index].coinAccountAmount = coin.amount; 364 | const ammOrder = OpenOrders.fromAccountInfo( 365 | pools[index].ammOpenOrders, 366 | allAccountInfo[index * 3 + 2], 367 | pools[index].serumProgramId 368 | ); 369 | pools[index].ammOrderquoteTokenTotal = ammOrder.quoteTokenTotal; 370 | pools[index].ammOrderbaseTokenTotal = ammOrder.baseTokenTotal; 371 | } 372 | return pools; 373 | } 374 | -------------------------------------------------------------------------------- /saber/instructions.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { 3 | PublicKey, 4 | SYSVAR_CLOCK_PUBKEY, 5 | Transaction, 6 | TransactionInstruction, 7 | SystemProgram, 8 | } from "@solana/web3.js"; 9 | import { TOKEN_PROGRAM_ID } from "@solana/spl-token"; 10 | import { 11 | SWAP_PROGRAM_ID, 12 | SABER_WRAP_PROGRAM_ID, 13 | QURARRY_MINE_PROGRAM_ID, 14 | SABER_QUARRY_REWARDER, 15 | SABER_FARM_MINTER, 16 | SABER_MINT_WRAPPER, 17 | QURARRY_MINT_WRAPPER, 18 | IOU_TOKEN_MINT, 19 | CLAIM_FEE_TOKEN_ACCOUNT, 20 | SABER_TOKEN_MINT, 21 | MINTER_PROGRAM_ID, 22 | } from "./ids"; 23 | import { 24 | CREATE_MINER_LAYOUT, 25 | DEPOSIT_LAYPOUT, 26 | DEPOSIT_TO_FARM_LAYOUT, 27 | UNWRAP_LAYOUT, 28 | WITHDRAW_FROM_FARM_LAYOUT, 29 | WITHDRAW_LAYOUT, 30 | WRAP_LAYOUT, 31 | } from "./layouts"; 32 | import { SwapInfo, WrapInfo, FarmInfo, getMinerKey } from "./infos"; 33 | import { findAssociatedTokenAddress } from "../utils"; 34 | 35 | enum SaberInstruction { 36 | swap = 1, 37 | deposit = 2, 38 | withdraw = 3, 39 | withdrawOne = 4, 40 | } 41 | 42 | export function deposit( 43 | swapInfo: SwapInfo, 44 | AtokenAmount: BN, 45 | BtokenAmount: BN, 46 | minimalRecieve: BN, 47 | wallet: PublicKey, 48 | AtokenSourceAccount: PublicKey, 49 | BtokenSourceAccount: PublicKey, 50 | LPtokenAccount: PublicKey 51 | ) { 52 | const data = Buffer.alloc(DEPOSIT_LAYPOUT.span); 53 | DEPOSIT_LAYPOUT.encode( 54 | { 55 | instruction: SaberInstruction.deposit, 56 | AtokenAmount: new BN(AtokenAmount), 57 | BtokenAmount: new BN(BtokenAmount), 58 | minimalRecieve: new BN(minimalRecieve), 59 | }, 60 | data 61 | ); 62 | const keys = [ 63 | { pubkey: swapInfo.infoPublicKey, isSigner: false, isWritable: false }, 64 | { pubkey: swapInfo.authority, isSigner: false, isWritable: false }, 65 | { pubkey: wallet, isSigner: true, isWritable: false }, 66 | { pubkey: AtokenSourceAccount, isSigner: false, isWritable: true }, 67 | { pubkey: BtokenSourceAccount, isSigner: false, isWritable: true }, 68 | { pubkey: swapInfo.tokenAccountA, isSigner: false, isWritable: true }, 69 | { pubkey: swapInfo.tokenAccountB, isSigner: false, isWritable: true }, 70 | { pubkey: swapInfo.poolMint, isSigner: false, isWritable: true }, 71 | { pubkey: LPtokenAccount, isSigner: false, isWritable: true }, 72 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 73 | { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, 74 | ]; 75 | 76 | return new TransactionInstruction({ 77 | keys, 78 | programId: SWAP_PROGRAM_ID, 79 | data, 80 | }); 81 | } 82 | 83 | export function withdrawOne( 84 | swapInfo: SwapInfo, 85 | tokenType: string, 86 | LPtokenAmount: BN, 87 | minimalRecieve: BN, 88 | wallet: PublicKey, 89 | LPtokenSourceAccount: PublicKey, 90 | recieveTokenAccount: PublicKey 91 | ) { 92 | const data = Buffer.alloc(WITHDRAW_LAYOUT.span); 93 | WITHDRAW_LAYOUT.encode( 94 | { 95 | instruction: SaberInstruction.withdrawOne, 96 | LPtokenAmount: new BN(LPtokenAmount), 97 | minimalRecieve: new BN(minimalRecieve), 98 | }, 99 | data 100 | ); 101 | let baseTokenAccount = PublicKey.default; 102 | let quoteTokenAccount = PublicKey.default; 103 | let feeTokenAccount = PublicKey.default; 104 | if (tokenType === "A") { 105 | baseTokenAccount = swapInfo.tokenAccountA; 106 | quoteTokenAccount = swapInfo.tokenAccountB; 107 | feeTokenAccount = swapInfo.adminFeeAccountA; 108 | } else if (tokenType === "B") { 109 | baseTokenAccount = swapInfo.tokenAccountB; 110 | quoteTokenAccount = swapInfo.tokenAccountA; 111 | feeTokenAccount = swapInfo.adminFeeAccountB; 112 | } else { 113 | console.log("panic!!, no withdraw type provided"); 114 | } 115 | 116 | const keys = [ 117 | { pubkey: swapInfo.infoPublicKey, isSigner: false, isWritable: false }, 118 | { pubkey: swapInfo.authority, isSigner: false, isWritable: false }, 119 | { pubkey: wallet, isSigner: true, isWritable: false }, 120 | { pubkey: swapInfo.poolMint, isSigner: false, isWritable: true }, 121 | { pubkey: LPtokenSourceAccount, isSigner: false, isWritable: true }, 122 | { pubkey: baseTokenAccount, isSigner: false, isWritable: true }, 123 | { pubkey: quoteTokenAccount, isSigner: false, isWritable: true }, 124 | { pubkey: recieveTokenAccount, isSigner: false, isWritable: true }, 125 | { pubkey: feeTokenAccount, isSigner: false, isWritable: true }, 126 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 127 | { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, 128 | ]; 129 | return new TransactionInstruction({ 130 | keys, 131 | programId: SWAP_PROGRAM_ID, 132 | data, 133 | }); 134 | } 135 | 136 | export function wrapToken( 137 | wrapInfo: WrapInfo, 138 | wallet: PublicKey, 139 | amount: BN, 140 | wrapInTokenAccount: PublicKey, 141 | wrapOutTokenAccount: PublicKey 142 | ) { 143 | if (amount.eq(new BN(0))) { 144 | return new Transaction(); 145 | } 146 | let data = Buffer.alloc(WRAP_LAYOUT.span); 147 | WRAP_LAYOUT.encode( 148 | { 149 | amount: new BN(amount), 150 | }, 151 | data 152 | ); 153 | const datahex = data.toString("hex"); 154 | const datastring = "f223c68952e1f2b6".concat(datahex); 155 | data = Buffer.from(datastring, "hex"); 156 | const keys = [ 157 | { pubkey: wrapInfo.wrapAuthority, isSigner: false, isWritable: true }, 158 | { pubkey: wrapInfo.wrappedTokenMint, isSigner: false, isWritable: true }, 159 | { 160 | pubkey: wrapInfo.underlyingTokenAccount, 161 | isSigner: false, 162 | isWritable: true, 163 | }, 164 | { pubkey: wallet, isSigner: true, isWritable: false }, 165 | { pubkey: wrapInTokenAccount, isSigner: false, isWritable: true }, 166 | { pubkey: wrapOutTokenAccount, isSigner: false, isWritable: true }, 167 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 168 | ]; 169 | return new TransactionInstruction({ 170 | keys, 171 | programId: SABER_WRAP_PROGRAM_ID, 172 | data, 173 | }); 174 | } 175 | 176 | export function unwrapToken( 177 | wrapInfo: WrapInfo, 178 | wallet: PublicKey, 179 | unwrapTokenAccount: PublicKey, 180 | originalTokenAccount: PublicKey 181 | ) { 182 | let data = Buffer.alloc(UNWRAP_LAYOUT.span); 183 | const datastring = "60f6a682e5322b46"; 184 | data = Buffer.from(datastring, "hex"); 185 | const keys = [ 186 | { pubkey: wrapInfo.wrapAuthority, isSigner: false, isWritable: true }, 187 | { pubkey: wrapInfo.wrappedTokenMint, isSigner: false, isWritable: true }, 188 | { 189 | pubkey: wrapInfo.underlyingTokenAccount, 190 | isSigner: false, 191 | isWritable: true, 192 | }, 193 | { pubkey: wallet, isSigner: true, isWritable: false }, 194 | { pubkey: originalTokenAccount, isSigner: false, isWritable: true }, 195 | { pubkey: unwrapTokenAccount, isSigner: false, isWritable: true }, 196 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 197 | ]; 198 | return new TransactionInstruction({ 199 | keys, 200 | programId: SABER_WRAP_PROGRAM_ID, 201 | data, 202 | }); 203 | } 204 | 205 | export async function depositToFarmIx( 206 | farmInfo: FarmInfo, 207 | wallet: PublicKey, 208 | amount: BN 209 | ) { 210 | const miner = await getMinerKey(wallet, farmInfo.infoPubkey); 211 | const minerVault = await findAssociatedTokenAddress( 212 | miner[0], 213 | farmInfo.tokenMintKey 214 | ); 215 | const minerLPAccount = await findAssociatedTokenAddress( 216 | wallet, 217 | farmInfo.tokenMintKey 218 | ); 219 | const amountData = Buffer.alloc(DEPOSIT_TO_FARM_LAYOUT.span); 220 | DEPOSIT_TO_FARM_LAYOUT.encode( 221 | { 222 | amount: new BN(amount), 223 | }, 224 | amountData 225 | ); 226 | const dataString = "887e5ba228830d7f".concat(amountData.toString("hex")); 227 | const data = Buffer.from(dataString, "hex"); 228 | const keys = [ 229 | { pubkey: wallet, isSigner: true, isWritable: true }, 230 | { pubkey: miner[0], isSigner: false, isWritable: true }, 231 | { pubkey: farmInfo.infoPubkey, isSigner: false, isWritable: true }, 232 | { pubkey: minerVault, isSigner: false, isWritable: true }, 233 | { pubkey: minerLPAccount, isSigner: false, isWritable: true }, 234 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 235 | { pubkey: SABER_QUARRY_REWARDER, isSigner: false, isWritable: false }, 236 | ]; 237 | return new TransactionInstruction({ 238 | keys, 239 | programId: QURARRY_MINE_PROGRAM_ID, 240 | data, 241 | }); 242 | } 243 | 244 | export async function createMinerAccountIx( 245 | FarmInfo: FarmInfo, 246 | wallet: PublicKey 247 | ) { 248 | const miner = await getMinerKey(wallet, FarmInfo.infoPubkey); 249 | const bumpData = Buffer.alloc(CREATE_MINER_LAYOUT.span); 250 | CREATE_MINER_LAYOUT.encode( 251 | { 252 | amount: new BN(miner[1]), 253 | }, 254 | bumpData 255 | ); 256 | const dataString = "7e179d01935ef545".concat(bumpData.toString("hex")); 257 | const data = Buffer.from(dataString, "hex"); 258 | const minerBytes = new Uint8Array(Buffer.from("Miner", "utf-8")); 259 | 260 | const minerVault = await findAssociatedTokenAddress( 261 | miner[0], 262 | FarmInfo.tokenMintKey 263 | ); 264 | const keys = [ 265 | { pubkey: wallet, isSigner: true, isWritable: true }, 266 | { pubkey: miner[0], isSigner: false, isWritable: true }, 267 | { pubkey: FarmInfo.infoPubkey, isSigner: false, isWritable: true }, 268 | { pubkey: SABER_QUARRY_REWARDER, isSigner: false, isWritable: false }, 269 | { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, 270 | { pubkey: wallet, isSigner: true, isWritable: true }, 271 | { pubkey: FarmInfo.tokenMintKey, isSigner: false, isWritable: false }, 272 | { pubkey: minerVault, isSigner: false, isWritable: true }, 273 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 274 | ]; 275 | return new TransactionInstruction({ 276 | keys, 277 | programId: QURARRY_MINE_PROGRAM_ID, 278 | data, 279 | }); 280 | } 281 | 282 | export async function withdrawFromFarmIx( 283 | farmInfo: FarmInfo, 284 | wallet: PublicKey, 285 | amount: BN 286 | ) { 287 | const miner = await getMinerKey(wallet, farmInfo.infoPubkey); 288 | const minerVault = await findAssociatedTokenAddress( 289 | miner[0], 290 | farmInfo.tokenMintKey 291 | ); 292 | const minerLPAccount = await findAssociatedTokenAddress( 293 | wallet, 294 | farmInfo.tokenMintKey 295 | ); 296 | const amountData = Buffer.alloc(WITHDRAW_FROM_FARM_LAYOUT.span); 297 | WITHDRAW_FROM_FARM_LAYOUT.encode( 298 | { 299 | amount: new BN(amount), 300 | }, 301 | amountData 302 | ); 303 | const dataString = "0204e13d13b66aaa".concat(amountData.toString("hex")); 304 | const data = Buffer.from(dataString, "hex"); 305 | const keys = [ 306 | { pubkey: wallet, isSigner: true, isWritable: true }, 307 | { pubkey: miner[0], isSigner: false, isWritable: true }, 308 | { pubkey: farmInfo.infoPubkey, isSigner: false, isWritable: true }, 309 | { pubkey: minerVault, isSigner: false, isWritable: true }, 310 | { pubkey: minerLPAccount, isSigner: false, isWritable: true }, 311 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 312 | { pubkey: SABER_QUARRY_REWARDER, isSigner: false, isWritable: false }, 313 | ]; 314 | return new TransactionInstruction({ 315 | keys, 316 | programId: QURARRY_MINE_PROGRAM_ID, 317 | data, 318 | }); 319 | } 320 | 321 | export async function claimReward(farmInfo: FarmInfo, wallet: PublicKey) { 322 | const tx = new Transaction(); 323 | const miner = await getMinerKey(wallet, farmInfo.infoPubkey); 324 | const minerVault = await findAssociatedTokenAddress( 325 | miner[0], 326 | farmInfo.tokenMintKey 327 | ); 328 | const minerLPAccount = await findAssociatedTokenAddress( 329 | wallet, 330 | farmInfo.tokenMintKey 331 | ); 332 | const iouTokenAccount = await findAssociatedTokenAddress( 333 | wallet, 334 | IOU_TOKEN_MINT 335 | ); 336 | const dataString = "0490844774179750"; 337 | const data = Buffer.from(dataString, "hex"); 338 | const keys = [ 339 | { pubkey: SABER_MINT_WRAPPER, isSigner: false, isWritable: true }, 340 | { pubkey: QURARRY_MINT_WRAPPER, isSigner: false, isWritable: false }, 341 | { pubkey: SABER_FARM_MINTER, isSigner: false, isWritable: true }, 342 | { pubkey: IOU_TOKEN_MINT, isSigner: false, isWritable: true }, 343 | { pubkey: iouTokenAccount, isSigner: false, isWritable: true }, 344 | { pubkey: CLAIM_FEE_TOKEN_ACCOUNT, isSigner: false, isWritable: true }, 345 | { pubkey: wallet, isSigner: true, isWritable: true }, 346 | { pubkey: miner[0], isSigner: false, isWritable: true }, 347 | { pubkey: farmInfo.infoPubkey, isSigner: false, isWritable: true }, 348 | { pubkey: minerVault, isSigner: false, isWritable: true }, 349 | { pubkey: minerLPAccount, isSigner: false, isWritable: true }, 350 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 351 | { pubkey: SABER_QUARRY_REWARDER, isSigner: false, isWritable: false }, 352 | ]; 353 | tx.add( 354 | new TransactionInstruction({ 355 | keys, 356 | programId: QURARRY_MINE_PROGRAM_ID, 357 | data, 358 | }) 359 | ); 360 | const sbrTokenAccount = await findAssociatedTokenAddress( 361 | wallet, 362 | SABER_TOKEN_MINT 363 | ); 364 | const keysMinter = [ 365 | { 366 | pubkey: new PublicKey("CL9wkGFT3SZRRNa9dgaovuRV7jrVVigBUZ6DjcgySsCU"), 367 | isSigner: false, 368 | isWritable: false, 369 | }, 370 | { pubkey: IOU_TOKEN_MINT, isSigner: false, isWritable: true }, 371 | { pubkey: SABER_TOKEN_MINT, isSigner: false, isWritable: true }, 372 | { 373 | pubkey: new PublicKey("ESg7xPUBioCqK4QaSvuZkhuekagvKcx326wNo3U7kRWc"), 374 | isSigner: false, 375 | isWritable: true, 376 | }, 377 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, 378 | { pubkey: wallet, isSigner: true, isWritable: true }, 379 | { pubkey: iouTokenAccount, isSigner: false, isWritable: true }, 380 | { pubkey: sbrTokenAccount, isSigner: false, isWritable: true }, 381 | { 382 | pubkey: new PublicKey("9qRjwMQYrkd5JvsENaYYxSCgwEuVhK4qAo5kCFHSmdmL"), 383 | isSigner: false, 384 | isWritable: false, 385 | }, 386 | { 387 | pubkey: new PublicKey("GyktbGXbH9kvxP8RGfWsnFtuRgC7QCQo2WBqpo3ryk7L"), 388 | isSigner: false, 389 | isWritable: false, 390 | }, 391 | { 392 | pubkey: new PublicKey("UBEBk5idELqykEEaycYtQ7iBVrCg6NmvFSzMpdr22mL"), 393 | isSigner: false, 394 | isWritable: false, 395 | }, 396 | { 397 | pubkey: new PublicKey("GNSuMDSnUP9oK4HRtCi41zAbUzEqeLK1QPoby6dLVD9v"), 398 | isSigner: false, 399 | isWritable: true, 400 | }, 401 | ]; 402 | const dataStringMinter = "dbeee821de003643"; 403 | const dataMinter = Buffer.from(dataStringMinter, "hex"); 404 | tx.add( 405 | new TransactionInstruction({ 406 | keys: keysMinter, 407 | programId: MINTER_PROGRAM_ID, 408 | data: dataMinter, 409 | }) 410 | ); 411 | return tx; 412 | } 413 | -------------------------------------------------------------------------------- /saber/infos.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { 3 | Connection, 4 | PublicKey, 5 | MemcmpFilter, 6 | GetProgramAccountsConfig, 7 | DataSizeFilter, 8 | } from "@solana/web3.js"; 9 | import { 10 | QURARRY_MINE_PROGRAM_ID, 11 | SABER_WRAP_PROGRAM_ID, 12 | SWAP_PROGRAM_ID, 13 | } from "./ids"; 14 | import { 15 | FARM_LAYOUT, 16 | MINER_LAYOUT, 17 | SWAPINFO_LAYOUT, 18 | WRAPINFO_LAYOUT, 19 | } from "./layouts"; 20 | import { getTokenAccountAmount, getTokenSupply } from "../utils"; 21 | 22 | export class FarmInfo { 23 | infoPubkey: PublicKey; 24 | rewarderKey: PublicKey; 25 | tokenMintKey: PublicKey; 26 | bump: BN; 27 | index: BN; 28 | tokenMintDecimals: BN; 29 | famineTs: BN; 30 | lastUpdateTs: BN; 31 | rewardsPerTokenStored: BN; 32 | annualRewardsRate: BN; 33 | rewardsShare: BN; 34 | totalTokensDeposited: BN; 35 | numMiners: BN; 36 | constructor( 37 | infoPubkey: PublicKey, 38 | rewarderKey: PublicKey, 39 | tokenMintKey: PublicKey, 40 | bump: BN, 41 | index: BN, 42 | tokenMintDecimals: BN, 43 | famineTs: BN, 44 | lastUpdateTs: BN, 45 | rewardsPerTokenStored: BN, 46 | annualRewardsRate: BN, 47 | rewardsShare: BN, 48 | totalTokensDeposited: BN, 49 | numMiners: BN 50 | ) { 51 | this.infoPubkey = infoPubkey; 52 | this.rewarderKey = rewarderKey; 53 | this.tokenMintKey = tokenMintKey; 54 | this.bump = bump; 55 | this.index = index; 56 | this.tokenMintDecimals = tokenMintDecimals; 57 | this.famineTs = famineTs; 58 | this.lastUpdateTs = lastUpdateTs; 59 | this.rewardsPerTokenStored = rewardsPerTokenStored; 60 | this.annualRewardsRate = annualRewardsRate; 61 | this.rewardsShare = rewardsShare; 62 | this.totalTokensDeposited = totalTokensDeposited; 63 | this.numMiners = numMiners; 64 | } 65 | } 66 | 67 | export function parseFarmInfo(data: any, farmPubkey: PublicKey): FarmInfo { 68 | const dataBuffer = data as Buffer; 69 | const infoData = dataBuffer.slice(8); 70 | const newFarmInfo = FARM_LAYOUT.decode(infoData); 71 | const { 72 | rewarderKey, 73 | tokenMintKey, 74 | bump, 75 | index, 76 | tokenMintDecimals, 77 | famineTs, 78 | lastUpdateTs, 79 | rewardsPerTokenStored, 80 | annualRewardsRate, 81 | rewardsShare, 82 | totalTokensDeposited, 83 | numMiners, 84 | } = newFarmInfo; 85 | return new FarmInfo( 86 | farmPubkey, 87 | rewarderKey, 88 | tokenMintKey, 89 | new BN(bump), 90 | new BN(index), 91 | new BN(tokenMintDecimals), 92 | new BN(famineTs), 93 | new BN(lastUpdateTs), 94 | new BN(rewardsPerTokenStored), 95 | new BN(annualRewardsRate), 96 | new BN(rewardsShare), 97 | new BN(totalTokensDeposited), 98 | new BN(numMiners) 99 | ); 100 | } 101 | 102 | export async function getAllFarms( 103 | connection: Connection, 104 | rewarderKey: PublicKey 105 | ): Promise { 106 | const adminIdMemcmp: MemcmpFilter = { 107 | memcmp: { 108 | offset: 8, 109 | bytes: rewarderKey.toString(), 110 | }, 111 | }; 112 | const sizeFilter: DataSizeFilter = { 113 | dataSize: 140, 114 | }; 115 | const filters = [adminIdMemcmp, sizeFilter]; 116 | const config: GetProgramAccountsConfig = { filters }; 117 | const allFarmAccount = await connection.getProgramAccounts( 118 | QURARRY_MINE_PROGRAM_ID, 119 | config 120 | ); 121 | const allFarmInfo: FarmInfo[] = []; 122 | for (const account of allFarmAccount) { 123 | const currentFarmInfo = parseFarmInfo(account.account.data, account.pubkey); 124 | allFarmInfo.push(currentFarmInfo); 125 | } 126 | return allFarmInfo; 127 | } 128 | export function checkFarming( 129 | allFarmInfo: FarmInfo[], 130 | mintPubkey: PublicKey 131 | ): [boolean, FarmInfo] { 132 | for (const info of allFarmInfo) { 133 | if (info.tokenMintKey.toString() === mintPubkey.toString()) { 134 | return [true, info]; 135 | } 136 | } 137 | return [false, defaultFarm()]; 138 | } 139 | 140 | export function defaultFarm(): FarmInfo { 141 | return new FarmInfo( 142 | PublicKey.default, 143 | PublicKey.default, 144 | PublicKey.default, 145 | new BN(0), 146 | new BN(0), 147 | new BN(0), 148 | new BN(0), 149 | new BN(0), 150 | new BN(0), 151 | new BN(0), 152 | new BN(0), 153 | new BN(0), 154 | new BN(0) 155 | ); 156 | } 157 | 158 | export async function getMinerKey( 159 | wallet: PublicKey, 160 | farmPubkey: PublicKey 161 | ): Promise<[PublicKey, number]> { 162 | const minerBytes = new Uint8Array(Buffer.from("Miner", "utf-8")); 163 | const miner = await PublicKey.findProgramAddress( 164 | [minerBytes, farmPubkey.toBuffer(), wallet.toBuffer()], 165 | QURARRY_MINE_PROGRAM_ID 166 | ); 167 | return miner; 168 | } 169 | 170 | export async function minerCreated( 171 | wallet: PublicKey, 172 | info: FarmInfo, 173 | connection: Connection 174 | ): Promise { 175 | const miner = await getMinerKey(wallet, info.infoPubkey); 176 | const minerAccountInfo = await connection.getAccountInfo(miner[0]); 177 | 178 | if ( 179 | minerAccountInfo?.owner.toString() === QURARRY_MINE_PROGRAM_ID.toString() 180 | ) { 181 | return true; 182 | } 183 | return false; 184 | } 185 | 186 | export class MinerInfo { 187 | infoPubkey: PublicKey; 188 | farmKey: PublicKey; 189 | owner: PublicKey; 190 | bump: BN; 191 | vault: PublicKey; 192 | rewardsEarned: BN; 193 | rewardsPerTokenPaid: BN; 194 | balance: BN; 195 | index: BN; 196 | constructor( 197 | infoPubkey: PublicKey, 198 | farmKey: PublicKey, 199 | owner: PublicKey, 200 | bump: BN, 201 | vault: PublicKey, 202 | rewardsEarned: BN, 203 | rewardsPerTokenPaid: BN, 204 | balance: BN, 205 | index: BN 206 | ) { 207 | this.infoPubkey = infoPubkey; 208 | this.farmKey = farmKey; 209 | this.owner = owner; 210 | this.bump = bump; 211 | this.index = index; 212 | this.vault = vault; 213 | this.rewardsEarned = rewardsEarned; 214 | this.rewardsPerTokenPaid = rewardsPerTokenPaid; 215 | this.balance = balance; 216 | } 217 | 218 | getUnclaimedRewards(swapInfo: SwapInfo) { 219 | if ( 220 | swapInfo.farmingInfo?.infoPubkey.toString() === this.farmKey.toString() 221 | ) { 222 | const unClaim = 223 | this.balance 224 | .mul( 225 | swapInfo.farmingInfo.rewardsPerTokenStored.sub( 226 | this.rewardsPerTokenPaid 227 | ) 228 | ) 229 | .div(new BN([255, 255, 255, 255, 255, 255, 255, 255])) 230 | .add(this.rewardsEarned) 231 | .toNumber() / Math.pow(10, 6); 232 | return unClaim; 233 | } else { 234 | return 0; 235 | } 236 | } 237 | } 238 | 239 | export function parseMinerInfo(data: any, miner: PublicKey): MinerInfo { 240 | const dataBuffer = data as Buffer; 241 | const infoData = dataBuffer.slice(8); 242 | const newMinerInfo = MINER_LAYOUT.decode(infoData); 243 | const { 244 | infoPubkey, 245 | farmKey, 246 | owner, 247 | bump, 248 | vault, 249 | rewardsEarned, 250 | rewardsPerTokenPaid, 251 | balance, 252 | index, 253 | } = newMinerInfo; 254 | return new MinerInfo( 255 | infoPubkey, 256 | farmKey, 257 | owner, 258 | new BN(bump), 259 | vault, 260 | new BN(rewardsEarned), 261 | new BN(rewardsPerTokenPaid), 262 | new BN(balance), 263 | new BN(index) 264 | ); 265 | } 266 | 267 | export async function getAllMiners( 268 | connection: Connection, 269 | wallet: PublicKey 270 | ): Promise { 271 | const adminIdMemcmp: MemcmpFilter = { 272 | memcmp: { 273 | offset: 8 + 32, 274 | bytes: wallet.toString(), 275 | }, 276 | }; 277 | const sizeFilter: DataSizeFilter = { 278 | dataSize: 145, 279 | }; 280 | const filters = [adminIdMemcmp, sizeFilter]; 281 | const config: GetProgramAccountsConfig = { filters }; 282 | const allMinerAccount = await connection.getProgramAccounts( 283 | QURARRY_MINE_PROGRAM_ID, 284 | config 285 | ); 286 | const allMinerInfo: MinerInfo[] = []; 287 | for (const account of allMinerAccount) { 288 | const currentFarmInfo = parseMinerInfo( 289 | account.account.data, 290 | account.pubkey 291 | ); 292 | if (currentFarmInfo.balance === new BN(0)) { 293 | continue; 294 | } 295 | allMinerInfo.push(currentFarmInfo); 296 | } 297 | return allMinerInfo; 298 | } 299 | 300 | export const defaultMiner = new MinerInfo( 301 | PublicKey.default, 302 | PublicKey.default, 303 | PublicKey.default, 304 | new BN(0), 305 | PublicKey.default, 306 | new BN(0), 307 | new BN(0), 308 | new BN(0), 309 | new BN(0) 310 | ); 311 | 312 | export interface SwapInfo { 313 | infoPublicKey: PublicKey; 314 | isInitialized: boolean; 315 | isPaused: boolean; 316 | nonce: BN; 317 | initialAmpFactor: BN; 318 | targetAmpFactor: BN; 319 | startRampTs: BN; 320 | stopRampTs: BN; 321 | futureAdminDeadline: BN; 322 | futureAdminKey: PublicKey; 323 | adminKey: PublicKey; 324 | tokenAccountA: PublicKey; 325 | tokenAccountB: PublicKey; 326 | AtokenAccountAmount?: BN; 327 | BtokenAccountAmount?: BN; 328 | poolMint: PublicKey; 329 | mintA: PublicKey; 330 | mintB: PublicKey; 331 | adminFeeAccountA: PublicKey; 332 | adminFeeAccountB: PublicKey; 333 | } 334 | 335 | export class SwapInfo implements SwapInfo { 336 | infoPublicKey: PublicKey; 337 | authority: PublicKey; 338 | isInitialized: boolean; 339 | isPaused: boolean; 340 | nonce: BN; 341 | initialAmpFactor: BN; 342 | targetAmpFactor: BN; 343 | startRampTs: BN; 344 | stopRampTs: BN; 345 | futureAdminDeadline: BN; 346 | futureAdminKey: PublicKey; 347 | adminKey: PublicKey; 348 | tokenAccountA: PublicKey; 349 | tokenAccountB: PublicKey; 350 | poolMint: PublicKey; 351 | mintA: PublicKey; 352 | mintB: PublicKey; 353 | adminFeeAccountA: PublicKey; 354 | adminFeeAccountB: PublicKey; 355 | AtokenAccountAmount?: BN; 356 | BtokenAccountAmount?: BN; 357 | LPtokenSupply?: BN; 358 | mintAWrapped?: boolean; 359 | mintAWrapInfo?: WrapInfo; 360 | mintBWrapped?: boolean; 361 | mintBWrapInfo?: WrapInfo; 362 | isFarming?: boolean; 363 | farmingInfo?: FarmInfo; 364 | constructor( 365 | infoPublicKey: PublicKey, 366 | authority: PublicKey, 367 | isInitialized: boolean, 368 | isPaused: boolean, 369 | nonce: BN, 370 | initialAmpFactor: BN, 371 | targetAmpFactor: BN, 372 | startRampTs: BN, 373 | stopRampTs: BN, 374 | futureAdminDeadline: BN, 375 | futureAdminKey: PublicKey, 376 | adminKey: PublicKey, 377 | tokenAccountA: PublicKey, 378 | tokenAccountB: PublicKey, 379 | poolMint: PublicKey, 380 | mintA: PublicKey, 381 | mintB: PublicKey, 382 | adminFeeAccountA: PublicKey, 383 | adminFeeAccountB: PublicKey 384 | ) { 385 | this.infoPublicKey = infoPublicKey; 386 | this.authority = authority; 387 | this.isInitialized = isInitialized; 388 | this.isPaused = isPaused; 389 | this.nonce = nonce; 390 | this.initialAmpFactor = initialAmpFactor; 391 | this.targetAmpFactor = targetAmpFactor; 392 | this.startRampTs = startRampTs; 393 | this.stopRampTs = stopRampTs; 394 | this.futureAdminDeadline = futureAdminDeadline; 395 | this.futureAdminKey = futureAdminKey; 396 | this.adminKey = adminKey; 397 | this.tokenAccountA = tokenAccountA; 398 | this.tokenAccountB = tokenAccountB; 399 | this.poolMint = poolMint; 400 | this.mintA = mintA; 401 | this.mintB = mintB; 402 | this.adminFeeAccountA = adminFeeAccountA; 403 | this.adminFeeAccountB = adminFeeAccountB; 404 | } 405 | 406 | async updateAmount(connection: Connection) { 407 | this.AtokenAccountAmount = await getTokenAccountAmount( 408 | connection, 409 | this.tokenAccountA 410 | ); 411 | this.BtokenAccountAmount = await getTokenAccountAmount( 412 | connection, 413 | this.tokenAccountB 414 | ); 415 | this.LPtokenSupply = await getTokenSupply(connection, this.poolMint); 416 | } 417 | async calculateDepositRecieve( 418 | connection: Connection, 419 | AtokenIn: BN, 420 | BtokenIN: BN 421 | ) { 422 | if (!this.AtokenAccountAmount) { 423 | await this.updateAmount(connection); 424 | } 425 | } 426 | } 427 | 428 | export async function parseSwapInfoData( 429 | data: any, 430 | pubkey: PublicKey 431 | ): Promise { 432 | const decodedData = SWAPINFO_LAYOUT.decode(data); 433 | const authority = ( 434 | await PublicKey.findProgramAddress([pubkey.toBuffer()], SWAP_PROGRAM_ID) 435 | )[0]; 436 | const { 437 | isInitialized, 438 | isPaused, 439 | nonce, 440 | initialAmpFactor, 441 | targetAmpFactor, 442 | startRampTs, 443 | stopRampTs, 444 | futureAdminDeadline, 445 | futureAdminKey, 446 | adminKey, 447 | tokenAccountA, 448 | tokenAccountB, 449 | poolMint, 450 | mintA, 451 | mintB, 452 | adminFeeAccountA, 453 | adminFeeAccountB, 454 | } = decodedData; 455 | const swapInfo = new SwapInfo( 456 | pubkey, 457 | authority, 458 | isInitialized, 459 | isPaused, 460 | new BN(nonce), 461 | new BN(initialAmpFactor), 462 | new BN(targetAmpFactor), 463 | new BN(startRampTs), 464 | new BN(stopRampTs), 465 | futureAdminDeadline, 466 | futureAdminKey, 467 | adminKey, 468 | tokenAccountA, 469 | tokenAccountB, 470 | poolMint, 471 | mintA, 472 | mintB, 473 | adminFeeAccountA, 474 | adminFeeAccountB 475 | ); 476 | return swapInfo; 477 | } 478 | 479 | export interface WrapInfo { 480 | wrapAuthority: PublicKey; 481 | decimal: BN; 482 | multiplyer: BN; 483 | underlyingWrappedTokenMint: PublicKey; 484 | underlyingTokenAccount: PublicKey; 485 | wrappedTokenMint: PublicKey; 486 | } 487 | 488 | export class WrapInfo implements WrapInfo { 489 | wrapAuthority: PublicKey; 490 | decimal: BN; 491 | multiplyer: BN; 492 | underlyingWrappedTokenMint: PublicKey; 493 | underlyingTokenAccount: PublicKey; 494 | wrappedTokenMint: PublicKey; 495 | constructor( 496 | wrapAuthority: PublicKey, 497 | decimal: BN, 498 | multiplyer: BN, 499 | underlyingWrappedTokenMint: PublicKey, 500 | underlyingTokenAccount: PublicKey, 501 | wrappedTokenMint: PublicKey 502 | ) { 503 | this.wrapAuthority = wrapAuthority; 504 | this.decimal = decimal; 505 | this.multiplyer = multiplyer; 506 | this.underlyingWrappedTokenMint = underlyingWrappedTokenMint; 507 | this.underlyingTokenAccount = underlyingTokenAccount; 508 | this.wrappedTokenMint = wrappedTokenMint; 509 | } 510 | } 511 | 512 | export function parseWrapInfoData(data: any): WrapInfo { 513 | const dataBuffer = data as Buffer; 514 | const cutttedData = dataBuffer.slice(8); 515 | const decodedData = WRAPINFO_LAYOUT.decode(cutttedData); 516 | const { 517 | wrapAuthority, 518 | decimal, 519 | multiplyer, 520 | underlyingWrappedTokenMint, 521 | underlyingTokenAccount, 522 | wrappedTokenMint, 523 | } = decodedData; 524 | const wrap = new WrapInfo( 525 | wrapAuthority, 526 | decimal, 527 | multiplyer, 528 | underlyingWrappedTokenMint, 529 | underlyingTokenAccount, 530 | wrappedTokenMint 531 | ); 532 | return wrap; 533 | } 534 | 535 | export async function checkWrapped( 536 | tokenMint: PublicKey, 537 | wrapInfoArray: WrapInfo[] 538 | ): Promise<[boolean, WrapInfo]> { 539 | for (const info of wrapInfoArray) { 540 | if (info.wrappedTokenMint.toString() === tokenMint.toString()) { 541 | return [true, info]; 542 | } 543 | } 544 | return [false, defaultWrapInfo()]; 545 | } 546 | 547 | function defaultWrapInfo(): WrapInfo { 548 | return new WrapInfo( 549 | PublicKey.default, 550 | new BN(0), 551 | new BN(0), 552 | PublicKey.default, 553 | PublicKey.default, 554 | PublicKey.default 555 | ); 556 | } 557 | 558 | export async function getAllWrap(connection: Connection): Promise { 559 | const sizeFilter: DataSizeFilter = { 560 | dataSize: 114, 561 | }; 562 | const filters = [sizeFilter]; 563 | const config: GetProgramAccountsConfig = { filters }; 564 | const allWrapAccount = await connection.getProgramAccounts( 565 | SABER_WRAP_PROGRAM_ID, 566 | config 567 | ); 568 | const infoArray: WrapInfo[] = []; 569 | for (const account of allWrapAccount) { 570 | const wrapAccountInfo = parseWrapInfoData(account.account.data); 571 | wrapAccountInfo.wrapAuthority = account.pubkey; 572 | infoArray.push(wrapAccountInfo); 573 | } 574 | return infoArray; 575 | } 576 | -------------------------------------------------------------------------------- /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", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5": 6 | version "7.17.2" 7 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" 8 | integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== 9 | dependencies: 10 | regenerator-runtime "^0.13.4" 11 | 12 | "@cspotcode/source-map-consumer@0.8.0": 13 | version "0.8.0" 14 | resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" 15 | integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== 16 | 17 | "@cspotcode/source-map-support@0.7.0": 18 | version "0.7.0" 19 | resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" 20 | integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== 21 | dependencies: 22 | "@cspotcode/source-map-consumer" "0.8.0" 23 | 24 | "@ethersproject/bytes@^5.5.0": 25 | version "5.5.0" 26 | resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" 27 | integrity sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog== 28 | dependencies: 29 | "@ethersproject/logger" "^5.5.0" 30 | 31 | "@ethersproject/logger@^5.5.0": 32 | version "5.5.0" 33 | resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" 34 | integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== 35 | 36 | "@ethersproject/sha2@^5.5.0": 37 | version "5.5.0" 38 | resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.5.0.tgz#a40a054c61f98fd9eee99af2c3cc6ff57ec24db7" 39 | integrity sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA== 40 | dependencies: 41 | "@ethersproject/bytes" "^5.5.0" 42 | "@ethersproject/logger" "^5.5.0" 43 | hash.js "1.1.7" 44 | 45 | "@hapi/hoek@^9.0.0": 46 | version "9.2.1" 47 | resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17" 48 | integrity sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw== 49 | 50 | "@hapi/topo@^5.0.0": 51 | version "5.1.0" 52 | resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" 53 | integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== 54 | dependencies: 55 | "@hapi/hoek" "^9.0.0" 56 | 57 | "@project-serum/anchor@^0.11.1": 58 | version "0.11.1" 59 | resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.11.1.tgz#155bff2c70652eafdcfd5559c81a83bb19cec9ff" 60 | integrity sha512-oIdm4vTJkUy6GmE6JgqDAuQPKI7XM4TPJkjtoIzp69RZe0iAD9JP2XHx7lV1jLdYXeYHqDXfBt3zcq7W91K6PA== 61 | dependencies: 62 | "@project-serum/borsh" "^0.2.2" 63 | "@solana/web3.js" "^1.17.0" 64 | base64-js "^1.5.1" 65 | bn.js "^5.1.2" 66 | bs58 "^4.0.1" 67 | buffer-layout "^1.2.0" 68 | camelcase "^5.3.1" 69 | crypto-hash "^1.3.0" 70 | eventemitter3 "^4.0.7" 71 | find "^0.3.0" 72 | js-sha256 "^0.9.0" 73 | pako "^2.0.3" 74 | snake-case "^3.0.4" 75 | toml "^3.0.0" 76 | 77 | "@project-serum/borsh@^0.2.2", "@project-serum/borsh@^0.2.5": 78 | version "0.2.5" 79 | resolved "https://registry.yarnpkg.com/@project-serum/borsh/-/borsh-0.2.5.tgz#6059287aa624ecebbfc0edd35e4c28ff987d8663" 80 | integrity sha512-UmeUkUoKdQ7rhx6Leve1SssMR/Ghv8qrEiyywyxSWg7ooV7StdpPBhciiy5eB3T0qU1BXvdRNC8TdrkxK7WC5Q== 81 | dependencies: 82 | bn.js "^5.1.2" 83 | buffer-layout "^1.2.0" 84 | 85 | "@project-serum/serum@^0.13.61": 86 | version "0.13.61" 87 | resolved "https://registry.yarnpkg.com/@project-serum/serum/-/serum-0.13.61.tgz#1f0e6dfa7786a71e4317593911e9915d8b2a06e6" 88 | integrity sha512-aebaRGQ0/K7a5kJ9UXO59BAQFJILVu5jbGobU8GD2CTSy6SPceprB6/pgZmZLQIabhXWUHaZRF/wXIClgWataA== 89 | dependencies: 90 | "@project-serum/anchor" "^0.11.1" 91 | "@solana/spl-token" "^0.1.6" 92 | "@solana/web3.js" "^1.21.0" 93 | bn.js "^5.1.2" 94 | buffer-layout "^1.2.0" 95 | 96 | "@sideway/address@^4.1.3": 97 | version "4.1.3" 98 | resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.3.tgz#d93cce5d45c5daec92ad76db492cc2ee3c64ab27" 99 | integrity sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ== 100 | dependencies: 101 | "@hapi/hoek" "^9.0.0" 102 | 103 | "@sideway/formula@^3.0.0": 104 | version "3.0.0" 105 | resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" 106 | integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== 107 | 108 | "@sideway/pinpoint@^2.0.0": 109 | version "2.0.0" 110 | resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" 111 | integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== 112 | 113 | "@solana/buffer-layout-utils@^0.2.0": 114 | version "0.2.0" 115 | resolved "https://registry.yarnpkg.com/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz#b45a6cab3293a2eb7597cceb474f229889d875ca" 116 | integrity sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g== 117 | dependencies: 118 | "@solana/buffer-layout" "^4.0.0" 119 | "@solana/web3.js" "^1.32.0" 120 | bigint-buffer "^1.1.5" 121 | bignumber.js "^9.0.1" 122 | 123 | "@solana/buffer-layout@^3.0.0": 124 | version "3.0.0" 125 | resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-3.0.0.tgz#b9353caeb9a1589cb77a1b145bcb1a9a93114326" 126 | integrity sha512-MVdgAKKL39tEs0l8je0hKaXLQFb7Rdfb0Xg2LjFZd8Lfdazkg6xiS98uAZrEKvaoF3i4M95ei9RydkGIDMeo3w== 127 | dependencies: 128 | buffer "~6.0.3" 129 | 130 | "@solana/buffer-layout@^4.0.0": 131 | version "4.0.0" 132 | resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.0.tgz#75b1b11adc487234821c81dfae3119b73a5fd734" 133 | integrity sha512-lR0EMP2HC3+Mxwd4YcnZb0smnaDw7Bl2IQWZiTevRH5ZZBZn6VRWn3/92E3qdU4SSImJkA6IDHawOHAnx/qUvQ== 134 | dependencies: 135 | buffer "~6.0.3" 136 | 137 | "@solana/spl-token@^0.1.6": 138 | version "0.1.8" 139 | resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.1.8.tgz#f06e746341ef8d04165e21fc7f555492a2a0faa6" 140 | integrity sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ== 141 | dependencies: 142 | "@babel/runtime" "^7.10.5" 143 | "@solana/web3.js" "^1.21.0" 144 | bn.js "^5.1.0" 145 | buffer "6.0.3" 146 | buffer-layout "^1.2.0" 147 | dotenv "10.0.0" 148 | 149 | "@solana/spl-token@^0.2.0": 150 | version "0.2.0" 151 | resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.2.0.tgz#329bb6babb5de0f9c40035ddb1657f01a8347acd" 152 | integrity sha512-RWcn31OXtdqIxmkzQfB2R+WpsJOVS6rKuvpxJFjvik2LyODd+WN58ZP3Rpjpro03fscGAkzlFuP3r42doRJgyQ== 153 | dependencies: 154 | "@solana/buffer-layout" "^4.0.0" 155 | "@solana/buffer-layout-utils" "^0.2.0" 156 | "@solana/web3.js" "^1.32.0" 157 | start-server-and-test "^1.14.0" 158 | 159 | "@solana/web3.js@^1.17.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.35.0": 160 | version "1.35.1" 161 | resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.35.1.tgz#777b039a3b51e63c347712a57c7db87c9d1db832" 162 | integrity sha512-3bDawFFI0KcvgI8Ae4N4hdQ8+Bg9gu6q+IkhPrYxOF6RYnB3U+9A4u+DhHZWLvTvgoTyesi/m5HzlleKtFEqRQ== 163 | dependencies: 164 | "@babel/runtime" "^7.12.5" 165 | "@ethersproject/sha2" "^5.5.0" 166 | "@solana/buffer-layout" "^3.0.0" 167 | bn.js "^5.0.0" 168 | borsh "^0.4.0" 169 | bs58 "^4.0.1" 170 | buffer "6.0.1" 171 | cross-fetch "^3.1.4" 172 | jayson "^3.4.4" 173 | js-sha3 "^0.8.0" 174 | rpc-websockets "^7.4.2" 175 | secp256k1 "^4.0.2" 176 | superstruct "^0.14.2" 177 | tweetnacl "^1.0.0" 178 | 179 | "@tsconfig/node10@^1.0.7": 180 | version "1.0.8" 181 | resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" 182 | integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== 183 | 184 | "@tsconfig/node12@^1.0.7": 185 | version "1.0.9" 186 | resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" 187 | integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== 188 | 189 | "@tsconfig/node14@^1.0.0": 190 | version "1.0.1" 191 | resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" 192 | integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== 193 | 194 | "@tsconfig/node16@^1.0.2": 195 | version "1.0.2" 196 | resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" 197 | integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== 198 | 199 | "@types/bn.js@^4.11.5": 200 | version "4.11.6" 201 | resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" 202 | integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== 203 | dependencies: 204 | "@types/node" "*" 205 | 206 | "@types/body-parser@*": 207 | version "1.19.2" 208 | resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" 209 | integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== 210 | dependencies: 211 | "@types/connect" "*" 212 | "@types/node" "*" 213 | 214 | "@types/connect@*", "@types/connect@^3.4.33": 215 | version "3.4.35" 216 | resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" 217 | integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== 218 | dependencies: 219 | "@types/node" "*" 220 | 221 | "@types/express-serve-static-core@^4.17.18", "@types/express-serve-static-core@^4.17.9": 222 | version "4.17.28" 223 | resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" 224 | integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== 225 | dependencies: 226 | "@types/node" "*" 227 | "@types/qs" "*" 228 | "@types/range-parser" "*" 229 | 230 | "@types/express@^4.17.13": 231 | version "4.17.13" 232 | resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" 233 | integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== 234 | dependencies: 235 | "@types/body-parser" "*" 236 | "@types/express-serve-static-core" "^4.17.18" 237 | "@types/qs" "*" 238 | "@types/serve-static" "*" 239 | 240 | "@types/lodash@^4.14.159": 241 | version "4.14.178" 242 | resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" 243 | integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw== 244 | 245 | "@types/mime@^1": 246 | version "1.3.2" 247 | resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" 248 | integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== 249 | 250 | "@types/node@*", "@types/node@^17.0.18": 251 | version "17.0.19" 252 | resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.19.tgz#726171367f404bfbe8512ba608a09ebad810c7e6" 253 | integrity sha512-PfeQhvcMR4cPFVuYfBN4ifG7p9c+Dlh3yUZR6k+5yQK7wX3gDgVxBly4/WkBRs9x4dmcy1TVl08SY67wwtEvmA== 254 | 255 | "@types/node@^12.12.54": 256 | version "12.20.46" 257 | resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.46.tgz#7e49dee4c54fd19584e6a9e0da5f3dc2e9136bc7" 258 | integrity sha512-cPjLXj8d6anFPzFvOPxS3fvly3Shm5nTfl6g8X5smexixbuGUf7hfr21J5tX9JW+UPStp/5P5R8qrKL5IyVJ+A== 259 | 260 | "@types/qs@*": 261 | version "6.9.7" 262 | resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" 263 | integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== 264 | 265 | "@types/range-parser@*": 266 | version "1.2.4" 267 | resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" 268 | integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== 269 | 270 | "@types/serve-static@*": 271 | version "1.13.10" 272 | resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" 273 | integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== 274 | dependencies: 275 | "@types/mime" "^1" 276 | "@types/node" "*" 277 | 278 | "@types/ws@^7.4.4": 279 | version "7.4.7" 280 | resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" 281 | integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== 282 | dependencies: 283 | "@types/node" "*" 284 | 285 | JSONStream@^1.3.5: 286 | version "1.3.5" 287 | resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" 288 | integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== 289 | dependencies: 290 | jsonparse "^1.2.0" 291 | through ">=2.2.7 <3" 292 | 293 | acorn-walk@^8.1.1: 294 | version "8.2.0" 295 | resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" 296 | integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== 297 | 298 | acorn@^8.4.1: 299 | version "8.7.0" 300 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" 301 | integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== 302 | 303 | arg@^4.1.0: 304 | version "4.1.3" 305 | resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" 306 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== 307 | 308 | axios@^0.21.1: 309 | version "0.21.4" 310 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" 311 | integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== 312 | dependencies: 313 | follow-redirects "^1.14.0" 314 | 315 | base-x@^3.0.2: 316 | version "3.0.9" 317 | resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" 318 | integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== 319 | dependencies: 320 | safe-buffer "^5.0.1" 321 | 322 | base64-js@^1.3.1, base64-js@^1.5.1: 323 | version "1.5.1" 324 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 325 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 326 | 327 | bigint-buffer@^1.1.5: 328 | version "1.1.5" 329 | resolved "https://registry.yarnpkg.com/bigint-buffer/-/bigint-buffer-1.1.5.tgz#d038f31c8e4534c1f8d0015209bf34b4fa6dd442" 330 | integrity sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA== 331 | dependencies: 332 | bindings "^1.3.0" 333 | 334 | bignumber.js@^9.0.1: 335 | version "9.0.2" 336 | resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673" 337 | integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== 338 | 339 | bindings@^1.3.0: 340 | version "1.5.0" 341 | resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" 342 | integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== 343 | dependencies: 344 | file-uri-to-path "1.0.0" 345 | 346 | bluebird@3.7.2: 347 | version "3.7.2" 348 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" 349 | integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== 350 | 351 | bn.js@^4.11.9: 352 | version "4.12.0" 353 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" 354 | integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== 355 | 356 | bn.js@^5.0.0, bn.js@^5.1.0, bn.js@^5.1.2: 357 | version "5.2.0" 358 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" 359 | integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== 360 | 361 | borsh@^0.4.0: 362 | version "0.4.0" 363 | resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.4.0.tgz#9dd6defe741627f1315eac2a73df61421f6ddb9f" 364 | integrity sha512-aX6qtLya3K0AkT66CmYWCCDr77qsE9arV05OmdFpmat9qu8Pg9J5tBUPDztAW5fNh/d/MyVG/OYziP52Ndzx1g== 365 | dependencies: 366 | "@types/bn.js" "^4.11.5" 367 | bn.js "^5.0.0" 368 | bs58 "^4.0.0" 369 | text-encoding-utf-8 "^1.0.2" 370 | 371 | brorand@^1.1.0: 372 | version "1.1.0" 373 | resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" 374 | integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= 375 | 376 | bs58@^4.0.0, bs58@^4.0.1: 377 | version "4.0.1" 378 | resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" 379 | integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= 380 | dependencies: 381 | base-x "^3.0.2" 382 | 383 | buffer-layout@^1.2.0, buffer-layout@^1.2.2: 384 | version "1.2.2" 385 | resolved "https://registry.yarnpkg.com/buffer-layout/-/buffer-layout-1.2.2.tgz#b9814e7c7235783085f9ca4966a0cfff112259d5" 386 | integrity sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA== 387 | 388 | buffer@6.0.1: 389 | version "6.0.1" 390 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.1.tgz#3cbea8c1463e5a0779e30b66d4c88c6ffa182ac2" 391 | integrity sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ== 392 | dependencies: 393 | base64-js "^1.3.1" 394 | ieee754 "^1.2.1" 395 | 396 | buffer@6.0.3, buffer@~6.0.3: 397 | version "6.0.3" 398 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" 399 | integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== 400 | dependencies: 401 | base64-js "^1.3.1" 402 | ieee754 "^1.2.1" 403 | 404 | bufferutil@^4.0.1: 405 | version "4.0.6" 406 | resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.6.tgz#ebd6c67c7922a0e902f053e5d8be5ec850e48433" 407 | integrity sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw== 408 | dependencies: 409 | node-gyp-build "^4.3.0" 410 | 411 | camelcase@^5.3.1: 412 | version "5.3.1" 413 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" 414 | integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== 415 | 416 | check-more-types@2.24.0: 417 | version "2.24.0" 418 | resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" 419 | integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= 420 | 421 | circular-json@^0.5.9: 422 | version "0.5.9" 423 | resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.9.tgz#932763ae88f4f7dead7a0d09c8a51a4743a53b1d" 424 | integrity sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ== 425 | 426 | commander@^2.20.3: 427 | version "2.20.3" 428 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 429 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 430 | 431 | create-require@^1.1.0: 432 | version "1.1.1" 433 | resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" 434 | integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== 435 | 436 | cross-fetch@^3.1.4: 437 | version "3.1.5" 438 | resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" 439 | integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== 440 | dependencies: 441 | node-fetch "2.6.7" 442 | 443 | cross-spawn@^7.0.3: 444 | version "7.0.3" 445 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 446 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 447 | dependencies: 448 | path-key "^3.1.0" 449 | shebang-command "^2.0.0" 450 | which "^2.0.1" 451 | 452 | crypto-hash@^1.3.0: 453 | version "1.3.0" 454 | resolved "https://registry.yarnpkg.com/crypto-hash/-/crypto-hash-1.3.0.tgz#b402cb08f4529e9f4f09346c3e275942f845e247" 455 | integrity sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg== 456 | 457 | debug@4.3.2: 458 | version "4.3.2" 459 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" 460 | integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== 461 | dependencies: 462 | ms "2.1.2" 463 | 464 | delay@^5.0.0: 465 | version "5.0.0" 466 | resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" 467 | integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== 468 | 469 | diff@^4.0.1: 470 | version "4.0.2" 471 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" 472 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 473 | 474 | dot-case@^3.0.4: 475 | version "3.0.4" 476 | resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" 477 | integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== 478 | dependencies: 479 | no-case "^3.0.4" 480 | tslib "^2.0.3" 481 | 482 | dotenv@10.0.0: 483 | version "10.0.0" 484 | resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" 485 | integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== 486 | 487 | duplexer@~0.1.1: 488 | version "0.1.2" 489 | resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" 490 | integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== 491 | 492 | elliptic@^6.5.4: 493 | version "6.5.4" 494 | resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" 495 | integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== 496 | dependencies: 497 | bn.js "^4.11.9" 498 | brorand "^1.1.0" 499 | hash.js "^1.0.0" 500 | hmac-drbg "^1.0.1" 501 | inherits "^2.0.4" 502 | minimalistic-assert "^1.0.1" 503 | minimalistic-crypto-utils "^1.0.1" 504 | 505 | es6-promise@^4.0.3: 506 | version "4.2.8" 507 | resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" 508 | integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== 509 | 510 | es6-promisify@^5.0.0: 511 | version "5.0.0" 512 | resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" 513 | integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= 514 | dependencies: 515 | es6-promise "^4.0.3" 516 | 517 | event-stream@=3.3.4: 518 | version "3.3.4" 519 | resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" 520 | integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= 521 | dependencies: 522 | duplexer "~0.1.1" 523 | from "~0" 524 | map-stream "~0.1.0" 525 | pause-stream "0.0.11" 526 | split "0.3" 527 | stream-combiner "~0.0.4" 528 | through "~2.3.1" 529 | 530 | eventemitter3@^4.0.7: 531 | version "4.0.7" 532 | resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" 533 | integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== 534 | 535 | execa@5.1.1: 536 | version "5.1.1" 537 | resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" 538 | integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== 539 | dependencies: 540 | cross-spawn "^7.0.3" 541 | get-stream "^6.0.0" 542 | human-signals "^2.1.0" 543 | is-stream "^2.0.0" 544 | merge-stream "^2.0.0" 545 | npm-run-path "^4.0.1" 546 | onetime "^5.1.2" 547 | signal-exit "^3.0.3" 548 | strip-final-newline "^2.0.0" 549 | 550 | eyes@^0.1.8: 551 | version "0.1.8" 552 | resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" 553 | integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= 554 | 555 | file-uri-to-path@1.0.0: 556 | version "1.0.0" 557 | resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" 558 | integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== 559 | 560 | find@^0.3.0: 561 | version "0.3.0" 562 | resolved "https://registry.yarnpkg.com/find/-/find-0.3.0.tgz#4082e8fc8d8320f1a382b5e4f521b9bc50775cb8" 563 | integrity sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw== 564 | dependencies: 565 | traverse-chain "~0.1.0" 566 | 567 | follow-redirects@^1.14.0: 568 | version "1.14.9" 569 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" 570 | integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== 571 | 572 | from@~0: 573 | version "0.1.7" 574 | resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" 575 | integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= 576 | 577 | get-stream@^6.0.0: 578 | version "6.0.1" 579 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" 580 | integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== 581 | 582 | hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: 583 | version "1.1.7" 584 | resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" 585 | integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== 586 | dependencies: 587 | inherits "^2.0.3" 588 | minimalistic-assert "^1.0.1" 589 | 590 | hmac-drbg@^1.0.1: 591 | version "1.0.1" 592 | resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" 593 | integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= 594 | dependencies: 595 | hash.js "^1.0.3" 596 | minimalistic-assert "^1.0.0" 597 | minimalistic-crypto-utils "^1.0.1" 598 | 599 | human-signals@^2.1.0: 600 | version "2.1.0" 601 | resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" 602 | integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== 603 | 604 | ieee754@^1.2.1: 605 | version "1.2.1" 606 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 607 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 608 | 609 | inherits@^2.0.3, inherits@^2.0.4: 610 | version "2.0.4" 611 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 612 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 613 | 614 | is-stream@^2.0.0: 615 | version "2.0.1" 616 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" 617 | integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== 618 | 619 | isexe@^2.0.0: 620 | version "2.0.0" 621 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 622 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 623 | 624 | isomorphic-ws@^4.0.1: 625 | version "4.0.1" 626 | resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" 627 | integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== 628 | 629 | jayson@^3.4.4: 630 | version "3.6.6" 631 | resolved "https://registry.yarnpkg.com/jayson/-/jayson-3.6.6.tgz#189984f624e398f831bd2be8e8c80eb3abf764a1" 632 | integrity sha512-f71uvrAWTtrwoww6MKcl9phQTC+56AopLyEenWvKVAIMz+q0oVGj6tenLZ7Z6UiPBkJtKLj4kt0tACllFQruGQ== 633 | dependencies: 634 | "@types/connect" "^3.4.33" 635 | "@types/express-serve-static-core" "^4.17.9" 636 | "@types/lodash" "^4.14.159" 637 | "@types/node" "^12.12.54" 638 | "@types/ws" "^7.4.4" 639 | JSONStream "^1.3.5" 640 | commander "^2.20.3" 641 | delay "^5.0.0" 642 | es6-promisify "^5.0.0" 643 | eyes "^0.1.8" 644 | isomorphic-ws "^4.0.1" 645 | json-stringify-safe "^5.0.1" 646 | lodash "^4.17.20" 647 | uuid "^8.3.2" 648 | ws "^7.4.5" 649 | 650 | joi@^17.4.0: 651 | version "17.6.0" 652 | resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.0.tgz#0bb54f2f006c09a96e75ce687957bd04290054b2" 653 | integrity sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw== 654 | dependencies: 655 | "@hapi/hoek" "^9.0.0" 656 | "@hapi/topo" "^5.0.0" 657 | "@sideway/address" "^4.1.3" 658 | "@sideway/formula" "^3.0.0" 659 | "@sideway/pinpoint" "^2.0.0" 660 | 661 | js-sha256@^0.9.0: 662 | version "0.9.0" 663 | resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" 664 | integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== 665 | 666 | js-sha3@^0.8.0: 667 | version "0.8.0" 668 | resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" 669 | integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== 670 | 671 | json-stringify-safe@^5.0.1: 672 | version "5.0.1" 673 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 674 | integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= 675 | 676 | jsonparse@^1.2.0: 677 | version "1.3.1" 678 | resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" 679 | integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= 680 | 681 | lazy-ass@1.6.0: 682 | version "1.6.0" 683 | resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" 684 | integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= 685 | 686 | lodash@^4.17.20, lodash@^4.17.21: 687 | version "4.17.21" 688 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 689 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 690 | 691 | lower-case@^2.0.2: 692 | version "2.0.2" 693 | resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" 694 | integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== 695 | dependencies: 696 | tslib "^2.0.3" 697 | 698 | make-error@^1.1.1: 699 | version "1.3.6" 700 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" 701 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 702 | 703 | map-stream@~0.1.0: 704 | version "0.1.0" 705 | resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" 706 | integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= 707 | 708 | merge-stream@^2.0.0: 709 | version "2.0.0" 710 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" 711 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== 712 | 713 | mimic-fn@^2.1.0: 714 | version "2.1.0" 715 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" 716 | integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== 717 | 718 | minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: 719 | version "1.0.1" 720 | resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" 721 | integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== 722 | 723 | minimalistic-crypto-utils@^1.0.1: 724 | version "1.0.1" 725 | resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" 726 | integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= 727 | 728 | minimist@^1.2.5: 729 | version "1.2.5" 730 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 731 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 732 | 733 | ms@2.1.2: 734 | version "2.1.2" 735 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 736 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 737 | 738 | no-case@^3.0.4: 739 | version "3.0.4" 740 | resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" 741 | integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== 742 | dependencies: 743 | lower-case "^2.0.2" 744 | tslib "^2.0.3" 745 | 746 | node-addon-api@^2.0.0: 747 | version "2.0.2" 748 | resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" 749 | integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== 750 | 751 | node-fetch@2.6.7: 752 | version "2.6.7" 753 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" 754 | integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== 755 | dependencies: 756 | whatwg-url "^5.0.0" 757 | 758 | node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: 759 | version "4.3.0" 760 | resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" 761 | integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== 762 | 763 | npm-run-path@^4.0.1: 764 | version "4.0.1" 765 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" 766 | integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== 767 | dependencies: 768 | path-key "^3.0.0" 769 | 770 | onetime@^5.1.2: 771 | version "5.1.2" 772 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" 773 | integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== 774 | dependencies: 775 | mimic-fn "^2.1.0" 776 | 777 | pako@^2.0.3: 778 | version "2.0.4" 779 | resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.4.tgz#6cebc4bbb0b6c73b0d5b8d7e8476e2b2fbea576d" 780 | integrity sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg== 781 | 782 | path-key@^3.0.0, path-key@^3.1.0: 783 | version "3.1.1" 784 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 785 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 786 | 787 | pause-stream@0.0.11: 788 | version "0.0.11" 789 | resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" 790 | integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= 791 | dependencies: 792 | through "~2.3" 793 | 794 | ps-tree@1.2.0: 795 | version "1.2.0" 796 | resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" 797 | integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA== 798 | dependencies: 799 | event-stream "=3.3.4" 800 | 801 | regenerator-runtime@^0.13.4: 802 | version "0.13.9" 803 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" 804 | integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== 805 | 806 | rpc-websockets@^7.4.2: 807 | version "7.4.17" 808 | resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.4.17.tgz#f38845dd96db0442bff9e15fba9df781beb44cc0" 809 | integrity sha512-eolVi/qlXS13viIUH9aqrde902wzSLAai0IjmOZSRefp5I3CSG/vCnD0c0fDSYCWuEyUoRL1BHQA8K1baEUyow== 810 | dependencies: 811 | "@babel/runtime" "^7.11.2" 812 | circular-json "^0.5.9" 813 | eventemitter3 "^4.0.7" 814 | uuid "^8.3.0" 815 | ws "^7.4.5" 816 | optionalDependencies: 817 | bufferutil "^4.0.1" 818 | utf-8-validate "^5.0.2" 819 | 820 | rxjs@^7.1.0: 821 | version "7.5.4" 822 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d" 823 | integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ== 824 | dependencies: 825 | tslib "^2.1.0" 826 | 827 | safe-buffer@^5.0.1: 828 | version "5.2.1" 829 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 830 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 831 | 832 | secp256k1@^4.0.2: 833 | version "4.0.3" 834 | resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" 835 | integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== 836 | dependencies: 837 | elliptic "^6.5.4" 838 | node-addon-api "^2.0.0" 839 | node-gyp-build "^4.2.0" 840 | 841 | shebang-command@^2.0.0: 842 | version "2.0.0" 843 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 844 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 845 | dependencies: 846 | shebang-regex "^3.0.0" 847 | 848 | shebang-regex@^3.0.0: 849 | version "3.0.0" 850 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 851 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 852 | 853 | signal-exit@^3.0.3: 854 | version "3.0.7" 855 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" 856 | integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== 857 | 858 | snake-case@^3.0.4: 859 | version "3.0.4" 860 | resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" 861 | integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== 862 | dependencies: 863 | dot-case "^3.0.4" 864 | tslib "^2.0.3" 865 | 866 | split@0.3: 867 | version "0.3.3" 868 | resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" 869 | integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= 870 | dependencies: 871 | through "2" 872 | 873 | start-server-and-test@^1.14.0: 874 | version "1.14.0" 875 | resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.14.0.tgz#c57f04f73eac15dd51733b551d775b40837fdde3" 876 | integrity sha512-on5ELuxO2K0t8EmNj9MtVlFqwBMxfWOhu4U7uZD1xccVpFlOQKR93CSe0u98iQzfNxRyaNTb/CdadbNllplTsw== 877 | dependencies: 878 | bluebird "3.7.2" 879 | check-more-types "2.24.0" 880 | debug "4.3.2" 881 | execa "5.1.1" 882 | lazy-ass "1.6.0" 883 | ps-tree "1.2.0" 884 | wait-on "6.0.0" 885 | 886 | stream-combiner@~0.0.4: 887 | version "0.0.4" 888 | resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" 889 | integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= 890 | dependencies: 891 | duplexer "~0.1.1" 892 | 893 | strip-final-newline@^2.0.0: 894 | version "2.0.0" 895 | resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" 896 | integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== 897 | 898 | superstruct@^0.14.2: 899 | version "0.14.2" 900 | resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.14.2.tgz#0dbcdf3d83676588828f1cf5ed35cda02f59025b" 901 | integrity sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ== 902 | 903 | text-encoding-utf-8@^1.0.2: 904 | version "1.0.2" 905 | resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" 906 | integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== 907 | 908 | through@2, "through@>=2.2.7 <3", through@~2.3, through@~2.3.1: 909 | version "2.3.8" 910 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 911 | integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= 912 | 913 | toml@^3.0.0: 914 | version "3.0.0" 915 | resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" 916 | integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== 917 | 918 | tr46@~0.0.3: 919 | version "0.0.3" 920 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 921 | integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= 922 | 923 | traverse-chain@~0.1.0: 924 | version "0.1.0" 925 | resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" 926 | integrity sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE= 927 | 928 | ts-node@^10.5.0: 929 | version "10.5.0" 930 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.5.0.tgz#618bef5854c1fbbedf5e31465cbb224a1d524ef9" 931 | integrity sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw== 932 | dependencies: 933 | "@cspotcode/source-map-support" "0.7.0" 934 | "@tsconfig/node10" "^1.0.7" 935 | "@tsconfig/node12" "^1.0.7" 936 | "@tsconfig/node14" "^1.0.0" 937 | "@tsconfig/node16" "^1.0.2" 938 | acorn "^8.4.1" 939 | acorn-walk "^8.1.1" 940 | arg "^4.1.0" 941 | create-require "^1.1.0" 942 | diff "^4.0.1" 943 | make-error "^1.1.1" 944 | v8-compile-cache-lib "^3.0.0" 945 | yn "3.1.1" 946 | 947 | tslib@^2.0.3, tslib@^2.1.0: 948 | version "2.3.1" 949 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" 950 | integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== 951 | 952 | tweetnacl@^1.0.0: 953 | version "1.0.3" 954 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" 955 | integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== 956 | 957 | typescript@^4.5.5: 958 | version "4.5.5" 959 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" 960 | integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== 961 | 962 | utf-8-validate@^5.0.2: 963 | version "5.0.8" 964 | resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.8.tgz#4a735a61661dbb1c59a0868c397d2fe263f14e58" 965 | integrity sha512-k4dW/Qja1BYDl2qD4tOMB9PFVha/UJtxTc1cXYOe3WwA/2m0Yn4qB7wLMpJyLJ/7DR0XnTut3HsCSzDT4ZvKgA== 966 | dependencies: 967 | node-gyp-build "^4.3.0" 968 | 969 | uuid@^8.3.0, uuid@^8.3.2: 970 | version "8.3.2" 971 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" 972 | integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== 973 | 974 | v8-compile-cache-lib@^3.0.0: 975 | version "3.0.0" 976 | resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" 977 | integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== 978 | 979 | wait-on@6.0.0: 980 | version "6.0.0" 981 | resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.0.tgz#7e9bf8e3d7fe2daecbb7a570ac8ca41e9311c7e7" 982 | integrity sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw== 983 | dependencies: 984 | axios "^0.21.1" 985 | joi "^17.4.0" 986 | lodash "^4.17.21" 987 | minimist "^1.2.5" 988 | rxjs "^7.1.0" 989 | 990 | webidl-conversions@^3.0.0: 991 | version "3.0.1" 992 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 993 | integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= 994 | 995 | whatwg-url@^5.0.0: 996 | version "5.0.0" 997 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 998 | integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= 999 | dependencies: 1000 | tr46 "~0.0.3" 1001 | webidl-conversions "^3.0.0" 1002 | 1003 | which@^2.0.1: 1004 | version "2.0.2" 1005 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1006 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1007 | dependencies: 1008 | isexe "^2.0.0" 1009 | 1010 | ws@^7.4.5: 1011 | version "7.5.7" 1012 | resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" 1013 | integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== 1014 | 1015 | yn@3.1.1: 1016 | version "3.1.1" 1017 | resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" 1018 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 1019 | --------------------------------------------------------------------------------