diff --git a/a3p-integration/proposals/f:replace-price-feeds/.yarnrc.yml b/a3p-integration/proposals/f:replace-price-feeds/.yarnrc.yml new file mode 100644 index 00000000000..3186f3f0795 --- /dev/null +++ b/a3p-integration/proposals/f:replace-price-feeds/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/a3p-integration/proposals/f:replace-price-feeds/README.md b/a3p-integration/proposals/f:replace-price-feeds/README.md new file mode 100644 index 00000000000..414bb07fe81 --- /dev/null +++ b/a3p-integration/proposals/f:replace-price-feeds/README.md @@ -0,0 +1,10 @@ +# CoreEvalProposal to replace existing price_feed and scaledPriceAuthority vats +# with new contracts. Auctions will need to be replaced, and Vaults will need to +# get at least a null upgrade in order to make use of the new prices. Oracle +# operators will need to accept new invitations, and sync to the roundId (0) of +# the new contracts in order to feed the new pipelines. + +The `submission` for this proposal is automatically generated during `yarn build` +in [a3p-integration](../..) using the code in agoric-sdk through +[build-all-submissions.sh](../../scripts/build-all-submissions.sh) and +[build-submission.sh](../../scripts/build-submission.sh). diff --git a/a3p-integration/proposals/f:replace-price-feeds/agd-tools.js b/a3p-integration/proposals/f:replace-price-feeds/agd-tools.js new file mode 100644 index 00000000000..c94718bc1ba --- /dev/null +++ b/a3p-integration/proposals/f:replace-price-feeds/agd-tools.js @@ -0,0 +1,23 @@ +import { agd } from '@agoric/synthetic-chain'; + +export const BID_OFFER_ID = 'bid-vaultUpgrade-test3'; + +/** @param {string} path */ +export const queryVstorage = path => + agd.query('vstorage', 'data', '--output', 'json', path); + +export const getOracleInstance = async price => { + const instanceRec = await queryVstorage(`published.agoricNames.instance`); + + const value = JSON.parse(instanceRec.value); + const body = JSON.parse(value.values.at(-1)); + + const feeds = JSON.parse(body.body.substring(1)); + const feedName = `${price}-USD price feed`; + + const key = Object.keys(feeds).find(k => feeds[k][0] === feedName); + if (key) { + return body.slots[key]; + } + return null; +}; diff --git a/a3p-integration/proposals/f:replace-price-feeds/agoric-tools.js b/a3p-integration/proposals/f:replace-price-feeds/agoric-tools.js new file mode 100644 index 00000000000..1c6e10ac8f6 --- /dev/null +++ b/a3p-integration/proposals/f:replace-price-feeds/agoric-tools.js @@ -0,0 +1,96 @@ +import assert from 'node:assert'; +import { agops, agoric, executeOffer } from '@agoric/synthetic-chain'; + +export const generateVaultDirectorParamChange = async ( + previousOfferId, + voteDur, + params, + paramsPath, +) => { + const voteDurSec = BigInt(voteDur); + const toSec = ms => BigInt(Math.round(ms / 1000)); + + const id = `propose-${Date.now()}`; + const deadline = toSec(Date.now()) + voteDurSec; + + const zip = (xs, ys) => xs.map((x, i) => [x, ys[i]]); + // KLUDGE: partial deconstruction of smallCaps values + const fromSmallCapsEntries = txt => { + const { body, slots } = JSON.parse(txt); + const theEntries = zip(JSON.parse(body.slice(1)), slots).map( + ([[name, ref], boardID]) => { + const iface = ref.replace(/^\$\d+\./, ''); + return [name, { iface, boardID }]; + }, + ); + return Object.fromEntries(theEntries); + }; + + const slots = []; // XXX global mutable state + const smallCaps = { + Nat: n => `+${n}`, + // XXX mutates obj + ref: obj => { + if (obj.ix) return obj.ix; + const ix = slots.length; + slots.push(obj.boardID); + obj.ix = `$${ix}.Alleged: ${obj.iface}`; + return obj.ix; + }, + }; + + await null; + const instance = fromSmallCapsEntries( + await agoric.follow('-lF', ':published.agoricNames.instance', '-o', 'text'), + ); + assert(instance.VaultFactory); + + const body = { + method: 'executeOffer', + offer: { + id, + invitationSpec: { + invitationMakerName: 'VoteOnParamChange', + previousOffer: previousOfferId, + source: 'continuing', + }, + offerArgs: { + deadline: smallCaps.Nat(deadline), + instance: smallCaps.ref(instance.VaultFactory), + params, + path: paramsPath, + }, + proposal: {}, + }, + }; + + const capData = { body: `#${JSON.stringify(body)}`, slots }; + return JSON.stringify(capData); +}; + +export const proposeVaultDirectorParamChange = async ( + address, + params, + path, +) => { + const charterAcceptOfferId = await agops.ec( + 'find-continuing-id', + '--for', + `${'charter\\ member\\ invitation'}`, + '--from', + address, + ); + + return executeOffer( + address, + generateVaultDirectorParamChange(charterAcceptOfferId, 30, params, path), + ); +}; + +export const voteForNewParams = (accounts, position) => { + return Promise.all( + accounts.map(account => + agops.ec('vote', '--forPosition', position, '--send-from', account), + ), + ); +}; diff --git a/a3p-integration/proposals/f:replace-price-feeds/eval.sh b/a3p-integration/proposals/f:replace-price-feeds/eval.sh new file mode 100755 index 00000000000..c44d11c5a35 --- /dev/null +++ b/a3p-integration/proposals/f:replace-price-feeds/eval.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Exit when any command fails +set -uxeo pipefail + +# The upgrade-vaults proposal needs to know the existing vaultDirector +# parameters in order to cleanly upgrade the contract. The governance notifier +# it relies on doesn't give the most recent value if there were no updates to +# the parameters, so we'll do a governance action to reset them to their current +# values so the notifier will work. + +./resetChargingPeriod.js + +cp /usr/src/upgrade-test-scripts/eval_submission.js . +./eval_submission.js diff --git a/a3p-integration/proposals/f:replace-price-feeds/package.json b/a3p-integration/proposals/f:replace-price-feeds/package.json new file mode 100644 index 00000000000..84abe583e48 --- /dev/null +++ b/a3p-integration/proposals/f:replace-price-feeds/package.json @@ -0,0 +1,28 @@ +{ + "agoricProposal": { + "source": "subdir", + "sdk-generate": [ + "inter-protocol/updatePriceFeeds.js submission A3P_INTEGRATION", + "vats/add-auction.js", + "vats/upgradeVaults.js" + ], + "type": "/agoric.swingset.CoreEvalProposal" + }, + "type": "module", + "license": "Apache-2.0", + "dependencies": { + "@agoric/synthetic-chain": "^0.3.0", + "ava": "^5.3.1" + }, + "ava": { + "concurrency": 1, + "timeout": "2m", + "files": [ + "!submission" + ] + }, + "scripts": { + "agops": "yarn --cwd /usr/src/agoric-sdk/ --silent agops" + }, + "packageManager": "yarn@4.2.2" +} diff --git a/a3p-integration/proposals/f:replace-price-feeds/priceFeedUpdate.test.js b/a3p-integration/proposals/f:replace-price-feeds/priceFeedUpdate.test.js new file mode 100644 index 00000000000..5cbacd019ad --- /dev/null +++ b/a3p-integration/proposals/f:replace-price-feeds/priceFeedUpdate.test.js @@ -0,0 +1,155 @@ +import test from 'ava'; + +import { + agops, + ATOM_DENOM, + bankSend, + createBid, + generateOracleMap, + getDetailsMatchingVats, + getInstanceBoardId, + getISTBalance, + getLiveOffers, + getPriceQuote, + getVaultPrices, + getVatDetails, + openVault, + pushPrices, + registerOraclesForBrand, + USER1ADDR, +} from '@agoric/synthetic-chain'; + +import { BID_OFFER_ID } from './agd-tools.js'; + +export const checkForOracle = async (t, name) => { + const instanceName = `${name}-USD price feed`; + const instance = await getInstanceBoardId(instanceName); + t.truthy(instance); +}; + +const checkPriceFeedVatsUpdated = async t => { + const atomDetails = await getVatDetails('ATOM-USD_price_feed'); + // both the original and the new ATOM vault are incarnation 0 + t.is(atomDetails.incarnation, 0); + const stAtomDetails = await getVatDetails('stATOM'); + t.is(stAtomDetails.incarnation, 0); + await checkForOracle(t, 'ATOM'); + await checkForOracle(t, 'stATOM'); +}; + +console.log('adding oracle for each brand'); +const oraclesByBrand = generateOracleMap('f-priceFeeds', ['ATOM', 'stATOM']); +await registerOraclesForBrand('ATOM', oraclesByBrand); +await registerOraclesForBrand('stATOM', oraclesByBrand); + +let roundId = 1; + +const tryPushPrices = async t => { + // There are no old prices for the other currencies. + // const atomOutPre = await getPriceQuote('ATOM'); + // t.is(atomOutPre, '+12010000'); + // const stAtomOutPre = await getPriceQuote('stATOM'); + // t.is(stAtomOutPre, '+12010000'); + + t.log('pushing new prices'); + await pushPrices(13.4, 'ATOM', oraclesByBrand, roundId); + await pushPrices(13.7, 'stATOM', oraclesByBrand, roundId); + roundId += 1; + + t.log('awaiting new quotes'); + const atomOut = await getPriceQuote('ATOM'); + t.is(atomOut, '+13400000'); + const stAtomOut = await getPriceQuote('stATOM'); + t.is(stAtomOut, '+13700000'); +}; + +const createNewBid = async t => { + await createBid('20', USER1ADDR, BID_OFFER_ID); + const liveOffer = await getLiveOffers(USER1ADDR); + t.true(liveOffer[0].includes(BID_OFFER_ID)); +}; + +const openMarginalVault = async t => { + let user1IST = await getISTBalance(USER1ADDR); + await bankSend(USER1ADDR, `20000000${ATOM_DENOM}`); + const currentVaults = await agops.vaults('list', '--from', USER1ADDR); + + t.log('opening a vault'); + await openVault(USER1ADDR, 5, 10); + user1IST += 5; + const istBalanceAfterVaultOpen = await getISTBalance(USER1ADDR); + t.is(istBalanceAfterVaultOpen, user1IST); + + const activeVaultsAfter = await agops.vaults('list', '--from', USER1ADDR); + t.log(currentVaults, activeVaultsAfter); + t.true( + activeVaultsAfter.length > currentVaults.length, + `vaults count should increase, ${activeVaultsAfter.length}, ${currentVaults.length}`, + ); +}; + +const triggerAuction = async t => { + await pushPrices(5.2, 'ATOM', oraclesByBrand, roundId); + + const atomOut = await getPriceQuote('ATOM'); + t.is(atomOut, '+5200000'); +}; + +const checkNewAuctionVat = async t => { + const details = await getDetailsMatchingVats('auctioneer'); + // This query matches both the auction and its governor, so double the count + t.is(Object.keys(details).length, 3 * 2); +}; + +const countPriceFeedVats = async t => { + // price_feed and governor, old and new for two tokens + const priceFeedDetails = await getDetailsMatchingVats('price_feed'); + t.is(Object.keys(priceFeedDetails).length, 8); + + // Two old SPAs, and two new ones + const details = await getDetailsMatchingVats('scaledPriceAuthority'); + t.is(Object.keys(details).length, 4); + + // ATOM vat name is something like zcf-DEADBEEF-ATOM_USD_price_feed + // initial '-' distinguishes this from stAOM + const atomDetails = await getDetailsMatchingVats('-ATOM-USD_price_feed'); + t.is(Object.keys(atomDetails).length, 4); + + const stAtomDetails = await getVatDetails('stATOM'); + t.is(Object.keys(stAtomDetails).length, 4); + await Promise.all([checkForOracle(t, 'ATOM'), checkForOracle(t, 'stATOM')]); +}; + +const verifyVaultPriceUpdate = async t => { + const ATOMManagerIndex = 0; + const quote = await getVaultPrices(ATOMManagerIndex); + t.true(quote.value[0].amountIn.brand.includes(' ATOM ')); + t.is(quote.value[0].amountOut.value, '+5200000'); +}; + +// test.serial() isn't guaranteed to run tests in order, so we run the intended tests here +test('liquidation post upgrade', async t => { + t.log('starting upgrade vaults test'); + await checkPriceFeedVatsUpdated(t); + + t.log('starting pushPrices'); + await tryPushPrices(t); + + t.log('create a new Bid for the auction'); + await createNewBid(t); + + t.log('open a marginal vault'); + await openMarginalVault(t); + + t.log('trigger Auction'); + await triggerAuction(t); + + t.log('check new auction'); + await checkNewAuctionVat(t); + + t.log('count vats'); + await countPriceFeedVats(t); + + t.log('verify Vault priceUpdate'); + await verifyVaultPriceUpdate(t); +}); diff --git a/a3p-integration/proposals/f:replace-price-feeds/resetChargingPeriod.js b/a3p-integration/proposals/f:replace-price-feeds/resetChargingPeriod.js new file mode 100755 index 00000000000..c77494dddc6 --- /dev/null +++ b/a3p-integration/proposals/f:replace-price-feeds/resetChargingPeriod.js @@ -0,0 +1,41 @@ +#!/usr/bin/env node + +/* global setTimeout */ + +import { + getQuoteBody, + GOV1ADDR, + GOV2ADDR, + GOV3ADDR, +} from '@agoric/synthetic-chain'; +import { + proposeVaultDirectorParamChange, + voteForNewParams, +} from './agoric-tools.js'; + +const GOV_ADDRESSES = [GOV1ADDR, GOV2ADDR, GOV3ADDR]; + +const readChargingPeriod = async () => { + const governanceBody = await getQuoteBody( + 'published.vaultFactory.governance', + ); + const period = + governanceBody.current.ChargingPeriod.value.match(/\+?(\d+)/)[1]; + return `+${period}`; +}; + +const setChargingPeriod = async period => { + const params = { + ChargingPeriod: period, + }; + + const path = { paramPath: { key: 'governedParams' } }; + + await proposeVaultDirectorParamChange(GOV1ADDR, params, path); + await voteForNewParams(GOV_ADDRESSES, 0); + + await new Promise(r => setTimeout(r, 65000)); +}; + +const period = await readChargingPeriod(); +await setChargingPeriod(period); diff --git a/a3p-integration/proposals/f:replace-price-feeds/test.sh b/a3p-integration/proposals/f:replace-price-feeds/test.sh new file mode 100755 index 00000000000..23a194f7f79 --- /dev/null +++ b/a3p-integration/proposals/f:replace-price-feeds/test.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# Place here any test that should be executed using the proposal. +# The effects of this step are not persisted in further layers. + +yarn ava ./*.test.js diff --git a/a3p-integration/proposals/f:replace-price-feeds/yarn.lock b/a3p-integration/proposals/f:replace-price-feeds/yarn.lock new file mode 100644 index 00000000000..ee7a03e8e81 --- /dev/null +++ b/a3p-integration/proposals/f:replace-price-feeds/yarn.lock @@ -0,0 +1,2345 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"@agoric/synthetic-chain@npm:^0.3.0": + version: 0.3.0 + resolution: "@agoric/synthetic-chain@npm:0.3.0" + dependencies: + "@endo/zip": "npm:^1.0.7" + better-sqlite3: "npm:^9.6.0" + chalk: "npm:^5.3.0" + cosmjs-types: "npm:^0.9.0" + execa: "npm:^9.3.1" + bin: + synthetic-chain: dist/cli/cli.js + checksum: 10c0/17c6241bdc48b8a2a7608c9d4d7c0a0c76fb10d4ee44a31a1150104a792bcd1133f4b1a7e8ab26673a07450b3ceabccd9911999117568221b49221b6ee4306a1 + languageName: node + linkType: hard + +"@endo/zip@npm:^1.0.7": + version: 1.0.7 + resolution: "@endo/zip@npm:1.0.7" + checksum: 10c0/a1c0d155448ce877012b34c8fe8cd3a58de9eb807514c81cddeebb802ee8e552b27d8a9a40fab3f3e4c49e0cb7fea6902fa1dd12a23ff6f30b56161fc3edc1f8 + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: "npm:^5.1.2" + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: "npm:^7.0.1" + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: "npm:^8.1.0" + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e + languageName: node + linkType: hard + +"@nodelib/fs.scandir@npm:2.1.5": + version: 2.1.5 + resolution: "@nodelib/fs.scandir@npm:2.1.5" + dependencies: + "@nodelib/fs.stat": "npm:2.0.5" + run-parallel: "npm:^1.1.9" + checksum: 10c0/732c3b6d1b1e967440e65f284bd06e5821fedf10a1bea9ed2bb75956ea1f30e08c44d3def9d6a230666574edbaf136f8cfd319c14fd1f87c66e6a44449afb2eb + languageName: node + linkType: hard + +"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": + version: 2.0.5 + resolution: "@nodelib/fs.stat@npm:2.0.5" + checksum: 10c0/88dafe5e3e29a388b07264680dc996c17f4bda48d163a9d4f5c1112979f0ce8ec72aa7116122c350b4e7976bc5566dc3ddb579be1ceaacc727872eb4ed93926d + languageName: node + linkType: hard + +"@nodelib/fs.walk@npm:^1.2.3": + version: 1.2.8 + resolution: "@nodelib/fs.walk@npm:1.2.8" + dependencies: + "@nodelib/fs.scandir": "npm:2.1.5" + fastq: "npm:^1.6.0" + checksum: 10c0/db9de047c3bb9b51f9335a7bb46f4fcfb6829fb628318c12115fbaf7d369bfce71c15b103d1fc3b464812d936220ee9bc1c8f762d032c9f6be9acc99249095b1 + languageName: node + linkType: hard + +"@npmcli/agent@npm:^2.0.0": + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae + languageName: node + linkType: hard + +"@npmcli/fs@npm:^3.1.0": + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd + languageName: node + linkType: hard + +"@sec-ant/readable-stream@npm:^0.4.1": + version: 0.4.1 + resolution: "@sec-ant/readable-stream@npm:0.4.1" + checksum: 10c0/64e9e9cf161e848067a5bf60cdc04d18495dc28bb63a8d9f8993e4dd99b91ad34e4b563c85de17d91ffb177ec17a0664991d2e115f6543e73236a906068987af + languageName: node + linkType: hard + +"@sindresorhus/merge-streams@npm:^4.0.0": + version: 4.0.0 + resolution: "@sindresorhus/merge-streams@npm:4.0.0" + checksum: 10c0/482ee543629aa1933b332f811a1ae805a213681ecdd98c042b1c1b89387df63e7812248bb4df3910b02b3cc5589d3d73e4393f30e197c9dde18046ccd471fc6b + languageName: node + linkType: hard + +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 10c0/f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372 + languageName: node + linkType: hard + +"acorn-walk@npm:^8.2.0": + version: 8.3.4 + resolution: "acorn-walk@npm:8.3.4" + dependencies: + acorn: "npm:^8.11.0" + checksum: 10c0/76537ac5fb2c37a64560feaf3342023dadc086c46da57da363e64c6148dc21b57d49ace26f949e225063acb6fb441eabffd89f7a3066de5ad37ab3e328927c62 + languageName: node + linkType: hard + +"acorn@npm:^8.11.0, acorn@npm:^8.8.2": + version: 8.12.1 + resolution: "acorn@npm:8.12.1" + bin: + acorn: bin/acorn + checksum: 10c0/51fb26cd678f914e13287e886da2d7021f8c2bc0ccc95e03d3e0447ee278dd3b40b9c57dc222acd5881adcf26f3edc40901a4953403232129e3876793cd17386 + languageName: node + linkType: hard + +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" + dependencies: + debug: "npm:^4.3.4" + checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: "npm:^2.0.0" + indent-string: "npm:^4.0.0" + checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 + languageName: node + linkType: hard + +"aggregate-error@npm:^4.0.0": + version: 4.0.1 + resolution: "aggregate-error@npm:4.0.1" + dependencies: + clean-stack: "npm:^4.0.0" + indent-string: "npm:^5.0.0" + checksum: 10c0/75fd739f5c4c60a667cce35ccaf0edf135e147ef0be9a029cab75de14ac9421779b15339d562e58d25b233ea0ef2bbd4c916f149fdbcb73c2b9a62209e611343 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.1.0 + resolution: "ansi-regex@npm:6.1.0" + checksum: 10c0/a91daeddd54746338478eef88af3439a7edf30f8e23196e2d6ed182da9add559c601266dbef01c2efa46a958ad6f1f8b176799657616c702b5b02e799e7fd8dc + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: "npm:^2.0.1" + checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c + languageName: node + linkType: hard + +"anymatch@npm:~3.1.2": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" + dependencies: + normalize-path: "npm:^3.0.0" + picomatch: "npm:^2.0.4" + checksum: 10c0/57b06ae984bc32a0d22592c87384cd88fe4511b1dd7581497831c56d41939c8a001b28e7b853e1450f2bf61992dfcaa8ae2d0d161a0a90c4fb631ef07098fbac + languageName: node + linkType: hard + +"argparse@npm:^1.0.7": + version: 1.0.10 + resolution: "argparse@npm:1.0.10" + dependencies: + sprintf-js: "npm:~1.0.2" + checksum: 10c0/b2972c5c23c63df66bca144dbc65d180efa74f25f8fd9b7d9a0a6c88ae839db32df3d54770dcb6460cf840d232b60695d1a6b1053f599d84e73f7437087712de + languageName: node + linkType: hard + +"array-find-index@npm:^1.0.1": + version: 1.0.2 + resolution: "array-find-index@npm:1.0.2" + checksum: 10c0/86b9485c74ddd324feab807e10a6de3f9c1683856267236fac4bb4d4667ada6463e106db3f6c540ae6b720e0442b590ec701d13676df4c6af30ebf4da09b4f57 + languageName: node + linkType: hard + +"arrgv@npm:^1.0.2": + version: 1.0.2 + resolution: "arrgv@npm:1.0.2" + checksum: 10c0/7e6e782e6b749923ac7cbc4048ef6fe0844c4a59bfc8932fcd4c44566ba25eed46501f94dd7cf3c7297da88f3f599ca056bfb77d0c2484aebc92f04239f69124 + languageName: node + linkType: hard + +"arrify@npm:^3.0.0": + version: 3.0.0 + resolution: "arrify@npm:3.0.0" + checksum: 10c0/2e26601b8486f29780f1f70f7ac05a226755814c2a3ab42e196748f650af1dc310cd575a11dd4b9841c70fd7460b2dd2b8fe6fb7a3375878e2660706efafa58e + languageName: node + linkType: hard + +"ava@npm:^5.3.1": + version: 5.3.1 + resolution: "ava@npm:5.3.1" + dependencies: + acorn: "npm:^8.8.2" + acorn-walk: "npm:^8.2.0" + ansi-styles: "npm:^6.2.1" + arrgv: "npm:^1.0.2" + arrify: "npm:^3.0.0" + callsites: "npm:^4.0.0" + cbor: "npm:^8.1.0" + chalk: "npm:^5.2.0" + chokidar: "npm:^3.5.3" + chunkd: "npm:^2.0.1" + ci-info: "npm:^3.8.0" + ci-parallel-vars: "npm:^1.0.1" + clean-yaml-object: "npm:^0.1.0" + cli-truncate: "npm:^3.1.0" + code-excerpt: "npm:^4.0.0" + common-path-prefix: "npm:^3.0.0" + concordance: "npm:^5.0.4" + currently-unhandled: "npm:^0.4.1" + debug: "npm:^4.3.4" + emittery: "npm:^1.0.1" + figures: "npm:^5.0.0" + globby: "npm:^13.1.4" + ignore-by-default: "npm:^2.1.0" + indent-string: "npm:^5.0.0" + is-error: "npm:^2.2.2" + is-plain-object: "npm:^5.0.0" + is-promise: "npm:^4.0.0" + matcher: "npm:^5.0.0" + mem: "npm:^9.0.2" + ms: "npm:^2.1.3" + p-event: "npm:^5.0.1" + p-map: "npm:^5.5.0" + picomatch: "npm:^2.3.1" + pkg-conf: "npm:^4.0.0" + plur: "npm:^5.1.0" + pretty-ms: "npm:^8.0.0" + resolve-cwd: "npm:^3.0.0" + stack-utils: "npm:^2.0.6" + strip-ansi: "npm:^7.0.1" + supertap: "npm:^3.0.1" + temp-dir: "npm:^3.0.0" + write-file-atomic: "npm:^5.0.1" + yargs: "npm:^17.7.2" + peerDependencies: + "@ava/typescript": "*" + peerDependenciesMeta: + "@ava/typescript": + optional: true + bin: + ava: entrypoints/cli.mjs + checksum: 10c0/262cbdb9e8c3ce7177be91b92ba521e9d5aef577dcc8095cc591f86baaa291b91c88925928f5d26832c4d1b381a6ae99f2e8804077c592d0d32322c1212605cc + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee + languageName: node + linkType: hard + +"base64-js@npm:^1.3.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf + languageName: node + linkType: hard + +"better-sqlite3@npm:^9.6.0": + version: 9.6.0 + resolution: "better-sqlite3@npm:9.6.0" + dependencies: + bindings: "npm:^1.5.0" + node-gyp: "npm:latest" + prebuild-install: "npm:^7.1.1" + checksum: 10c0/8db9b38f414e26a56d4c40fc16e94a253118491dae0e2c054338a9e470f1a883c7eb4cb330f2f5737db30f704d4f2e697c59071ca04e03364ee9fe04375aa9c8 + languageName: node + linkType: hard + +"binary-extensions@npm:^2.0.0": + version: 2.3.0 + resolution: "binary-extensions@npm:2.3.0" + checksum: 10c0/75a59cafc10fb12a11d510e77110c6c7ae3f4ca22463d52487709ca7f18f69d886aa387557cc9864fbdb10153d0bdb4caacabf11541f55e89ed6e18d12ece2b5 + languageName: node + linkType: hard + +"bindings@npm:^1.5.0": + version: 1.5.0 + resolution: "bindings@npm:1.5.0" + dependencies: + file-uri-to-path: "npm:1.0.0" + checksum: 10c0/3dab2491b4bb24124252a91e656803eac24292473e56554e35bbfe3cc1875332cfa77600c3bac7564049dc95075bf6fcc63a4609920ff2d64d0fe405fcf0d4ba + languageName: node + linkType: hard + +"bl@npm:^4.0.3": + version: 4.1.0 + resolution: "bl@npm:4.1.0" + dependencies: + buffer: "npm:^5.5.0" + inherits: "npm:^2.0.4" + readable-stream: "npm:^3.4.0" + checksum: 10c0/02847e1d2cb089c9dc6958add42e3cdeaf07d13f575973963335ac0fdece563a50ac770ac4c8fa06492d2dd276f6cc3b7f08c7cd9c7a7ad0f8d388b2a28def5f + languageName: node + linkType: hard + +"blueimp-md5@npm:^2.10.0": + version: 2.19.0 + resolution: "blueimp-md5@npm:2.19.0" + checksum: 10c0/85d04343537dd99a288c62450341dcce7380d3454c81f8e5a971ddd80307d6f9ef51b5b92ad7d48aaaa92fd6d3a1f6b2f4fada068faae646887f7bfabc17a346 + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: "npm:^1.0.0" + checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f + languageName: node + linkType: hard + +"braces@npm:^3.0.3, braces@npm:~3.0.2": + version: 3.0.3 + resolution: "braces@npm:3.0.3" + dependencies: + fill-range: "npm:^7.1.1" + checksum: 10c0/7c6dfd30c338d2997ba77500539227b9d1f85e388a5f43220865201e407e076783d0881f2d297b9f80951b4c957fcf0b51c1d2d24227631643c3f7c284b0aa04 + languageName: node + linkType: hard + +"buffer@npm:^5.5.0": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.1.13" + checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.4 + resolution: "cacache@npm:18.0.4" + dependencies: + "@npmcli/fs": "npm:^3.1.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^4.0.0" + ssri: "npm:^10.0.0" + tar: "npm:^6.1.11" + unique-filename: "npm:^3.0.0" + checksum: 10c0/6c055bafed9de4f3dcc64ac3dc7dd24e863210902b7c470eb9ce55a806309b3efff78033e3d8b4f7dcc5d467f2db43c6a2857aaaf26f0094b8a351d44c42179f + languageName: node + linkType: hard + +"callsites@npm:^4.0.0": + version: 4.2.0 + resolution: "callsites@npm:4.2.0" + checksum: 10c0/8f7e269ec09fc0946bb22d838a8bc7932e1909ab4a833b964749f4d0e8bdeaa1f253287c4f911f61781f09620b6925ccd19a5ea4897489c4e59442c660c312a3 + languageName: node + linkType: hard + +"cbor@npm:^8.1.0": + version: 8.1.0 + resolution: "cbor@npm:8.1.0" + dependencies: + nofilter: "npm:^3.1.0" + checksum: 10c0/a836e2e7ea0efb1b9c4e5a4be906c57113d730cc42293a34072e0164ed110bb8ac035dc7dca2e3ebb641bd4b37e00fdbbf09c951aa864b3d4888a6ed8c6243f7 + languageName: node + linkType: hard + +"chalk@npm:^5.2.0, chalk@npm:^5.3.0": + version: 5.3.0 + resolution: "chalk@npm:5.3.0" + checksum: 10c0/8297d436b2c0f95801103ff2ef67268d362021b8210daf8ddbe349695333eb3610a71122172ff3b0272f1ef2cf7cc2c41fdaa4715f52e49ffe04c56340feed09 + languageName: node + linkType: hard + +"chokidar@npm:^3.5.3": + version: 3.6.0 + resolution: "chokidar@npm:3.6.0" + dependencies: + anymatch: "npm:~3.1.2" + braces: "npm:~3.0.2" + fsevents: "npm:~2.3.2" + glob-parent: "npm:~5.1.2" + is-binary-path: "npm:~2.1.0" + is-glob: "npm:~4.0.1" + normalize-path: "npm:~3.0.0" + readdirp: "npm:~3.6.0" + dependenciesMeta: + fsevents: + optional: true + checksum: 10c0/8361dcd013f2ddbe260eacb1f3cb2f2c6f2b0ad118708a343a5ed8158941a39cb8fb1d272e0f389712e74ee90ce8ba864eece9e0e62b9705cb468a2f6d917462 + languageName: node + linkType: hard + +"chownr@npm:^1.1.1": + version: 1.1.4 + resolution: "chownr@npm:1.1.4" + checksum: 10c0/ed57952a84cc0c802af900cf7136de643d3aba2eecb59d29344bc2f3f9bf703a301b9d84cdc71f82c3ffc9ccde831b0d92f5b45f91727d6c9da62f23aef9d9db + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6 + languageName: node + linkType: hard + +"chunkd@npm:^2.0.1": + version: 2.0.1 + resolution: "chunkd@npm:2.0.1" + checksum: 10c0/4e0c5aac6048ecedfa4cd0a5f6c4f010c70a7b7645aeca7bfeb47cb0733c3463054f0ced3f2667b2e0e67edd75d68a8e05481b01115ba3f8a952a93026254504 + languageName: node + linkType: hard + +"ci-info@npm:^3.8.0": + version: 3.9.0 + resolution: "ci-info@npm:3.9.0" + checksum: 10c0/6f0109e36e111684291d46123d491bc4e7b7a1934c3a20dea28cba89f1d4a03acd892f5f6a81ed3855c38647e285a150e3c9ba062e38943bef57fee6c1554c3a + languageName: node + linkType: hard + +"ci-parallel-vars@npm:^1.0.1": + version: 1.0.1 + resolution: "ci-parallel-vars@npm:1.0.1" + checksum: 10c0/80952f699cbbc146092b077b4f3e28d085620eb4e6be37f069b4dbb3db0ee70e8eec3beef4ebe70ff60631e9fc743b9d0869678489f167442cac08b260e5ac08 + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 + languageName: node + linkType: hard + +"clean-stack@npm:^4.0.0": + version: 4.2.0 + resolution: "clean-stack@npm:4.2.0" + dependencies: + escape-string-regexp: "npm:5.0.0" + checksum: 10c0/2bdf981a0fef0a23c14255df693b30eb9ae27eedf212470d8c400a0c0b6fb82fbf1ff8c5216ccd5721e3670b700389c886b1dce5070776dc9fbcc040957758c0 + languageName: node + linkType: hard + +"clean-yaml-object@npm:^0.1.0": + version: 0.1.0 + resolution: "clean-yaml-object@npm:0.1.0" + checksum: 10c0/a6505310590038afb9f0adc7f17a4c66787719c94d23f8491267ea4d9c405cdd378bd576ae1926169b6d997d4c59a8b86516bf4d16ba228280cf615598c58e05 + languageName: node + linkType: hard + +"cli-truncate@npm:^3.1.0": + version: 3.1.0 + resolution: "cli-truncate@npm:3.1.0" + dependencies: + slice-ansi: "npm:^5.0.0" + string-width: "npm:^5.0.0" + checksum: 10c0/a19088878409ec0e5dc2659a5166929629d93cfba6d68afc9cde2282fd4c751af5b555bf197047e31c87c574396348d011b7aa806fec29c4139ea4f7f00b324c + languageName: node + linkType: hard + +"cliui@npm:^8.0.1": + version: 8.0.1 + resolution: "cliui@npm:8.0.1" + dependencies: + string-width: "npm:^4.2.0" + strip-ansi: "npm:^6.0.1" + wrap-ansi: "npm:^7.0.0" + checksum: 10c0/4bda0f09c340cbb6dfdc1ed508b3ca080f12992c18d68c6be4d9cf51756033d5266e61ec57529e610dacbf4da1c634423b0c1b11037709cc6b09045cbd815df5 + languageName: node + linkType: hard + +"code-excerpt@npm:^4.0.0": + version: 4.0.0 + resolution: "code-excerpt@npm:4.0.0" + dependencies: + convert-to-spaces: "npm:^2.0.1" + checksum: 10c0/b6c5a06e039cecd2ab6a0e10ee0831de8362107d1f298ca3558b5f9004cb8e0260b02dd6c07f57b9a0e346c76864d2873311ee1989809fdeb05bd5fbbadde773 + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: "npm:~1.1.4" + checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 + languageName: node + linkType: hard + +"common-path-prefix@npm:^3.0.0": + version: 3.0.0 + resolution: "common-path-prefix@npm:3.0.0" + checksum: 10c0/c4a74294e1b1570f4a8ab435285d185a03976c323caa16359053e749db4fde44e3e6586c29cd051100335e11895767cbbd27ea389108e327d62f38daf4548fdb + languageName: node + linkType: hard + +"concordance@npm:^5.0.4": + version: 5.0.4 + resolution: "concordance@npm:5.0.4" + dependencies: + date-time: "npm:^3.1.0" + esutils: "npm:^2.0.3" + fast-diff: "npm:^1.2.0" + js-string-escape: "npm:^1.0.1" + lodash: "npm:^4.17.15" + md5-hex: "npm:^3.0.1" + semver: "npm:^7.3.2" + well-known-symbols: "npm:^2.0.0" + checksum: 10c0/59b440f330df3a7c9aa148ba588b3e99aed86acab225b4f01ffcea34ace4cf11f817e31153254e8f38ed48508998dad40b9106951a743c334d751f7ab21afb8a + languageName: node + linkType: hard + +"convert-to-spaces@npm:^2.0.1": + version: 2.0.1 + resolution: "convert-to-spaces@npm:2.0.1" + checksum: 10c0/d90aa0e3b6a27f9d5265a8d32def3c5c855b3e823a9db1f26d772f8146d6b91020a2fdfd905ce8048a73fad3aaf836fef8188c67602c374405e2ae8396c4ac46 + languageName: node + linkType: hard + +"cosmjs-types@npm:^0.9.0": + version: 0.9.0 + resolution: "cosmjs-types@npm:0.9.0" + checksum: 10c0/bc20f4293fb34629d7c5f96bafe533987f753df957ff68eb078d0128ae5a418320cb945024441769a07bb9bc5dde9d22b972fd40d485933e5706ea191c43727b + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.3": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 + languageName: node + linkType: hard + +"currently-unhandled@npm:^0.4.1": + version: 0.4.1 + resolution: "currently-unhandled@npm:0.4.1" + dependencies: + array-find-index: "npm:^1.0.1" + checksum: 10c0/32d197689ec32f035910202c1abb0dc6424dce01d7b51779c685119b380d98535c110ffff67a262fc7e367612a7dfd30d3d3055f9a6634b5a9dd1302de7ef11c + languageName: node + linkType: hard + +"date-time@npm:^3.1.0": + version: 3.1.0 + resolution: "date-time@npm:3.1.0" + dependencies: + time-zone: "npm:^1.0.0" + checksum: 10c0/aa3e2e930d74b0b9e90f69de7a16d3376e30f21f1f4ce9a2311d8fec32d760e776efea752dafad0ce188187265235229013036202be053fc2d7979813bfb6ded + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.3.4": + version: 4.3.7 + resolution: "debug@npm:4.3.7" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/1471db19c3b06d485a622d62f65947a19a23fbd0dd73f7fd3eafb697eec5360cde447fb075919987899b1a2096e85d35d4eb5a4de09a57600ac9cf7e6c8e768b + languageName: node + linkType: hard + +"decompress-response@npm:^6.0.0": + version: 6.0.0 + resolution: "decompress-response@npm:6.0.0" + dependencies: + mimic-response: "npm:^3.1.0" + checksum: 10c0/bd89d23141b96d80577e70c54fb226b2f40e74a6817652b80a116d7befb8758261ad073a8895648a29cc0a5947021ab66705cb542fa9c143c82022b27c5b175e + languageName: node + linkType: hard + +"deep-extend@npm:^0.6.0": + version: 0.6.0 + resolution: "deep-extend@npm:0.6.0" + checksum: 10c0/1c6b0abcdb901e13a44c7d699116d3d4279fdb261983122a3783e7273844d5f2537dc2e1c454a23fcf645917f93fbf8d07101c1d03c015a87faa662755212566 + languageName: node + linkType: hard + +"detect-libc@npm:^2.0.0": + version: 2.0.3 + resolution: "detect-libc@npm:2.0.3" + checksum: 10c0/88095bda8f90220c95f162bf92cad70bd0e424913e655c20578600e35b91edc261af27531cf160a331e185c0ced93944bc7e09939143225f56312d7fd800fdb7 + languageName: node + linkType: hard + +"dir-glob@npm:^3.0.1": + version: 3.0.1 + resolution: "dir-glob@npm:3.0.1" + dependencies: + path-type: "npm:^4.0.0" + checksum: 10c0/dcac00920a4d503e38bb64001acb19df4efc14536ada475725e12f52c16777afdee4db827f55f13a908ee7efc0cb282e2e3dbaeeb98c0993dd93d1802d3bf00c + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 + languageName: node + linkType: hard + +"emittery@npm:^1.0.1": + version: 1.0.3 + resolution: "emittery@npm:1.0.3" + checksum: 10c0/91605d044f3891dd1f8ab731aeb94b520488b21e707f7064dcbcf5303bac3b4e7133dfa23c343ede1fc970340bd78a9b1aed522b805bc15104606bba630dd71e + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: "npm:^0.6.2" + checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 + languageName: node + linkType: hard + +"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": + version: 1.4.4 + resolution: "end-of-stream@npm:1.4.4" + dependencies: + once: "npm:^1.4.0" + checksum: 10c0/870b423afb2d54bb8d243c63e07c170409d41e20b47eeef0727547aea5740bd6717aca45597a9f2745525667a6b804c1e7bede41f856818faee5806dd9ff3975 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 + languageName: node + linkType: hard + +"escalade@npm:^3.1.1": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 + languageName: node + linkType: hard + +"escape-string-regexp@npm:5.0.0, escape-string-regexp@npm:^5.0.0": + version: 5.0.0 + resolution: "escape-string-regexp@npm:5.0.0" + checksum: 10c0/6366f474c6f37a802800a435232395e04e9885919873e382b157ab7e8f0feb8fed71497f84a6f6a81a49aab41815522f5839112bd38026d203aea0c91622df95 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^2.0.0": + version: 2.0.0 + resolution: "escape-string-regexp@npm:2.0.0" + checksum: 10c0/2530479fe8db57eace5e8646c9c2a9c80fa279614986d16dcc6bcaceb63ae77f05a851ba6c43756d816c61d7f4534baf56e3c705e3e0d884818a46808811c507 + languageName: node + linkType: hard + +"esprima@npm:^4.0.0": + version: 4.0.1 + resolution: "esprima@npm:4.0.1" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: 10c0/ad4bab9ead0808cf56501750fd9d3fb276f6b105f987707d059005d57e182d18a7c9ec7f3a01794ebddcca676773e42ca48a32d67a250c9d35e009ca613caba3 + languageName: node + linkType: hard + +"esutils@npm:^2.0.3": + version: 2.0.3 + resolution: "esutils@npm:2.0.3" + checksum: 10c0/9a2fe69a41bfdade834ba7c42de4723c97ec776e40656919c62cbd13607c45e127a003f05f724a1ea55e5029a4cf2de444b13009f2af71271e42d93a637137c7 + languageName: node + linkType: hard + +"execa@npm:^9.3.1": + version: 9.4.0 + resolution: "execa@npm:9.4.0" + dependencies: + "@sindresorhus/merge-streams": "npm:^4.0.0" + cross-spawn: "npm:^7.0.3" + figures: "npm:^6.1.0" + get-stream: "npm:^9.0.0" + human-signals: "npm:^8.0.0" + is-plain-obj: "npm:^4.1.0" + is-stream: "npm:^4.0.1" + npm-run-path: "npm:^6.0.0" + pretty-ms: "npm:^9.0.0" + signal-exit: "npm:^4.1.0" + strip-final-newline: "npm:^4.0.0" + yoctocolors: "npm:^2.0.0" + checksum: 10c0/6ad06c627b5d7bb007bc7b6cc35d7e32b5a3365375ffc8ddbcc12d2423651fa9928ba0c447cc9e60079e505e9b24fbe0a57f80371511d7d20302c04c2d3ce95e + languageName: node + linkType: hard + +"expand-template@npm:^2.0.3": + version: 2.0.3 + resolution: "expand-template@npm:2.0.3" + checksum: 10c0/1c9e7afe9acadf9d373301d27f6a47b34e89b3391b1ef38b7471d381812537ef2457e620ae7f819d2642ce9c43b189b3583813ec395e2938319abe356a9b2f51 + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 + languageName: node + linkType: hard + +"fast-diff@npm:^1.2.0": + version: 1.3.0 + resolution: "fast-diff@npm:1.3.0" + checksum: 10c0/5c19af237edb5d5effda008c891a18a585f74bf12953be57923f17a3a4d0979565fc64dbc73b9e20926b9d895f5b690c618cbb969af0cf022e3222471220ad29 + languageName: node + linkType: hard + +"fast-glob@npm:^3.3.0": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" + dependencies: + "@nodelib/fs.stat": "npm:^2.0.2" + "@nodelib/fs.walk": "npm:^1.2.3" + glob-parent: "npm:^5.1.2" + merge2: "npm:^1.3.0" + micromatch: "npm:^4.0.4" + checksum: 10c0/42baad7b9cd40b63e42039132bde27ca2cb3a4950d0a0f9abe4639ea1aa9d3e3b40f98b1fe31cbc0cc17b664c9ea7447d911a152fa34ec5b72977b125a6fc845 + languageName: node + linkType: hard + +"fastq@npm:^1.6.0": + version: 1.17.1 + resolution: "fastq@npm:1.17.1" + dependencies: + reusify: "npm:^1.0.4" + checksum: 10c0/1095f16cea45fb3beff558bb3afa74ca7a9250f5a670b65db7ed585f92b4b48381445cd328b3d87323da81e43232b5d5978a8201bde84e0cd514310f1ea6da34 + languageName: node + linkType: hard + +"figures@npm:^5.0.0": + version: 5.0.0 + resolution: "figures@npm:5.0.0" + dependencies: + escape-string-regexp: "npm:^5.0.0" + is-unicode-supported: "npm:^1.2.0" + checksum: 10c0/ce0f17d4ea8b0fc429c5207c343534a2f5284ecfb22aa08607da7dc84ed9e1cf754f5b97760e8dcb98d3c9d1a1e4d3d578fe3b5b99c426f05d0f06c7ba618e16 + languageName: node + linkType: hard + +"figures@npm:^6.1.0": + version: 6.1.0 + resolution: "figures@npm:6.1.0" + dependencies: + is-unicode-supported: "npm:^2.0.0" + checksum: 10c0/9159df4264d62ef447a3931537de92f5012210cf5135c35c010df50a2169377581378149abfe1eb238bd6acbba1c0d547b1f18e0af6eee49e30363cedaffcfe4 + languageName: node + linkType: hard + +"file-uri-to-path@npm:1.0.0": + version: 1.0.0 + resolution: "file-uri-to-path@npm:1.0.0" + checksum: 10c0/3b545e3a341d322d368e880e1c204ef55f1d45cdea65f7efc6c6ce9e0c4d22d802d5629320eb779d006fe59624ac17b0e848d83cc5af7cd101f206cb704f5519 + languageName: node + linkType: hard + +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" + dependencies: + to-regex-range: "npm:^5.0.1" + checksum: 10c0/b75b691bbe065472f38824f694c2f7449d7f5004aa950426a2c28f0306c60db9b880c0b0e4ed819997ffb882d1da02cfcfc819bddc94d71627f5269682edf018 + languageName: node + linkType: hard + +"find-up@npm:^6.0.0": + version: 6.3.0 + resolution: "find-up@npm:6.3.0" + dependencies: + locate-path: "npm:^7.1.0" + path-exists: "npm:^5.0.0" + checksum: 10c0/07e0314362d316b2b13f7f11ea4692d5191e718ca3f7264110127520f3347996349bf9e16805abae3e196805814bc66ef4bff2b8904dc4a6476085fc9b0eba07 + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.3.0 + resolution: "foreground-child@npm:3.3.0" + dependencies: + cross-spawn: "npm:^7.0.0" + signal-exit: "npm:^4.0.1" + checksum: 10c0/028f1d41000553fcfa6c4bb5c372963bf3d9bf0b1f25a87d1a6253014343fb69dfb1b42d9625d7cf44c8ba429940f3d0ff718b62105d4d4a4f6ef8ca0a53faa2 + languageName: node + linkType: hard + +"fs-constants@npm:^1.0.0": + version: 1.0.0 + resolution: "fs-constants@npm:1.0.0" + checksum: 10c0/a0cde99085f0872f4d244e83e03a46aa387b74f5a5af750896c6b05e9077fac00e9932fdf5aef84f2f16634cd473c63037d7a512576da7d5c2b9163d1909f3a8 + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 + languageName: node + linkType: hard + +"fsevents@npm:~2.3.2": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + +"get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde + languageName: node + linkType: hard + +"get-stream@npm:^9.0.0": + version: 9.0.1 + resolution: "get-stream@npm:9.0.1" + dependencies: + "@sec-ant/readable-stream": "npm:^0.4.1" + is-stream: "npm:^4.0.1" + checksum: 10c0/d70e73857f2eea1826ac570c3a912757dcfbe8a718a033fa0c23e12ac8e7d633195b01710e0559af574cbb5af101009b42df7b6f6b29ceec8dbdf7291931b948 + languageName: node + linkType: hard + +"github-from-package@npm:0.0.0": + version: 0.0.0 + resolution: "github-from-package@npm:0.0.0" + checksum: 10c0/737ee3f52d0a27e26332cde85b533c21fcdc0b09fb716c3f8e522cfaa9c600d4a631dec9fcde179ec9d47cca89017b7848ed4d6ae6b6b78f936c06825b1fcc12 + languageName: node + linkType: hard + +"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": + version: 5.1.2 + resolution: "glob-parent@npm:5.1.2" + dependencies: + is-glob: "npm:^4.0.1" + checksum: 10c0/cab87638e2112bee3f839ef5f6e0765057163d39c66be8ec1602f3823da4692297ad4e972de876ea17c44d652978638d2fd583c6713d0eb6591706825020c9ee + languageName: node + linkType: hard + +"glob@npm:^10.2.2, glob@npm:^10.3.10": + version: 10.4.5 + resolution: "glob@npm:10.4.5" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e + languageName: node + linkType: hard + +"globby@npm:^13.1.4": + version: 13.2.2 + resolution: "globby@npm:13.2.2" + dependencies: + dir-glob: "npm:^3.0.1" + fast-glob: "npm:^3.3.0" + ignore: "npm:^5.2.4" + merge2: "npm:^1.4.1" + slash: "npm:^4.0.0" + checksum: 10c0/a8d7cc7cbe5e1b2d0f81d467bbc5bc2eac35f74eaded3a6c85fc26d7acc8e6de22d396159db8a2fc340b8a342e74cac58de8f4aee74146d3d146921a76062664 + languageName: node + linkType: hard + +"graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.5 + resolution: "https-proxy-agent@npm:7.0.5" + dependencies: + agent-base: "npm:^7.0.2" + debug: "npm:4" + checksum: 10c0/2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c + languageName: node + linkType: hard + +"human-signals@npm:^8.0.0": + version: 8.0.0 + resolution: "human-signals@npm:8.0.0" + checksum: 10c0/e4dac4f7d3eb791ed04129fc6a85bd454a9102d3e3b76c911d0db7057ebd60b2956b435b5b5712aec18960488ede3c21ef7c56e42cdd70760c0d84d3c05cd92e + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 + languageName: node + linkType: hard + +"ieee754@npm:^1.1.13": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb + languageName: node + linkType: hard + +"ignore-by-default@npm:^2.1.0": + version: 2.1.0 + resolution: "ignore-by-default@npm:2.1.0" + checksum: 10c0/3a6040dac25ed9da39dee73bf1634fdd1e15b0eb7cf52a6bdec81c310565782d8811c104ce40acb3d690d61c5fc38a91c78e6baee830a8a2232424dbc6b66981 + languageName: node + linkType: hard + +"ignore@npm:^5.2.4": + version: 5.3.2 + resolution: "ignore@npm:5.3.2" + checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f + languageName: node + linkType: hard + +"indent-string@npm:^5.0.0": + version: 5.0.0 + resolution: "indent-string@npm:5.0.0" + checksum: 10c0/8ee77b57d92e71745e133f6f444d6fa3ed503ad0e1bcd7e80c8da08b42375c07117128d670589725ed07b1978065803fa86318c309ba45415b7fe13e7f170220 + languageName: node + linkType: hard + +"inherits@npm:^2.0.3, inherits@npm:^2.0.4": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 + languageName: node + linkType: hard + +"ini@npm:~1.3.0": + version: 1.3.8 + resolution: "ini@npm:1.3.8" + checksum: 10c0/ec93838d2328b619532e4f1ff05df7909760b6f66d9c9e2ded11e5c1897d6f2f9980c54dd638f88654b00919ce31e827040631eab0a3969e4d1abefa0719516a + languageName: node + linkType: hard + +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: "npm:1.1.0" + sprintf-js: "npm:^1.1.3" + checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc + languageName: node + linkType: hard + +"irregular-plurals@npm:^3.3.0": + version: 3.5.0 + resolution: "irregular-plurals@npm:3.5.0" + checksum: 10c0/7c033bbe7325e5a6e0a26949cc6863b6ce273403d4cd5b93bd99b33fecb6605b0884097c4259c23ed0c52c2133bf7d1cdcdd7a0630e8c325161fe269b3447918 + languageName: node + linkType: hard + +"is-binary-path@npm:~2.1.0": + version: 2.1.0 + resolution: "is-binary-path@npm:2.1.0" + dependencies: + binary-extensions: "npm:^2.0.0" + checksum: 10c0/a16eaee59ae2b315ba36fad5c5dcaf8e49c3e27318f8ab8fa3cdb8772bf559c8d1ba750a589c2ccb096113bb64497084361a25960899cb6172a6925ab6123d38 + languageName: node + linkType: hard + +"is-error@npm:^2.2.2": + version: 2.2.2 + resolution: "is-error@npm:2.2.2" + checksum: 10c0/475d3463968bf16e94485555d7cb7a879ed68685e08d365a3370972e626054f1846ebbb3934403091e06682445568601fe919e41646096e5007952d0c1f4fd9b + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: 10c0/5487da35691fbc339700bbb2730430b07777a3c21b9ebaecb3072512dfd7b4ba78ac2381a87e8d78d20ea08affb3f1971b4af629173a6bf435ff8a4c47747912 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^4.0.0": + version: 4.0.0 + resolution: "is-fullwidth-code-point@npm:4.0.0" + checksum: 10c0/df2a717e813567db0f659c306d61f2f804d480752526886954a2a3e2246c7745fd07a52b5fecf2b68caf0a6c79dcdace6166fdf29cc76ed9975cc334f0a018b8 + languageName: node + linkType: hard + +"is-glob@npm:^4.0.1, is-glob@npm:~4.0.1": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: "npm:^2.1.1" + checksum: 10c0/17fb4014e22be3bbecea9b2e3a76e9e34ff645466be702f1693e8f1ee1adac84710d0be0bd9f967d6354036fd51ab7c2741d954d6e91dae6bb69714de92c197a + languageName: node + linkType: hard + +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d + languageName: node + linkType: hard + +"is-number@npm:^7.0.0": + version: 7.0.0 + resolution: "is-number@npm:7.0.0" + checksum: 10c0/b4686d0d3053146095ccd45346461bc8e53b80aeb7671cc52a4de02dbbf7dc0d1d2a986e2fe4ae206984b4d34ef37e8b795ebc4f4295c978373e6575e295d811 + languageName: node + linkType: hard + +"is-plain-obj@npm:^4.1.0": + version: 4.1.0 + resolution: "is-plain-obj@npm:4.1.0" + checksum: 10c0/32130d651d71d9564dc88ba7e6fda0e91a1010a3694648e9f4f47bb6080438140696d3e3e15c741411d712e47ac9edc1a8a9de1fe76f3487b0d90be06ac9975e + languageName: node + linkType: hard + +"is-plain-object@npm:^5.0.0": + version: 5.0.0 + resolution: "is-plain-object@npm:5.0.0" + checksum: 10c0/893e42bad832aae3511c71fd61c0bf61aa3a6d853061c62a307261842727d0d25f761ce9379f7ba7226d6179db2a3157efa918e7fe26360f3bf0842d9f28942c + languageName: node + linkType: hard + +"is-promise@npm:^4.0.0": + version: 4.0.0 + resolution: "is-promise@npm:4.0.0" + checksum: 10c0/ebd5c672d73db781ab33ccb155fb9969d6028e37414d609b115cc534654c91ccd061821d5b987eefaa97cf4c62f0b909bb2f04db88306de26e91bfe8ddc01503 + languageName: node + linkType: hard + +"is-stream@npm:^4.0.1": + version: 4.0.1 + resolution: "is-stream@npm:4.0.1" + checksum: 10c0/2706c7f19b851327ba374687bc4a3940805e14ca496dc672b9629e744d143b1ad9c6f1b162dece81c7bfbc0f83b32b61ccc19ad2e05aad2dd7af347408f60c7f + languageName: node + linkType: hard + +"is-unicode-supported@npm:^1.2.0": + version: 1.3.0 + resolution: "is-unicode-supported@npm:1.3.0" + checksum: 10c0/b8674ea95d869f6faabddc6a484767207058b91aea0250803cbf1221345cb0c56f466d4ecea375dc77f6633d248d33c47bd296fb8f4cdba0b4edba8917e83d8a + languageName: node + linkType: hard + +"is-unicode-supported@npm:^2.0.0": + version: 2.1.0 + resolution: "is-unicode-supported@npm:2.1.0" + checksum: 10c0/a0f53e9a7c1fdbcf2d2ef6e40d4736fdffff1c9f8944c75e15425118ff3610172c87bf7bc6c34d3903b04be59790bb2212ddbe21ee65b5a97030fc50370545a5 + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 + languageName: node + linkType: hard + +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 + languageName: node + linkType: hard + +"js-string-escape@npm:^1.0.1": + version: 1.0.1 + resolution: "js-string-escape@npm:1.0.1" + checksum: 10c0/2c33b9ff1ba6b84681c51ca0997e7d5a1639813c95d5b61cb7ad47e55cc28fa4a0b1935c3d218710d8e6bcee5d0cd8c44755231e3a4e45fc604534d9595a3628 + languageName: node + linkType: hard + +"js-yaml@npm:^3.14.1": + version: 3.14.1 + resolution: "js-yaml@npm:3.14.1" + dependencies: + argparse: "npm:^1.0.7" + esprima: "npm:^4.0.0" + bin: + js-yaml: bin/js-yaml.js + checksum: 10c0/6746baaaeac312c4db8e75fa22331d9a04cccb7792d126ed8ce6a0bbcfef0cedaddd0c5098fade53db067c09fe00aa1c957674b4765610a8b06a5a189e46433b + languageName: node + linkType: hard + +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 + languageName: node + linkType: hard + +"load-json-file@npm:^7.0.0": + version: 7.0.1 + resolution: "load-json-file@npm:7.0.1" + checksum: 10c0/7117459608a0b6329c7f78e6e1f541b3162dd901c29dd5af721fec8b270177d2e3d7999c971f344fff04daac368d052732e2c7146014bc84d15e0b636975e19a + languageName: node + linkType: hard + +"locate-path@npm:^7.1.0": + version: 7.2.0 + resolution: "locate-path@npm:7.2.0" + dependencies: + p-locate: "npm:^6.0.0" + checksum: 10c0/139e8a7fe11cfbd7f20db03923cacfa5db9e14fa14887ea121345597472b4a63c1a42a8a5187defeeff6acf98fd568da7382aa39682d38f0af27433953a97751 + languageName: node + linkType: hard + +"lodash@npm:^4.17.15": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb + languageName: node + linkType: hard + +"make-fetch-happen@npm:^13.0.0": + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" + dependencies: + "@npmcli/agent": "npm:^2.0.0" + cacache: "npm:^18.0.0" + http-cache-semantics: "npm:^4.1.1" + is-lambda: "npm:^1.0.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^3.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^0.6.3" + proc-log: "npm:^4.2.0" + promise-retry: "npm:^2.0.1" + ssri: "npm:^10.0.0" + checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e + languageName: node + linkType: hard + +"map-age-cleaner@npm:^0.1.3": + version: 0.1.3 + resolution: "map-age-cleaner@npm:0.1.3" + dependencies: + p-defer: "npm:^1.0.0" + checksum: 10c0/7495236c7b0950956c144fd8b4bc6399d4e78072a8840a4232fe1c4faccbb5eb5d842e5c0a56a60afc36d723f315c1c672325ca03c1b328650f7fcc478f385fd + languageName: node + linkType: hard + +"matcher@npm:^5.0.0": + version: 5.0.0 + resolution: "matcher@npm:5.0.0" + dependencies: + escape-string-regexp: "npm:^5.0.0" + checksum: 10c0/eda5471fc9d5b7264d63c81727824adc3585ddb5cfdc5fce5a9b7c86f946ff181610735d330b1c37a84811df872d1290bf4e9401d2be2a414204343701144b18 + languageName: node + linkType: hard + +"md5-hex@npm:^3.0.1": + version: 3.0.1 + resolution: "md5-hex@npm:3.0.1" + dependencies: + blueimp-md5: "npm:^2.10.0" + checksum: 10c0/ee2b4d8da16b527b3a3fe4d7a96720f43afd07b46a82d49421208b5a126235fb75cfb30b80d4029514772c8844273f940bddfbf4155c787f968f3be4060d01e4 + languageName: node + linkType: hard + +"mem@npm:^9.0.2": + version: 9.0.2 + resolution: "mem@npm:9.0.2" + dependencies: + map-age-cleaner: "npm:^0.1.3" + mimic-fn: "npm:^4.0.0" + checksum: 10c0/c2c56141399e520d8f0e50186bb7e4b49300b33984dc919682f3f13e53dec0e6608fbd327d5ae99494f45061a3a05a8ee04ccba6dcf795c3c215b5aa906eb41f + languageName: node + linkType: hard + +"merge2@npm:^1.3.0, merge2@npm:^1.4.1": + version: 1.4.1 + resolution: "merge2@npm:1.4.1" + checksum: 10c0/254a8a4605b58f450308fc474c82ac9a094848081bf4c06778200207820e5193726dc563a0d2c16468810516a5c97d9d3ea0ca6585d23c58ccfff2403e8dbbeb + languageName: node + linkType: hard + +"micromatch@npm:^4.0.4": + version: 4.0.8 + resolution: "micromatch@npm:4.0.8" + dependencies: + braces: "npm:^3.0.3" + picomatch: "npm:^2.3.1" + checksum: 10c0/166fa6eb926b9553f32ef81f5f531d27b4ce7da60e5baf8c021d043b27a388fb95e46a8038d5045877881e673f8134122b59624d5cecbd16eb50a42e7a6b5ca8 + languageName: node + linkType: hard + +"mimic-fn@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-fn@npm:4.0.0" + checksum: 10c0/de9cc32be9996fd941e512248338e43407f63f6d497abe8441fa33447d922e927de54d4cc3c1a3c6d652857acd770389d5a3823f311a744132760ce2be15ccbf + languageName: node + linkType: hard + +"mimic-response@npm:^3.1.0": + version: 3.1.0 + resolution: "mimic-response@npm:3.1.0" + checksum: 10c0/0d6f07ce6e03e9e4445bee655202153bdb8a98d67ee8dc965ac140900d7a2688343e6b4c9a72cfc9ef2f7944dfd76eef4ab2482eb7b293a68b84916bac735362 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.4": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed + languageName: node + linkType: hard + +"minimist@npm:^1.2.0, minimist@npm:^1.2.3": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e + languageName: node + linkType: hard + +"minipass-fetch@npm:^3.0.0": + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^2.1.2" + dependenciesMeta: + encoding: + optional: true + checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c + languageName: node + linkType: hard + +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: "npm:^3.0.0" + yallist: "npm:^4.0.0" + checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78 + languageName: node + linkType: hard + +"mkdirp-classic@npm:^0.5.2, mkdirp-classic@npm:^0.5.3": + version: 0.5.3 + resolution: "mkdirp-classic@npm:0.5.3" + checksum: 10c0/95371d831d196960ddc3833cc6907e6b8f67ac5501a6582f47dfae5eb0f092e9f8ce88e0d83afcae95d6e2b61a01741ba03714eeafb6f7a6e9dcc158ac85b168 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf + languageName: node + linkType: hard + +"ms@npm:^2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 + languageName: node + linkType: hard + +"napi-build-utils@npm:^1.0.1": + version: 1.0.2 + resolution: "napi-build-utils@npm:1.0.2" + checksum: 10c0/37fd2cd0ff2ad20073ce78d83fd718a740d568b225924e753ae51cb69d68f330c80544d487e5e5bd18e28702ed2ca469c2424ad948becd1862c1b0209542b2e9 + languageName: node + linkType: hard + +"negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 + languageName: node + linkType: hard + +"node-abi@npm:^3.3.0": + version: 3.67.0 + resolution: "node-abi@npm:3.67.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/72ce2edbdfb84745bc201a4e48aa7146fd88a0d2c80046b6b17f28439c9a7683eab846f40f1e819349c31f7d9331ed5c50d1e741208d938dd5f38b29cab2275e + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.2.0 + resolution: "node-gyp@npm:10.2.0" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^13.0.0" + nopt: "npm:^7.0.0" + proc-log: "npm:^4.1.0" + semver: "npm:^7.3.5" + tar: "npm:^6.2.1" + which: "npm:^4.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10c0/00630d67dbd09a45aee0a5d55c05e3916ca9e6d427ee4f7bc392d2d3dc5fad7449b21fc098dd38260a53d9dcc9c879b36704a1994235d4707e7271af7e9a835b + languageName: node + linkType: hard + +"nofilter@npm:^3.1.0": + version: 3.1.0 + resolution: "nofilter@npm:3.1.0" + checksum: 10c0/92459f3864a067b347032263f0b536223cbfc98153913b5dce350cb39c8470bc1813366e41993f22c33cc6400c0f392aa324a4b51e24c22040635c1cdb046499 + languageName: node + linkType: hard + +"nopt@npm:^7.0.0": + version: 7.2.1 + resolution: "nopt@npm:7.2.1" + dependencies: + abbrev: "npm:^2.0.0" + bin: + nopt: bin/nopt.js + checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: 10c0/e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046 + languageName: node + linkType: hard + +"npm-run-path@npm:^6.0.0": + version: 6.0.0 + resolution: "npm-run-path@npm:6.0.0" + dependencies: + path-key: "npm:^4.0.0" + unicorn-magic: "npm:^0.3.0" + checksum: 10c0/b223c8a0dcd608abf95363ea5c3c0ccc3cd877daf0102eaf1b0f2390d6858d8337fbb7c443af2403b067a7d2c116d10691ecd22ab3c5273c44da1ff8d07753bd + languageName: node + linkType: hard + +"once@npm:^1.3.1, once@npm:^1.4.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: "npm:1" + checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 + languageName: node + linkType: hard + +"p-defer@npm:^1.0.0": + version: 1.0.0 + resolution: "p-defer@npm:1.0.0" + checksum: 10c0/ed603c3790e74b061ac2cb07eb6e65802cf58dce0fbee646c113a7b71edb711101329ad38f99e462bd2e343a74f6e9366b496a35f1d766c187084d3109900487 + languageName: node + linkType: hard + +"p-event@npm:^5.0.1": + version: 5.0.1 + resolution: "p-event@npm:5.0.1" + dependencies: + p-timeout: "npm:^5.0.2" + checksum: 10c0/2317171489537f316661fa863f3bb711b2ceb89182937238422cec10223cbb958c432d6c26a238446a622d788187bdd295b1d8ecedbe2e467e045930d60202b0 + languageName: node + linkType: hard + +"p-limit@npm:^4.0.0": + version: 4.0.0 + resolution: "p-limit@npm:4.0.0" + dependencies: + yocto-queue: "npm:^1.0.0" + checksum: 10c0/a56af34a77f8df2ff61ddfb29431044557fcbcb7642d5a3233143ebba805fc7306ac1d448de724352861cb99de934bc9ab74f0d16fe6a5460bdbdf938de875ad + languageName: node + linkType: hard + +"p-locate@npm:^6.0.0": + version: 6.0.0 + resolution: "p-locate@npm:6.0.0" + dependencies: + p-limit: "npm:^4.0.0" + checksum: 10c0/d72fa2f41adce59c198270aa4d3c832536c87a1806e0f69dffb7c1a7ca998fb053915ca833d90f166a8c082d3859eabfed95f01698a3214c20df6bb8de046312 + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: "npm:^3.0.0" + checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 + languageName: node + linkType: hard + +"p-map@npm:^5.5.0": + version: 5.5.0 + resolution: "p-map@npm:5.5.0" + dependencies: + aggregate-error: "npm:^4.0.0" + checksum: 10c0/410bce846b1e3db6bb2ccab6248372ecf4e635fc2b31331c8f56478e73fec9e146e8b4547585e635703160a3d252a6a65b8f855834aebc2c3408eb5789630cc4 + languageName: node + linkType: hard + +"p-timeout@npm:^5.0.2": + version: 5.1.0 + resolution: "p-timeout@npm:5.1.0" + checksum: 10c0/1b026cf9d5878c64bec4341ca9cda8ec6b8b3aea8a57885ca0fe2b35753a20d767fb6f9d3aa41e1252f42bc95432c05ea33b6b18f271fb10bfb0789591850a41 + languageName: node + linkType: hard + +"package-json-from-dist@npm:^1.0.0": + version: 1.0.0 + resolution: "package-json-from-dist@npm:1.0.0" + checksum: 10c0/e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033 + languageName: node + linkType: hard + +"parse-ms@npm:^3.0.0": + version: 3.0.0 + resolution: "parse-ms@npm:3.0.0" + checksum: 10c0/056b4a32a9d3749f3f4cfffefb45c45540491deaa8e1d8ad43c2ddde7ba04edd076bd1b298f521238bb5fb084a9b2c4a2ebb78aefa651afbc4c2b0af4232fc54 + languageName: node + linkType: hard + +"parse-ms@npm:^4.0.0": + version: 4.0.0 + resolution: "parse-ms@npm:4.0.0" + checksum: 10c0/a7900f4f1ebac24cbf5e9708c16fb2fd482517fad353aecd7aefb8c2ba2f85ce017913ccb8925d231770404780df46244ea6fec598b3bde6490882358b4d2d16 + languageName: node + linkType: hard + +"path-exists@npm:^5.0.0": + version: 5.0.0 + resolution: "path-exists@npm:5.0.0" + checksum: 10c0/b170f3060b31604cde93eefdb7392b89d832dfbc1bed717c9718cbe0f230c1669b7e75f87e19901da2250b84d092989a0f9e44d2ef41deb09aa3ad28e691a40a + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c + languageName: node + linkType: hard + +"path-key@npm:^4.0.0": + version: 4.0.0 + resolution: "path-key@npm:4.0.0" + checksum: 10c0/794efeef32863a65ac312f3c0b0a99f921f3e827ff63afa5cb09a377e202c262b671f7b3832a4e64731003fa94af0263713962d317b9887bd1e0c48a342efba3 + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: "npm:^10.2.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d + languageName: node + linkType: hard + +"path-type@npm:^4.0.0": + version: 4.0.0 + resolution: "path-type@npm:4.0.0" + checksum: 10c0/666f6973f332f27581371efaf303fd6c272cc43c2057b37aa99e3643158c7e4b2626549555d88626e99ea9e046f82f32e41bbde5f1508547e9a11b149b52387c + languageName: node + linkType: hard + +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.3.1": + version: 2.3.1 + resolution: "picomatch@npm:2.3.1" + checksum: 10c0/26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be + languageName: node + linkType: hard + +"pkg-conf@npm:^4.0.0": + version: 4.0.0 + resolution: "pkg-conf@npm:4.0.0" + dependencies: + find-up: "npm:^6.0.0" + load-json-file: "npm:^7.0.0" + checksum: 10c0/27d027609f27228edcde121f6f707b4ba1f5488e95e98f2e58652ae4e99792081bd1de67d591f4a0f05b02c0b66d745591d49f82041cbc8d41e2238ef5d73eb4 + languageName: node + linkType: hard + +"plur@npm:^5.1.0": + version: 5.1.0 + resolution: "plur@npm:5.1.0" + dependencies: + irregular-plurals: "npm:^3.3.0" + checksum: 10c0/26bb622b8545fcfd47bbf56fbcca66c08693708a232e403fa3589e00003c56c14231ac57c7588ca5db83ef4be1f61383402c4ea954000768f779f8aef6eb6da8 + languageName: node + linkType: hard + +"prebuild-install@npm:^7.1.1": + version: 7.1.2 + resolution: "prebuild-install@npm:7.1.2" + dependencies: + detect-libc: "npm:^2.0.0" + expand-template: "npm:^2.0.3" + github-from-package: "npm:0.0.0" + minimist: "npm:^1.2.3" + mkdirp-classic: "npm:^0.5.3" + napi-build-utils: "npm:^1.0.1" + node-abi: "npm:^3.3.0" + pump: "npm:^3.0.0" + rc: "npm:^1.2.7" + simple-get: "npm:^4.0.0" + tar-fs: "npm:^2.0.0" + tunnel-agent: "npm:^0.6.0" + bin: + prebuild-install: bin.js + checksum: 10c0/e64868ba9ef2068fd7264f5b03e5298a901e02a450acdb1f56258d88c09dea601eefdb3d1dfdff8513fdd230a92961712be0676192626a3b4d01ba154d48bdd3 + languageName: node + linkType: hard + +"pretty-ms@npm:^8.0.0": + version: 8.0.0 + resolution: "pretty-ms@npm:8.0.0" + dependencies: + parse-ms: "npm:^3.0.0" + checksum: 10c0/e960d633ecca45445cf5c6dffc0f5e4bef6744c92449ab0e8c6c704800675ab71e181c5e02ece5265e02137a33e313d3f3e355fbf8ea30b4b5b23de423329f8d + languageName: node + linkType: hard + +"pretty-ms@npm:^9.0.0": + version: 9.1.0 + resolution: "pretty-ms@npm:9.1.0" + dependencies: + parse-ms: "npm:^4.0.0" + checksum: 10c0/fd111aad8800a04dfd654e6016da69bdaa6fc6a4c280f8e727cffd8b5960558e94942f1a94d4aa6e4d179561a0fbb0366a9ebe0ccefbbb0f8ff853b129cdefb9 + languageName: node + linkType: hard + +"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: "npm:^2.0.2" + retry: "npm:^0.12.0" + checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 + languageName: node + linkType: hard + +"pump@npm:^3.0.0": + version: 3.0.2 + resolution: "pump@npm:3.0.2" + dependencies: + end-of-stream: "npm:^1.1.0" + once: "npm:^1.3.1" + checksum: 10c0/5ad655cb2a7738b4bcf6406b24ad0970d680649d996b55ad20d1be8e0c02394034e4c45ff7cd105d87f1e9b96a0e3d06fd28e11fae8875da26e7f7a8e2c9726f + languageName: node + linkType: hard + +"queue-microtask@npm:^1.2.2": + version: 1.2.3 + resolution: "queue-microtask@npm:1.2.3" + checksum: 10c0/900a93d3cdae3acd7d16f642c29a642aea32c2026446151f0778c62ac089d4b8e6c986811076e1ae180a694cedf077d453a11b58ff0a865629a4f82ab558e102 + languageName: node + linkType: hard + +"rc@npm:^1.2.7": + version: 1.2.8 + resolution: "rc@npm:1.2.8" + dependencies: + deep-extend: "npm:^0.6.0" + ini: "npm:~1.3.0" + minimist: "npm:^1.2.0" + strip-json-comments: "npm:~2.0.1" + bin: + rc: ./cli.js + checksum: 10c0/24a07653150f0d9ac7168e52943cc3cb4b7a22c0e43c7dff3219977c2fdca5a2760a304a029c20811a0e79d351f57d46c9bde216193a0f73978496afc2b85b15 + languageName: node + linkType: hard + +"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 + languageName: node + linkType: hard + +"readdirp@npm:~3.6.0": + version: 3.6.0 + resolution: "readdirp@npm:3.6.0" + dependencies: + picomatch: "npm:^2.2.1" + checksum: 10c0/6fa848cf63d1b82ab4e985f4cf72bd55b7dcfd8e0a376905804e48c3634b7e749170940ba77b32804d5fe93b3cc521aa95a8d7e7d725f830da6d93f3669ce66b + languageName: node + linkType: hard + +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 + languageName: node + linkType: hard + +"resolve-cwd@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-cwd@npm:3.0.0" + dependencies: + resolve-from: "npm:^5.0.0" + checksum: 10c0/e608a3ebd15356264653c32d7ecbc8fd702f94c6703ea4ac2fb81d9c359180cba0ae2e6b71faa446631ed6145454d5a56b227efc33a2d40638ac13f8beb20ee4 + languageName: node + linkType: hard + +"resolve-from@npm:^5.0.0": + version: 5.0.0 + resolution: "resolve-from@npm:5.0.0" + checksum: 10c0/b21cb7f1fb746de8107b9febab60095187781137fd803e6a59a76d421444b1531b641bba5857f5dc011974d8a5c635d61cec49e6bd3b7fc20e01f0fafc4efbf2 + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe + languageName: node + linkType: hard + +"reusify@npm:^1.0.4": + version: 1.0.4 + resolution: "reusify@npm:1.0.4" + checksum: 10c0/c19ef26e4e188f408922c46f7ff480d38e8dfc55d448310dfb518736b23ed2c4f547fb64a6ed5bdba92cd7e7ddc889d36ff78f794816d5e71498d645ef476107 + languageName: node + linkType: hard + +"root-workspace-0b6124@workspace:.": + version: 0.0.0-use.local + resolution: "root-workspace-0b6124@workspace:." + dependencies: + "@agoric/synthetic-chain": "npm:^0.3.0" + ava: "npm:^5.3.1" + languageName: unknown + linkType: soft + +"run-parallel@npm:^1.1.9": + version: 1.2.0 + resolution: "run-parallel@npm:1.2.0" + dependencies: + queue-microtask: "npm:^1.2.2" + checksum: 10c0/200b5ab25b5b8b7113f9901bfe3afc347e19bb7475b267d55ad0eb86a62a46d77510cb0f232507c9e5d497ebda569a08a9867d0d14f57a82ad5564d991588b39 + languageName: node + linkType: hard + +"safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"semver@npm:^7.3.2, semver@npm:^7.3.5": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf + languageName: node + linkType: hard + +"serialize-error@npm:^7.0.1": + version: 7.0.1 + resolution: "serialize-error@npm:7.0.1" + dependencies: + type-fest: "npm:^0.13.1" + checksum: 10c0/7982937d578cd901276c8ab3e2c6ed8a4c174137730f1fb0402d005af209a0e84d04acc874e317c936724c7b5b26c7a96ff7e4b8d11a469f4924a4b0ea814c05 + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 + languageName: node + linkType: hard + +"simple-concat@npm:^1.0.0": + version: 1.0.1 + resolution: "simple-concat@npm:1.0.1" + checksum: 10c0/62f7508e674414008910b5397c1811941d457dfa0db4fd5aa7fa0409eb02c3609608dfcd7508cace75b3a0bf67a2a77990711e32cd213d2c76f4fd12ee86d776 + languageName: node + linkType: hard + +"simple-get@npm:^4.0.0": + version: 4.0.1 + resolution: "simple-get@npm:4.0.1" + dependencies: + decompress-response: "npm:^6.0.0" + once: "npm:^1.3.1" + simple-concat: "npm:^1.0.0" + checksum: 10c0/b0649a581dbca741babb960423248899203165769747142033479a7dc5e77d7b0fced0253c731cd57cf21e31e4d77c9157c3069f4448d558ebc96cf9e1eebcf0 + languageName: node + linkType: hard + +"slash@npm:^4.0.0": + version: 4.0.0 + resolution: "slash@npm:4.0.0" + checksum: 10c0/b522ca75d80d107fd30d29df0549a7b2537c83c4c4ecd12cd7d4ea6c8aaca2ab17ada002e7a1d78a9d736a0261509f26ea5b489082ee443a3a810586ef8eff18 + languageName: node + linkType: hard + +"slice-ansi@npm:^5.0.0": + version: 5.0.0 + resolution: "slice-ansi@npm:5.0.0" + dependencies: + ansi-styles: "npm:^6.0.0" + is-fullwidth-code-point: "npm:^4.0.0" + checksum: 10c0/2d4d40b2a9d5cf4e8caae3f698fe24ae31a4d778701724f578e984dcb485ec8c49f0c04dab59c401821e80fcdfe89cace9c66693b0244e40ec485d72e543914f + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.4 + resolution: "socks-proxy-agent@npm:8.0.4" + dependencies: + agent-base: "npm:^7.1.1" + debug: "npm:^4.3.4" + socks: "npm:^2.8.3" + checksum: 10c0/345593bb21b95b0508e63e703c84da11549f0a2657d6b4e3ee3612c312cb3a907eac10e53b23ede3557c6601d63252103494caa306b66560f43af7b98f53957a + languageName: node + linkType: hard + +"socks@npm:^2.8.3": + version: 2.8.3 + resolution: "socks@npm:2.8.3" + dependencies: + ip-address: "npm:^9.0.5" + smart-buffer: "npm:^4.2.0" + checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 + languageName: node + linkType: hard + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec + languageName: node + linkType: hard + +"sprintf-js@npm:~1.0.2": + version: 1.0.3 + resolution: "sprintf-js@npm:1.0.3" + checksum: 10c0/ecadcfe4c771890140da5023d43e190b7566d9cf8b2d238600f31bec0fc653f328da4450eb04bd59a431771a8e9cc0e118f0aa3974b683a4981b4e07abc2a5bb + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.6 + resolution: "ssri@npm:10.0.6" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 + languageName: node + linkType: hard + +"stack-utils@npm:^2.0.6": + version: 2.0.6 + resolution: "stack-utils@npm:2.0.6" + dependencies: + escape-string-regexp: "npm:^2.0.0" + checksum: 10c0/651c9f87667e077584bbe848acaecc6049bc71979f1e9a46c7b920cad4431c388df0f51b8ad7cfd6eed3db97a2878d0fc8b3122979439ea8bac29c61c95eec8a + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: "npm:^8.0.0" + is-fullwidth-code-point: "npm:^3.0.0" + strip-ansi: "npm:^6.0.1" + checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b + languageName: node + linkType: hard + +"string-width@npm:^5.0.0, string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: "npm:^0.2.0" + emoji-regex: "npm:^9.2.2" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca + languageName: node + linkType: hard + +"string_decoder@npm:^1.1.1": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: "npm:~5.2.0" + checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: "npm:^5.0.1" + checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: "npm:^6.0.1" + checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 + languageName: node + linkType: hard + +"strip-final-newline@npm:^4.0.0": + version: 4.0.0 + resolution: "strip-final-newline@npm:4.0.0" + checksum: 10c0/b0cf2b62d597a1b0e3ebc42b88767f0a0d45601f89fd379a928a1812c8779440c81abba708082c946445af1d6b62d5f16e2a7cf4f30d9d6587b89425fae801ff + languageName: node + linkType: hard + +"strip-json-comments@npm:~2.0.1": + version: 2.0.1 + resolution: "strip-json-comments@npm:2.0.1" + checksum: 10c0/b509231cbdee45064ff4f9fd73609e2bcc4e84a4d508e9dd0f31f70356473fde18abfb5838c17d56fb236f5a06b102ef115438de0600b749e818a35fbbc48c43 + languageName: node + linkType: hard + +"supertap@npm:^3.0.1": + version: 3.0.1 + resolution: "supertap@npm:3.0.1" + dependencies: + indent-string: "npm:^5.0.0" + js-yaml: "npm:^3.14.1" + serialize-error: "npm:^7.0.1" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/8164674f2e280cab875f0fef5bb36c15553c13e29697ff92f4e0d6bc62149f0303a89eee47535413ed145ea72e14a24d065bab233059d48a499ec5ebb4566b0f + languageName: node + linkType: hard + +"tar-fs@npm:^2.0.0": + version: 2.1.1 + resolution: "tar-fs@npm:2.1.1" + dependencies: + chownr: "npm:^1.1.1" + mkdirp-classic: "npm:^0.5.2" + pump: "npm:^3.0.0" + tar-stream: "npm:^2.1.4" + checksum: 10c0/871d26a934bfb7beeae4c4d8a09689f530b565f79bd0cf489823ff0efa3705da01278160da10bb006d1a793fa0425cf316cec029b32a9159eacbeaff4965fb6d + languageName: node + linkType: hard + +"tar-stream@npm:^2.1.4": + version: 2.2.0 + resolution: "tar-stream@npm:2.2.0" + dependencies: + bl: "npm:^4.0.3" + end-of-stream: "npm:^1.4.1" + fs-constants: "npm:^1.0.0" + inherits: "npm:^2.0.3" + readable-stream: "npm:^3.1.1" + checksum: 10c0/2f4c910b3ee7196502e1ff015a7ba321ec6ea837667220d7bcb8d0852d51cb04b87f7ae471008a6fb8f5b1a1b5078f62f3a82d30c706f20ada1238ac797e7692 + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.2.1": + version: 6.2.1 + resolution: "tar@npm:6.2.1" + dependencies: + chownr: "npm:^2.0.0" + fs-minipass: "npm:^2.0.0" + minipass: "npm:^5.0.0" + minizlib: "npm:^2.1.1" + mkdirp: "npm:^1.0.3" + yallist: "npm:^4.0.0" + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 + languageName: node + linkType: hard + +"temp-dir@npm:^3.0.0": + version: 3.0.0 + resolution: "temp-dir@npm:3.0.0" + checksum: 10c0/a86978a400984cd5f315b77ebf3fe53bb58c61f192278cafcb1f3fb32d584a21dc8e08b93171d7874b7cc972234d3455c467306cc1bfc4524b622e5ad3bfd671 + languageName: node + linkType: hard + +"time-zone@npm:^1.0.0": + version: 1.0.0 + resolution: "time-zone@npm:1.0.0" + checksum: 10c0/d00ebd885039109011b6e2423ebbf225160927333c2ade6d833e9cc4676db20759f1f3855fafde00d1bd668c243a6aa68938ce71fe58aab0d514e820d59c1d81 + languageName: node + linkType: hard + +"to-regex-range@npm:^5.0.1": + version: 5.0.1 + resolution: "to-regex-range@npm:5.0.1" + dependencies: + is-number: "npm:^7.0.0" + checksum: 10c0/487988b0a19c654ff3e1961b87f471702e708fa8a8dd02a298ef16da7206692e8552a0250e8b3e8759270f62e9d8314616f6da274734d3b558b1fc7b7724e892 + languageName: node + linkType: hard + +"tunnel-agent@npm:^0.6.0": + version: 0.6.0 + resolution: "tunnel-agent@npm:0.6.0" + dependencies: + safe-buffer: "npm:^5.0.1" + checksum: 10c0/4c7a1b813e7beae66fdbf567a65ec6d46313643753d0beefb3c7973d66fcec3a1e7f39759f0a0b4465883499c6dc8b0750ab8b287399af2e583823e40410a17a + languageName: node + linkType: hard + +"type-fest@npm:^0.13.1": + version: 0.13.1 + resolution: "type-fest@npm:0.13.1" + checksum: 10c0/0c0fa07ae53d4e776cf4dac30d25ad799443e9eef9226f9fddbb69242db86b08584084a99885cfa5a9dfe4c063ebdc9aa7b69da348e735baede8d43f1aeae93b + languageName: node + linkType: hard + +"unicorn-magic@npm:^0.3.0": + version: 0.3.0 + resolution: "unicorn-magic@npm:0.3.0" + checksum: 10c0/0a32a997d6c15f1c2a077a15b1c4ca6f268d574cf5b8975e778bb98e6f8db4ef4e86dfcae4e158cd4c7e38fb4dd383b93b13eefddc7f178dea13d3ac8a603271 + languageName: node + linkType: hard + +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: "npm:^4.0.0" + checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635 + languageName: node + linkType: hard + +"util-deprecate@npm:^1.0.1": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 + languageName: node + linkType: hard + +"well-known-symbols@npm:^2.0.0": + version: 2.0.0 + resolution: "well-known-symbols@npm:2.0.0" + checksum: 10c0/cb6c12e98877e8952ec28d13ae6f4fdb54ae1cb49b16a728720276dadd76c930e6cb0e174af3a4620054dd2752546f842540122920c6e31410208abd4958ee6b + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f + languageName: node + linkType: hard + +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: "npm:^6.1.0" + string-width: "npm:^5.0.1" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 + languageName: node + linkType: hard + +"write-file-atomic@npm:^5.0.1": + version: 5.0.1 + resolution: "write-file-atomic@npm:5.0.1" + dependencies: + imurmurhash: "npm:^0.1.4" + signal-exit: "npm:^4.0.1" + checksum: 10c0/e8c850a8e3e74eeadadb8ad23c9d9d63e4e792bd10f4836ed74189ef6e996763959f1249c5650e232f3c77c11169d239cbfc8342fc70f3fe401407d23810505d + languageName: node + linkType: hard + +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a + languageName: node + linkType: hard + +"yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 + languageName: node + linkType: hard + +"yargs@npm:^17.7.2": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: "npm:^8.0.1" + escalade: "npm:^3.1.1" + get-caller-file: "npm:^2.0.5" + require-directory: "npm:^2.1.1" + string-width: "npm:^4.2.3" + y18n: "npm:^5.0.5" + yargs-parser: "npm:^21.1.1" + checksum: 10c0/ccd7e723e61ad5965fffbb791366db689572b80cca80e0f96aad968dfff4156cd7cd1ad18607afe1046d8241e6fb2d6c08bf7fa7bfb5eaec818735d8feac8f05 + languageName: node + linkType: hard + +"yocto-queue@npm:^1.0.0": + version: 1.1.1 + resolution: "yocto-queue@npm:1.1.1" + checksum: 10c0/cb287fe5e6acfa82690acb43c283de34e945c571a78a939774f6eaba7c285bacdf6c90fbc16ce530060863984c906d2b4c6ceb069c94d1e0a06d5f2b458e2a92 + languageName: node + linkType: hard + +"yoctocolors@npm:^2.0.0": + version: 2.1.1 + resolution: "yoctocolors@npm:2.1.1" + checksum: 10c0/85903f7fa96f1c70badee94789fade709f9d83dab2ec92753d612d84fcea6d34c772337a9f8914c6bed2f5fc03a428ac5d893e76fab636da5f1236ab725486d0 + languageName: node + linkType: hard diff --git a/a3p-integration/proposals/n:upgrade-next/priceFeed-follower-auction.test.js b/a3p-integration/proposals/n:upgrade-next/priceFeed-follower-auction.test.js index 30ae903b075..1dc0df73472 100644 --- a/a3p-integration/proposals/n:upgrade-next/priceFeed-follower-auction.test.js +++ b/a3p-integration/proposals/n:upgrade-next/priceFeed-follower-auction.test.js @@ -3,6 +3,7 @@ import { getDetailsMatchingVats } from './vatDetails.js'; test('new auction vat', async t => { const details = await getDetailsMatchingVats('auctioneer'); - // This query matches both the auction and its governor, so 2*2 - t.is(Object.keys(details).length, 4); + // This query matches both the auction and its governor, so 2*3 for the + // original, the vaults&auctions coreEval, and the priceFeed coreEval. + t.is(Object.keys(details).length, 6); }); diff --git a/a3p-integration/proposals/z:acceptance/test-lib/sync-tools.js b/a3p-integration/proposals/z:acceptance/test-lib/sync-tools.js new file mode 100644 index 00000000000..70ffbee37db --- /dev/null +++ b/a3p-integration/proposals/z:acceptance/test-lib/sync-tools.js @@ -0,0 +1,70 @@ +/** + * @file These tools mostly duplicate code that will be added in other PRs + * and eventually migrated to synthetic-chain. Sorry for the duplication. + */ + +/** + * @typedef {object} RetryOptions + * @property {number} [maxRetries] + * @property {number} [retryIntervalMs] + * @property {(...arg0: string[]) => void} [log] + * @property {(object) => void} [setTimeout] + * @property {string} [errorMessage=Error] + */ + +const ambientSetTimeout = globalThis.setTimeout; + +/** + * From https://github.com/Agoric/agoric-sdk/blob/442f07c8f0af03281b52b90e90c27131eef6f331/multichain-testing/tools/sleep.ts#L10 + * + * @param {number} ms + * @param {*} sleepOptions + */ +const sleep = (ms, { log = () => {}, setTimeout = ambientSetTimeout }) => + new Promise(resolve => { + log(`Sleeping for ${ms}ms...`); + setTimeout(resolve, ms); + }); + +/** + * From https://github.com/Agoric/agoric-sdk/blob/442f07c8f0af03281b52b90e90c27131eef6f331/multichain-testing/tools/sleep.ts#L24 + * + * @param {() => Promise} operation + * @param {(result: any) => boolean} condition + * @param {string} message + * @param {RetryOptions} options + */ +export const retryUntilCondition = async ( + operation, + condition, + message, + { maxRetries = 6, retryIntervalMs = 3500, log, setTimeout }, +) => { + console.log({ maxRetries, retryIntervalMs, message }); + let retries = 0; + + await null; + while (retries < maxRetries) { + try { + const result = await operation(); + log('RESULT', result); + if (condition(result)) { + return result; + } + } catch (error) { + if (error instanceof Error) { + log(`Error: ${error.message}`); + } else { + log(`Unknown error: ${String(error)}`); + } + } + + retries += 1; + console.log( + `Retry ${retries}/${maxRetries} - Waiting for ${retryIntervalMs}ms for ${message}...`, + ); + await sleep(retryIntervalMs, { log, setTimeout }); + } + + throw Error(`${message} condition failed after ${maxRetries} retries.`); +}; diff --git a/a3p-integration/proposals/z:acceptance/vaults.test.js b/a3p-integration/proposals/z:acceptance/vaults.test.js index eea9b5899e9..a33ac7319b8 100644 --- a/a3p-integration/proposals/z:acceptance/vaults.test.js +++ b/a3p-integration/proposals/z:acceptance/vaults.test.js @@ -7,12 +7,52 @@ import { adjustVault, closeVault, getISTBalance, + getPriceQuote, + pushPrices, getContractInfo, ATOM_DENOM, USER1ADDR, waitForBlock, + registerOraclesForBrand, + generateOracleMap, } from '@agoric/synthetic-chain'; import { getBalances, agopsVaults } from './test-lib/utils.js'; +import { retryUntilCondition } from './test-lib/sync-tools.js'; + +export const scale6 = x => BigInt(x * 1_000_000); + +// There may be a new vaultFactory that doesn't have prices yet, so we publish +// prices now +test.before(async t => { + const pushPriceRetryOpts = { + maxRetries: 5, // arbitrary + retryIntervalMs: 5000, // in ms + }; + t.context = { + roundId: 1, + retryOpts: { + pushPriceRetryOpts, + }, + }; + const oraclesByBrand = generateOracleMap('z-acc', ['ATOM']); + await registerOraclesForBrand('ATOM', oraclesByBrand); + + const price = 15.2; + // @ts-expect-error t.context is fine + await pushPrices(price, 'ATOM', oraclesByBrand, t.context.roundId); + + await retryUntilCondition( + () => getPriceQuote('ATOM'), + res => res === `+${scale6(price).toString()}`, + 'price not pushed yet', + { + log: t.log, + setTimeout: globalThis.setTimeout, + // @ts-expect-error t.context is fine + ...t.context.pushPriceRetryOpts, + }, + ); +}); test.serial('attempt to open vaults under the minimum amount', async t => { const activeVaultsBefore = await agopsVaults(USER1ADDR); diff --git a/a3p-integration/scripts/build-submission.sh b/a3p-integration/scripts/build-submission.sh index 2c90949ef42..3470c24cf52 100755 --- a/a3p-integration/scripts/build-submission.sh +++ b/a3p-integration/scripts/build-submission.sh @@ -9,8 +9,9 @@ a3pProposalDir=$1 builderScript=$2 submissionDirName=${3:-submission} submissionDir="./a3p-integration/$a3pProposalDir/$submissionDirName" +extraParams=${4:-} -yarn agoric run "packages/builders/scripts/$builderScript" +yarn agoric run "packages/builders/scripts/$builderScript" $extraParams mkdir -p "$submissionDir" plans=*-plan.json diff --git a/packages/boot/test/bootstrapTests/price-feed-replace.test.ts b/packages/boot/test/bootstrapTests/price-feed-replace.test.ts new file mode 100644 index 00000000000..c137ba91017 --- /dev/null +++ b/packages/boot/test/bootstrapTests/price-feed-replace.test.ts @@ -0,0 +1,200 @@ +/** + * @file The goal of this test is to see that the + * upgrade scripts re-wire all the contracts so new auctions and + * price feeds are connected to vaults correctly. + * + * 1. enter a bid + * 2. force prices to drop so a vault liquidates + * 3. verify that the bidder gets the liquidated assets. + */ +import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js'; + +import type { TestFn } from 'ava'; +import { ScheduleNotification } from '@agoric/inter-protocol/src/auction/scheduler.js'; +import { NonNullish } from '@agoric/internal'; +import { eventLoopIteration } from '@agoric/internal/src/testing-utils.js'; +import { Fail } from '@endo/errors'; + +import { + LiquidationTestContext, + likePayouts, + makeLiquidationTestContext, + scale6, + LiquidationSetup, +} from '../../tools/liquidation.js'; +import { + updateVaultDirectorParams, + updateVaultManagerParams, +} from '../tools/changeVaultParams.js'; + +const test = anyTest as TestFn; +test.before( + async t => + (t.context = await makeLiquidationTestContext(t, { env: process.env })), +); +test.after.always(t => t.context.shutdown()); + +const collateralBrandKey = 'ATOM'; +const managerIndex = 0; + +const setup: LiquidationSetup = { + vaults: [{ atom: 15, ist: 100, debt: 100.5 }], + bids: [{ give: '20IST', discount: 0.1 }], + price: { + starting: 12.34, + trigger: 9.99, + }, + auction: { + start: { collateral: 15, debt: 100.5 }, + end: { collateral: 9.659301, debt: 0 }, + }, +}; + +const outcome = { + bids: [{ payouts: { Bid: 0, Collateral: 2.224446 } }], +}; + +test.serial('setupVaults; run updatePriceFeeds proposals', async t => { + const { + agoricNamesRemotes, + buildProposal, + evalProposal, + priceFeedDrivers, + refreshAgoricNamesRemotes, + setupVaults, + governanceDriver: gd, + } = t.context; + + await setupVaults(collateralBrandKey, managerIndex, setup); + + const instancePre = agoricNamesRemotes.instance['ATOM-USD price feed']; + + const priceFeedBuilder = + '@agoric/builders/scripts/inter-protocol/updatePriceFeeds.js'; + t.log('building', priceFeedBuilder); + const brandName = collateralBrandKey; + + const { ATOM } = agoricNamesRemotes.brand; + ATOM || Fail`ATOM missing from agoricNames`; + await updateVaultManagerParams(t, gd, ATOM, 50_000_000n); + + const SOME_GUI = 'someGUIHASH'; + await updateVaultDirectorParams(t, gd, SOME_GUI); + + t.log('building all relevant CoreEvals'); + const coreEvals = await Promise.all([ + buildProposal(priceFeedBuilder, ['main']), + buildProposal('@agoric/builders/scripts/vats/upgradeVaults.js'), + buildProposal('@agoric/builders/scripts/vats/add-auction.js'), + ]); + const combined = { + evals: coreEvals.flatMap(e => e.evals), + bundles: coreEvals.flatMap(e => e.bundles), + }; + t.log('evaluating', coreEvals.length, 'scripts'); + await evalProposal(combined); + + refreshAgoricNamesRemotes(); + const instancePost = agoricNamesRemotes.instance['ATOM-USD price feed']; + t.not(instancePre, instancePost); + + await priceFeedDrivers[collateralBrandKey].refreshInvitations(); +}); + +test.serial('1. place bid', async t => { + const { placeBids, readLatest } = t.context; + await placeBids(collateralBrandKey, 'agoric1buyer', setup, 0); + + t.like(readLatest('published.wallet.agoric1buyer.current'), { + liveOffers: [['ATOM-bid1', { id: 'ATOM-bid1' }]], + }); +}); + +test.serial('2. trigger liquidation by changing price', async t => { + const { priceFeedDrivers, readLatest } = t.context; + + await priceFeedDrivers[collateralBrandKey].setPrice(9.99); + + t.log(readLatest('published.priceFeed.ATOM-USD_price_feed'), { + // aka 9.99 + amountIn: { value: 1000000n }, + amountOut: { value: 9990000n }, + }); + + // check nothing liquidating yet + const liveSchedule: ScheduleNotification = readLatest( + 'published.auction.schedule', + ); + t.is(liveSchedule.activeStartTime, null); + const metricsPath = `published.vaultFactory.managers.manager${managerIndex}.metrics`; + + t.like(readLatest(metricsPath), { + numActiveVaults: setup.vaults.length, + numLiquidatingVaults: 0, + }); +}); + +test.serial('3. verify liquidation', async t => { + const { advanceTimeBy, advanceTimeTo, readLatest } = t.context; + + const liveSchedule: ScheduleNotification = readLatest( + 'published.auction.schedule', + ); + const metricsPath = `published.vaultFactory.managers.manager${managerIndex}.metrics`; + + // advance time to start an auction + console.log(collateralBrandKey, 'step 1 of 10'); + await advanceTimeTo(NonNullish(liveSchedule.nextDescendingStepTime)); + await eventLoopIteration(); // let promises to update vstorage settle + + // vaultFactory sent collateral for liquidation + t.like(readLatest(metricsPath), { + numActiveVaults: 0, + numLiquidatingVaults: setup.vaults.length, + liquidatingCollateral: { + value: scale6(setup.auction.start.collateral), + }, + liquidatingDebt: { value: scale6(setup.auction.start.debt) }, + lockedQuote: null, + }); + + console.log(collateralBrandKey, 'step 2 of 10'); + await advanceTimeBy(3, 'minutes'); + t.like(readLatest(`published.auction.book${managerIndex}`), { + collateralAvailable: { value: scale6(setup.auction.start.collateral) }, + startCollateral: { value: scale6(setup.auction.start.collateral) }, + startProceedsGoal: { value: scale6(setup.auction.start.debt) }, + }); + + console.log(collateralBrandKey, 'step 3 of 10'); + await advanceTimeBy(3, 'minutes'); + + console.log(collateralBrandKey, 'step 4 of 10'); + await advanceTimeBy(3, 'minutes'); + + console.log(collateralBrandKey, 'step 5 of 10'); + await advanceTimeBy(3, 'minutes'); + + console.log(collateralBrandKey, 'step 6 of 10'); + await advanceTimeBy(3, 'minutes'); + t.like(readLatest(`published.auction.book${managerIndex}`), { + // 15_000_000 - ( 20_000_000 / 8.991 ) + collateralAvailable: { value: 12775554n }, + }); + + console.log(collateralBrandKey, 'step 7 of 10'); + await advanceTimeBy(3, 'minutes'); + + console.log(collateralBrandKey, 'step 8 of 10'); + await advanceTimeBy(3, 'minutes'); + + console.log(collateralBrandKey, 'step 9 of 10'); + await advanceTimeBy(3, 'minutes'); + + t.like(readLatest('published.wallet.agoric1buyer'), { + status: { + id: `${collateralBrandKey}-bid1`, + payouts: likePayouts(outcome.bids[0].payouts), + }, + }); +}); diff --git a/packages/boot/test/bootstrapTests/updateGovernedParams.test.ts b/packages/boot/test/bootstrapTests/updateGovernedParams.test.ts new file mode 100644 index 00000000000..7fe5c25f582 --- /dev/null +++ b/packages/boot/test/bootstrapTests/updateGovernedParams.test.ts @@ -0,0 +1,155 @@ +/** + * @file The goal of this test is to ensure that governance can update params + * after an upgrade. There was a point when the contractGovernor kept trying to + * use the old paramManager which was ephemeral and no longer useable. + * + * 1. enter a bid + * 2. force prices to drop so a vault liquidates + * 3. verify that the bidder gets the liquidated assets. + */ +import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js'; + +import type { TestFn } from 'ava'; +import { makeAgoricNamesRemotesFromFakeStorage } from '@agoric/vats/tools/board-utils'; +import { Fail } from '@endo/errors'; + +import { makeSwingsetTestKit } from '../../tools/supports.js'; +import { + makeGovernanceDriver, + makeWalletFactoryDriver, +} from '../../tools/drivers.js'; +import { + updateVaultDirectorParams, + updateVaultManagerParams, +} from '../tools/changeVaultParams.js'; + +const makeDefaultTestContext = async t => { + console.time('DefaultTestContext'); + const swingsetTestKit = await makeSwingsetTestKit(t.log); + + const { runUtils, storage } = swingsetTestKit; + console.timeLog('DefaultTestContext', 'swingsetTestKit'); + const { EV } = runUtils; + + // Wait for ATOM to make it into agoricNames + await EV.vat('bootstrap').consumeItem('vaultFactoryKit'); + console.timeLog('DefaultTestContext', 'vaultFactoryKit'); + + // has to be late enough for agoricNames data to have been published + const agoricNamesRemotes = makeAgoricNamesRemotesFromFakeStorage( + swingsetTestKit.storage, + ); + agoricNamesRemotes.brand.ATOM || Fail`ATOM missing from agoricNames`; + console.timeLog('DefaultTestContext', 'agoricNamesRemotes'); + + const walletFactoryDriver = await makeWalletFactoryDriver( + runUtils, + storage, + agoricNamesRemotes, + ); + console.timeLog('DefaultTestContext', 'walletFactoryDriver'); + + console.timeEnd('DefaultTestContext'); + + const gd = await makeGovernanceDriver( + swingsetTestKit, + agoricNamesRemotes, + walletFactoryDriver, + [ + 'agoric1ldmtatp24qlllgxmrsjzcpe20fvlkp448zcuce', + 'agoric140dmkrz2e42ergjj7gyvejhzmjzurvqeq82ang', + 'agoric1w8wktaur4zf8qmmtn3n7x3r0jhsjkjntcm3u6h', + ], + ); + + return { ...swingsetTestKit, agoricNamesRemotes, gd }; +}; + +const test = anyTest as TestFn< + Awaited> +>; + +test.before(async t => { + t.context = await makeDefaultTestContext(t); +}); +test.after.always(t => { + return t.context.shutdown && t.context.shutdown(); +}); + +test('modify manager & director params; update vats, check', async t => { + const { agoricNamesRemotes, evalProposal, buildProposal, gd } = t.context; + + const { ATOM } = agoricNamesRemotes.brand; + ATOM || Fail`ATOM missing from agoricNames`; + + const { EV } = t.context.runUtils; + const zoe: ZoeService = await EV.vat('bootstrap').consumeItem('zoe'); + const vaultFactoryKit = + await EV.vat('bootstrap').consumeItem('vaultFactoryKit'); + const brands = await EV(zoe).getBrands(vaultFactoryKit.instance); + + // /// Modify Manager params /////////////// + t.log('modify manager params'); + const getDebtLimitValue = async () => { + const params = await EV(vaultFactoryKit.publicFacet).getGovernedParams({ + collateralBrand: brands.ATOM, + }); + + // @ts-expect-error getGovernedParams doesn't declare these fields + return params.DebtLimit.value.value; + }; + + t.is(await getDebtLimitValue(), 1_000_000_000n); + await updateVaultManagerParams(t, gd, ATOM, 50_000_000n); + + t.is(await getDebtLimitValue(), 50_000_000n); + + // /// Modify Director params /////////////// + t.log('modify director params'); + const directorPF = vaultFactoryKit.publicFacet; + const subscriptionPre = await EV(directorPF).getElectorateSubscription(); + + const iteratorP = await EV(subscriptionPre)[Symbol.asyncIterator](); + let next = await EV(iteratorP).next(); + + const ORIGINAL_GUI = + 'bafybeidvpbtlgefi3ptuqzr2fwfyfjqfj6onmye63ij7qkrb4yjxekdh3e'; + + t.is(next.value.current.ReferencedUI.value, ORIGINAL_GUI); + + const SOME_GUI = 'someGUIHASH'; + await updateVaultDirectorParams(t, gd, SOME_GUI); + + next = await EV(iteratorP).next(); + t.is(next.value.current.ReferencedUI.value, SOME_GUI); + + const ANOTHER_GUI = 'anotherGUIHASH'; + await updateVaultDirectorParams(t, gd, ANOTHER_GUI); + + next = await EV(iteratorP).next(); + t.is(next.value.current.ReferencedUI.value, ANOTHER_GUI); + + // /// run the coreEval /////////////// + t.log('upgrade priceFeeds, vaults, and auctions'); + const priceFeedBuilder = + '@agoric/builders/scripts/inter-protocol/updatePriceFeeds.js'; + const coreEvals = await Promise.all([ + buildProposal(priceFeedBuilder, ['main']), + buildProposal('@agoric/builders/scripts/vats/upgradeVaults.js'), + buildProposal('@agoric/builders/scripts/vats/add-auction.js'), + ]); + const combined = { + evals: coreEvals.flatMap(e => e.evals), + bundles: coreEvals.flatMap(e => e.bundles), + }; + t.log('evaluating', coreEvals.length, 'scripts'); + await evalProposal(combined); + + // verify manager params restored to latest value + t.is(await getDebtLimitValue(), 50_000_000n); + + // verify director params restored to latest value + const subscriptionPost = await EV(directorPF).getElectorateSubscription(); + const { head } = await EV(subscriptionPost).subscribeAfter(); + t.is(head.value.current.ReferencedUI.value, ANOTHER_GUI); +}); diff --git a/packages/boot/test/tools/changeVaultParams.ts b/packages/boot/test/tools/changeVaultParams.ts new file mode 100644 index 00000000000..4cff2fc526a --- /dev/null +++ b/packages/boot/test/tools/changeVaultParams.ts @@ -0,0 +1,47 @@ +import { ParamChangesOfferArgs } from '@agoric/inter-protocol/src/econCommitteeCharter'; + +export const updateVaultManagerParams = async (t, gd, brand, newDebtLimit) => { + const { agoricNamesRemotes } = t.context; + + const vaults = agoricNamesRemotes.instance.VaultFactory; + const timerBrand = agoricNamesRemotes.brand.timer; + assert(timerBrand); + + /* XXX @type {Partial} */ + const params = { + DebtLimit: { brand: agoricNamesRemotes.brand.IST, value: newDebtLimit }, + }; + + const offerArgs: ParamChangesOfferArgs = { + deadline: 1000n, + params, + instance: vaults, + path: { paramPath: { key: { collateralBrand: brand } } }, + }; + + await gd.changeParams(vaults, params, offerArgs.path); + + return newDebtLimit; +}; +export const updateVaultDirectorParams = async (t, gd, referenceUI) => { + const { agoricNamesRemotes } = t.context; + + const vaults = agoricNamesRemotes.instance.VaultFactory; + const timerBrand = agoricNamesRemotes.brand.timer; + assert(timerBrand); + + const params = { + ReferencedUI: referenceUI, + }; + + const offerArgs: ParamChangesOfferArgs = { + deadline: 1000n, + params, + instance: vaults, + path: { paramPath: { key: 'governedParams' } }, + }; + + await gd.changeParams(vaults, params, offerArgs.path); + + return referenceUI; +}; diff --git a/packages/boot/tools/drivers.ts b/packages/boot/tools/drivers.ts index b1877c0a31c..c042ec0f4ec 100644 --- a/packages/boot/tools/drivers.ts +++ b/packages/boot/tools/drivers.ts @@ -155,24 +155,28 @@ export const makePriceFeedDriver = async ( oracleAddresses.map(addr => walletFactoryDriver.provideSmartWallet(addr)), ); - const priceFeedInstance = agoricNamesRemotes.instance[priceFeedName]; - priceFeedInstance || Fail`no price feed ${priceFeedName}`; - const adminOfferId = `accept-${collateralBrandKey}-oracleInvitation`; - - // accept invitations - await Promise.all( - oracleWallets.map(w => - w.executeOffer({ - id: adminOfferId, - invitationSpec: { - source: 'purse', - instance: priceFeedInstance, - description: 'oracle invitation', - }, - proposal: {}, - }), - ), - ); + let nonce = 0; + let adminOfferId; + const acceptInvitations = async () => { + const priceFeedInstance = agoricNamesRemotes.instance[priceFeedName]; + priceFeedInstance || Fail`no price feed ${priceFeedName}`; + nonce += 1; + adminOfferId = `accept-${collateralBrandKey}-oracleInvitation${nonce}`; + return Promise.all( + oracleWallets.map(w => + w.executeOffer({ + id: adminOfferId, + invitationSpec: { + source: 'purse', + instance: priceFeedInstance, + description: 'oracle invitation', + }, + proposal: {}, + }), + ), + ); + }; + await acceptInvitations(); // zero is the initial lastReportedRoundId so causes an error: cannot report on previous rounds let roundId = 1n; @@ -196,6 +200,10 @@ export const makePriceFeedDriver = async ( roundId += 1n; // TODO confirm the new price is written to storage }, + async refreshInvitations() { + roundId = 1n; + await acceptInvitations(); + }, }; }; harden(makePriceFeedDriver); diff --git a/packages/boot/tools/liquidation.ts b/packages/boot/tools/liquidation.ts index 221f98e7260..1945abdc9fe 100644 --- a/packages/boot/tools/liquidation.ts +++ b/packages/boot/tools/liquidation.ts @@ -53,6 +53,17 @@ export type LiquidationSetup = { }; }; +// TODO read from the config file +export const atomConfig = { + oracleAddresses: [ + 'agoric1krunjcqfrf7la48zrvdfeeqtls5r00ep68mzkr', + 'agoric19uscwxdac6cf6z7d5e26e0jm0lgwstc47cpll8', + 'agoric144rrhh4m09mh7aaffhm6xy223ym76gve2x7y78', + 'agoric19d6gnr9fyp6hev4tlrg87zjrzsd5gzr5qlfq2p', + 'agoric1n4fcxsnkxe4gj6e24naec99hzmc4pjfdccy5nj', + ], +}; + export const scale6 = x => BigInt(Math.round(x * 1_000_000)); const DebtLimitValue = scale6(100_000); @@ -103,14 +114,7 @@ export const makeLiquidationTestKit = async ({ collateralBrandKey, agoricNamesRemotes, walletFactoryDriver, - // TODO read from the config file - [ - 'agoric1krunjcqfrf7la48zrvdfeeqtls5r00ep68mzkr', - 'agoric19uscwxdac6cf6z7d5e26e0jm0lgwstc47cpll8', - 'agoric144rrhh4m09mh7aaffhm6xy223ym76gve2x7y78', - 'agoric19d6gnr9fyp6hev4tlrg87zjrzsd5gzr5qlfq2p', - 'agoric1n4fcxsnkxe4gj6e24naec99hzmc4pjfdccy5nj', - ], + atomConfig.oracleAddresses, ); } @@ -304,8 +308,14 @@ export const makeLiquidationTestKit = async ({ }; }; -export const makeLiquidationTestContext = async t => { - const swingsetTestKit = await makeSwingsetTestKit(t.log); +export const makeLiquidationTestContext = async ( + t, + io: { env?: Record } = {}, +) => { + const { env = {} } = io; + const swingsetTestKit = await makeSwingsetTestKit(t.log, undefined, { + slogFile: env.SLOGFILE, + }); console.time('DefaultTestContext'); const { runUtils, storage } = swingsetTestKit; diff --git a/packages/builders/scripts/inter-protocol/updatePriceFeeds.js b/packages/builders/scripts/inter-protocol/updatePriceFeeds.js new file mode 100644 index 00000000000..eefb2e54a47 --- /dev/null +++ b/packages/builders/scripts/inter-protocol/updatePriceFeeds.js @@ -0,0 +1,83 @@ +/* global process */ + +import { makeHelpers } from '@agoric/deploy-script-support'; +import { getManifestForPriceFeeds } from '@agoric/inter-protocol/src/proposals/deploy-price-feeds.js'; + +/** @import {PriceFeedConfig} from '@agoric/inter-protocol/src/proposals/deploy-price-feeds.js'; */ + +/** @type {Record} */ +const configurations = { + A3P_INTEGRATION: { + oracleAddresses: [ + 'agoric1ee9hr0jyrxhy999y755mp862ljgycmwyp4pl7q', // GOV1 + 'agoric1wrfh296eu2z34p6pah7q04jjuyj3mxu9v98277', // GOV2 + 'agoric1ydzxwh6f893jvpaslmaz6l8j2ulup9a7x8qvvq', // GOV3 + ], + inBrandNames: ['ATOM', 'stATOM'], + }, + main: { + oracleAddresses: [ + 'agoric144rrhh4m09mh7aaffhm6xy223ym76gve2x7y78', // DSRV + 'agoric19d6gnr9fyp6hev4tlrg87zjrzsd5gzr5qlfq2p', // Stakin + 'agoric19uscwxdac6cf6z7d5e26e0jm0lgwstc47cpll8', // 01node + 'agoric1krunjcqfrf7la48zrvdfeeqtls5r00ep68mzkr', // Simply Staking + 'agoric1n4fcxsnkxe4gj6e24naec99hzmc4pjfdccy5nj', // P2P + ], + inBrandNames: ['ATOM', 'stATOM', 'stOSMO', 'stTIA', 'stkATOM'], + contractTerms: { minSubmissionCount: 3 }, + }, + devnet: { + oracleAddresses: [ + 'agoric1lw4e4aas9q84tq0q92j85rwjjjapf8dmnllnft', // DSRV + 'agoric1zj6vrrrjq4gsyr9lw7dplv4vyejg3p8j2urm82', // Stakin + 'agoric1ra0g6crtsy6r3qnpu7ruvm7qd4wjnznyzg5nu4', // 01node + 'agoric1qj07c7vfk3knqdral0sej7fa6eavkdn8vd8etf', // Simply Staking + 'agoric10vjkvkmpp9e356xeh6qqlhrny2htyzp8hf88fk', // P2P + ], + inBrandNames: ['ATOM', 'stTIA', 'stkATOM'], + }, +}; + +/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */ +export const defaultProposalBuilder = async ({ publishRef, install }, opts) => { + return harden({ + sourceSpec: '@agoric/inter-protocol/src/proposals/deploy-price-feeds.js', + getManifestCall: [ + getManifestForPriceFeeds.name, + { + ...opts, + priceAggregatorRef: publishRef( + install( + '@agoric/inter-protocol/src/price/fluxAggregatorContract.js', + '../bundles/bundle-fluxAggregatorKit.js', + ), + ), + scaledPARef: publishRef( + install( + '@agoric/zoe/src/contracts/scaledPriceAuthority.js', + '../bundles/bundle-scaledPriceAuthority.js', + ), + ), + }, + ], + }); +}; + +const { keys } = Object; +const Usage = `agoric run updatePriceFeed.js ${keys(configurations).join(' | ')}`; + +export default async (homeP, endowments) => { + const { scriptArgs } = endowments; + const config = configurations[scriptArgs?.[0]]; + if (!config) { + console.error(Usage); + process.exit(1); + } + console.log('UPPrices', scriptArgs, config); + + const { writeCoreEval } = await makeHelpers(homeP, endowments); + + await writeCoreEval('gov-price-feeds', (utils, opts) => + defaultProposalBuilder(utils, { ...opts, ...config }), + ); +}; diff --git a/packages/inter-protocol/src/econCommitteeCharter.js b/packages/inter-protocol/src/econCommitteeCharter.js index b718e4d9337..468fe413c4c 100644 --- a/packages/inter-protocol/src/econCommitteeCharter.js +++ b/packages/inter-protocol/src/econCommitteeCharter.js @@ -25,7 +25,7 @@ export const INVITATION_MAKERS_DESC = 'charter member invitation'; * @property {bigint} deadline * @property {Instance} instance * @property {Record} params - * @property {{ paramPath: { key: string } }} [path] + * @property {{ paramPath: unknown }} [path] paramPath is determined by contract */ const ParamChangesOfferArgsShape = M.splitRecord( { diff --git a/packages/inter-protocol/src/price/fluxAggregatorContract.js b/packages/inter-protocol/src/price/fluxAggregatorContract.js index 0eb968edd2b..37eb8f077f0 100644 --- a/packages/inter-protocol/src/price/fluxAggregatorContract.js +++ b/packages/inter-protocol/src/price/fluxAggregatorContract.js @@ -195,3 +195,5 @@ export const start = async (zcf, privateArgs, baggage) => { }); }; harden(start); + +/** @typedef {typeof start} FluxStartFn */ diff --git a/packages/inter-protocol/src/proposals/add-auction.js b/packages/inter-protocol/src/proposals/add-auction.js index ca5bb004759..6bfad088ee6 100644 --- a/packages/inter-protocol/src/proposals/add-auction.js +++ b/packages/inter-protocol/src/proposals/add-auction.js @@ -27,7 +27,7 @@ export const addAuction = async ( chainTimerService, economicCommitteeCreatorFacet: electorateCreatorFacet, econCharterKit, - priceAuthority, + priceAuthority8400, zoe, }, produce: { auctioneerKit: produceAuctioneerKit, auctionUpgradeNewInstance }, @@ -95,7 +95,7 @@ export const addAuction = async ( const auctionTerms = makeGovernedATerms( { storageNode, marshaller }, chainTimerService, - priceAuthority, + priceAuthority8400, reservePublicFacet, { ...params, @@ -197,7 +197,7 @@ export const ADD_AUCTION_MANIFEST = harden({ chainTimerService: true, econCharterKit: true, economicCommitteeCreatorFacet: true, - priceAuthority: true, + priceAuthority8400: true, zoe: true, }, produce: { diff --git a/packages/inter-protocol/src/proposals/addAssetToVault.js b/packages/inter-protocol/src/proposals/addAssetToVault.js index 7bd27147cbd..2173895349b 100644 --- a/packages/inter-protocol/src/proposals/addAssetToVault.js +++ b/packages/inter-protocol/src/proposals/addAssetToVault.js @@ -129,7 +129,7 @@ export const publishInterchainAssetFromBank = async ( * @param {object} config.options * @param {InterchainAssetOptions} config.options.interchainAssetOptions */ -export const registerScaledPriceAuthority = async ( +export const startScaledPriceAuthority = async ( { consume: { agoricNamesAdmin, @@ -137,7 +137,6 @@ export const registerScaledPriceAuthority = async ( priceAuthorityAdmin, priceAuthority, }, - instance: { produce: produceInstance }, }, { options: { interchainAssetOptions } }, ) => { @@ -231,6 +230,25 @@ export const registerScaledPriceAuthority = async ( true, // force ); + return spaKit; +}; + +/** + * @param {BootstrapPowers} powers + * @param {object} config + * @param {object} config.options + */ +export const registerScaledPriceAuthority = async (powers, { options }) => { + const { + instance: { produce: produceInstance }, + } = powers; + + const { keyword, issuerName = keyword } = options.interchainAssetOptions; + + const spaKit = await startScaledPriceAuthority(powers, { options }); + + const label = scaledPriceFeedName(issuerName); + // publish into agoricNames so that others can await its presence. // This must stay after registerPriceAuthority above so it's evidence of registration. // eslint-disable-next-line no-restricted-syntax -- computed property diff --git a/packages/inter-protocol/src/proposals/deploy-price-feeds.js b/packages/inter-protocol/src/proposals/deploy-price-feeds.js new file mode 100644 index 00000000000..a80c50edf43 --- /dev/null +++ b/packages/inter-protocol/src/proposals/deploy-price-feeds.js @@ -0,0 +1,312 @@ +import { makeTracer } from '@agoric/internal'; +import { makeStorageNodeChild } from '@agoric/internal/src/lib-chainStorage.js'; +import { E } from '@endo/far'; + +import { unitAmount } from '@agoric/zoe/src/contractSupport/priceQuote.js'; +import { + oracleBrandFeedName, + reserveThenDeposit, + sanitizePathSegment, +} from './utils.js'; +import { replaceScaledPriceAuthorities } from './replace-scaledPriceAuthorities.js'; + +const STORAGE_PATH = 'priceFeed'; + +/** @type {ChainlinkConfig} */ +export const DEFAULT_CONTRACT_TERMS = { + maxSubmissionCount: 1000, + minSubmissionCount: 2, + restartDelay: 1n, // the number of rounds an Oracle has to wait before they can initiate another round + timeout: 10, // in seconds according to chainTimerService + minSubmissionValue: 1, + maxSubmissionValue: 2 ** 256, +}; + +/** @import {EconomyBootstrapPowers} from './econ-behaviors.js'; */ +/** @import {ChainlinkConfig} from '@agoric/inter-protocol/src/price/fluxAggregatorKit.js'; */ +/** @import {FluxStartFn} from '@agoric/inter-protocol/src/price/fluxAggregatorContract.js'; */ + +const trace = makeTracer('DeployPriceFeed', true); + +/** + * @typedef {{ + * oracleAddresses: string[]; + * inBrandNames: string[]; + * contractTerms?: Partial; + * }} PriceFeedConfig + */ + +/** + * @param {EconomyBootstrapPowers} powers + * @param {string} bundleID + */ +const installPriceAggregator = async ( + { + consume: { zoe }, + installation: { + produce: { priceAggregator }, + }, + }, + bundleID, +) => { + /** @type {Installation} */ + const installation = await E(zoe).installBundleID(bundleID); + priceAggregator.reset(); + priceAggregator.resolve(installation); + trace('installed priceAggregator', bundleID.slice(0, 'b1-1234567'.length)); + return installation; +}; + +/** + * Provide (find/create) inert brands (no mint or issuer) referred to by oracles + * + * @param {EconomyBootstrapPowers & NamedVatPowers} space + * @param {{ name: string; decimalPlaces: number }} opt + * @returns {Promise>} + */ +export const ensureOracleBrand = async ( + { + namedVat: { + consume: { agoricNames }, + }, + oracleBrand: { produce: oracleBrandProduce }, + }, + { name, decimalPlaces }, +) => { + const brand = E(agoricNames).provideInertBrand(name, { + assetKind: 'nat', + decimalPlaces, + }); + + oracleBrandProduce[name].reset(); + oracleBrandProduce[name].resolve(brand); + return brand; +}; + +/** + * @param {EconomyBootstrapPowers} powers + * @param {{ + * AGORIC_INSTANCE_NAME: string; + * contractTerms: import('@agoric/inter-protocol/src/price/fluxAggregatorKit.js').ChainlinkConfig; + * brandIn: Brand<'nat'>; + * brandOut: Brand<'nat'>; + * }} config + * @param {Installation} installation + */ +const startPriceAggregatorInstance = async ( + { + consume: { + board, + chainStorage, + chainTimerService, + econCharterKit, + highPrioritySendersManager, + namesByAddressAdmin, + startGovernedUpgradable, + }, + instance: { produce: produceInstance }, + }, + { AGORIC_INSTANCE_NAME, contractTerms, brandIn, brandOut }, + installation, +) => { + trace('startPriceAggregatorInstance', AGORIC_INSTANCE_NAME); + const label = sanitizePathSegment(AGORIC_INSTANCE_NAME); + + const feedsStorage = await makeStorageNodeChild(chainStorage, STORAGE_PATH); + const storageNode = await E(feedsStorage).makeChildNode(label); + const marshaller = await E(board).getReadonlyMarshaller(); + + const terms = harden({ + ...contractTerms, + description: AGORIC_INSTANCE_NAME, + brandIn, + brandOut, + // XXX powerful TimerService, see #6003 + timer: await chainTimerService, + unitAmountIn: await unitAmount(brandIn), + }); + const privateArgs = { + highPrioritySendersManager: await highPrioritySendersManager, + marshaller, + namesByAddressAdmin, + storageNode, + }; + const governedKit = await E(startGovernedUpgradable)({ + governedParams: {}, + privateArgs, + terms, + label, + // @ts-expect-error GovernableStartFn vs. fluxAggregatorContract.js start + installation, + }); + produceInstance[AGORIC_INSTANCE_NAME].reset(); + produceInstance[AGORIC_INSTANCE_NAME].resolve(governedKit.instance); + trace( + 'new instance', + label, + { terms, privateArgs, installation }, + governedKit, + ); + + await E(E.get(econCharterKit).creatorFacet).addInstance( + governedKit.instance, + governedKit.governorCreatorFacet, + AGORIC_INSTANCE_NAME, + ); + trace('added', label, 'instance to econCharter'); + + /** @type {import('@agoric/zoe/src/zoeService/utils.js').StartedInstanceKit} */ + // @ts-expect-error + const { instance, publicFacet, creatorFacet } = governedKit; + + return harden({ instance, publicFacet, creatorFacet }); +}; + +/** + * Send invitations to oracle operators for a price feed. + * + * @param {EconomyBootstrapPowers} powers + * @param {{ oracleAddresses: string[]; AGORIC_INSTANCE_NAME: string }} config + * @param {any} creatorFacet + */ +const distributeInvitations = async ( + { consume: { namesByAddressAdmin } }, + { oracleAddresses, AGORIC_INSTANCE_NAME }, + creatorFacet, +) => { + /** @param {string} addr */ + const addOracle = async addr => { + const invitation = await E(creatorFacet).makeOracleInvitation(addr); + const debugName = `${AGORIC_INSTANCE_NAME} member ${addr}`; + await reserveThenDeposit(debugName, namesByAddressAdmin, addr, [ + invitation, + ]).catch(err => console.error(`failed deposit to ${debugName}`, err)); + }; + + trace('distributing invitations', oracleAddresses); + // This doesn't resolve until oracle operators create their smart wallets. + // Don't block completion on it. + void Promise.all(oracleAddresses.map(addOracle)); + trace('createPriceFeed complete'); +}; + +/** + * @param {EconomyBootstrapPowers & NamedVatPowers} powers + * @param {{ + * options: PriceFeedConfig & { + * priceAggregatorRef: { bundleID: string }; + * scaledPARef: { bundleID: string }; + * inBrandsDecimals?: number; + * contractTerms?: ChainlinkConfig; + * outBrandName?: string; + * outBrandDecimals?: number; + * }; + * }} config + */ +export const deployPriceFeeds = async (powers, config) => { + const { + inBrandNames, + oracleAddresses, + contractTerms, + priceAggregatorRef, + scaledPARef, + inBrandsDecimals = 6, + outBrandName = 'USD', + outBrandDecimals = 6, + } = config.options; + await null; + + const installation = await installPriceAggregator( + powers, + priceAggregatorRef.bundleID, + ); + + const { priceAuthorityAdmin, priceAuthority } = powers.consume; + for (const inBrandName of inBrandNames) { + const AGORIC_INSTANCE_NAME = oracleBrandFeedName(inBrandName, outBrandName); + const brandIn = await ensureOracleBrand(powers, { + name: inBrandName, + decimalPlaces: inBrandsDecimals, + }); + const brandOut = await ensureOracleBrand(powers, { + name: outBrandName, + decimalPlaces: outBrandDecimals, + }); + const kit = await startPriceAggregatorInstance( + powers, + { + AGORIC_INSTANCE_NAME, + brandIn, + brandOut, + contractTerms: { ...DEFAULT_CONTRACT_TERMS, ...contractTerms }, + }, + installation, + ); + + const forceReplace = true; + await E(priceAuthorityAdmin).registerPriceAuthority( + E(kit.publicFacet).getPriceAuthority(), + brandIn, + brandOut, + forceReplace, + ); + + await distributeInvitations( + powers, + { oracleAddresses, AGORIC_INSTANCE_NAME }, + kit.creatorFacet, + ); + } + + // @ts-expect-error replaceScaledPriceAuthorities uses a subset of the powers. + await replaceScaledPriceAuthorities(powers, { + options: { scaledPARef }, + }); + + // cf. #8400 QuotePayments storage leak + powers.produce.priceAuthority8400.resolve(priceAuthority); +}; + +const t = 'priceFeed'; + +/** + * Thread price feed upgrade options through from builder to core-eval. + * + * @param {object} utils + * @param {any} utils.restoreRef + * @param {PriceFeedConfig & { priceAggregatorRef: any }} priceFeedOptions + */ +export const getManifestForPriceFeeds = async ( + { restoreRef: _restoreRef }, + priceFeedOptions, +) => ({ + manifest: { + [deployPriceFeeds.name]: { + namedVat: t, + consume: { + agoricNamesAdmin: t, + agoricNames: t, + board: t, + chainStorage: t, + chainTimerService: t, + contractKits: t, + econCharterKit: t, + highPrioritySendersManager: t, + instancePrivateArgs: t, + namesByAddressAdmin: t, + priceAuthority: t, + priceAuthorityAdmin: t, + startGovernedUpgradable: t, + startUpgradable: t, + zoe: t, + }, + installation: { produce: { priceAggregator: t } }, + instance: { + produce: t, + }, + oracleBrand: { produce: t }, + produce: { priceAuthority8400: t }, + }, + }, + options: { ...priceFeedOptions }, +}); diff --git a/packages/inter-protocol/src/proposals/price-feed-proposal.js b/packages/inter-protocol/src/proposals/price-feed-proposal.js index ef0808cea6e..ffe124dbd4d 100644 --- a/packages/inter-protocol/src/proposals/price-feed-proposal.js +++ b/packages/inter-protocol/src/proposals/price-feed-proposal.js @@ -227,7 +227,8 @@ export const createPriceFeed = async ( // being after the above awaits means that when this resolves, the consumer // gets notified that the authority is in the registry and its instance is in - // agoricNames. + // agoricNames. reset() in case we're replacing an existing feed. + produceInstance[AGORIC_INSTANCE_NAME].reset(); produceInstance[AGORIC_INSTANCE_NAME].resolve(faKit.instance); E(E.get(econCharterKit).creatorFacet).addInstance( diff --git a/packages/inter-protocol/src/proposals/replace-scaledPriceAuthorities.js b/packages/inter-protocol/src/proposals/replace-scaledPriceAuthorities.js new file mode 100644 index 00000000000..8723af3ce7b --- /dev/null +++ b/packages/inter-protocol/src/proposals/replace-scaledPriceAuthorities.js @@ -0,0 +1,124 @@ +import { makeTracer } from '@agoric/internal'; +import { E } from '@endo/far'; + +import { startScaledPriceAuthority } from './addAssetToVault.js'; +import { scaledPriceFeedName } from './utils.js'; + +const trace = makeTracer('replaceScaledPA', true); + +/** + * @param {BootstrapPowers} powers + * @param {object} config + * @param {object} config.options + */ +export const replaceScaledPriceAuthority = async (powers, { options }) => { + const { + instance: { produce: produceInstance }, + } = powers; + const { issuerName } = options.interchainAssetOptions; + + const spaKit = await startScaledPriceAuthority(powers, { options }); + + const label = scaledPriceFeedName(issuerName); + produceInstance[label].reset(); + + // publish into agoricNames. This must stay after registerPriceAuthority, + // which is called by startScaledPriceAuthority() + produceInstance[label].resolve(spaKit.instance); +}; + +/** + * Look up the existing assets known to auctions, and replace the corresponding + * scaledPriceAuthorities. The existing contracts will be left behind to be + * cleaned up later. + * + * @param {ChainBootstrapSpace & BootstrapPowers} powers + * @param {{ options: { scaledPARef: { bundleID: string } } }} options + */ +export const replaceScaledPriceAuthorities = async (powers, { options }) => { + trace('start'); + const { + consume: { + agoricNamesAdmin, + agoricNames, + contractKits: contractKitsP, + zoe, + }, + } = powers; + + const { scaledPARef } = options; + + const installationsAdmin = E(agoricNamesAdmin).lookupAdmin('installation'); + const [spaInstallation, contractKits] = await Promise.all([ + E(E(installationsAdmin).readonly()).lookup('scaledPriceAuthority'), + contractKitsP, + ]); + + const bundleID = scaledPARef.bundleID; + if (scaledPARef && bundleID) { + await E.when( + E(zoe).installBundleID(bundleID), + installation => + E(installationsAdmin).update('scaledPriceAuthority', installation), + err => + console.error( + `🚨 failed to update scaledPriceAuthority installation`, + err, + ), + ); + trace('installed scaledPriceAuthority bundle', bundleID); + } + + // Ask Zoe for the installation for each kit's instance, and return all the + // kits where that matches the given installation. + async function maybeSPAKit(kit) { + const installation = await E(zoe).getInstallationForInstance(kit.instance); + return spaInstallation === installation ? [kit] : []; + } + const scaledPAKits = ( + await Promise.all([...contractKits.values()].map(maybeSPAKit)) + ).flat(); + + const namedBrands = await E(E(agoricNames).lookup('brand')).entries(); + + for (const kitEntry of scaledPAKits) { + const { instance } = kitEntry; + const terms = await E(powers.consume.zoe).getTerms(instance); + const { brand } = terms.scaleIn.denominator; + const entry = namedBrands.find(([_k, v]) => v === brand); + assert(entry, 'unable to find issuerName for ', brand); + const issuerName = entry[0]; + await replaceScaledPriceAuthority(powers, { + options: { interchainAssetOptions: { issuerName } }, + }); + } +}; + +const t = 'replaceScaledPriceAuthority'; +export const getManifestForReplaceScaledPriceAuthorities = async ( + _ign, + upgradeSPAOptions, +) => ({ + manifest: { + [replaceScaledPriceAuthorities.name]: { + consume: { + // //// Widely known //// + agoricNames: t, + priceAuthority: t, + startUpgradable: t, + zoe: t, + + // //// closely held, powerful //// + agoricNamesAdmin: t, + contractKits: t, + priceAuthorityAdmin: t, + }, + instance: { + // This is a right to add/replace any instance. That we update only the + // relevant ones must be verified by inspection. + produce: t, + }, + }, + }, + options: { ...upgradeSPAOptions }, +}); diff --git a/packages/inter-protocol/src/proposals/upgrade-vaults.js b/packages/inter-protocol/src/proposals/upgrade-vaults.js index 2088aac9e67..8befdd0c5a3 100644 --- a/packages/inter-protocol/src/proposals/upgrade-vaults.js +++ b/packages/inter-protocol/src/proposals/upgrade-vaults.js @@ -1,6 +1,5 @@ import { E } from '@endo/far'; import { makeNotifierFromAsyncIterable } from '@agoric/notifier'; -import { AmountMath } from '@agoric/ertp/src/index.js'; import { makeTracer } from '@agoric/internal/src/index.js'; import { Fail } from '@endo/errors'; import { TimeMath } from '@agoric/time'; @@ -9,6 +8,7 @@ const trace = makeTracer('upgrade Vaults proposal'); /** * @typedef {PromiseSpaceOf<{ + * priceAuthority8400: Instance; * auctionUpgradeNewInstance: Instance; * }>} interlockPowers */ @@ -27,6 +27,7 @@ export const upgradeVaults = async ( reserveKit, vaultFactoryKit, zoe, + priceAuthority8400, }, produce: { auctionUpgradeNewInstance: auctionUpgradeNewInstanceProducer }, installation: { @@ -44,6 +45,8 @@ export const upgradeVaults = async ( const allBrands = await E(zoe).getBrands(directorInstance); const { Minted: _istBrand, ...vaultBrands } = allBrands; + await priceAuthority8400; + const bundleID = vaultsRef.bundleID; console.log(`upgradeVaults: bundleId`, bundleID); /** @@ -77,24 +80,21 @@ export const upgradeVaults = async ( const subscription = E(directorPF).getElectorateSubscription(); const notifier = makeNotifierFromAsyncIterable(subscription); - let { value, updateCount } = await notifier.getUpdateSince(0n); - // @ts-expect-error It's an amount. - while (AmountMath.isEmpty(value.current.MinInitialDebt.value)) { - ({ value, updateCount } = await notifier.getUpdateSince(updateCount)); - trace( - `minInitialDebt was empty, retried`, - value.current.MinInitialDebt.value, - ); - } + const { updateCount } = await notifier.getUpdateSince(); + + // subscribeAfter() retrieves the latest value. + const after = await E(subscription).subscribeAfter(updateCount); + const { current } = after.head.value; return harden({ - MinInitialDebt: value.current.MinInitialDebt.value, - ReferencedUI: value.current.ReferencedUI.value, - RecordingPeriod: value.current.RecordingPeriod.value, - ChargingPeriod: value.current.ChargingPeriod.value, + MinInitialDebt: current.MinInitialDebt.value, + ReferencedUI: current.ReferencedUI.value, + RecordingPeriod: current.RecordingPeriod.value, + ChargingPeriod: current.ChargingPeriod.value, }); }; const directorParamOverrides = await readCurrentDirectorParams(); + trace({ directorParamOverrides }); const readManagerParams = async () => { const { publicFacet: directorPF } = kit; @@ -104,34 +104,22 @@ export const upgradeVaults = async ( const params = {}; for (const kwd of Object.keys(vaultBrands)) { const collateralBrand = vaultBrands[kwd]; - const subscription = E(directorPF).getSubscription({ + + /** @type {any} */ + const governedParams = await E(directorPF).getGovernedParams({ collateralBrand, }); - const notifier = makeNotifierFromAsyncIterable(subscription); - let { value, updateCount } = await notifier.getUpdateSince(0n); - // @ts-expect-error It's an amount. - if (AmountMath.isEmpty(value.current.DebtLimit.value)) { - // The parameters might have been empty at start, and the notifier might - // give the first state before the current state. - trace(`debtLimit was empty, retrying`, value.current.DebtLimit.value); - ({ value, updateCount } = await notifier.getUpdateSince(updateCount)); - - // @ts-expect-error It's an amount. - if (AmountMath.isEmpty(value.current.DebtLimit.value)) { - trace('debtLimit was empty after retrying'); - throw Error('🚨Governed parameters empty after retry, Giving up'); - } - } - trace(kwd, 'params at', updateCount, 'are', value.current); + trace({ kwd, governedParams }); params[kwd] = harden({ brand: collateralBrand, - debtLimit: value.current.DebtLimit.value, - interestRate: value.current.InterestRate.value, - liquidationMargin: value.current.LiquidationMargin.value, - liquidationPadding: value.current.LiquidationPadding.value, - liquidationPenalty: value.current.LiquidationPenalty.value, - mintFee: value.current.MintFee.value, + debtLimit: governedParams.DebtLimit.value, + interestRate: governedParams.InterestRate.value, + liquidationMargin: governedParams.LiquidationMargin.value, + liquidationPadding: governedParams.LiquidationPadding.value, + liquidationPenalty: governedParams.LiquidationPenalty.value, + mintFee: governedParams.MintFee.value, }); + trace(kwd, params[kwd]); } return params; }; @@ -167,12 +155,11 @@ export const upgradeVaults = async ( trace('upgraded vaultFactory.', upgradeResult); }; - await upgradeVaultFactory(); // @ts-expect-error It's saved in econ-behaviors.js:startVaultFactory() const vaultFactoryPrivateArgs = kit.privateArgs; - console.log('UPGV upgraded vaults, restarting governor'); + trace('restarting governor'); const ecf = await electorateCreatorFacet; // restart vaultFactory governor @@ -183,7 +170,7 @@ export const upgradeVaults = async ( }), ); - console.log('UPGV restarted governor'); + trace('restarted governor'); }; const uV = 'upgradeVaults'; @@ -200,6 +187,7 @@ export const getManifestForUpgradeVaults = async ( manifest: { [upgradeVaults.name]: { consume: { + priceAuthority8400: uV, auctionUpgradeNewInstance: uV, chainTimerService: uV, economicCommitteeCreatorFacet: uV, diff --git a/packages/inter-protocol/src/proposals/utils.js b/packages/inter-protocol/src/proposals/utils.js index f0c00e9e18e..c191824468f 100644 --- a/packages/inter-protocol/src/proposals/utils.js +++ b/packages/inter-protocol/src/proposals/utils.js @@ -2,6 +2,7 @@ import { Fail } from '@endo/errors'; import { E } from '@endo/far'; import { WalletName } from '@agoric/internal'; import { getCopyMapEntries, makeCopyMap } from '@agoric/store'; +import { assertPathSegment } from '@agoric/internal/src/lib-chainStorage.js'; /** @import {CopyMap} from '@endo/patterns'; */ @@ -163,3 +164,10 @@ export const oracleBrandFeedName = (inBrandName, outBrandName) => export const scaledPriceFeedName = issuerName => `scaledPriceAuthority-${issuerName}`; + +/** @type {(name: string) => string} */ +export const sanitizePathSegment = name => { + const candidate = name.replace(/ /g, '_'); + assertPathSegment(candidate); + return candidate; +}; diff --git a/packages/inter-protocol/src/vaultFactory/vaultManager.js b/packages/inter-protocol/src/vaultFactory/vaultManager.js index 20ffb29ab71..474d7843927 100644 --- a/packages/inter-protocol/src/vaultFactory/vaultManager.js +++ b/packages/inter-protocol/src/vaultFactory/vaultManager.js @@ -455,6 +455,7 @@ export const prepareVaultManagerKit = ( // will throw. See https://github.com/Agoric/agoric-sdk/issues/4317 const quoteWatcher = harden({ onFulfilled(value) { + trace('watcher updated price', value); ephemera.storedCollateralQuote = value; }, onRejected() { diff --git a/packages/vats/src/core/types-ambient.d.ts b/packages/vats/src/core/types-ambient.d.ts index db262a6f4de..333898e6481 100644 --- a/packages/vats/src/core/types-ambient.d.ts +++ b/packages/vats/src/core/types-ambient.d.ts @@ -230,6 +230,7 @@ type WellKnownContracts = { mintHolder: typeof import('@agoric/vats/src/mintHolder.js').start; psm: typeof import('@agoric/inter-protocol/src/psm/psm.js').start; provisionPool: typeof import('@agoric/inter-protocol/src/provisionPool.js').start; + priceAggregator: typeof import('@agoric/inter-protocol/src/price/fluxAggregatorContract.js').start; reserve: typeof import('@agoric/inter-protocol/src/reserve/assetReserve.js').start; VaultFactory: typeof import('@agoric/inter-protocol/src/vaultFactory/vaultFactory.js').start; // no typeof because walletFactory is exporting `start` as a type @@ -377,6 +378,8 @@ type ChainBootstrapSpaceT = { powerStore: MapStore; priceAuthorityVat: Awaited; priceAuthority: import('@agoric/zoe/tools/types.js').PriceAuthority; + // signal that price feeds have #8400 QuotePayments storage leak fixed + priceAuthority8400: import('@agoric/zoe/tools/types.js').PriceAuthority; priceAuthorityAdmin: import('@agoric/vats/src/priceAuthorityRegistry').PriceAuthorityRegistryAdmin; provisioning: Awaited | undefined; provisionBridgeManager: diff --git a/packages/zoe/src/contractSupport/priceAuthorityInitial.js b/packages/zoe/src/contractSupport/priceAuthorityInitial.js index b5378654542..fc19c7747fb 100644 --- a/packages/zoe/src/contractSupport/priceAuthorityInitial.js +++ b/packages/zoe/src/contractSupport/priceAuthorityInitial.js @@ -109,7 +109,7 @@ export const makeInitialTransform = ( : quoteP; }; - return Far('PriceAuthority', { + return Far('PriceAuthorityWithInitialValue', { ...priceAuthority, makeQuoteNotifier, quoteGiven, diff --git a/packages/zoe/src/contractSupport/priceAuthorityTransform.js b/packages/zoe/src/contractSupport/priceAuthorityTransform.js index ce2d79217b9..ac6425c2b9f 100644 --- a/packages/zoe/src/contractSupport/priceAuthorityTransform.js +++ b/packages/zoe/src/contractSupport/priceAuthorityTransform.js @@ -182,7 +182,7 @@ export const makePriceAuthorityTransform = async ({ }; /** @type {PriceAuthority} */ - const priceAuthority = Far('PriceAuthority', { + const priceAuthority = Far('ScaledPriceAuthority', { getQuoteIssuer(brandIn, brandOut) { assertBrands(brandIn, brandOut); return quoteIssuer; diff --git a/packages/zoe/src/contracts/scaledPriceAuthority.js b/packages/zoe/src/contracts/scaledPriceAuthority.js index b558a315c16..2b43bff8fcf 100644 --- a/packages/zoe/src/contracts/scaledPriceAuthority.js +++ b/packages/zoe/src/contracts/scaledPriceAuthority.js @@ -52,7 +52,9 @@ export const prepare = async (zcf, privateArgs, baggage) => { const priceAuthority = makePriceAuthorityTransform({ quoteMint, - sourcePriceAuthority, + // If the priceAuthority is overridden in privateArgs, use that version + sourcePriceAuthority: + privateArgs?.newPriceAuthority || sourcePriceAuthority, sourceBrandIn, sourceBrandOut, actualBrandIn,