From e5364fb953a751c2648c4a45eca2e513ac3ee07d Mon Sep 17 00:00:00 2001 From: Maximilian Schneider Date: Tue, 26 Nov 2024 20:12:01 +0000 Subject: [PATCH 1/3] sb2 crank can update 6 feeds at once --- package.json | 2 +- ts/client/scripts/manageFeeWs.ts | 4 +- ts/client/scripts/sb-on-demand-crank.ts | 68 +++++++++++-------------- ts/client/src/accounts/oracle.ts | 2 +- ts/client/src/utils/rpc.ts | 9 ++++ yarn.lock | 33 +++++++++--- 6 files changed, 69 insertions(+), 49 deletions(-) diff --git a/package.json b/package.json index 508b751e0..44ed869ba 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "@solana/spl-token": "0.4.8", "@solana/web3.js": "^1.95.2", "@switchboard-xyz/common": "^2.4.4", - "@switchboard-xyz/on-demand": "^1.2.38", + "@switchboard-xyz/on-demand": "^1.2.51", "@switchboard-xyz/sbv2-lite": "^0.1.6", "@switchboard-xyz/solana.js": "^3.2.5", "big.js": "^6.1.1", diff --git a/ts/client/scripts/manageFeeWs.ts b/ts/client/scripts/manageFeeWs.ts index 01006deb2..47a414aca 100644 --- a/ts/client/scripts/manageFeeWs.ts +++ b/ts/client/scripts/manageFeeWs.ts @@ -42,8 +42,8 @@ export function manageFeeWebSocket( }); ws.addEventListener('error', (error) => { - console.log('Fee WebSocket error:', error); - onMeanCalculated(-1); + // console.log('Fee WebSocket error:', error); + onMeanCalculated(null); ws?.close(); }); diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index a3a715e55..11a4abdd1 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -34,7 +34,7 @@ import { import { PerpMarketIndex } from '../src/accounts/perp'; import { MangoClient } from '../src/client'; import { MANGO_V4_ID, MANGO_V4_MAIN_GROUP } from '../src/constants'; -import { createComputeBudgetIx } from '../src/utils/rpc'; +import { createComputeBudgetIx, createComputeLimitIx } from '../src/utils/rpc'; import { manageFeeWebSocket } from './manageFeeWs'; import { getOraclesForMangoGroup, @@ -202,7 +202,7 @@ async function setupBackgroundRefresh( function (a, b) { return a.oracle.oraclePk.equals(b.oracle.oraclePk); }, - ); + ).slice(0, 6); console.log( `[main] round candidates | Stale: ${staleOracles @@ -212,68 +212,62 @@ async function setupBackgroundRefresh( .join(', ')}`, ); - // todo use chunk - // todo use luts - - // const [pullIxs, luts] = await PullFeed.fetchUpdateManyIx( - // sbOnDemandProgram as any, - // { - // feeds: oraclesToCrank.map((o) => new PublicKey(o.oracle.oraclePk)), - // numSignatures: 3, - // }, - // ); - - const recentSlothashes = await RecentSlotHashes.fetchLatestNSlothashes( - connection as any, - 30, + if ( + oraclesToCrank.length == 0 + ) { + await new Promise((r) => setTimeout(r, SLEEP_MS)); + continue; + } + + // can do 6 per tx + const numSignatures = 2; + const [pullIx, _luts] = await PullFeed.fetchUpdateManyIx( + sbOnDemandProgram as any, + { + feeds: oraclesToCrank.map((o) => new PublicKey(o.oracle.oraclePk)), + numSignatures, + crossbarClient, + payer: user.publicKey, + }, ); - const pullIxs = ( - await Promise.all( - oraclesToCrank.map(async (oracle) => { - const pullIx = await preparePullIx( - sbOnDemandProgram, - oracle, - recentSlothashes, - ); - return pullIx !== undefined ? pullIx : null; - }), - ) - ).filter((pullIx) => pullIx !== null); const ixPreparedAt = Date.now(); - const ixsChunks = chunk(shuffle(pullIxs), 2, false); const lamportsPerCu_ = Math.min( Math.max(lamportsPerCu ?? 150_000, 150_000), 500_000, ); + const cuLimit = 150_000 + oraclesToCrank.length * 30_000 * numSignatures; + // dont await, fire and forget sendSignAndConfirmTransactions({ connection, wallet: new Wallet(user), backupConnections: [ - ...(CLUSTER_URL_2 ? [new Connection(LITE_RPC_URL!, 'recent')] : []), + ...(LITE_RPC_URL ? [new Connection(LITE_RPC_URL!, 'recent')] : []), ...(CLUSTER_URL_2 ? [new Connection(CLUSTER_URL_2!, 'recent')] : []), ], // fail rather quickly and retry submission from scratch // timeout using finalized to stay below switchboard oracle staleness limit timeoutStrategy: { block, startBlockCheckAfterSecs: 20 }, - transactionInstructions: ixsChunks.map((txChunk) => ({ + transactionInstructions: [{ instructionsSet: [ { signers: [], transactionInstruction: createComputeBudgetIx(lamportsPerCu_), }, - ...txChunk.map((tx) => ({ + { + signers: [], + transactionInstruction: createComputeLimitIx(cuLimit), + }, + { signers: [], - transactionInstruction: tx, - // TODO disable alts for now - // alts: SBOD_ORACLE_LUTS.map(x=>new PublicKey(x)), - })), + transactionInstruction: pullIx, + } ], sequenceType: SequenceType.Parallel, - })), + }], config: { maxTxesInBatch: 10, autoRetry: false, diff --git a/ts/client/src/accounts/oracle.ts b/ts/client/src/accounts/oracle.ts index 94d33ed2c..d1b606e44 100644 --- a/ts/client/src/accounts/oracle.ts +++ b/ts/client/src/accounts/oracle.ts @@ -434,7 +434,7 @@ export function isOracleStaleOrUnconfident( } if (debug && deviation) { console.log( - `- ${debugPrefix?.padStart(30)}: deviation within confidence tolerance ${deviation.mul(I80F48.fromNumber(100)).div(confFilter).toFixed(3)}%`, + `- ${debugPrefix?.padStart(30)}: deviation within confidence tolerance ${deviation.div(price).mul(I80F48.fromNumber(100)).toFixed(3)}%`, ); } diff --git a/ts/client/src/utils/rpc.ts b/ts/client/src/utils/rpc.ts index 7e01a7987..053f7b322 100644 --- a/ts/client/src/utils/rpc.ts +++ b/ts/client/src/utils/rpc.ts @@ -288,6 +288,15 @@ export const createComputeBudgetIx = ( return computeBudgetIx; }; +export const createComputeLimitIx = ( + units: number, +): TransactionInstruction => { + const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({ + units, + }); + return computeBudgetIx; +}; + export class MangoError extends Error { message: string; txid: string; diff --git a/yarn.lock b/yarn.lock index 963b02d3b..477d2007c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -901,7 +901,7 @@ dependencies: tslib "^2.4.0" -"@switchboard-xyz/common@^2.3.16", "@switchboard-xyz/common@^2.4.4", "@switchboard-xyz/common@^2.4.7": +"@switchboard-xyz/common@^2.3.16", "@switchboard-xyz/common@^2.4.4": version "2.4.7" resolved "https://registry.yarnpkg.com/@switchboard-xyz/common/-/common-2.4.7.tgz#7b582e7cdd4c17a3d4e36beead520a5363f4f0a8" integrity sha512-gkUuy7n15gq+D0IKkqKsSqgWb1w5t3rfpjdTkJX0AAlL75QXZfi5fL4Ttwb22ALOWYLYuvYCD0uXFyczgMMkIQ== @@ -918,16 +918,33 @@ protobufjs "^7.2.6" yaml "^2.5.0" -"@switchboard-xyz/on-demand@^1.2.38": - version "1.2.38" - resolved "https://registry.yarnpkg.com/@switchboard-xyz/on-demand/-/on-demand-1.2.38.tgz#de368176a89b05c365d916c5cb419e1cf918acf3" - integrity sha512-BaZc78dDbmofJmk60SD0dDsf953rnQ9MaTeUrFyn8Z0zRiu79hTJMeKisKbC/pOCG7EMpZZRF/sqXujRfG6QFw== +"@switchboard-xyz/common@^2.5.3": + version "2.5.5" + resolved "https://registry.yarnpkg.com/@switchboard-xyz/common/-/common-2.5.5.tgz#773c20584877af86abe724e9787de8f3e6385bce" + integrity sha512-/qUmZlrfQyckvHGzS5Cj2+Ocd3eE64rPjQb1eEocc5dv4HXZMqbBbpM6BwURrQhZ65i3jO1evhTcAk3TVqCA8w== + dependencies: + "@solana/web3.js" "^1.93.0" + axios "^1.7.2" + big.js "^6.2.1" + bn.js "^5.2.1" + bs58 "^5.0.0" + cron-validator "^1.3.1" + decimal.js "^10.4.3" + js-sha256 "^0.11.0" + lodash "^4.17.21" + protobufjs "^7.2.6" + yaml "^2.5.0" + +"@switchboard-xyz/on-demand@^1.2.51": + version "1.2.51" + resolved "https://registry.yarnpkg.com/@switchboard-xyz/on-demand/-/on-demand-1.2.51.tgz#ad42a0855dcff59d3cd7e34ba4dc9ea4531bfddf" + integrity sha512-IqtAEtYdCRQqG8a3tL5WOcLgBco8Iionu60Q+hQzCslQw76zDlkToHkI+71ASulFdZ2z+2XjaKV5ZVqPcYgP7g== dependencies: "@brokerloop/ttlcache" "^3.2.3" "@coral-xyz/anchor-30" "npm:@coral-xyz/anchor@0.30.1" "@solana/web3.js" "^1.95.0" "@solworks/soltoolkit-sdk" "^0.0.23" - "@switchboard-xyz/common" "^2.4.7" + "@switchboard-xyz/common" "^2.5.3" axios "^1.7.4" big.js "^6.2.1" bs58 "^5.0.0" @@ -2766,14 +2783,14 @@ node-addon-api@^5.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== -node-fetch@3.3.2, "node-fetch@npm:@blockworks-foundation/node-fetch@2.6.11": +node-fetch@3.3.2, node-fetch@^2.6.12, node-fetch@^2.7.0, "node-fetch@npm:@blockworks-foundation/node-fetch@2.6.11": version "2.6.11" resolved "https://registry.yarnpkg.com/@blockworks-foundation/node-fetch/-/node-fetch-2.6.11.tgz#fb536ef0e6a960e7b7993f3c1d3b3bba9bdfbc56" integrity sha512-HeDTxpIypSR4qCoqgUXGr8YL4OG1z7BbV4VhQ9iQs+pt2wV3MtqO+sQk2vXK3WDKu5C6BsbGmWE22BmIrcuOOw== dependencies: whatwg-url "^5.0.0" -node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.7.0: +node-fetch@^2.6.1: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== From 8035330b72d41835956ea4834eda91dce3116da3 Mon Sep 17 00:00:00 2001 From: Maximilian Schneider Date: Sat, 30 Nov 2024 14:46:26 +0100 Subject: [PATCH 2/3] add logic for variance threshold per tier and simplify logic for fallbacks --- ts/client/scripts/sb-on-demand-crank-utils.ts | 9 +- ts/client/scripts/sb-on-demand-crank.ts | 382 ++++++++---------- 2 files changed, 172 insertions(+), 219 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank-utils.ts b/ts/client/scripts/sb-on-demand-crank-utils.ts index 8a2b99db4..f69a5a043 100644 --- a/ts/client/scripts/sb-on-demand-crank-utils.ts +++ b/ts/client/scripts/sb-on-demand-crank-utils.ts @@ -7,11 +7,10 @@ import { ZERO_I80F48 } from '../src/numbers/I80F48'; export interface OraclesFromMangoGroupInterface { oraclePk: PublicKey; name: string; + tier: string; fallbackForOracle: PublicKey | undefined; tokenIndex: TokenIndex | undefined; // todo remove perpMarketIndex: PerpMarketIndex | undefined; - isOracleStaleOrUnconfident: boolean; - // todo: add tier when program mango-v4 24.3 is released } /** @@ -37,10 +36,10 @@ export function getOraclesForMangoGroup( return { oraclePk: b[0].oracle, name: b[0].name, + tier: b[0].tier, fallbackForOracle: undefined, tokenIndex: b[0].tokenIndex, perpMarketIndex: undefined, - isOracleStaleOrUnconfident: false, }; }); @@ -51,10 +50,10 @@ export function getOraclesForMangoGroup( return { oraclePk: pM.oracle, name: pM.name, + tier: "S", fallbackForOracle: undefined, tokenIndex: undefined, perpMarketIndex: pM.perpMarketIndex, - isOracleStaleOrUnconfident: false, }; }); @@ -74,10 +73,10 @@ export function getOraclesForMangoGroup( return { oraclePk: b[0].fallbackOracle, name: b[0].name, + tier: b[0].tier, fallbackForOracle: b[0].oracle, tokenIndex: b[0].tokenIndex, perpMarketIndex: undefined, - isOracleStaleOrUnconfident: false, }; }) .filter((item) => !item.oraclePk.equals(PublicKey.default)); diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 11a4abdd1..74ceeab33 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -12,25 +12,18 @@ import { ON_DEMAND_MAINNET_PID, PullFeed, Queue, - RecentSlotHashes, } from '@switchboard-xyz/on-demand'; import fs from 'fs'; import chunk from 'lodash/chunk'; -import shuffle from 'lodash/shuffle'; import uniqWith from 'lodash/uniqWith'; -import zipWith from 'lodash/zipWith'; import { Program as Anchor30Program, BN, Idl } from 'switchboard-anchor'; import { SequenceType } from '@blockworks-foundation/mangolana/lib/globalTypes'; import { sendSignAndConfirmTransactions } from '@blockworks-foundation/mangolana/lib/transactions'; -import { BorshAccountsCoder } from '@coral-xyz/anchor'; import { AnchorProvider, Wallet } from 'switchboard-anchor'; -import { TokenIndex } from '../src/accounts/bank'; +import { Bank, TokenIndex } from '../src/accounts/bank'; import { Group } from '../src/accounts/group'; -import { - isOracleStaleOrUnconfident, - parseSwitchboardOracle, -} from '../src/accounts/oracle'; +import { parseSwitchboardOracle } from '../src/accounts/oracle'; import { PerpMarketIndex } from '../src/accounts/perp'; import { MangoClient } from '../src/client'; import { MANGO_V4_ID, MANGO_V4_MAIN_GROUP } from '../src/constants'; @@ -73,10 +66,10 @@ interface OracleMetaInterface { oracle: { oraclePk: PublicKey; name: string; + tier: string; fallbackForOracle: PublicKey | undefined; tokenIndex: TokenIndex | undefined; perpMarketIndex: PerpMarketIndex | undefined; - isOracleStaleOrUnconfident: boolean; }; ai: AccountInfo | null; decodedPullFeed: any; @@ -92,11 +85,11 @@ interface OracleMetaInterface { } /// refresh mango group to detect new oracles added through governance -/// without a restart within 1 minute, result object will be dynamically -/// updated +/// without a restart within 3 minutes, result object will be dynamically +/// updated as well as the passed group async function setupBackgroundRefresh( client: MangoClient, - group: Group, + group: Group, /// modified periodically sbOnDemandProgram: Anchor30Program, crossbarClient: CrossbarClient, ): Promise<{ oracles: OracleMetaInterface[] }> { @@ -110,7 +103,7 @@ async function setupBackgroundRefresh( const result = { oracles }; - const GROUP_REFRESH_INTERVAL = 60_000; + const GROUP_REFRESH_INTERVAL = 180_000; // refresh every 3 minutes const refreshGroup = async function (): Promise { try { await group.reloadAll(client); @@ -146,6 +139,7 @@ async function setupBackgroundRefresh( while (true) { try { // pull a fresh reference to the oracles from the background refresher + // group is updated in place const { oracles } = refresh; const startedAt = Date.now(); @@ -156,30 +150,23 @@ async function setupBackgroundRefresh( client.connection.getSlot('processed'), ]); - await updateFilteredOraclesAis( - client, - sbOnDemandProgram, - group, - slot, - oracles, - ); - - const onlyEssentialOracles = oracles.filter( - (o) => o.oracle.isOracleStaleOrUnconfident, - ); + // refresh oracle accounts to know when each oracle was late updated + // updates oracle in place + await updateFilteredOraclesAis(client, sbOnDemandProgram, oracles); const aisUpdatedAt = Date.now(); const staleOracles = await filterForStaleOracles( - onlyEssentialOracles, + oracles, client, + group, slot, ); const staleFilteredAt = Date.now(); const crossBarSims = await Promise.all( - onlyEssentialOracles.map((o) => + oracles.map((o) => crossbarClient.simulateFeeds([ new Buffer(o.parsedConfigs.feedHash).toString('hex'), ]), @@ -189,11 +176,7 @@ async function setupBackgroundRefresh( const simulatedAt = Date.now(); const varianceThresholdCrossedOracles = - await filterForVarianceThresholdOracles( - onlyEssentialOracles, - client, - crossBarSims, - ); + await filterForVarianceThresholdOracles(oracles, client, crossBarSims); const varianceFilteredAt = Date.now(); @@ -202,8 +185,7 @@ async function setupBackgroundRefresh( function (a, b) { return a.oracle.oraclePk.equals(b.oracle.oraclePk); }, - ).slice(0, 6); - + ); console.log( `[main] round candidates | Stale: ${staleOracles .map((o) => o.oracle.name) @@ -212,101 +194,116 @@ async function setupBackgroundRefresh( .join(', ')}`, ); - if ( - oraclesToCrank.length == 0 - ) { - await new Promise((r) => setTimeout(r, SLEEP_MS)); - continue; - } - // can do 6 per tx - const numSignatures = 2; - const [pullIx, _luts] = await PullFeed.fetchUpdateManyIx( - sbOnDemandProgram as any, - { - feeds: oraclesToCrank.map((o) => new PublicKey(o.oracle.oraclePk)), - numSignatures, - crossbarClient, - payer: user.publicKey, - }, - ); + const crankChunks: OracleMetaInterface[][] = chunk(oraclesToCrank, 6); - const ixPreparedAt = Date.now(); + // don't wait for switchboard API or delay retry + crankChunks.map(async (oracleChunk) => { + if (oracleChunk.length == 0) return; - const lamportsPerCu_ = Math.min( - Math.max(lamportsPerCu ?? 150_000, 150_000), - 500_000, - ); - - const cuLimit = 150_000 + oraclesToCrank.length * 30_000 * numSignatures; - - // dont await, fire and forget - sendSignAndConfirmTransactions({ - connection, - wallet: new Wallet(user), - backupConnections: [ - ...(LITE_RPC_URL ? [new Connection(LITE_RPC_URL!, 'recent')] : []), - ...(CLUSTER_URL_2 ? [new Connection(CLUSTER_URL_2!, 'recent')] : []), - ], - // fail rather quickly and retry submission from scratch - // timeout using finalized to stay below switchboard oracle staleness limit - timeoutStrategy: { block, startBlockCheckAfterSecs: 20 }, - transactionInstructions: [{ - instructionsSet: [ + const numSignatures = 2; + try { + // TODO: don't ignore LUTS + const [pullIx, _luts] = await PullFeed.fetchUpdateManyIx( + sbOnDemandProgram as any, { - signers: [], - transactionInstruction: createComputeBudgetIx(lamportsPerCu_), + feeds: oracleChunk.map((o) => new PublicKey(o.oracle.oraclePk)), + numSignatures, + crossbarClient, + payer: user.publicKey, }, - { - signers: [], - transactionInstruction: createComputeLimitIx(cuLimit), + ); + + const ixPreparedAt = Date.now(); + + const lamportsPerCu_ = Math.min( + Math.max(lamportsPerCu ?? 150_000, 150_000), + 500_000, + ); + + const cuLimit = 150_000 + oracleChunk.length * 30_000 * numSignatures; + + // no need to await, fire and forget + sendSignAndConfirmTransactions({ + connection, + wallet: new Wallet(user), + backupConnections: [ + ...(LITE_RPC_URL + ? [new Connection(LITE_RPC_URL!, 'recent')] + : []), + ...(CLUSTER_URL_2 + ? [new Connection(CLUSTER_URL_2!, 'recent')] + : []), + ], + // fail rather quickly and retry submission from scratch + // timeout using finalized to stay below switchboard oracle staleness limit + timeoutStrategy: { block, startBlockCheckAfterSecs: 20 }, + transactionInstructions: [ + { + instructionsSet: [ + { + signers: [], + transactionInstruction: + createComputeBudgetIx(lamportsPerCu_), + }, + { + signers: [], + transactionInstruction: createComputeLimitIx(cuLimit), + }, + { + signers: [], + transactionInstruction: pullIx, + }, + ], + sequenceType: SequenceType.Parallel, + }, + ], + config: { + maxTxesInBatch: 10, + autoRetry: false, + logFlowInfo: false, + // TODO disable alts for now + // useVersionedTransactions: true, }, - { - signers: [], - transactionInstruction: pullIx, - } - ], - sequenceType: SequenceType.Parallel, - }], - config: { - maxTxesInBatch: 10, - autoRetry: false, - logFlowInfo: false, - // TODO disable alts for now - // useVersionedTransactions: true, - }, - callbacks: { - afterEveryTxSend: function (data) { - const sentAt = Date.now(); - const total = (sentAt - startedAt) / 1000; - const aiUpdate = (aisUpdatedAt - startedAt) / 1000; - const staleFilter = (staleFilteredAt - aisUpdatedAt) / 1000; - const simulate = (simulatedAt - staleFilteredAt) / 1000; - const varianceFilter = (varianceFilteredAt - simulatedAt) / 1000; - const ixPrepare = (ixPreparedAt - varianceFilteredAt) / 1000; - const timing = { - aiUpdate, - staleFilter, - simulate, - varianceFilter, - ixPrepare, - }; - - console.log( - `[tx send] https://solscan.io/tx/${data['txid']}, in ${total}s, lamportsPerCu_ ${lamportsPerCu_}, lamportsPerCu ${lamportsPerCu}, timiming ${JSON.stringify(timing)}`, - ); - }, - onError: function (e, notProcessedTransactions) { + callbacks: { + afterEveryTxSend: function (data) { + const sentAt = Date.now(); + const total = (sentAt - startedAt) / 1000; + const aiUpdate = (aisUpdatedAt - startedAt) / 1000; + const staleFilter = (staleFilteredAt - aisUpdatedAt) / 1000; + const simulate = (simulatedAt - staleFilteredAt) / 1000; + const varianceFilter = + (varianceFilteredAt - simulatedAt) / 1000; + const ixPrepare = (ixPreparedAt - varianceFilteredAt) / 1000; + const timing = { + aiUpdate, + staleFilter, + simulate, + varianceFilter, + ixPrepare, + }; + + console.log( + `[tx send] https://solscan.io/tx/${data['txid']}, in ${total}s, lamportsPerCu_ ${lamportsPerCu_}, lamportsPerCu ${lamportsPerCu}, timiming ${JSON.stringify(timing)}`, + ); + }, + onError: function (e, notProcessedTransactions) { + console.error( + `[tx send] ${notProcessedTransactions.length} error(s) after ${(Date.now() - ixPreparedAt) / 1000}s ${JSON.stringify(e)}`, + ); + }, + }, + }).catch((reason) => console.error( - `[tx send] ${notProcessedTransactions.length} error(s) after ${(Date.now() - ixPreparedAt) / 1000}s ${JSON.stringify(e)}`, - ); - }, - }, - }).catch((reason) => - console.error( - `[tx send] promise rejected after ${(Date.now() - ixPreparedAt) / 1000}s ${JSON.stringify(reason)}`, - ), - ); + `[tx send] promise rejected after ${(Date.now() - ixPreparedAt) / 1000}s ${JSON.stringify(reason)}`, + ), + ); + } catch (e) { + console.error( + `[ix fetch] error after ${(Date.now() - varianceFilteredAt) / 1000}s ${JSON.stringify(e)}`, + ); + } + }); await new Promise((r) => setTimeout(r, SLEEP_MS)); } catch (error) { @@ -345,6 +342,19 @@ async function preparePullIx( } } +const VARIANCE_THRESHOLD_PCT_BY_TIER = { + S: 0.5, + AAA: 1, + AA: 1, + A: 1, + 'A-': 1, + BBB: 2, + BB: 2, + B: 2, + C: 4, + D: Number.MAX_VALUE, +}; + async function filterForVarianceThresholdOracles( filteredOracles: OracleMetaInterface[], client: MangoClient, @@ -366,18 +376,15 @@ async function filterForVarianceThresholdOracles( crossBarSim[0].results.length; const changePct = (Math.abs(res.price - simPrice) * 100) / res.price; - if (changePct > item.decodedPullFeed.maxVariance / 1000000000) { + const thresholdPct = VARIANCE_THRESHOLD_PCT_BY_TIER[item.oracle.tier]; + if (changePct > thresholdPct) { console.log( - `[filter variance] ${item.oracle.name}, candidate, ${ - item.decodedPullFeed.maxVariance / 1000000000 - }, ${simPrice}, ${res.price}, ${changePct}`, + `[filter variance] ${item.oracle.name}, candidate: ${thresholdPct} < ${changePct}, ${simPrice}, ${res.price}`, ); varianceThresholdCrossedOracles.push(item); } else { console.log( - `[filter variance] ${item.oracle.name}, non-candidate, ${ - item.decodedPullFeed.maxVariance / 1000000000 - }, ${simPrice}, ${res.price}, ${changePct}`, + `[filter variance] ${item.oracle.name}, non-candidate: ${thresholdPct} > ${changePct}, ${simPrice}, ${res.price},`, ); } } @@ -387,31 +394,49 @@ async function filterForVarianceThresholdOracles( async function filterForStaleOracles( filteredOracles: OracleMetaInterface[], client: MangoClient, - slot: number, + group: Group, + lastProcessedSlot: number, ): Promise { const staleOracles = new Array(); for (const item of filteredOracles) { + // we know that all these oracles are SBOD const res = await parseSwitchboardOracle( item.oracle.oraclePk, item.ai!, client.connection, ); - const diff = slot - res.lastUpdatedSlot; - if ( - // maxStaleness will usually be 250 (=100s) - // one iteration takes 10s, retry is every 20s - // this allows for 2 retries until the oracle becomes stale - diff > - item.decodedPullFeed.maxStaleness * 0.3 - ) { + const slotsSinceLastUpdate = lastProcessedSlot - res.lastUpdatedSlot; + // one iteration takes 10s, retry is every 20s + // this allows for at least 2 retries until the oracle becomes stale + const safetySeconds = 20 * 3 + 10; + const safetySlots = safetySeconds * 2.5; + const slotsUntilUpdate = item.decodedPullFeed.maxStaleness - safetySlots; + if (slotsSinceLastUpdate > slotsUntilUpdate) { console.log( - `[filter stale] ${item.oracle.name}, candidate, ${item.decodedPullFeed.maxStaleness}, ${slot}, ${res.lastUpdatedSlot}, ${diff}`, + `[filter stale] ${item.oracle.name}, candidate, ${item.decodedPullFeed.maxStaleness}, ${lastProcessedSlot}, ${res.lastUpdatedSlot}, ${slotsSinceLastUpdate}`, ); + + // check if oracle is fallback and primary is not stale + if (item.oracle.fallbackForOracle) { + const mainOraclePk = item.oracle.fallbackForOracle.toString(); + const [bank] = group.banksMapByOracle.get(mainOraclePk) as Bank[]; + // we need a working staleness check for every oracle type not only SBOD in this case + // this info is up to date bc. of setupBackgroundRefresh + if (!bank.isOracleStaleOrUnconfident(lastProcessedSlot + safetySlots)) { + console.log( + `[filter stale] fallback ${item.oracle.name}, non-candidate, bc. main oracle is up to date ${mainOraclePk}`, + ); + // skip to save on gas, primary is good enough + continue; + } + } + + // this oracle is stale and there's no fresh primary either staleOracles.push(item); } else { console.log( - `[filter stale] ${item.oracle.name}, non-candidate, ${item.decodedPullFeed.maxStaleness}, ${slot}, ${res.lastUpdatedSlot}, ${diff}`, + `[filter stale] ${item.oracle.name}, non-candidate, ${item.decodedPullFeed.maxStaleness}, ${lastProcessedSlot}, ${res.lastUpdatedSlot}, ${slotsSinceLastUpdate}`, ); } } @@ -461,7 +486,7 @@ async function prepareCandidateOracles( ); } - // combine account info + // combine account info and remove non sbod owned oracles const sbodOracles = oracles .map((o, i) => { return { oracle: o, ai: ais[i] }; @@ -517,10 +542,10 @@ function extendOraclesManually( { oraclePk: new PublicKey('EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf'), name: 'BTC/USD', + tier: 'S', fallbackForOracle: undefined, tokenIndex: undefined, perpMarketIndex: undefined, - isOracleStaleOrUnconfident: false, }, ]; } @@ -537,10 +562,10 @@ function extendOraclesManually( return { oraclePk: new PublicKey(item[1]), name: item[0], + tier: 'S', fallbackForOracle: undefined, tokenIndex: undefined, perpMarketIndex: undefined, - isOracleStaleOrUnconfident: false, }; }); } @@ -606,8 +631,6 @@ async function setupSwitchboard(client: MangoClient): Promise<{ async function updateFilteredOraclesAis( client: MangoClient, sbOnDemandProgram: Anchor30Program, - group: Group, - nowSlot: number, filteredOracles: OracleMetaInterface[], ): Promise { const ais = ( @@ -631,73 +654,4 @@ async function updateFilteredOraclesAis( ); fo.decodedPullFeed = decodedPullFeed; }); - - // make a note iff a sbod oracle, is a fallback for another oracle, where the main oracle is stale or unconfident - { - // filter where sbod oracle is a fallback for another oracle - const publicKeysWithIndices = filteredOracles - .map((item, idx) => { - return { publicKey: item.oracle.fallbackForOracle, idx: idx }; - }) - .filter((item) => item.publicKey !== undefined); - const ais = ( - await Promise.all( - chunk( - publicKeysWithIndices.map((item) => item.publicKey), - 50, - false, - ).map((chunk_) => - client.program.provider.connection.getMultipleAccountsInfo(chunk_), - ), - ) - ).flat(); - - const coder = new BorshAccountsCoder(client.program.idl); - - await Promise.all( - zipWith(publicKeysWithIndices, ais, function (publicKeyWithIndex, ai) { - return { publicKeyWithIndex, ai }; - }).map(async (item) => { - // fetch main oracle, and check if it is stale or unconfident - const filteredOracle = filteredOracles[item.publicKeyWithIndex.idx]; - let mintDecimals, maxStalenessSlots, confFilter; - if (filteredOracle.oracle.tokenIndex !== undefined) { - const bank = group.getFirstBankByTokenIndex( - filteredOracle.oracle.tokenIndex, - ); - mintDecimals = bank.mintDecimals; - maxStalenessSlots = bank.oracleConfig.maxStalenessSlots; - confFilter = bank.oracleConfig.confFilter; - } else if (filteredOracle.oracle.perpMarketIndex !== undefined) { - const pm = group.getPerpMarketByMarketIndex( - filteredOracle.oracle.perpMarketIndex, - ); - mintDecimals = pm.baseDecimals; - maxStalenessSlots = pm.oracleConfig.maxStalenessSlots; - confFilter = pm.oracleConfig.confFilter; - } else { - return; - } - const result = await Group.decodePriceFromOracleAi( - group, - coder, - filteredOracle.oracle.oraclePk, - item.ai, - mintDecimals, - client, - ); - filteredOracle.oracle.isOracleStaleOrUnconfident = - isOracleStaleOrUnconfident( - nowSlot, - maxStalenessSlots.toNumber() - 100, // mark as stale a bit early, so we can keep fallback prepared - result.lastUpdatedSlot, - result.deviation, - confFilter, - result.price, - true, - `${filteredOracle.oracle.name} fallback-main-oracle-check`, - ); - }), - ); - } } From a8e751aac081e561c4ede6d52954d740632c9c4f Mon Sep 17 00:00:00 2001 From: Maximilian Schneider Date: Sat, 30 Nov 2024 16:28:23 +0100 Subject: [PATCH 3/3] setup prometheus metrics --- package.json | 7 +- ts/client/scripts/sb-on-demand-crank.ts | 96 +++- ts/client/scripts/sb-on-demand-metrics.ts | 104 ++++ yarn.lock | 550 +++++++++++++++++++++- 4 files changed, 729 insertions(+), 28 deletions(-) create mode 100644 ts/client/scripts/sb-on-demand-metrics.ts diff --git a/package.json b/package.json index 44ed869ba..a2f2ffbcd 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,10 @@ "tsx": "^4.15.7", "tweetnacl": "1.0.3", "typedoc": "^0.26.5", - "typescript": "^5.5.4" + "typescript": "^5.5.4", + "express": "^4.18.2", + "express-prom-bundle": "^8.0.0", + "prom-client": "^15.1.3" }, "prettier": { "singleQuote": true, @@ -95,4 +98,4 @@ "strip-ansi": "6.0.1" }, "license": "MIT" -} +} \ No newline at end of file diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 74ceeab33..c509b4230 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -33,6 +33,21 @@ import { getOraclesForMangoGroup, OraclesFromMangoGroupInterface, } from './sb-on-demand-crank-utils'; +import { + cycleDurationHistogram, + exposePromMetrics, + fetchIxDurationHistogram, + fetchIxFailureCounter, + fetchIxSuccessCounter, + refreshFailureCounter, + refreshSuccessCounter, + relativeSlotsSinceLastUpdateHistogram, + relativeVarianceSinceLastUpdateHistogram, + sendTxCounter, + sendTxErrorCounter, + updateBlockhashSlotDurationHistogram, + updateOracleAiDurationHistogram, +} from './sb-on-demand-metrics'; const CLUSTER: Cluster = (process.env.CLUSTER_OVERRIDE as Cluster) || 'mainnet-beta'; @@ -107,14 +122,17 @@ async function setupBackgroundRefresh( const refreshGroup = async function (): Promise { try { await group.reloadAll(client); + refreshSuccessCounter.labels({ label: 'group.reloadAll' }).inc(1); result.oracles = await prepareCandidateOracles( client, group, sbOnDemandProgram, crossbarClient, ); - } catch (e) { - console.error('[group]', e); + refreshSuccessCounter.labels({ label: 'prepareCandidateOracles' }).inc(1); + } catch (err) { + console.error('[refresh]', err); + refreshFailureCounter.label({ err }).inc(1); } setTimeout(refreshGroup, GROUP_REFRESH_INTERVAL); }; @@ -150,11 +168,20 @@ async function setupBackgroundRefresh( client.connection.getSlot('processed'), ]); - // refresh oracle accounts to know when each oracle was late updated + refreshSuccessCounter.labels({ label: 'getLatestBlockhash+getSlot' }).inc(1); + const blockhashSlotUpdateAt = Date.now(); + updateBlockhashSlotDurationHistogram.observe( + blockhashSlotUpdateAt - startedAt, + ); + + // refresh oracle accounts to know when each oracle was last updated // updates oracle in place await updateFilteredOraclesAis(client, sbOnDemandProgram, oracles); - + refreshSuccessCounter.labels({ label: 'updateFilteredOraclesAis' }).inc(1); const aisUpdatedAt = Date.now(); + updateOracleAiDurationHistogram.observe( + aisUpdatedAt - blockhashSlotUpdateAt, + ); const staleOracles = await filterForStaleOracles( oracles, @@ -162,7 +189,7 @@ async function setupBackgroundRefresh( group, slot, ); - + refreshSuccessCounter.labels({ label: 'filterForStaleOracles' }).inc(1); const staleFilteredAt = Date.now(); const crossBarSims = await Promise.all( @@ -172,12 +199,15 @@ async function setupBackgroundRefresh( ]), ), ); - + refreshSuccessCounter.labels({ label: 'simulateFeeds' }).inc(1); const simulatedAt = Date.now(); + fetchIxDurationHistogram.observe(simulatedAt - staleFilteredAt); const varianceThresholdCrossedOracles = await filterForVarianceThresholdOracles(oracles, client, crossBarSims); - + refreshSuccessCounter.labels({ label: 'filterForVarianceThresholdOracles' }).inc( + 1, + ); const varianceFilteredAt = Date.now(); const oraclesToCrank: OracleMetaInterface[] = uniqWith( @@ -203,7 +233,8 @@ async function setupBackgroundRefresh( const numSignatures = 2; try { - // TODO: don't ignore LUTS + // TODO: don't ignore LUTS + // TODO: investigate if more data can be prefetced (as was before) const [pullIx, _luts] = await PullFeed.fetchUpdateManyIx( sbOnDemandProgram as any, { @@ -213,8 +244,11 @@ async function setupBackgroundRefresh( payer: user.publicKey, }, ); - + for (const oracle of oracleChunk) { + fetchIxSuccessCounter.labels({ oracle: oracle.oracle.name }).inc(1); + } const ixPreparedAt = Date.now(); + fetchIxDurationHistogram.observe(ixPreparedAt - simulatedAt); const lamportsPerCu_ = Math.min( Math.max(lamportsPerCu ?? 150_000, 150_000), @@ -267,15 +301,20 @@ async function setupBackgroundRefresh( }, callbacks: { afterEveryTxSend: function (data) { + sendTxCounter.inc(1); const sentAt = Date.now(); const total = (sentAt - startedAt) / 1000; - const aiUpdate = (aisUpdatedAt - startedAt) / 1000; + cycleDurationHistogram.observe(sentAt - startedAt); + const blockhashSlotUpdate = + (blockhashSlotUpdateAt - startedAt) / 1000; + const aiUpdate = (aisUpdatedAt - blockhashSlotUpdateAt) / 1000; const staleFilter = (staleFilteredAt - aisUpdatedAt) / 1000; const simulate = (simulatedAt - staleFilteredAt) / 1000; const varianceFilter = (varianceFilteredAt - simulatedAt) / 1000; const ixPrepare = (ixPreparedAt - varianceFilteredAt) / 1000; const timing = { + blockhashSlotUpdate, aiUpdate, staleFilter, simulate, @@ -287,35 +326,42 @@ async function setupBackgroundRefresh( `[tx send] https://solscan.io/tx/${data['txid']}, in ${total}s, lamportsPerCu_ ${lamportsPerCu_}, lamportsPerCu ${lamportsPerCu}, timiming ${JSON.stringify(timing)}`, ); }, - onError: function (e, notProcessedTransactions) { + onError: function (err, notProcessedTransactions) { + sendTxErrorCounter.labels(err).inc(1); console.error( - `[tx send] ${notProcessedTransactions.length} error(s) after ${(Date.now() - ixPreparedAt) / 1000}s ${JSON.stringify(e)}`, + `[tx send] ${notProcessedTransactions.length} error(s) after ${(Date.now() - ixPreparedAt) / 1000}s ${JSON.stringify(err)}`, ); }, }, - }).catch((reason) => + }).catch((reason) => { + sendTxErrorCounter + .labels({ err: `prom rejected: ${JSON.stringify(reason)}` }) + .inc(1); console.error( `[tx send] promise rejected after ${(Date.now() - ixPreparedAt) / 1000}s ${JSON.stringify(reason)}`, - ), - ); - } catch (e) { + ); + }); + } catch (err) { console.error( - `[ix fetch] error after ${(Date.now() - varianceFilteredAt) / 1000}s ${JSON.stringify(e)}`, + `[ix fetch] error after ${(Date.now() - varianceFilteredAt) / 1000}s ${JSON.stringify(err)}`, ); + fetchIxFailureCounter.labels({ err }).inc(1); } }); await new Promise((r) => setTimeout(r, SLEEP_MS)); - } catch (error) { - console.error('[main]', error); + } catch (err) { + console.error('[main]', err); + refreshFailureCounter.labels({ err }).inc(1); } } })(); +exposePromMetrics(Number(process.env.PORT!), process.env.BIND); /** * prepares the instruction to update an individual oracle using the cached data on oracle */ -async function preparePullIx( +async function _preparePullIx( sbOnDemandProgram, oracle: OracleMetaInterface, recentSlothashes?: Array<[BN, string]>, @@ -377,6 +423,9 @@ async function filterForVarianceThresholdOracles( const changePct = (Math.abs(res.price - simPrice) * 100) / res.price; const thresholdPct = VARIANCE_THRESHOLD_PCT_BY_TIER[item.oracle.tier]; + relativeVarianceSinceLastUpdateHistogram + .labels({ oracle: item.oracle.name }) + .observe(changePct / thresholdPct); if (changePct > thresholdPct) { console.log( `[filter variance] ${item.oracle.name}, candidate: ${thresholdPct} < ${changePct}, ${simPrice}, ${res.price}`, @@ -412,9 +461,12 @@ async function filterForStaleOracles( const safetySeconds = 20 * 3 + 10; const safetySlots = safetySeconds * 2.5; const slotsUntilUpdate = item.decodedPullFeed.maxStaleness - safetySlots; + relativeSlotsSinceLastUpdateHistogram + .labels({ oracle: item.oracle.name }) + .observe(slotsSinceLastUpdate / slotsUntilUpdate); if (slotsSinceLastUpdate > slotsUntilUpdate) { console.log( - `[filter stale] ${item.oracle.name}, candidate, ${item.decodedPullFeed.maxStaleness}, ${lastProcessedSlot}, ${res.lastUpdatedSlot}, ${slotsSinceLastUpdate}`, + `[filter stale] ${item.oracle.name}, candidate, ${slotsSinceLastUpdate} > ${slotsUntilUpdate}, ${lastProcessedSlot}`, ); // check if oracle is fallback and primary is not stale @@ -436,7 +488,7 @@ async function filterForStaleOracles( staleOracles.push(item); } else { console.log( - `[filter stale] ${item.oracle.name}, non-candidate, ${item.decodedPullFeed.maxStaleness}, ${lastProcessedSlot}, ${res.lastUpdatedSlot}, ${slotsSinceLastUpdate}`, + `[filter stale] ${item.oracle.name}, non-candidate, ${slotsSinceLastUpdate} < ${slotsUntilUpdate}, ${lastProcessedSlot}` ); } } diff --git a/ts/client/scripts/sb-on-demand-metrics.ts b/ts/client/scripts/sb-on-demand-metrics.ts new file mode 100644 index 000000000..46b036c2a --- /dev/null +++ b/ts/client/scripts/sb-on-demand-metrics.ts @@ -0,0 +1,104 @@ +import express from "express"; +import * as prom from "prom-client"; +import promBundle from "express-prom-bundle"; + +const collectDefaultMetrics = prom.collectDefaultMetrics; +collectDefaultMetrics({ + labels: { + app: process.env.FLY_APP_NAME, + instance: process.env.FLY_ALLOC_ID, + }, +}); + +export const refreshSuccessCounter = new prom.Counter({ + name: "refresh_success_count", + help: "number of successful refreshes", + labelNames: ["label"], +}); + +export const refreshFailureCounter = new prom.Counter({ + name: "refresher_failure_count", + help: "number of failed refreshes", + labelNames: ["err"], +}); + +export const relativeSlotsSinceLastUpdateHistogram = new prom.Histogram({ + name: "relative_slots_since_last_update", + help: "distribution of the relative slot since last update during filterForStaleOracles", + labelNames: ["oracle"], + buckets: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.75, 2.0, 3.0, 4.0, 5.0], +}); + +export const relativeVarianceSinceLastUpdateHistogram = new prom.Histogram({ + name: "relative_variance_since_last_update", + help: "distribution of the relative variance since last update during filterForVarianceThresholdOracles", + labelNames: ["oracle"], + buckets: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.75, 2.0, 3.0, 4.0, 5.0], +}); + +export const fetchIxSuccessCounter = new prom.Counter({ + name: "fetch_ix_success_count", + help: "number of successful oracle instructions fetched", + labelNames: ["oracle"], +}); + +export const fetchIxFailureCounter = new prom.Counter({ + name: "fetch_ix_failure_count", + help: "number of failed ix fetches", + labelNames: ["err"], +}); + +export const fetchIxDurationHistogram = new prom.Histogram({ + name: "fetch_ix_duration_histogram", + help: "duration of fetchIx calls in ms", + buckets: [100, 200, 400, 800, 1_600, 3_200, 6_400, 12_800, 25_600, 51_200, 102_400], +}); + + +export const simulateFeedDurationHistogram = new prom.Histogram({ + name: "simulate_feed_duration_histogram", + help: "duration of simulateFeeds calls in ms", + buckets: [100, 200, 400, 800, 1_600, 3_200, 6_400, 12_800, 25_600, 51_200, 102_400], +}); + +export const updateOracleAiDurationHistogram = new prom.Histogram({ + name: "update_oracle_ai_duration_histogram", + help: "duration of updateFilteredOraclesAis calls in ms", + buckets: [100, 200, 400, 800, 1_600, 3_200, 6_400, 12_800, 25_600, 51_200, 102_400], +}); + +export const updateBlockhashSlotDurationHistogram = new prom.Histogram({ + name: "update_blockhash_slot_duration_histogram", + help: "duration of getLatestBlockhash+getSlot calls in ms", + buckets: [100, 200, 400, 800, 1_600, 3_200, 6_400, 12_800, 25_600, 51_200, 102_400], +}); + +export const cycleDurationHistogram = new prom.Histogram({ + name: "cycle_duration_histogram", + help: "duration of full update cycle in ms", + buckets: [100, 200, 400, 800, 1_600, 3_200, 6_400, 12_800, 25_600, 51_200, 102_400], +}); + +export const sendTxCounter = new prom.Counter({ + name: "send_tx_counter", + help: "number of oracle update transactions sent", +}); + +export const sendTxErrorCounter = new prom.Counter({ + name: "send_tx_error_counter", + help: "number of failed oracle update transactions", + labelNames: ["err"], +}); + + +export const metricsMiddleware = promBundle({ includeMethod: true }); + + +export function exposePromMetrics(port: number, bind: string | undefined): void { + const app = express(); + app.use(metricsMiddleware); + app.listen(port, bind, () => { + console.log(`prom metrics exposed on ${bind}:${port}`); + }); +} + diff --git a/yarn.lock b/yarn.lock index 477d2007c..455c2c58e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -409,6 +409,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@opentelemetry/api@^1.4.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" + integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -1015,6 +1020,14 @@ dependencies: "@types/node" "*" +"@types/body-parser@*": + version "1.19.5" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== + dependencies: + "@types/connect" "*" + "@types/node" "*" + "@types/bs58@^4.0.1": version "4.0.4" resolved "https://registry.yarnpkg.com/@types/bs58/-/bs58-4.0.4.tgz#49fbcb0c7db5f7cea26f0e0f61dc4a41a2445aab" @@ -1028,7 +1041,7 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.17.tgz#9195f9d242f2ac3b429908864b6b871a8f73f489" integrity sha512-zmZ21EWzR71B4Sscphjief5djsLre50M6lI622OSySTmn9DB3j+C3kWroHfBQWXbOBwbgg/M8CG/hUxDLIloow== -"@types/connect@^3.4.33": +"@types/connect@*", "@types/connect@^3.4.33": version "3.4.38" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== @@ -1040,6 +1053,26 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== +"@types/express-serve-static-core@^5.0.0": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz#812d2871e5eea17fb0bd5214dda7a7b748c0e12a" + integrity sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + +"@types/express@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.0.tgz#13a7d1f75295e90d19ed6e74cab3678488eaa96c" + integrity sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^5.0.0" + "@types/qs" "*" + "@types/serve-static" "*" + "@types/hast@^3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" @@ -1047,11 +1080,21 @@ dependencies: "@types/unist" "*" +"@types/http-errors@*": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== + "@types/mocha@^9.1.0": version "9.1.1" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" @@ -1089,6 +1132,33 @@ dependencies: undici-types "~5.26.4" +"@types/qs@*": + version "6.9.17" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.17.tgz#fc560f60946d0aeff2f914eb41679659d3310e1a" + integrity sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ== + +"@types/range-parser@*": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== + +"@types/send@*": + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/serve-static@*": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + "@types/unist@*": version "3.0.2" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.2.tgz#6dd61e43ef60b34086287f83683a5c1b2dc53d20" @@ -1207,6 +1277,14 @@ JSONStream@^1.3.5: jsonparse "^1.2.0" through ">=2.2.7 <3" +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -1293,6 +1371,11 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" @@ -1386,6 +1469,11 @@ bindings@^1.3.0: dependencies: file-uri-to-path "1.0.0" +bintrees@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8" + integrity sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw== + bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -1396,6 +1484,24 @@ bn.js@^5.0.0, bn.js@^5.1.0, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0, bn.js@^5.2 resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.13.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + borsh@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.3.1.tgz#c31c3a149610e37913deada80e89073fb15cf55b" @@ -1493,11 +1599,27 @@ bundle-require@^5.0.0: dependencies: load-tsconfig "^0.2.3" +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + cac@^6.7.14: version "6.7.14" resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -1645,6 +1767,28 @@ console-table-printer@^2.11.1: dependencies: simple-wcswidth "^1.0.1" +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" + integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== + crc@^4.1.0: version "4.3.2" resolved "https://registry.yarnpkg.com/crc/-/crc-4.3.2.tgz#49b7821cbf2cf61dfd079ed93863bbebd5469b9a" @@ -1688,6 +1832,13 @@ crypto-hash@^1.3.0: resolved "https://registry.yarnpkg.com/crypto-hash/-/crypto-hash-1.3.0.tgz#b402cb08f4529e9f4f09346c3e275942f845e247" integrity sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg== +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5: version "4.3.6" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" @@ -1729,6 +1880,15 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + delay@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" @@ -1739,6 +1899,16 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + diff@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" @@ -1784,6 +1954,11 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + elliptic@^6.5.4: version "6.5.6" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.6.tgz#ee5f7c3a00b98a2144ac84d67d01f04d438fa53e" @@ -1807,11 +1982,33 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + entities@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es6-promise@^4.0.3: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" @@ -1859,6 +2056,11 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -1960,6 +2162,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -1985,6 +2192,52 @@ execa@^5.1.1: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +express-prom-bundle@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/express-prom-bundle/-/express-prom-bundle-8.0.0.tgz#22a434b87854d98a1ea75c487c9d65f669e8e93e" + integrity sha512-UHdpaMks6Z/tvxQsNzhsE7nkdXb4/zEh/jwN0tfZSZOEF+aD0dlfl085EU4jveOq09v01c5sIUfjV4kJODZ2eQ== + dependencies: + "@types/express" "^5.0.0" + on-finished "^2.3.0" + url-value-parser "^2.0.0" + +express@^4.18.2: + version "4.21.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.1.tgz#9dae5dda832f16b4eec941a4e44aa89ec481b281" + integrity sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.3" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.7.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~2.0.0" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.3.1" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.3" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.10" + proxy-addr "~2.0.7" + qs "6.13.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.19.0" + serve-static "1.16.2" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + eyes@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" @@ -2065,6 +2318,19 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== + dependencies: + debug "2.6.9" + encodeurl "~2.0.0" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -2120,6 +2386,16 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2130,6 +2406,11 @@ fsevents@~2.3.2, fsevents@~2.3.3: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -2140,6 +2421,17 @@ get-func-name@^2.0.1, get-func-name@^2.0.2: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== +get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + get-stream@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" @@ -2207,6 +2499,13 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +gopd@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.1.0.tgz#df8f0839c2d48caefc32a025a49294d39606c912" + integrity sha512-FQoVQnqcdk4hVM4JN1eromaun4iuS34oStkdlLENLdpULsuQcTyXj8w7ayhuUfPwEYZ1ZOooOTT6fdA9Vmx/RA== + dependencies: + get-intrinsic "^1.2.4" + graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -2222,6 +2521,23 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + 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" @@ -2230,6 +2546,13 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -2244,6 +2567,17 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -2264,6 +2598,13 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -2295,11 +2636,16 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@^2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -2628,6 +2974,16 @@ mdurl@^2.0.0: resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -2638,6 +2994,11 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + micromatch@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" @@ -2651,13 +3012,18 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12: +mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -2741,6 +3107,11 @@ mocha@^9.1.3: yargs-parser "20.2.4" yargs-unparser "2.0.0" +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -2770,6 +3141,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -2831,6 +3207,18 @@ object-assign@^4.0.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== +object-inspect@^1.13.1: + version "1.13.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a" + integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== + +on-finished@2.4.1, on-finished@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -2888,6 +3276,11 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -2911,6 +3304,11 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-to-regexp@0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" + integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -2953,6 +3351,14 @@ prettier@^3.3.3: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== +prom-client@^15.1.3: + version "15.1.3" + resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-15.1.3.tgz#69fa8de93a88bc9783173db5f758dc1c69fa8fc2" + integrity sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g== + dependencies: + "@opentelemetry/api" "^1.4.0" + tdigest "^0.1.1" + protobufjs@^7.2.6: version "7.3.2" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.3.2.tgz#60f3b7624968868f6f739430cfbc8c9370e26df4" @@ -2971,6 +3377,14 @@ protobufjs@^7.2.6: "@types/node" ">=13.7.0" long "^5.0.0" +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -2986,6 +3400,13 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -2998,6 +3419,21 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -3088,11 +3524,16 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.0.1, safe-buffer@^5.1.0: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.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== +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + secp256k1@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-5.0.0.tgz#be6f0c8c7722e2481e9773336d351de8cddd12f7" @@ -3107,6 +3548,25 @@ semver@^7.6.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -3114,6 +3574,33 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== + dependencies: + encodeurl "~2.0.0" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.19.0" + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -3134,6 +3621,16 @@ shiki@^1.9.1: "@shikijs/core" "1.12.1" "@types/hast" "^3.0.4" +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -3182,6 +3679,11 @@ source-map@^0.6.0: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0: name string-width-cjs version "4.2.3" @@ -3260,6 +3762,13 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +tdigest@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.2.tgz#96c64bac4ff10746b910b0e23b515794e12faced" + integrity sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA== + dependencies: + bintrees "1.0.2" + 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" @@ -3301,6 +3810,11 @@ toformat@^2.0.0: resolved "https://registry.yarnpkg.com/toformat/-/toformat-2.0.0.tgz#7a043fd2dfbe9021a4e36e508835ba32056739d8" integrity sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + toml@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" @@ -3449,6 +3963,14 @@ type-detect@^4.0.0, type-detect@^4.1.0: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + typedoc@^0.26.5: version "0.26.5" resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.26.5.tgz#08032bd57cac3d56e8ac296a07e3482dc0c645ac" @@ -3485,6 +4007,11 @@ undici-types@~6.13.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.13.0.tgz#e3e79220ab8c81ed1496b5812471afd7cf075ea5" integrity sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg== +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -3492,6 +4019,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +url-value-parser@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/url-value-parser/-/url-value-parser-2.2.0.tgz#f38ae8cd24604ec69bc219d66929ddbbd93a2b32" + integrity sha512-yIQdxJpgkPamPPAPuGdS7Q548rLhny42tg8d4vyTNzFqvOnwqrgHXvgehT09U7fwrzxi3RxCiXjoNUNnNOlQ8A== + utf-8-validate@^5.0.2, utf-8-validate@^5.0.9: version "5.0.10" resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" @@ -3499,6 +4031,11 @@ utf-8-validate@^5.0.2, utf-8-validate@^5.0.9: dependencies: node-gyp-build "^4.3.0" +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -3509,6 +4046,11 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"