From eac21f6d44fa845cbe71e5c28a8d9b9c85fe6019 Mon Sep 17 00:00:00 2001 From: dd Date: Sun, 21 Feb 2021 18:27:48 -0500 Subject: [PATCH] trying to integrate new aggregator --- package.json | 5 +- src/client.ts | 744 ++++++++++++++++++++++++--------------------- src/instruction.ts | 34 +++ src/layout.ts | 102 ++++--- yarn.lock | 460 ++++++++++++++++++++++++++-- 5 files changed, 941 insertions(+), 404 deletions(-) diff --git a/package.json b/package.json index 5e3a217..0e75330 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "ts-jest": "^26.2.0", "ts-node": "^9.1.1", "typescript": "^4.1.3" + }, "files": [ "lib" @@ -60,7 +61,9 @@ "@project-serum/sol-wallet-adapter": "^0.1.4", "@solana/web3.js": "^0.90.0", "bn.js": "^5.1.2", - "buffer-layout": "^1.2.0" + "buffer-layout": "^1.2.0", + + "solink": "git+ssh://git@github.com:blockworks-foundation/solana-flux-aggregator.git" }, "browserslist": [ ">0.2%", diff --git a/src/client.ts b/src/client.ts index f919785..74020c8 100644 --- a/src/client.ts +++ b/src/client.ts @@ -19,19 +19,13 @@ import { WideBits, } from './layout'; import BN from 'bn.js'; -import { - createAccountInstruction, - decodeAggregatorInfo, - getMintDecimals, - nativeToUi, - uiToNative, - zeroKey, -} from './utils'; +import { createAccountInstruction, decodeAggregatorInfo, nativeToUi, uiToNative, zeroKey } from './utils'; import { Market, OpenOrders, Orderbook } from '@project-serum/serum'; import { SRM_DECIMALS, TOKEN_PROGRAM_ID } from '@project-serum/serum/lib/token-instructions'; import { Order } from '@project-serum/serum/lib/market'; import Wallet from '@project-serum/sol-wallet-adapter'; import { makeCancelOrderInstruction, makeSettleFundsInstruction } from './instruction'; +import { Aggregator } from 'solink'; export class MangoGroup { publicKey: PublicKey; @@ -39,7 +33,7 @@ export class MangoGroup { accountFlags!: WideBits; tokens!: PublicKey[]; vaults!: PublicKey[]; - indexes!: { lastUpdate: BN; borrow: number; deposit: number }; + indexes!: { lastUpdate: BN, borrow: number, deposit: number }; spotMarkets!: PublicKey[]; oracles!: PublicKey[]; signerNonce!: BN; @@ -50,6 +44,8 @@ export class MangoGroup { maintCollRatio!: number; initCollRatio!: number; srmVault!: PublicKey; + admin!: PublicKey; + borrowLimits!: number[]; mintDecimals!: number[]; oracleDecimals!: number[]; @@ -58,47 +54,58 @@ export class MangoGroup { Object.assign(this, decoded); } - async getPrices(connection: Connection): Promise { + async getPrices( + connection: Connection, + ): Promise { + + const aggs = await Promise.all(this.oracles.map((pk) => (Aggregator.load(pk)))) + const oracleAccs = await getMultipleAccounts(connection, this.oracles); - return oracleAccs.map((oa) => decodeAggregatorInfo(oa.accountInfo).submissionValue).concat(1.0); + return oracleAccs.map((oa) => decodeAggregatorInfo(oa.accountInfo).submissionValue).concat(1.0) } getMarketIndex(spotMarket: Market): number { for (let i = 0; i < this.spotMarkets.length; i++) { if (this.spotMarkets[i].equals(spotMarket.publicKey)) { - return i; + return i } } - throw new Error('This Market does not belong to this MangoGroup'); + throw new Error("This Market does not belong to this MangoGroup") } getTokenIndex(token: PublicKey): number { for (let i = 0; i < this.tokens.length; i++) { if (this.tokens[i].equals(token)) { - return i; + return i } } - throw new Error('This token does not belong in this MangoGroup'); + throw new Error("This token does not belong in this MangoGroup") } getBorrowRate(tokenIndex: number): number { - return 0.0; // TODO + + const optimalUtil = 0.7 + const optimalRate = 0.1 + const index = this.indexes[tokenIndex] + + + return 0.0 // TODO } getDepositRate(tokenIndex: number): number { - return 0.0; // TODO + return 0.0 // TODO } getUiTotalDeposit(tokenIndex: number): number { - return nativeToUi(this.totalDeposits[tokenIndex] * this.indexes[tokenIndex].deposit, this.mintDecimals[tokenIndex]); + return nativeToUi(this.totalDeposits[tokenIndex] * this.indexes[tokenIndex].deposit, this.mintDecimals[tokenIndex]) } getUiTotalBorrow(tokenIndex: number): number { - return nativeToUi(this.totalBorrows[tokenIndex] * this.indexes[tokenIndex].borrow, this.mintDecimals[tokenIndex]); + return nativeToUi(this.totalBorrows[tokenIndex] * this.indexes[tokenIndex].borrow, this.mintDecimals[tokenIndex]) } } export class MarginAccount { publicKey: PublicKey; - createTime: number; // used to determine when to update + createTime: number; // used to determine when to update // TODO maybe this is obviated by websocket feed onUpdate accountFlags!: WideBits; @@ -108,144 +115,151 @@ export class MarginAccount { borrows!: number[]; openOrders!: PublicKey[]; srmBalance!: number; - openOrdersAccounts: (OpenOrders | undefined)[]; // undefined if an openOrdersAccount not yet initialized and has zeroKey + openOrdersAccounts: (OpenOrders | undefined)[] // undefined if an openOrdersAccount not yet initialized and has zeroKey // TODO keep updated with websocket constructor(publicKey: PublicKey, decoded: any) { - this.publicKey = publicKey; - this.createTime = getUnixTs(); - this.openOrdersAccounts = new Array(NUM_MARKETS).fill(undefined); - Object.assign(this, decoded); + this.publicKey = publicKey + this.createTime = getUnixTs() + this.openOrdersAccounts = new Array(NUM_MARKETS).fill(undefined) + Object.assign(this, decoded) } - getNativeDeposit(mangoGroup: MangoGroup, tokenIndex: number): number { - // insufficient precision - return Math.round(mangoGroup.indexes[tokenIndex].deposit * this.deposits[tokenIndex]); + getNativeDeposit(mangoGroup: MangoGroup, tokenIndex: number): number { // insufficient precision + return Math.round(mangoGroup.indexes[tokenIndex].deposit * this.deposits[tokenIndex]) } - getNativeBorrow(mangoGroup: MangoGroup, tokenIndex: number): number { - // insufficient precision - return Math.round(mangoGroup.indexes[tokenIndex].borrow * this.borrows[tokenIndex]); + getNativeBorrow(mangoGroup: MangoGroup, tokenIndex: number): number { // insufficient precision + return Math.round(mangoGroup.indexes[tokenIndex].borrow * this.borrows[tokenIndex]) } - getUiDeposit(mangoGroup: MangoGroup, tokenIndex: number): number { - // insufficient precision - return nativeToUi(this.getNativeDeposit(mangoGroup, tokenIndex), mangoGroup.mintDecimals[tokenIndex]); + getUiDeposit(mangoGroup: MangoGroup, tokenIndex: number): number { // insufficient precision + return nativeToUi(this.getNativeDeposit(mangoGroup, tokenIndex), mangoGroup.mintDecimals[tokenIndex]) } - getUiBorrow(mangoGroup: MangoGroup, tokenIndex: number): number { - // insufficient precision - return nativeToUi(this.getNativeBorrow(mangoGroup, tokenIndex), mangoGroup.mintDecimals[tokenIndex]); + getUiBorrow(mangoGroup: MangoGroup, tokenIndex: number): number { // insufficient precision + return nativeToUi(this.getNativeBorrow(mangoGroup, tokenIndex), mangoGroup.mintDecimals[tokenIndex]) } getUiSrmBalance() { - return nativeToUi(this.srmBalance, SRM_DECIMALS); + return nativeToUi(this.srmBalance, SRM_DECIMALS) } - async loadOpenOrders(connection: Connection, dexProgramId: PublicKey): Promise<(OpenOrders | undefined)[]> { - const promises: Promise[] = []; + async loadOpenOrders( + connection: Connection, + dexProgramId: PublicKey + ): Promise<(OpenOrders | undefined)[]> { + const promises: Promise[] = [] for (let i = 0; i < this.openOrders.length; i++) { if (this.openOrders[i].equals(zeroKey)) { - promises.push(promiseUndef()); + promises.push(promiseUndef()) } else { - promises.push(OpenOrders.load(connection, this.openOrders[i], dexProgramId)); + promises.push(OpenOrders.load(connection, this.openOrders[i], dexProgramId)) } } - this.openOrdersAccounts = await Promise.all(promises); - return this.openOrdersAccounts; + this.openOrdersAccounts = await Promise.all(promises) + return this.openOrdersAccounts } - toPrettyString(mangoGroup: MangoGroup): string { - const lines = [`MarginAccount: ${this.publicKey.toBase58()}`, `Asset Deposits Borrows`]; + toPrettyString( + mangoGroup: MangoGroup + ): string { + const lines = [ + `MarginAccount: ${this.publicKey.toBase58()}`, + `Asset Deposits Borrows`, + ] - const tokenNames = ['BTC', 'ETH', 'USDC']; // TODO pull this from somewhere + const tokenNames = ["BTC", "ETH", "USDC"] // TODO pull this from somewhere for (let i = 0; i < mangoGroup.tokens.length; i++) { - lines.push(`${tokenNames[i]} ${this.getUiDeposit(mangoGroup, i)} ${this.getUiBorrow(mangoGroup, i)}`); + lines.push( + `${tokenNames[i]} ${this.getUiDeposit(mangoGroup, i)} ${this.getUiBorrow(mangoGroup, i)}` + ) } - return lines.join('\n'); + return lines.join('\n') } - async getValue(connection: Connection, mangoGroup: MangoGroup): Promise { - const prices = await mangoGroup.getPrices(connection); + async getValue( + connection: Connection, + mangoGroup: MangoGroup + ): Promise { + const prices = await mangoGroup.getPrices(connection) - let value = 0; + let value = 0 for (let i = 0; i < this.deposits.length; i++) { - value += (this.getUiDeposit(mangoGroup, i) - this.getUiBorrow(mangoGroup, i)) * prices[i]; + value += (this.getUiDeposit(mangoGroup, i) - this.getUiBorrow(mangoGroup, i)) * prices[i] } for (let i = 0; i < this.openOrdersAccounts.length; i++) { - const oos = this.openOrdersAccounts[i]; + const oos = this.openOrdersAccounts[i] if (oos != undefined) { - value += nativeToUi(oos.baseTokenTotal.toNumber(), mangoGroup.mintDecimals[i]) * prices[i]; - value += nativeToUi(oos.quoteTokenTotal.toNumber(), mangoGroup.mintDecimals[NUM_TOKENS - 1]); + value += nativeToUi(oos.baseTokenTotal.toNumber(), mangoGroup.mintDecimals[i]) * prices[i] + value += nativeToUi(oos.quoteTokenTotal.toNumber(), mangoGroup.mintDecimals[NUM_TOKENS-1]) } } - return value; + return value } getAssets(mangoGroup: MangoGroup): number[] { - const assets = new Array(NUM_TOKENS); + const assets = new Array(NUM_TOKENS) for (let i = 0; i < NUM_TOKENS; i++) { - assets[i] = this.getUiDeposit(mangoGroup, i); + assets[i] = this.getUiDeposit(mangoGroup, i) } for (let i = 0; i < NUM_MARKETS; i++) { - const openOrdersAccount = this.openOrdersAccounts[i]; + const openOrdersAccount = this.openOrdersAccounts[i] if (openOrdersAccount == undefined) { - continue; + continue } - assets[i] += nativeToUi(openOrdersAccount.baseTokenTotal.toNumber(), mangoGroup.mintDecimals[i]); - assets[NUM_TOKENS - 1] += nativeToUi( - openOrdersAccount.quoteTokenTotal.toNumber(), - mangoGroup.mintDecimals[NUM_TOKENS - 1], - ); + assets[i] += nativeToUi(openOrdersAccount.baseTokenTotal.toNumber(), mangoGroup.mintDecimals[i]) + assets[NUM_TOKENS-1] += nativeToUi(openOrdersAccount.quoteTokenTotal.toNumber(), mangoGroup.mintDecimals[NUM_TOKENS-1]) } - return assets; + + return assets } getLiabs(mangoGroup: MangoGroup): number[] { - const liabs = new Array(NUM_TOKENS); + const liabs = new Array(NUM_TOKENS) for (let i = 0; i < NUM_TOKENS; i++) { - liabs[i] = this.getUiBorrow(mangoGroup, i); + liabs[i] = this.getUiBorrow(mangoGroup, i) } - return liabs; + return liabs } getAssetsVal(mangoGroup: MangoGroup, prices: number[]): number { - let assetsVal = 0; + let assetsVal = 0 for (let i = 0; i < NUM_TOKENS; i++) { - assetsVal += this.getUiDeposit(mangoGroup, i) * prices[i]; + assetsVal += this.getUiDeposit(mangoGroup, i) * prices[i] } for (let i = 0; i < NUM_MARKETS; i++) { - const openOrdersAccount = this.openOrdersAccounts[i]; + const openOrdersAccount = this.openOrdersAccounts[i] if (openOrdersAccount == undefined) { - continue; + continue } - assetsVal += nativeToUi(openOrdersAccount.baseTokenTotal.toNumber(), mangoGroup.mintDecimals[i]) * prices[i]; - assetsVal += nativeToUi(openOrdersAccount.quoteTokenTotal.toNumber(), mangoGroup.mintDecimals[NUM_TOKENS - 1]); + assetsVal += nativeToUi(openOrdersAccount.baseTokenTotal.toNumber(), mangoGroup.mintDecimals[i]) * prices[i] + assetsVal += nativeToUi(openOrdersAccount.quoteTokenTotal.toNumber(), mangoGroup.mintDecimals[NUM_TOKENS-1]) } - return assetsVal; + return assetsVal } getLiabsVal(mangoGroup: MangoGroup, prices: number[]) { - let liabsVal = 0; + let liabsVal = 0 for (let i = 0; i < NUM_TOKENS; i++) { - liabsVal += this.getUiBorrow(mangoGroup, i) * prices[i]; + liabsVal += this.getUiBorrow(mangoGroup, i) * prices[i] } - return liabsVal; + return liabsVal } getCollateralRatio(mangoGroup: MangoGroup, prices: number[]): number { - const assetsVal = this.getAssetsVal(mangoGroup, prices); - const liabsVal = this.getLiabsVal(mangoGroup, prices); + const assetsVal = this.getAssetsVal(mangoGroup, prices) + const liabsVal = this.getLiabsVal(mangoGroup, prices) - return assetsVal / liabsVal; + return assetsVal / liabsVal } async cancelAllOrdersByMarket( @@ -256,76 +270,93 @@ export class MarginAccount { market: Market, bids: Orderbook, asks: Orderbook, - owner: Account, + owner: Account ): Promise { - const marketIndex = mangoGroup.getMarketIndex(market); - const openOrdersAccount = this.openOrdersAccounts[marketIndex]; - if (openOrdersAccount == undefined) { - // no open orders for this market - return []; + + const marketIndex = mangoGroup.getMarketIndex(market) + const openOrdersAccount = this.openOrdersAccounts[marketIndex] + if (openOrdersAccount == undefined) { // no open orders for this market + return [] } - const orders = market.filterForOpenOrders(bids, asks, [openOrdersAccount]); - return await Promise.all( - orders.map((order) => client.cancelOrder(connection, programId, mangoGroup, this, owner, market, order)), - ); + const orders = market.filterForOpenOrders(bids, asks, [openOrdersAccount]) + return await Promise.all(orders.map( + (order) => ( + client.cancelOrder(connection, programId, mangoGroup, this, owner, market, order) + ) + )) + } + } export class MangoClient { - async initMangoGroup() { - throw new Error('Not Implemented'); - } + async sendTransaction( connection: Connection, transaction: Transaction, payer: Account, additionalSigners: Account[], - ): Promise { +): Promise { // TODO test on mainnet - transaction.recentBlockhash = (await connection.getRecentBlockhash('singleGossip')).blockhash; - transaction.setSigners(payer.publicKey, ...additionalSigners.map((a) => a.publicKey)); + transaction.recentBlockhash = (await connection.getRecentBlockhash('singleGossip')).blockhash + transaction.setSigners(payer.publicKey, ...additionalSigners.map( a => a.publicKey )) + + const signers = [payer].concat(additionalSigners) + transaction.sign(...signers) + const rawTransaction = transaction.serialize() + return await sendAndConfirmRawTransaction(connection, rawTransaction, {skipPreflight: true}) - const signers = [payer].concat(additionalSigners); - transaction.sign(...signers); - const rawTransaction = transaction.serialize(); - return await sendAndConfirmRawTransaction(connection, rawTransaction, { skipPreflight: true }); } + + async initMangoGroup( + connection: Connection, + programId: PublicKey, + payer: PublicKey, + + ) { + + throw new Error("Not Implemented"); + } + async initMarginAccount( connection: Connection, programId: PublicKey, mangoGroup: MangoGroup, - owner: Account, // assumed to be same as payer for now + owner: Account, // assumed to be same as payer for now ): Promise { // Create a Solana account for the MarginAccount and allocate space - const accInstr = await createAccountInstruction(connection, owner.publicKey, MarginAccountLayout.span, programId); + const accInstr = await createAccountInstruction(connection, + owner.publicKey, MarginAccountLayout.span, programId) // Specify the accounts this instruction takes in (see program/src/instruction.rs) const keys = [ { isSigner: false, isWritable: false, pubkey: mangoGroup.publicKey }, - { isSigner: false, isWritable: true, pubkey: accInstr.account.publicKey }, - { isSigner: true, isWritable: false, pubkey: owner.publicKey }, - { isSigner: false, isWritable: false, pubkey: SYSVAR_RENT_PUBKEY }, - ]; + { isSigner: false, isWritable: true, pubkey: accInstr.account.publicKey }, + { isSigner: true, isWritable: false, pubkey: owner.publicKey }, + { isSigner: false, isWritable: false, pubkey: SYSVAR_RENT_PUBKEY } + ] // Encode and create instruction for actual initMarginAccount instruction - const data = encodeMangoInstruction({ InitMarginAccount: {} }); - const initMarginAccountInstruction = new TransactionInstruction({ keys, data, programId }); + const data = encodeMangoInstruction({ InitMarginAccount: {} }) + const initMarginAccountInstruction = new TransactionInstruction( { keys, data, programId }) // Add all instructions to one atomic transaction - const transaction = new Transaction(); - transaction.add(accInstr.instruction); - transaction.add(initMarginAccountInstruction); + const transaction = new Transaction() + transaction.add(accInstr.instruction) + transaction.add(initMarginAccountInstruction) // Specify signers in addition to the wallet - const additionalSigners = [accInstr.account]; + const additionalSigners = [ + accInstr.account, + ] // sign, send and confirm transaction - await this.sendTransaction(connection, transaction, owner, additionalSigners); + await this.sendTransaction(connection, transaction, owner, additionalSigners) - return accInstr.account.publicKey; + return accInstr.account.publicKey } async deposit( @@ -337,29 +368,30 @@ export class MangoClient { token: PublicKey, tokenAcc: PublicKey, - quantity: number, + quantity: number ): Promise { - const tokenIndex = mangoGroup.getTokenIndex(token); - const nativeQuantity = uiToNative(quantity, mangoGroup.mintDecimals[tokenIndex]); + const tokenIndex = mangoGroup.getTokenIndex(token) + const nativeQuantity = uiToNative(quantity, mangoGroup.mintDecimals[tokenIndex]) const keys = [ - { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, - { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, + { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey}, + { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, { isSigner: true, isWritable: false, pubkey: owner.publicKey }, - { isSigner: false, isWritable: true, pubkey: tokenAcc }, - { isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[tokenIndex] }, + { isSigner: false, isWritable: true, pubkey: tokenAcc }, + { isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[tokenIndex] }, { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, - { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, - ]; - const data = encodeMangoInstruction({ Deposit: { quantity: nativeQuantity } }); + { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY } + ] + const data = encodeMangoInstruction({Deposit: {quantity: nativeQuantity}}) - const instruction = new TransactionInstruction({ keys, data, programId }); - const transaction = new Transaction(); - transaction.add(instruction); - const additionalSigners = []; + const instruction = new TransactionInstruction( { keys, data, programId }) - return await this.sendTransaction(connection, transaction, owner, additionalSigners); + const transaction = new Transaction() + transaction.add(instruction) + const additionalSigners = [] + + return await this.sendTransaction(connection, transaction, owner, additionalSigners) } async withdraw( @@ -371,32 +403,33 @@ export class MangoClient { token: PublicKey, tokenAcc: PublicKey, - quantity: number, + quantity: number ): Promise { - const tokenIndex = mangoGroup.getTokenIndex(token); - const nativeQuantity = uiToNative(quantity, mangoGroup.mintDecimals[tokenIndex]); + const tokenIndex = mangoGroup.getTokenIndex(token) + const nativeQuantity = uiToNative(quantity, mangoGroup.mintDecimals[tokenIndex]) const keys = [ - { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, - { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, + { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey}, + { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, { isSigner: true, isWritable: false, pubkey: owner.publicKey }, - { isSigner: false, isWritable: true, pubkey: tokenAcc }, - { isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[tokenIndex] }, - { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, + { isSigner: false, isWritable: true, pubkey: tokenAcc }, + { isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[tokenIndex] }, + { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, - ...marginAccount.openOrders.map((pubkey) => ({ isSigner: false, isWritable: false, pubkey })), - ...mangoGroup.oracles.map((pubkey) => ({ isSigner: false, isWritable: false, pubkey })), - ]; - const data = encodeMangoInstruction({ Withdraw: { quantity: nativeQuantity } }); + ...marginAccount.openOrders.map( (pubkey) => ( { isSigner: false, isWritable: false, pubkey })), + ...mangoGroup.oracles.map( (pubkey) => ( { isSigner: false, isWritable: false, pubkey })) + ] + const data = encodeMangoInstruction({Withdraw: {quantity: nativeQuantity}}) - const instruction = new TransactionInstruction({ keys, data, programId }); - const transaction = new Transaction(); - transaction.add(instruction); - const additionalSigners = []; + const instruction = new TransactionInstruction( { keys, data, programId }) - return await this.sendTransaction(connection, transaction, owner, additionalSigners); + const transaction = new Transaction() + transaction.add(instruction) + const additionalSigners = [] + + return await this.sendTransaction(connection, transaction, owner, additionalSigners) } async borrow( @@ -407,28 +440,29 @@ export class MangoClient { owner: Account, token: PublicKey, - quantity: number, + quantity: number ): Promise { - const tokenIndex = mangoGroup.getTokenIndex(token); - const nativeQuantity = uiToNative(quantity, mangoGroup.mintDecimals[tokenIndex]); + const tokenIndex = mangoGroup.getTokenIndex(token) + const nativeQuantity = uiToNative(quantity, mangoGroup.mintDecimals[tokenIndex]) const keys = [ - { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, - { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, + { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey}, + { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, { isSigner: true, isWritable: false, pubkey: owner.publicKey }, { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, - ...marginAccount.openOrders.map((pubkey) => ({ isSigner: false, isWritable: false, pubkey })), - ...mangoGroup.oracles.map((pubkey) => ({ isSigner: false, isWritable: false, pubkey })), - ]; - const data = encodeMangoInstruction({ Borrow: { tokenIndex: new BN(tokenIndex), quantity: nativeQuantity } }); + ...marginAccount.openOrders.map( (pubkey) => ( { isSigner: false, isWritable: false, pubkey })), + ...mangoGroup.oracles.map( (pubkey) => ( { isSigner: false, isWritable: false, pubkey })), + ] + const data = encodeMangoInstruction({Borrow: {tokenIndex: new BN(tokenIndex), quantity: nativeQuantity}}) - const instruction = new TransactionInstruction({ keys, data, programId }); - const transaction = new Transaction(); - transaction.add(instruction); - const additionalSigners = []; + const instruction = new TransactionInstruction( { keys, data, programId }) - return await this.sendTransaction(connection, transaction, owner, additionalSigners); + const transaction = new Transaction() + transaction.add(instruction) + const additionalSigners = [] + + return await this.sendTransaction(connection, transaction, owner, additionalSigners) } async settleBorrow( @@ -439,25 +473,26 @@ export class MangoClient { owner: Account, token: PublicKey, - quantity: number, + quantity: number ): Promise { - const tokenIndex = mangoGroup.getTokenIndex(token); - const nativeQuantity = uiToNative(quantity, mangoGroup.mintDecimals[tokenIndex]); + + const tokenIndex = mangoGroup.getTokenIndex(token) + const nativeQuantity = uiToNative(quantity, mangoGroup.mintDecimals[tokenIndex]) const keys = [ - { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, - { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, - { isSigner: true, isWritable: false, pubkey: owner.publicKey }, - { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, - ]; - const data = encodeMangoInstruction({ SettleBorrow: { tokenIndex: new BN(tokenIndex), quantity: nativeQuantity } }); + { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey}, + { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, + { isSigner: true, isWritable: false, pubkey: owner.publicKey }, + { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY } + ] + const data = encodeMangoInstruction({SettleBorrow: {tokenIndex: new BN(tokenIndex), quantity: nativeQuantity}}) - const instruction = new TransactionInstruction({ keys, data, programId }); - const transaction = new Transaction(); - transaction.add(instruction); - const additionalSigners = []; + const instruction = new TransactionInstruction( { keys, data, programId }) + const transaction = new Transaction() + transaction.add(instruction) + const additionalSigners = [] - return await this.sendTransaction(connection, transaction, owner, additionalSigners); + return await this.sendTransaction(connection, transaction, owner, additionalSigners) } /** @@ -475,23 +510,27 @@ export class MangoClient { mangoGroup: MangoGroup, marginAccount: MarginAccount, markets: Market[], - owner: Account, + owner: Account ): Promise { - const transaction = new Transaction(); + + const transaction = new Transaction() for (let i = 0; i < NUM_MARKETS; i++) { if (marginAccount.openOrdersAccounts[i] == undefined) { - continue; + continue } - const spotMarket = markets[i]; + const spotMarket = markets[i] const dexSigner = await PublicKey.createProgramAddress( - [spotMarket.publicKey.toBuffer(), spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8)], - spotMarket.programId, - ); + [ + spotMarket.publicKey.toBuffer(), + spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8) + ], + spotMarket.programId + ) const keys = [ - { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, - { isSigner: true, isWritable: false, pubkey: owner.publicKey }, - { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, + { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey}, + { isSigner: true, isWritable: false, pubkey: owner.publicKey }, + { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, { isSigner: false, isWritable: false, pubkey: spotMarket.programId }, { isSigner: false, isWritable: true, pubkey: spotMarket.publicKey }, @@ -503,70 +542,69 @@ export class MangoClient { { isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[mangoGroup.vaults.length - 1] }, { isSigner: false, isWritable: false, pubkey: dexSigner }, { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, - ]; - const data = encodeMangoInstruction({ SettleFunds: {} }); + ] + const data = encodeMangoInstruction( {SettleFunds: {}} ) - const instruction = new TransactionInstruction({ keys, data, programId }); - transaction.add(instruction); + const instruction = new TransactionInstruction( { keys, data, programId }) + transaction.add(instruction) } - const assets = marginAccount.getAssets(mangoGroup); - const liabs = marginAccount.getLiabs(mangoGroup); + const assets = marginAccount.getAssets(mangoGroup) + const liabs = marginAccount.getLiabs(mangoGroup) - for (let i = 0; i < NUM_TOKENS; i++) { - // TODO test this. maybe it hits transaction size limit + for (let i = 0; i < NUM_TOKENS; i++) { // TODO test this. maybe it hits transaction size limit const keys = [ - { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, - { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, - { isSigner: true, isWritable: false, pubkey: owner.publicKey }, - { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, - ]; - const data = encodeMangoInstruction({ - SettleBorrow: { tokenIndex: new BN(i), quantity: uiToNative(liabs[i] * 2, mangoGroup.mintDecimals[i]) }, - }); + { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey}, + { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, + { isSigner: true, isWritable: false, pubkey: owner.publicKey }, + { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY } + ] + const data = encodeMangoInstruction({SettleBorrow: {tokenIndex: new BN(i), quantity: uiToNative(liabs[i] * 2, mangoGroup.mintDecimals[i])}}) - const instruction = new TransactionInstruction({ keys, data, programId }); - transaction.add(instruction); + const instruction = new TransactionInstruction( { keys, data, programId }) + transaction.add(instruction) } - const additionalSigners = []; - return await this.sendTransaction(connection, transaction, owner, additionalSigners); + const additionalSigners = [] + return await this.sendTransaction(connection, transaction, owner, additionalSigners) } async liquidate( connection: Connection, programId: PublicKey, mangoGroup: MangoGroup, - liqeeMarginAccount: MarginAccount, // liquidatee marginAccount - liqor: Account, // liquidator + liqeeMarginAccount: MarginAccount, // liquidatee marginAccount + liqor: Account, // liquidator tokenAccs: PublicKey[], - depositQuantities: number[], + depositQuantities: number[] ): Promise { - const depositsBN: BN[] = []; + + const depositsBN: BN[] = [] for (let i = 0; i < mangoGroup.tokens.length; i++) { - depositsBN[i] = uiToNative(depositQuantities[i], mangoGroup.mintDecimals[i]); + depositsBN[i] = uiToNative(depositQuantities[i], mangoGroup.mintDecimals[i]) } const keys = [ - { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, + { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey}, { isSigner: true, isWritable: false, pubkey: liqor.publicKey }, - { isSigner: false, isWritable: true, pubkey: liqeeMarginAccount.publicKey }, + { isSigner: false, isWritable: true, pubkey: liqeeMarginAccount.publicKey }, { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, - ...liqeeMarginAccount.openOrders.map((pubkey) => ({ isSigner: false, isWritable: false, pubkey })), - ...mangoGroup.oracles.map((pubkey) => ({ isSigner: false, isWritable: false, pubkey })), - ...mangoGroup.vaults.map((pubkey) => ({ isSigner: false, isWritable: true, pubkey })), - ...tokenAccs.map((pubkey) => ({ isSigner: false, isWritable: true, pubkey })), - ]; - const data = encodeMangoInstruction({ Liquidate: { depositQuantities: depositsBN } }); + ...liqeeMarginAccount.openOrders.map( (pubkey) => ( { isSigner: false, isWritable: false, pubkey })), + ...mangoGroup.oracles.map( (pubkey) => ( { isSigner: false, isWritable: false, pubkey })), + ...mangoGroup.vaults.map( (pubkey) => ( { isSigner: false, isWritable: true, pubkey })), + ...tokenAccs.map( (pubkey) => ( { isSigner: false, isWritable: true, pubkey })), + ] + const data = encodeMangoInstruction({Liquidate: {depositQuantities: depositsBN}}) - const instruction = new TransactionInstruction({ keys, data, programId }); - const transaction = new Transaction(); - transaction.add(instruction); - const additionalSigners = []; + const instruction = new TransactionInstruction( { keys, data, programId }) - return await this.sendTransaction(connection, transaction, liqor, additionalSigners); + const transaction = new Transaction() + transaction.add(instruction) + const additionalSigners = [] + + return await this.sendTransaction(connection, transaction, liqor, additionalSigners) } async depositSrm( @@ -577,28 +615,28 @@ export class MangoClient { owner: Account, srmAccount: PublicKey, - quantity: number, + quantity: number ): Promise { - const nativeQuantity = uiToNative(quantity, SRM_DECIMALS); + const nativeQuantity = uiToNative(quantity, SRM_DECIMALS) const keys = [ { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, - { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, + { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, { isSigner: true, isWritable: false, pubkey: owner.publicKey }, - { isSigner: false, isWritable: true, pubkey: srmAccount }, - { isSigner: false, isWritable: true, pubkey: mangoGroup.srmVault }, + { isSigner: false, isWritable: true, pubkey: srmAccount }, + { isSigner: false, isWritable: true, pubkey: mangoGroup.srmVault }, { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, - { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, - ]; - const data = encodeMangoInstruction({ DepositSrm: { quantity: nativeQuantity } }); + { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY } + ] + const data = encodeMangoInstruction({DepositSrm: {quantity: nativeQuantity}}) - const instruction = new TransactionInstruction({ keys, data, programId }); + const instruction = new TransactionInstruction( { keys, data, programId }) - const transaction = new Transaction(); - transaction.add(instruction); - const additionalSigners = []; + const transaction = new Transaction() + transaction.add(instruction) + const additionalSigners = [] - return await this.sendTransaction(connection, transaction, owner, additionalSigners); + return await this.sendTransaction(connection, transaction, owner, additionalSigners) } async withdrawSrm( @@ -609,29 +647,29 @@ export class MangoClient { owner: Account, srmAccount: PublicKey, - quantity: number, + quantity: number ): Promise { - const nativeQuantity = uiToNative(quantity, SRM_DECIMALS); + const nativeQuantity = uiToNative(quantity, SRM_DECIMALS) const keys = [ { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, - { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, + { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, { isSigner: true, isWritable: false, pubkey: owner.publicKey }, - { isSigner: false, isWritable: true, pubkey: srmAccount }, - { isSigner: false, isWritable: true, pubkey: mangoGroup.srmVault }, - { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, + { isSigner: false, isWritable: true, pubkey: srmAccount }, + { isSigner: false, isWritable: true, pubkey: mangoGroup.srmVault }, + { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, - { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, - ]; - const data = encodeMangoInstruction({ WithdrawSrm: { quantity: nativeQuantity } }); + { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY } + ] + const data = encodeMangoInstruction({WithdrawSrm: {quantity: nativeQuantity}}) - const instruction = new TransactionInstruction({ keys, data, programId }); + const instruction = new TransactionInstruction( { keys, data, programId }) - const transaction = new Transaction(); - transaction.add(instruction); - const additionalSigners = []; + const transaction = new Transaction() + transaction.add(instruction) + const additionalSigners = [] - return await this.sendTransaction(connection, transaction, owner, additionalSigners); + return await this.sendTransaction(connection, transaction, owner, additionalSigners) } async placeOrder( @@ -647,62 +685,59 @@ export class MangoClient { size: number, orderType?: 'limit' | 'ioc' | 'postOnly', clientId?: BN, + ): Promise { // TODO allow wrapped SOL wallets // TODO allow fee discounts - orderType = orderType == undefined ? 'limit' : orderType; + orderType = orderType == undefined ? 'limit' : orderType // orderType = orderType ?? 'limit' - const limitPrice = spotMarket.priceNumberToLots(price); - const maxBaseQuantity = spotMarket.baseSizeNumberToLots(size); + const limitPrice = spotMarket.priceNumberToLots(price) + const maxBaseQuantity = spotMarket.baseSizeNumberToLots(size) // TODO verify if multiplying by highest fee tier is appropriate const maxQuoteQuantity = new BN(spotMarket['_decoded'].quoteLotSize.toNumber()).mul( maxBaseQuantity.mul(limitPrice), - ); + ) if (maxBaseQuantity.lte(new BN(0))) { - throw new Error('size too small'); + throw new Error('size too small') } if (limitPrice.lte(new BN(0))) { - throw new Error('invalid price'); + throw new Error('invalid price') } - const selfTradeBehavior = 'decrementTake'; - const marketIndex = mangoGroup.getMarketIndex(spotMarket); - const vaultIndex = side === 'buy' ? mangoGroup.vaults.length - 1 : marketIndex; + const selfTradeBehavior = 'decrementTake' + const marketIndex = mangoGroup.getMarketIndex(spotMarket) + const vaultIndex = (side === 'buy') ? mangoGroup.vaults.length - 1 : marketIndex // Add all instructions to one atomic transaction - const transaction = new Transaction(); + const transaction = new Transaction() // Specify signers in addition to the wallet - const additionalSigners: Account[] = []; + const additionalSigners: Account[] = [] // Create a Solana account for the open orders account if it's missing const openOrdersKeys: PublicKey[] = []; for (let i = 0; i < marginAccount.openOrders.length; i++) { if (i === marketIndex && marginAccount.openOrders[marketIndex].equals(zeroKey)) { // open orders missing for this market; create a new one now - const openOrdersSpace = OpenOrders.getLayout(mangoGroup.dexProgramId).span; - const openOrdersLamports = await connection.getMinimumBalanceForRentExemption(openOrdersSpace, 'singleGossip'); + const openOrdersSpace = OpenOrders.getLayout(mangoGroup.dexProgramId).span + const openOrdersLamports = await connection.getMinimumBalanceForRentExemption(openOrdersSpace, 'singleGossip') const accInstr = await createAccountInstruction( - connection, - owner.publicKey, - openOrdersSpace, - mangoGroup.dexProgramId, - openOrdersLamports, - ); + connection, owner.publicKey, openOrdersSpace, mangoGroup.dexProgramId, openOrdersLamports + ) - transaction.add(accInstr.instruction); - additionalSigners.push(accInstr.account); - openOrdersKeys.push(accInstr.account.publicKey); + transaction.add(accInstr.instruction) + additionalSigners.push(accInstr.account) + openOrdersKeys.push(accInstr.account.publicKey) } else { - openOrdersKeys.push(marginAccount.openOrders[i]); + openOrdersKeys.push(marginAccount.openOrders[i]) } } const keys = [ - { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, - { isSigner: true, isWritable: false, pubkey: owner.publicKey }, + { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey}, + { isSigner: true, isWritable: false, pubkey: owner.publicKey }, { isSigner: false, isWritable: true, pubkey: marginAccount.publicKey }, { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, { isSigner: false, isWritable: false, pubkey: spotMarket.programId }, @@ -718,21 +753,24 @@ export class MangoClient { { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, { isSigner: false, isWritable: false, pubkey: SYSVAR_RENT_PUBKEY }, { isSigner: false, isWritable: true, pubkey: mangoGroup.srmVault }, - ...openOrdersKeys.map((pubkey) => ({ isSigner: false, isWritable: true, pubkey })), - ...mangoGroup.oracles.map((pubkey) => ({ isSigner: false, isWritable: false, pubkey })), - ]; + ...openOrdersKeys.map( (pubkey) => ( { isSigner: false, isWritable: true, pubkey })), + ...mangoGroup.oracles.map( (pubkey) => ( { isSigner: false, isWritable: false, pubkey })), + ] - const data = encodeMangoInstruction({ - PlaceOrder: clientId - ? { side, limitPrice, maxBaseQuantity, maxQuoteQuantity, selfTradeBehavior, orderType, clientId, limit: 65535 } - : { side, limitPrice, maxBaseQuantity, maxQuoteQuantity, selfTradeBehavior, orderType, limit: 65535 }, - }); + const data = encodeMangoInstruction( + { + PlaceOrder: + clientId + ? { side, limitPrice, maxBaseQuantity, maxQuoteQuantity, selfTradeBehavior, orderType, clientId, limit: 65535} + : { side, limitPrice, maxBaseQuantity, maxQuoteQuantity, selfTradeBehavior, orderType, limit: 65535} + } + ) - const placeOrderInstruction = new TransactionInstruction({ keys, data, programId }); - transaction.add(placeOrderInstruction); + const placeOrderInstruction = new TransactionInstruction( { keys, data, programId }) + transaction.add(placeOrderInstruction) // sign, send and confirm transaction - return await this.sendTransaction(connection, transaction, owner, additionalSigners); + return await this.sendTransaction(connection, transaction, owner, additionalSigners) } async settleFunds( connection: Connection, @@ -741,12 +779,17 @@ export class MangoClient { marginAccount: MarginAccount, owner: Account, spotMarket: Market, + ): Promise { - const marketIndex = mangoGroup.getMarketIndex(spotMarket); + + const marketIndex = mangoGroup.getMarketIndex(spotMarket) const dexSigner = await PublicKey.createProgramAddress( - [spotMarket.publicKey.toBuffer(), spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8)], - spotMarket.programId, - ); + [ + spotMarket.publicKey.toBuffer(), + spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8) + ], + spotMarket.programId + ) const instruction = makeSettleFundsInstruction( programId, @@ -761,19 +804,20 @@ export class MangoClient { spotMarket['_decoded'].quoteVault, mangoGroup.vaults[marketIndex], mangoGroup.vaults[mangoGroup.vaults.length - 1], - dexSigner, - ); + dexSigner + ) - const transaction = new Transaction(); - transaction.add(instruction); + const transaction = new Transaction() + transaction.add(instruction) // Specify signers in addition to the owner account - const additionalSigners = []; + const additionalSigners = [] // sign, send and confirm transaction - return await this.sendTransaction(connection, transaction, owner, additionalSigners); + return await this.sendTransaction(connection, transaction, owner, additionalSigners) } + async cancelOrder( connection: Connection, programId: PublicKey, @@ -795,16 +839,19 @@ export class MangoClient { order.openOrdersAddress, mangoGroup.signerKey, spotMarket['_decoded'].eventQueue, - order, - ); - const transaction = new Transaction(); - transaction.add(instruction); - const additionalSigners = []; + order + ) + const transaction = new Transaction() + transaction.add(instruction) + const additionalSigners = [] - return await this.sendTransaction(connection, transaction, owner, additionalSigners); + return await this.sendTransaction(connection, transaction, owner, additionalSigners) } - async getMangoGroup(connection: Connection, mangoGroupPk: PublicKey): Promise { + async getMangoGroup( + connection: Connection, + mangoGroupPk: PublicKey + ): Promise { const acc = await connection.getAccountInfo(mangoGroupPk); const decoded = MangoGroupLayout.decode(acc == null ? undefined : acc.data); return new MangoGroup(mangoGroupPk, decoded); @@ -813,25 +860,25 @@ export class MangoClient { async getMarginAccount( connection: Connection, marginAccountPk: PublicKey, - dexProgramId: PublicKey, + dexProgramId: PublicKey ): Promise { - const acc = await connection.getAccountInfo(marginAccountPk, 'singleGossip'); - const ma = new MarginAccount(marginAccountPk, MarginAccountLayout.decode(acc == null ? undefined : acc.data)); - await ma.loadOpenOrders(connection, dexProgramId); - return ma; + const acc = await connection.getAccountInfo(marginAccountPk, 'singleGossip') + const ma = new MarginAccount(marginAccountPk, MarginAccountLayout.decode(acc == null ? undefined : acc.data)) + await ma.loadOpenOrders(connection, dexProgramId) + return ma } async getAllMarginAccounts( connection: Connection, programId: PublicKey, - mangoGroup: MangoGroup, - ): Promise { + mangoGroup: MangoGroup + ): Promise{ const filters = [ { memcmp: { offset: MarginAccountLayout.offsetOf('mangoGroup'), bytes: mangoGroup.publicKey.toBase58(), - }, + } }, { @@ -842,19 +889,21 @@ export class MangoClient { const accounts = await getFilteredProgramAccounts(connection, programId, filters); const marginAccounts = accounts.map( ({ publicKey, accountInfo }) => - new MarginAccount(publicKey, MarginAccountLayout.decode(accountInfo == null ? undefined : accountInfo.data)), - ); + new MarginAccount(publicKey, MarginAccountLayout.decode(accountInfo == null ? undefined : accountInfo.data)) + ) + + await Promise.all(marginAccounts.map((ma) => ma.loadOpenOrders(connection, mangoGroup.dexProgramId))) + return marginAccounts - await Promise.all(marginAccounts.map((ma) => ma.loadOpenOrders(connection, mangoGroup.dexProgramId))); - return marginAccounts; } async getMarginAccountsForOwner( connection: Connection, programId: PublicKey, mangoGroup: MangoGroup, - owner: Account | Wallet, + owner: Account | Wallet ): Promise { + const filters = [ { memcmp: { @@ -866,7 +915,7 @@ export class MangoClient { memcmp: { offset: MarginAccountLayout.offsetOf('owner'), bytes: owner.publicKey.toBase58(), - }, + } }, { @@ -877,33 +926,37 @@ export class MangoClient { const accounts = await getFilteredProgramAccounts(connection, programId, filters); const marginAccounts = accounts.map( ({ publicKey, accountInfo }) => - new MarginAccount(publicKey, MarginAccountLayout.decode(accountInfo == null ? undefined : accountInfo.data)), - ); - await Promise.all(marginAccounts.map((ma) => ma.loadOpenOrders(connection, mangoGroup.dexProgramId))); - return marginAccounts; + new MarginAccount(publicKey, MarginAccountLayout.decode(accountInfo == null ? undefined : accountInfo.data)) + ) + await Promise.all(marginAccounts.map((ma) => ma.loadOpenOrders(connection, mangoGroup.dexProgramId))) + return marginAccounts } + } async function getMultipleAccounts( connection: Connection, - publicKeys: PublicKey[], + publicKeys: PublicKey[] + ): Promise<{ publicKey: PublicKey; accountInfo: AccountInfo }[]> { - const publickKeyStrs = publicKeys.map((pk) => pk.toBase58()); + const publickKeyStrs = publicKeys.map((pk) => (pk.toBase58())); // @ts-ignore const resp = await connection._rpcRequest('getMultipleAccounts', [publickKeyStrs]); if (resp.error) { throw new Error(resp.error.message); } - return resp.result.value.map(({ data, executable, lamports, owner }, i) => ({ - publicKey: publicKeys[i], - accountInfo: { - data: Buffer.from(data[0], 'base64'), - executable, - owner: new PublicKey(owner), - lamports, - }, - })); + return resp.result.value.map( + ({ data, executable, lamports, owner } , i) => ({ + publicKey: publicKeys[i], + accountInfo: { + data: Buffer.from(data[0], 'base64'), + executable, + owner: new PublicKey(owner), + lamports, + }, + }), + ); } async function getFilteredProgramAccounts( @@ -923,19 +976,22 @@ async function getFilteredProgramAccounts( if (resp.error) { throw new Error(resp.error.message); } - return resp.result.map(({ pubkey, account: { data, executable, owner, lamports } }) => ({ - publicKey: new PublicKey(pubkey), - accountInfo: { - data: Buffer.from(data[0], 'base64'), - executable, - owner: new PublicKey(owner), - lamports, - }, - })); + return resp.result.map( + ({ pubkey, account: { data, executable, owner, lamports } }) => ({ + publicKey: new PublicKey(pubkey), + accountInfo: { + data: Buffer.from(data[0], 'base64'), + executable, + owner: new PublicKey(owner), + lamports, + }, + }), + ); } + async function promiseUndef(): Promise { - return undefined; + return undefined } export const getUnixTs = () => { diff --git a/src/instruction.ts b/src/instruction.ts index 2740dcf..ea11e39 100644 --- a/src/instruction.ts +++ b/src/instruction.ts @@ -3,6 +3,40 @@ import { PublicKey, SYSVAR_CLOCK_PUBKEY, TransactionInstruction } from '@solana/ import { Order } from '@project-serum/serum/lib/market'; import { encodeMangoInstruction } from './layout'; import { TOKEN_PROGRAM_ID } from '@project-serum/serum/lib/token-instructions'; +import BN from 'bn.js'; + +// export function makeInitMangoGroupInstruction( +// programId: PublicKey, +// mangoGroupPk: PublicKey, +// signerKey: PublicKey, +// dexProgramId: PublicKey, +// srmVaultPk: PublicKey, +// mintPks: PublicKey[], +// vaultPks: PublicKey[], +// spotMarketPks: PublicKey[], +// oraclePks: PublicKey[], +// signerNonce: BN, +// maintCollRatio: number, +// initCollRatio: number +// ): TransactionInstruction { +// +// new BN() +// const keys = [ +// { isSigner: false, isWritable: true, pubkey: mangoGroupPk}, +// { isSigner: true, isWritable: false, pubkey: ownerPk }, +// { isSigner: false, isWritable: true, pubkey: marginAccountPk }, +// { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, +// { isSigner: false, isWritable: false, pubkey: dexProgramId }, +// { isSigner: false, isWritable: true, pubkey: spotMarketPk }, +// { isSigner: false, isWritable: true, pubkey: bidsPk }, +// { isSigner: false, isWritable: true, pubkey: asksPk }, +// { isSigner: false, isWritable: true, pubkey: openOrdersPk }, +// { isSigner: false, isWritable: false, pubkey: signerKey }, +// { isSigner: false, isWritable: true, pubkey: eventQueuePk }, +// ] +// +// +// } export function makeCancelOrderInstruction( programId: PublicKey, diff --git a/src/layout.ts b/src/layout.ts index cb368aa..506b704 100644 --- a/src/layout.ts +++ b/src/layout.ts @@ -4,7 +4,7 @@ import BN from 'bn.js'; export const NUM_TOKENS = 3; export const NUM_MARKETS = NUM_TOKENS - 1; -export const MANGO_GROUP_PADDING = 8 - ((NUM_TOKENS + NUM_MARKETS) % 8); +export const MANGO_GROUP_PADDING = 8 - (NUM_TOKENS + NUM_MARKETS) % 8; class PublicKeyLayout extends Blob { constructor(property) { @@ -20,7 +20,7 @@ class PublicKeyLayout extends Blob { } } -export function publicKeyLayout(property = '') { +export function publicKeyLayout(property = "") { return new PublicKeyLayout(property); } @@ -28,7 +28,7 @@ class BNLayout extends Blob { constructor(number: number, property) { super(number, property); // restore prototype chain - Object.setPrototypeOf(this, new.target.prototype); + Object.setPrototypeOf(this, new.target.prototype) } decode(b, offset) { @@ -40,14 +40,15 @@ class BNLayout extends Blob { } } -export function u64(property = '') { +export function u64(property = "") { return new BNLayout(8, property); } -export function u128(property = '') { +export function u128(property = "") { return new BNLayout(16, property); } + class U64F64Layout extends Blob { constructor(property: string) { super(16, property); @@ -65,8 +66,8 @@ class U64F64Layout extends Blob { } } -export function U64F64(property = '') { - return new U64F64Layout(property); +export function U64F64(property = "") { + return new U64F64Layout(property) } export class WideBits extends Layout { @@ -97,7 +98,10 @@ export class WideBits extends Layout { return super.replicate(property); } encode(src, b, offset = 0) { - return this._lower.encode(src, b, offset) + this._upper.encode(src, b, offset + this._lower.span); + return ( + this._lower.encode(src, b, offset) + + this._upper.encode(src, b, offset + this._lower.span) + ); } } const ACCOUNT_FLAGS_LAYOUT = new WideBits(undefined); @@ -106,13 +110,13 @@ ACCOUNT_FLAGS_LAYOUT.addBoolean('MangoGroup'); ACCOUNT_FLAGS_LAYOUT.addBoolean('MarginAccount'); export function accountFlagsLayout(property = 'accountFlags') { - return ACCOUNT_FLAGS_LAYOUT.replicate(property); // TODO: when ts check is on, replicate throws error, doesn't compile + return ACCOUNT_FLAGS_LAYOUT.replicate(property); // TODO: when ts check is on, replicate throws error, doesn't compile } export const MangoIndexLayout = struct([ u64('lastUpdate'), U64F64('borrow'), // U64F64 - U64F64('deposit'), // U64F64 + U64F64('deposit') // U64F64 ]); export const MangoGroupLayout = struct([ @@ -131,11 +135,14 @@ export const MangoGroupLayout = struct([ U64F64('maintCollRatio'), U64F64('initCollRatio'), publicKeyLayout('srmVault'), + publicKeyLayout('admin'), + seq(u64(), NUM_TOKENS, 'borrowLimits'), seq(u8(), NUM_TOKENS, 'mintDecimals'), seq(u8(), NUM_MARKETS, 'oracleDecimals'), - seq(u8(), MANGO_GROUP_PADDING, 'padding'), + seq(u8(), MANGO_GROUP_PADDING, 'padding') ]); + export const MarginAccountLayout = struct([ accountFlagsLayout('accountFlags'), publicKeyLayout('mangoGroup'), @@ -144,14 +151,15 @@ export const MarginAccountLayout = struct([ seq(U64F64(), NUM_TOKENS, 'deposits'), seq(U64F64(), NUM_TOKENS, 'borrows'), seq(publicKeyLayout(), NUM_MARKETS, 'openOrders'), - u64('srmBalance'), + u64('srmBalance') ]); + class EnumLayout extends UInt { values: any; constructor(values, span, property) { super(span, property); - this.values = values; + this.values = values } encode(src, b, offset) { if (this.values[src] !== undefined) { @@ -162,7 +170,9 @@ class EnumLayout extends UInt { decode(b, offset) { const decodedValue = super.decode(b, offset); - const entry = Object.entries(this.values).find(([, value]) => value === decodedValue); + const entry = Object.entries(this.values).find( + ([, value]) => value === decodedValue, + ); if (entry) { return entry[0]; } @@ -182,37 +192,47 @@ export function selfTradeBehaviorLayout(property) { return new EnumLayout({ decrementTake: 0, cancelProvide: 1, abortTransaction: 2 }, 4, property); } -export const MangoInstructionLayout = union(u32('instruction')); +export const MangoInstructionLayout = union(u32('instruction')) -MangoInstructionLayout.addVariant(0, struct([]), 'InitMangoGroup'); -MangoInstructionLayout.addVariant(1, struct([]), 'InitMarginAccount'); -MangoInstructionLayout.addVariant(2, struct([u64('quantity')]), 'Deposit'); -MangoInstructionLayout.addVariant(3, struct([u64('quantity')]), 'Withdraw'); -MangoInstructionLayout.addVariant(4, struct([u64('tokenIndex'), u64('quantity')]), 'Borrow'); -MangoInstructionLayout.addVariant(5, struct([u64('tokenIndex'), u64('quantity')]), 'SettleBorrow'); -MangoInstructionLayout.addVariant(6, struct([seq(u64(), NUM_TOKENS, 'depositQuantities')]), 'Liquidate'); -MangoInstructionLayout.addVariant(7, struct([u64('quantity')]), 'DepositSrm'); -MangoInstructionLayout.addVariant(8, struct([u64('quantity')]), 'WithdrawSrm'); +MangoInstructionLayout.addVariant(0, struct([]), 'InitMangoGroup') // TODO this is unimplemented +MangoInstructionLayout.addVariant(1, struct([]), 'InitMarginAccount') +MangoInstructionLayout.addVariant(2, struct([u64('quantity')]), 'Deposit') +MangoInstructionLayout.addVariant(3, struct([u64('quantity')]), 'Withdraw') +MangoInstructionLayout.addVariant(4, struct([u64('tokenIndex'), u64('quantity')]), 'Borrow') +MangoInstructionLayout.addVariant(5, struct([u64('tokenIndex'), u64('quantity')]), 'SettleBorrow') +MangoInstructionLayout.addVariant(6, struct([seq(u64(), NUM_TOKENS, 'depositQuantities')]), 'Liquidate') +MangoInstructionLayout.addVariant(7, struct([u64('quantity')]), 'DepositSrm') +MangoInstructionLayout.addVariant(8, struct([u64('quantity')]), 'WithdrawSrm') -MangoInstructionLayout.addVariant( - 9, - struct([ - sideLayout('side'), - u64('limitPrice'), - u64('maxBaseQuantity'), - u64('maxQuoteQuantity'), - selfTradeBehaviorLayout('selfTradeBehavior'), - orderTypeLayout('orderType'), - u64('clientId'), - u16('limit'), - ]), - 'PlaceOrder', -); +MangoInstructionLayout.addVariant(9, + struct( + [ + sideLayout('side'), + u64('limitPrice'), + u64('maxBaseQuantity'), + u64('maxQuoteQuantity'), + selfTradeBehaviorLayout('selfTradeBehavior'), + orderTypeLayout('orderType'), + u64('clientId'), + u16('limit'), + ] + ), + 'PlaceOrder' +) -MangoInstructionLayout.addVariant(10, struct([]), 'SettleFunds'); -MangoInstructionLayout.addVariant(11, struct([sideLayout('side'), u128('orderId')]), 'CancelOrder'); +MangoInstructionLayout.addVariant(10, struct([]), 'SettleFunds') +MangoInstructionLayout.addVariant(11, + struct( + [ + sideLayout('side'), + u128('orderId') + ] + ), + 'CancelOrder' +) -MangoInstructionLayout.addVariant(12, struct([u64('clientId')]), 'CancelOrderByClientId'); +MangoInstructionLayout.addVariant(12, struct([u64('clientId')]), 'CancelOrderByClientId') +MangoInstructionLayout.addVariant(13, struct([u64('tokenIndex'), u64('borrowLimit')]), 'ChangeBorrowLimit') // @ts-ignore const instructionMaxSpan = Math.max(...Object.values(MangoInstructionLayout.registry).map((r) => r.span)); diff --git a/yarn.lock b/yarn.lock index 5b22544..bb19118 100644 --- a/yarn.lock +++ b/yarn.lock @@ -255,6 +255,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.12.5": + version "7.12.18" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.18.tgz#af137bd7e7d9705a412b3caaf991fe6aaa97831b" + integrity sha512-BogPQ7ciE6SYAUPtlm9tWbgI9+2AgqSam6QivMgXgAT+fKbgppaj4ZX15MHeLC1PVF5sNk70huBu20XxWOs8Cg== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.12.13", "@babel/template@^7.3.3": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" @@ -301,6 +308,15 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@dabh/diagnostics@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31" + integrity sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q== + dependencies: + colorspace "1.1.x" + enabled "2.0.x" + kuler "^2.0.0" + "@eslint/eslintrc@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" @@ -504,6 +520,11 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@ltd/j-toml@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@ltd/j-toml/-/j-toml-1.6.0.tgz#11301811b7acc80299bfd312a0234bd5cc0edc3f" + integrity sha512-Jyyx+mVYy8sIf2Tas5R5qchHerJZrvWnnNg8F9dnE/gpz15RCQLEmUXZhWsM2CVHxjZhR9aE6Miqv/hfnGZAIg== + "@nodelib/fs.scandir@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" @@ -579,7 +600,7 @@ tweetnacl "^1.0.0" ws "^7.0.0" -"@solana/web3.js@^0.90.0": +"@solana/web3.js@^0.90.0", "@solana/web3.js@^0.90.5": version "0.90.5" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-0.90.5.tgz#5be7d78a19f0b5e01bf82c52e3cbf0bb72a38cfd" integrity sha512-2elnwfIkdtrUjLdTBKu7Rc3mTv95k2cn+JtNtmO2fY/PFRZm7mnGS/gk/wWzGCpBVLiqz2o6o21oONqyDtLG/w== @@ -602,6 +623,25 @@ tweetnacl "^1.0.0" ws "^7.0.0" +"@solana/web3.js@^0.91.3": + version "0.91.3" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-0.91.3.tgz#826c9ee01040177798b963bf5fb2b0f0662560bb" + integrity sha512-eMKJFDJewiTUEBHyQpk1h6aNQ6d1ac+hyzwzRxQKWzquQgbvNIKBTM2FxmeYF5Os1Vc9SEYG2+AyIWTtdjm0zw== + dependencies: + "@babel/runtime" "^7.12.5" + bn.js "^5.0.0" + bs58 "^4.0.1" + buffer "6.0.1" + buffer-layout "^1.2.0" + crypto-hash "^1.2.2" + jayson "^3.4.4" + js-sha3 "^0.8.0" + node-fetch "^2.6.1" + rpc-websockets "^7.4.2" + secp256k1 "^4.0.2" + superstruct "^0.8.3" + tweetnacl "^1.0.0" + "@tsconfig/node14@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.0.tgz#5bd046e508b1ee90bc091766758838741fdefd6e" @@ -640,7 +680,7 @@ dependencies: "@babel/types" "^7.3.0" -"@types/bn.js@^4.11.6": +"@types/bn.js@^4.11.5", "@types/bn.js@^4.11.6": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== @@ -722,6 +762,16 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.28.tgz#cade4b64f8438f588951a6b35843ce536853f25b" integrity sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g== +"@types/node@10.12.18": + version "10.12.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" + integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== + +"@types/node@11.11.6": + version "11.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" + integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== + "@types/node@^12.12.54": version "12.20.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.1.tgz#63d36c10e162666f0107f247cdca76542c3c7472" @@ -1018,6 +1068,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +async@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" + integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1148,7 +1203,37 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -bn.js@^4.11.9: +bindings@^1.3.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bip32@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/bip32/-/bip32-2.0.6.tgz#6a81d9f98c4cd57d05150c60d8f9e75121635134" + integrity sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA== + dependencies: + "@types/node" "10.12.18" + bs58check "^2.1.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + tiny-secp256k1 "^1.1.3" + typeforce "^1.11.5" + wif "^2.0.6" + +bip39@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.3.tgz#4a8b79067d6ed2e74f9199ac994a2ab61b176760" + integrity sha512-P0dKrz4g0V0BjXfx7d9QNkJ/Txcz/k+hM9TnjqjUaXtuOfAvxXSw2rJw8DX0e3ZPwnK/IgDxoRqf0bvoVCqbMg== + dependencies: + "@types/node" "11.11.6" + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + +bn.js@^4.11.8, bn.js@^4.11.9: version "4.11.9" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== @@ -1163,6 +1248,15 @@ boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +"borsh@https://github.com/defactojob/borsh-js#field-mapper": + version "0.3.1" + resolved "https://github.com/defactojob/borsh-js#33a0d24af281112c0a48efb3fa503f3212443de9" + dependencies: + "@types/bn.js" "^4.11.5" + bn.js "^5.0.0" + bs58 "^4.0.0" + text-encoding-utf-8 "^1.0.2" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1211,13 +1305,22 @@ bs-logger@0.x: dependencies: fast-json-stable-stringify "2.x" -bs58@^4.0.1: +bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= dependencies: base-x "^3.0.2" +bs58check@<3.0.0, bs58check@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -1235,6 +1338,14 @@ buffer-layout@^1.2.0: resolved "https://registry.yarnpkg.com/buffer-layout/-/buffer-layout-1.2.0.tgz#ee1f5ef05a8afd5db6b3a8fe2056c111bc69c737" integrity sha512-iiyRoho/ERzBUv6kFvfsrLNgTlVwOkqQcSQN7WrO3Y+c5SeuEhCn6+y1KwhM0V3ndptF5mI/RI44zkw0qcR5Jg== +buffer@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.1.tgz#3cbea8c1463e5a0779e30b66d4c88c6ffa182ac2" + integrity sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + buffer@^5.4.3: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" @@ -1374,6 +1485,14 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + circular-json@^0.5.9: version "0.5.9" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.9.tgz#932763ae88f4f7dead7a0d09c8a51a4743a53b1d" @@ -1426,7 +1545,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.9.0: +color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -1445,11 +1564,40 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@~1.1.4: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^1.5.2: + version "1.5.4" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6" + integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@3.0.x: + version "3.0.0" + resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a" + integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + +colors@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +colorspace@1.1.x: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5" + integrity sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ== + dependencies: + color "3.0.x" + text-hex "1.0.x" + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -1462,6 +1610,11 @@ commander@^2.20.3: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -1489,11 +1642,34 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-util-is@1.0.2: +core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -1751,6 +1927,11 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" +dotenv@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" + integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -1759,7 +1940,7 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -elliptic@^6.5.2: +elliptic@^6.4.0, elliptic@^6.5.2: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -1782,6 +1963,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +enabled@2.0.x: + version "2.0.0" + resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" + integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== + end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -2146,6 +2332,11 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-safe-stringify@^2.0.4: + version "2.0.7" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" + integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== + fastq@^1.6.0: version "1.10.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.1.tgz#8b8f2ac8bf3632d67afcd65dac248d5fdc45385e" @@ -2160,6 +2351,11 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fecha@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.0.tgz#3ffb6395453e3f3efff850404f0a59b6747f5f41" + integrity sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg== + file-entry-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" @@ -2167,6 +2363,11 @@ file-entry-cache@^6.0.0: dependencies: flat-cache "^3.0.4" +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -2205,6 +2406,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== +fn.name@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" + integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2444,6 +2650,15 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -2555,7 +2770,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2584,6 +2799,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -2765,7 +2985,7 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@1.0.0: +isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -2833,7 +3053,7 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jayson@^3.0.1: +jayson@^3.0.1, jayson@^3.4.4: version "3.4.4" resolved "https://registry.yarnpkg.com/jayson/-/jayson-3.4.4.tgz#dcedffba0c02785c4aa22dbff8c28966cae59773" integrity sha512-fgQflh+Qnhdv9fjxTnpTsa2WUG/dgyeKQzIh5MJ77Qv2sqFyyAZn7mTUYgPjJMFjsKfb4HNsSBh6ktJeeQiAGQ== @@ -3223,6 +3443,11 @@ jest@^26.6.3: import-local "^3.0.2" jest-cli "^26.6.3" +js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -3393,6 +3618,11 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +kuler@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" + integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -3506,6 +3736,17 @@ lodash@4.x, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +logform@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.2.0.tgz#40f036d19161fc76b68ab50fdc7fe495544492f2" + integrity sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg== + dependencies: + colors "^1.2.1" + fast-safe-stringify "^2.0.4" + fecha "^4.2.0" + ms "^2.1.1" + triple-beam "^1.3.0" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -3544,6 +3785,15 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + memorystream@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" @@ -3648,6 +3898,11 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -3657,6 +3912,11 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" +nan@^2.13.2: + version "2.14.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" + integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -3689,7 +3949,7 @@ node-addon-api@^2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== -node-fetch@^2.2.0: +node-fetch@^2.2.0, node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== @@ -3844,6 +4104,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +one-time@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" + integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== + dependencies: + fn.name "1.x.x" + onetime@^5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -3981,6 +4248,17 @@ pathval@^1.1.0: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== +pbkdf2@^3.0.9: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -4045,6 +4323,11 @@ pretty-format@^26.0.0, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -4086,6 +4369,13 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.2.tgz#abf64491e6ecf0f38a6502403d4cda04f372dfd3" integrity sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg== +randombytes@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + react-is@^17.0.1: version "17.0.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" @@ -4119,7 +4409,20 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@^3.1.1: +readable-stream@^2.3.7: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -4265,6 +4568,14 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + rpc-websockets@^7.4.2: version "7.4.8" resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.4.8.tgz#5c1e4b2ccfd50081126e159ebbba4a1e9b3717ce" @@ -4292,12 +4603,12 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.1: +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -4377,6 +4688,14 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -4416,6 +4735,13 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -4465,6 +4791,31 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +"solink@git+ssh://git@github.com:blockworks-foundation/solana-flux-aggregator.git": + version "1.0.0" + resolved "git+ssh://git@github.com:blockworks-foundation/solana-flux-aggregator.git#d63fec94e92d1f745c170d1c8b2f60951615f3ae" + dependencies: + "@ltd/j-toml" "^1.6.0" + "@solana/web3.js" "^0.90.5" + borsh "https://github.com/defactojob/borsh-js#field-mapper" + buffer-layout "^1.2.0" + commander "^6.2.0" + dotenv "^8.2.0" + solray "git+https://github.com/defactojob/solray" + winston "^3.3.3" + ws "^7.4.1" + +"solray@git+https://github.com/defactojob/solray": + version "0.0.1" + resolved "git+https://github.com/defactojob/solray#66c34e74a27e8556668410372d5a96d11f1da14a" + dependencies: + "@solana/web3.js" "^0.91.3" + bip32 "^2.0.6" + bip39 "^3.0.3" + bs58 "^4.0.1" + commander "^6.2.0" + tweetnacl "^1.0.3" + source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -4557,6 +4908,11 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + stack-utils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" @@ -4626,6 +4982,13 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -4720,6 +5083,16 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-encoding-utf-8@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" + integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== + +text-hex@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" + integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -4754,6 +5127,17 @@ tiny-invariant@^1.0.6: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== +tiny-secp256k1@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz#7e224d2bee8ab8283f284e40e6b4acb74ffe047c" + integrity sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA== + dependencies: + bindings "^1.3.0" + bn.js "^4.11.8" + create-hmac "^1.1.7" + elliptic "^6.4.0" + nan "^2.13.2" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -4820,6 +5204,11 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +triple-beam@^1.2.0, triple-beam@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" + integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== + ts-jest@^26.2.0: version "26.5.1" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.5.1.tgz#4d53ee4481552f57c1624f0bd3425c8b17996150" @@ -4873,7 +5262,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -tweetnacl@^1.0.0: +tweetnacl@^1.0.0, tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== @@ -4924,6 +5313,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typeforce@^1.11.5: + version "1.18.0" + resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" + integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== + typescript@^4.1.3: version "4.1.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72" @@ -4971,7 +5365,7 @@ utf-8-validate@^5.0.2: dependencies: node-gyp-build "^4.2.0" -util-deprecate@^1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -5088,6 +5482,36 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" +wif@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/wif/-/wif-2.0.6.tgz#08d3f52056c66679299726fade0d432ae74b4704" + integrity sha1-CNP1IFbGZnkplyb63g1DKudLRwQ= + dependencies: + bs58check "<3.0.0" + +winston-transport@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59" + integrity sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw== + dependencies: + readable-stream "^2.3.7" + triple-beam "^1.2.0" + +winston@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.3.3.tgz#ae6172042cafb29786afa3d09c8ff833ab7c9170" + integrity sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw== + dependencies: + "@dabh/diagnostics" "^2.0.2" + async "^3.1.0" + is-stream "^2.0.0" + logform "^2.2.0" + one-time "^1.0.0" + readable-stream "^3.4.0" + stack-trace "0.0.x" + triple-beam "^1.3.0" + winston-transport "^4.4.0" + word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -5117,7 +5541,7 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -ws@^7.0.0, ws@^7.2.3, ws@^7.3.1: +ws@^7.0.0, ws@^7.2.3, ws@^7.3.1, ws@^7.4.1: version "7.4.3" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.3.tgz#1f9643de34a543b8edb124bdcbc457ae55a6e5cd" integrity sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==