From d32e1bdd2a2de98996ea473c7f99aa9276f7ce4d Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Fri, 28 May 2021 15:32:41 -0700 Subject: [PATCH 01/11] feat: manage parameters for a contract closes #3186 outstanding issues: * should this validate types? * is there a clean way to assert something is an amount? * should managed amounts (and ratios) only set the value and leave the brand to the managed contract? * are there others types to add or remove? --- package.json | 1 + packages/governance/CHANGELOG.md | 5 + packages/governance/NEWS.md | 0 packages/governance/jsconfig.json | 18 ++ packages/governance/package.json | 83 +++++++++ packages/governance/src/param-manager.js | 93 ++++++++++ packages/governance/src/types.js | 34 ++++ .../governance/test/test-param-manager.js | 163 ++++++++++++++++++ 8 files changed, 397 insertions(+) create mode 100644 packages/governance/CHANGELOG.md create mode 100644 packages/governance/NEWS.md create mode 100644 packages/governance/jsconfig.json create mode 100644 packages/governance/package.json create mode 100644 packages/governance/src/param-manager.js create mode 100644 packages/governance/src/types.js create mode 100644 packages/governance/test/test-param-manager.js diff --git a/package.json b/package.json index fbfa4c8b59b..633debfc2f2 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "packages/bundle-source", "packages/import-bundle", "packages/eventual-send", + "packages/governance", "packages/promise-kit", "packages/tame-metering", "packages/transform-metering", diff --git a/packages/governance/CHANGELOG.md b/packages/governance/CHANGELOG.md new file mode 100644 index 00000000000..767840ada8e --- /dev/null +++ b/packages/governance/CHANGELOG.md @@ -0,0 +1,5 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + diff --git a/packages/governance/NEWS.md b/packages/governance/NEWS.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/governance/jsconfig.json b/packages/governance/jsconfig.json new file mode 100644 index 00000000000..195554cb5e5 --- /dev/null +++ b/packages/governance/jsconfig.json @@ -0,0 +1,18 @@ +// This file can contain .js-specific Typescript compiler config. +{ + "compilerOptions": { + "target": "esnext", + + "noEmit": true, +/* + // The following flags are for creating .d.ts files: + "noEmit": false, + "declaration": true, + "emitDeclarationOnly": true, +*/ + "downlevelIteration": true, + "strictNullChecks": true, + "moduleResolution": "node", + }, + "include": ["src/**/*.js", "test/**/*.js", "exported.js", "globals.d.ts"], +} diff --git a/packages/governance/package.json b/packages/governance/package.json new file mode 100644 index 00000000000..bdebba1b597 --- /dev/null +++ b/packages/governance/package.json @@ -0,0 +1,83 @@ +{ + "name": "@agoric/governance", + "version": "0.1.0", + "description": "Core governance support", + "parsers": { + "js": "mjs" + }, + "main": "src/missing.js", + "engines": { + "node": ">=11.0" + }, + "scripts": { + "build": "exit 0", + "test": "ava", + "test:xs": "exit 0", + "lint-fix": "yarn lint:eslint --fix && yarn lint:types", + "lint-check": "yarn lint", + "lint": "yarn lint:types && yarn lint:eslint", + "lint:eslint": "eslint '**/*.js'", + "lint:types": "tsc -p jsconfig.json" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Agoric/agoric-sdk.git" + }, + "author": "Agoric", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/Agoric/agoric-sdk/issues" + }, + "homepage": "https://github.com/Agoric/agoric-sdk#readme", + "dependencies": { + "@agoric/assert": "^0.2.12", + "@agoric/bundle-source": "^1.3.7", + "@agoric/captp": "^1.7.13", + "@agoric/deploy-script-support": "^0.2.9", + "@agoric/ertp": "^0.11.2", + "@agoric/eventual-send": "^0.13.14", + "@agoric/marshal": "^0.4.11", + "@agoric/nat": "^4.0.0", + "@agoric/notifier": "^0.3.14", + "@agoric/promise-kit": "^0.2.13", + "@agoric/store": "^0.4.14", + "@agoric/swingset-vat": "^0.17.2", + "@agoric/zoe": "^0.15.7" + }, + "devDependencies": { + "@agoric/install-ses": "^0.5.13", + "ava": "^3.12.1", + "esm": "^3.2.25", + "ses": "^0.12.7" + }, + "files": [ + "bundles/", + "src/", + "exported.js", + "NEWS.md" + ], + "ava": { + "files": [ + "test/**/test-*.js" + ], + "require": [ + "esm" + ], + "timeout": "10m" + }, + "eslintConfig": { + "extends": [ + "@agoric" + ] + }, + "eslintIgnore": [ + "bundle-*.js" + ], + "prettier": { + "trailingComma": "all", + "singleQuote": true + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/governance/src/param-manager.js b/packages/governance/src/param-manager.js new file mode 100644 index 00000000000..b06771ea882 --- /dev/null +++ b/packages/governance/src/param-manager.js @@ -0,0 +1,93 @@ +// @ts-check + +import { makeStore } from '@agoric/store'; +import { assert, details as X } from '@agoric/assert'; +import { Nat } from '@agoric/nat'; +import { assertIsRatio } from '@agoric/zoe/src/contractSupport'; +import { AmountMath, looksLikeBrand } from '@agoric/ertp'; + +const ParamType = { + NAT: 'nat', + BIGINT: 'bigint', + STRING: 'string', + RATIO: 'ratio', + AMOUNT: 'amount', + BRAND: 'brand', +}; +harden(ParamType); + +function assertType(type, value, name) { + if (!type) { + // undefined type means don't verify. Did we omit an interesting type? + return; + } + + switch (type) { + case ParamType.NAT: + Nat(value); + break; + case ParamType.BIGINT: + assert.typeof(value, 'bigint'); + break; + case ParamType.STRING: + assert.typeof(value, 'string'); + break; + case ParamType.RATIO: + assertIsRatio(value); + break; + case ParamType.AMOUNT: + // TODO(hibbert): is there a clean way to assert something is an amount? + // An alternate approach would be to say the contract knows the brand and + // the managed parameter only needs to supply the value. + assert( + AmountMath.isEqual(value, value), + X`value for ${name} must be an Amount, was ${value}`, + ); + break; + case ParamType.BRAND: + assert( + looksLikeBrand(value), + X`value for ${name} must be a brand, was ${value}`, + ); + break; + default: + assert.fail(X`unknown type guard ${type}`); + } +} + +function parse(paramDesc) { + const bindings = makeStore('name'); + const types = makeStore('name'); + + paramDesc.forEach(({ name, value, type }) => { + assert.typeof(name, 'string'); + assertType(type, value, name); + bindings.init(name, value); + types.init(name, type); + }); + + return { bindings, types }; +} + +/** @type {BuildParamManager} */ +function buildParamManager(paramDesc) { + const { bindings, types } = parse(paramDesc); + + const publicFacet = { + lookup(name) { + return bindings.get(name); + }, + }; + + const manager = { + update(name, value) { + assertType(types.get(name), value, name); + bindings.set(name, value); + }, + }; + + return { publicFacet, manager }; +} +harden(buildParamManager); + +export { ParamType, buildParamManager }; diff --git a/packages/governance/src/types.js b/packages/governance/src/types.js new file mode 100644 index 00000000000..0521a569f59 --- /dev/null +++ b/packages/governance/src/types.js @@ -0,0 +1,34 @@ +// @ts-check + +/** + * @typedef {'nat' | 'bigint' | 'string' | 'ratio' | 'amount' | 'brand' } ParamType + */ + +/** + * @typedef {Object} ParamManager + * @property {(name: string, value: any) => void} update + */ + +/** + * @typedef {Object} ParamManagerPublic + * @property {(name: string) => any} lookup + */ + +/** + * @typedef {{name: string, + * value: any, + * type: string, + * }} ParamDescription + */ + +// type: string above should be type: ParamType + +/** + * @typedef {Array} ParamDescriptions + */ + +/** + * @callback BuildParamManager + * @param {ParamDescriptions} paramDesc + * @returns {{publicFacet: ParamManagerPublic, manager: ParamManager }} + */ diff --git a/packages/governance/test/test-param-manager.js b/packages/governance/test/test-param-manager.js new file mode 100644 index 00000000000..60c3dfd3bab --- /dev/null +++ b/packages/governance/test/test-param-manager.js @@ -0,0 +1,163 @@ +// @ts-check + +import { test } from '@agoric/zoe/tools/prepare-test-env-ava'; +import '@agoric/zoe/exported'; +import { AmountMath, AssetKind, makeIssuerKit } from '@agoric/ertp'; +import { makeRatio } from '@agoric/zoe/src/contractSupport'; + +import { buildParamManager, ParamType } from '../src/param-manager'; + +const BASIS_POINTS = 10_000; + +test('params one Nat', async t => { + const { publicFacet, manager } = buildParamManager([ + { + name: 'number', + value: 13, + type: ParamType.NAT, + }, + ]); + t.is(publicFacet.lookup('number'), 13); + manager.update('number', 42); + t.is(publicFacet.lookup('number'), 42); + + t.throws( + () => manager.update('string', 'foo'), + { + message: '"name" not found: "string"', + }, + '"string" was not a registered name', + ); + t.throws( + () => manager.update('number', 18.1), + { + message: '18.1 not a safe integer', + }, + 'value should be a nat', + ); +}); + +test('params one String', async t => { + const { publicFacet, manager } = buildParamManager([ + { + name: 'string', + value: 'foo', + type: ParamType.STRING, + }, + ]); + t.is(publicFacet.lookup('string'), 'foo'); + manager.update('string', 'bar'); + t.is(publicFacet.lookup('string'), 'bar'); + + t.throws( + () => manager.update('number', 'foo'), + { + message: '"name" not found: "number"', + }, + '"number" was not a registered name', + ); + t.throws( + () => manager.update('string', 18.1), + { + message: '18.1 must be a string', + }, + 'value should be a string', + ); +}); + +test('params one Amount', async t => { + const { brand } = makeIssuerKit('roses', AssetKind.SET); + const { publicFacet, manager } = buildParamManager([ + { + name: 'amount', + value: AmountMath.makeEmpty(brand), + type: ParamType.AMOUNT, + }, + ]); + t.deepEqual(publicFacet.lookup('amount'), AmountMath.makeEmpty(brand)); + manager.update('amount', AmountMath.make(brand, [13])); + t.deepEqual(publicFacet.lookup('amount'), AmountMath.make(brand, [13])); + + t.throws( + () => manager.update('number', 13), + { + message: '"name" not found: "number"', + }, + '"number" was not a registered name', + ); + + t.throws( + () => manager.update('amount', 18.1), + { + message: + "The amount 18.1 doesn't look like an amount. Did you pass a value instead?", + }, + 'value should be a amount', + ); +}); + +test('params one BigInt', async t => { + const { publicFacet, manager } = buildParamManager([ + { + name: 'bigint', + value: 314159n, + type: ParamType.BIGINT, + }, + ]); + t.deepEqual(publicFacet.lookup('bigint'), 314159n); + manager.update('bigint', 271828182845904523536n); + t.deepEqual(publicFacet.lookup('bigint'), 271828182845904523536n); + + t.throws( + () => manager.update('bigint', 18.1), + { + message: '18.1 must be a bigint', + }, + 'value should be a bigint', + ); +}); + +test('params one ratio', async t => { + const { brand } = makeIssuerKit('roses', AssetKind.SET); + const { publicFacet, manager } = buildParamManager([ + { + name: 'ratio', + value: makeRatio(7, brand), + type: ParamType.RATIO, + }, + ]); + t.deepEqual(publicFacet.lookup('ratio'), makeRatio(7, brand)); + manager.update('ratio', makeRatio(701, brand, BASIS_POINTS)); + t.deepEqual(publicFacet.lookup('ratio'), makeRatio(701, brand, BASIS_POINTS)); + + t.throws( + () => manager.update('ratio', 18.1), + { + message: 'Ratio 18.1 must be a record with 2 fields.', + }, + 'value should be a ratio', + ); +}); + +test('params one brand', async t => { + const { brand: roseBrand } = makeIssuerKit('roses', AssetKind.SET); + const { brand: thornBrand } = makeIssuerKit('thorns'); + const { publicFacet, manager } = buildParamManager([ + { + name: 'brand', + value: roseBrand, + type: ParamType.BRAND, + }, + ]); + t.deepEqual(publicFacet.lookup('brand'), roseBrand); + manager.update('brand', thornBrand); + t.deepEqual(publicFacet.lookup('brand'), thornBrand); + + t.throws( + () => manager.update('brand', 18.1), + { + message: 'value for "brand" must be a brand, was 18.1', + }, + 'value should be a brand', + ); +}); From 4563d42614555a5a088559f03c57ae44fa22f66a Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Tue, 8 Jun 2021 11:17:05 -0700 Subject: [PATCH 02/11] chore: convert functions to arrow functions --- packages/governance/src/param-manager.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/governance/src/param-manager.js b/packages/governance/src/param-manager.js index b06771ea882..cca890c6262 100644 --- a/packages/governance/src/param-manager.js +++ b/packages/governance/src/param-manager.js @@ -16,7 +16,7 @@ const ParamType = { }; harden(ParamType); -function assertType(type, value, name) { +const assertType = (type, value, name) => { if (!type) { // undefined type means don't verify. Did we omit an interesting type? return; @@ -53,9 +53,9 @@ function assertType(type, value, name) { default: assert.fail(X`unknown type guard ${type}`); } -} +}; -function parse(paramDesc) { +const parse = paramDesc => { const bindings = makeStore('name'); const types = makeStore('name'); @@ -67,10 +67,10 @@ function parse(paramDesc) { }); return { bindings, types }; -} +}; /** @type {BuildParamManager} */ -function buildParamManager(paramDesc) { +const buildParamManager = paramDesc => { const { bindings, types } = parse(paramDesc); const publicFacet = { @@ -87,7 +87,7 @@ function buildParamManager(paramDesc) { }; return { publicFacet, manager }; -} +}; harden(buildParamManager); export { ParamType, buildParamManager }; From 5ce2ecf874b6b74a78c1a4353f3bc70afa296114 Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Wed, 9 Jun 2021 17:10:54 -0700 Subject: [PATCH 03/11] chore: add types for handle and any. --- packages/governance/src/param-manager.js | 43 +++++++++++-------- .../governance/test/test-param-manager.js | 39 +++++++++++++++++ 2 files changed, 65 insertions(+), 17 deletions(-) diff --git a/packages/governance/src/param-manager.js b/packages/governance/src/param-manager.js index cca890c6262..f57b766a8c4 100644 --- a/packages/governance/src/param-manager.js +++ b/packages/governance/src/param-manager.js @@ -7,12 +7,14 @@ import { assertIsRatio } from '@agoric/zoe/src/contractSupport'; import { AmountMath, looksLikeBrand } from '@agoric/ertp'; const ParamType = { - NAT: 'nat', - BIGINT: 'bigint', - STRING: 'string', - RATIO: 'ratio', AMOUNT: 'amount', + ANY: 'any', + BIGINT: 'bigint', BRAND: 'brand', + HANDLE: 'handle', + NAT: 'nat', + RATIO: 'ratio', + STRING: 'string', }; harden(ParamType); @@ -23,18 +25,6 @@ const assertType = (type, value, name) => { } switch (type) { - case ParamType.NAT: - Nat(value); - break; - case ParamType.BIGINT: - assert.typeof(value, 'bigint'); - break; - case ParamType.STRING: - assert.typeof(value, 'string'); - break; - case ParamType.RATIO: - assertIsRatio(value); - break; case ParamType.AMOUNT: // TODO(hibbert): is there a clean way to assert something is an amount? // An alternate approach would be to say the contract knows the brand and @@ -44,12 +34,32 @@ const assertType = (type, value, name) => { X`value for ${name} must be an Amount, was ${value}`, ); break; + case ParamType.ANY: + break; + case ParamType.BIGINT: + assert.typeof(value, 'bigint'); + break; case ParamType.BRAND: assert( looksLikeBrand(value), X`value for ${name} must be a brand, was ${value}`, ); break; + case ParamType.HANDLE: + assert( + typeof value === 'object' && !Object.getOwnPropertyNames(value).length, + X`value for ${name} must be an empty object, was ${value}`, + ); + break; + case ParamType.NAT: + Nat(value); + break; + case ParamType.RATIO: + assertIsRatio(value); + break; + case ParamType.STRING: + assert.typeof(value, 'string'); + break; default: assert.fail(X`unknown type guard ${type}`); } @@ -60,7 +70,6 @@ const parse = paramDesc => { const types = makeStore('name'); paramDesc.forEach(({ name, value, type }) => { - assert.typeof(name, 'string'); assertType(type, value, name); bindings.init(name, value); types.init(name, type); diff --git a/packages/governance/test/test-param-manager.js b/packages/governance/test/test-param-manager.js index 60c3dfd3bab..69d88dcfc48 100644 --- a/packages/governance/test/test-param-manager.js +++ b/packages/governance/test/test-param-manager.js @@ -5,6 +5,8 @@ import '@agoric/zoe/exported'; import { AmountMath, AssetKind, makeIssuerKit } from '@agoric/ertp'; import { makeRatio } from '@agoric/zoe/src/contractSupport'; +import { makeHandle } from '@agoric/zoe/src/makeHandle'; +import { bar } from '@agoric/bundle-source/demo/circular/b'; import { buildParamManager, ParamType } from '../src/param-manager'; const BASIS_POINTS = 10_000; @@ -161,3 +163,40 @@ test('params one brand', async t => { 'value should be a brand', ); }); + +test('params one handle', async t => { + const fooHandle = makeHandle('foo'); + const barHandle = makeHandle('bar'); + const { publicFacet, manager } = buildParamManager([ + { + name: 'handle', + value: fooHandle, + type: ParamType.HANDLE, + }, + ]); + t.deepEqual(publicFacet.lookup('handle'), fooHandle); + manager.update('handle', barHandle); + t.deepEqual(publicFacet.lookup('handle'), barHandle); + + t.throws( + () => manager.update('handle', 18.1), + { + message: 'value for "handle" must be an empty object, was 18.1', + }, + 'value for "handle" must be an empty object, was 18.1', + ); +}); + +test('params one any', async t => { + const fooHandle = makeHandle('foo'); + const { publicFacet, manager } = buildParamManager([ + { + name: 'stuff', + value: fooHandle, + type: ParamType.ANY, + }, + ]); + t.deepEqual(publicFacet.lookup('stuff'), fooHandle); + manager.update('stuff', 18.1); + t.deepEqual(publicFacet.lookup('stuff'), 18.1); +}); From e1dc132c53c52b57ef71a572507f29fbdbcdd233 Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Wed, 9 Jun 2021 17:43:40 -0700 Subject: [PATCH 04/11] chore: drop an inadvertant import --- packages/governance/test/test-param-manager.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/governance/test/test-param-manager.js b/packages/governance/test/test-param-manager.js index 69d88dcfc48..4c10b6cb20a 100644 --- a/packages/governance/test/test-param-manager.js +++ b/packages/governance/test/test-param-manager.js @@ -6,7 +6,6 @@ import { AmountMath, AssetKind, makeIssuerKit } from '@agoric/ertp'; import { makeRatio } from '@agoric/zoe/src/contractSupport'; import { makeHandle } from '@agoric/zoe/src/makeHandle'; -import { bar } from '@agoric/bundle-source/demo/circular/b'; import { buildParamManager, ParamType } from '../src/param-manager'; const BASIS_POINTS = 10_000; From 07ec824eeea17881dcd3b1b32b56195b33964e63 Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Tue, 15 Jun 2021 17:50:23 -0700 Subject: [PATCH 05/11] feat: add lookup for param names and details --- packages/governance/src/param-manager.js | 10 ++++-- .../governance/test/test-param-manager.js | 31 +++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/governance/src/param-manager.js b/packages/governance/src/param-manager.js index f57b766a8c4..bbaf468fd4e 100644 --- a/packages/governance/src/param-manager.js +++ b/packages/governance/src/param-manager.js @@ -83,9 +83,13 @@ const buildParamManager = paramDesc => { const { bindings, types } = parse(paramDesc); const publicFacet = { - lookup(name) { - return bindings.get(name); - }, + lookup: name => bindings.get(name), + getDetails: name => ({ + name, + value: bindings.get(name), + type: types.get(name), + }), + definedNames: () => bindings.keys(), }; const manager = { diff --git a/packages/governance/test/test-param-manager.js b/packages/governance/test/test-param-manager.js index 4c10b6cb20a..a48b76e31be 100644 --- a/packages/governance/test/test-param-manager.js +++ b/packages/governance/test/test-param-manager.js @@ -199,3 +199,34 @@ test('params one any', async t => { manager.update('stuff', 18.1); t.deepEqual(publicFacet.lookup('stuff'), 18.1); }); + +test('params keys', async t => { + const fooHandle = makeHandle('foo'); + const { publicFacet, manager } = buildParamManager([ + { + name: 'stuff', + value: fooHandle, + type: ParamType.ANY, + }, + { + name: 'bigint', + value: 314159n, + type: ParamType.BIGINT, + }, + ]); + t.deepEqual(publicFacet.lookup('stuff'), fooHandle); + manager.update('stuff', 18.1); + t.deepEqual(publicFacet.lookup('stuff'), 18.1); + + t.deepEqual(publicFacet.getDetails('stuff'), { + name: 'stuff', + value: 18.1, + type: ParamType.ANY, + }); + t.deepEqual(publicFacet.getDetails('bigint'), { + name: 'bigint', + value: 314159n, + type: ParamType.BIGINT, + }); + t.deepEqual(publicFacet.definedNames(), ['stuff', 'bigint']); +}); From ce7ef0b87bf164cf3a1326d03b6344924cec855f Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Tue, 15 Jun 2021 17:56:54 -0700 Subject: [PATCH 06/11] chore: update version info --- packages/governance/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/governance/package.json b/packages/governance/package.json index bdebba1b597..57bf30646f1 100644 --- a/packages/governance/package.json +++ b/packages/governance/package.json @@ -30,7 +30,7 @@ }, "homepage": "https://github.com/Agoric/agoric-sdk#readme", "dependencies": { - "@agoric/assert": "^0.2.12", + "@agoric/assert": "^0.3.0", "@agoric/bundle-source": "^1.3.7", "@agoric/captp": "^1.7.13", "@agoric/deploy-script-support": "^0.2.9", @@ -42,7 +42,7 @@ "@agoric/promise-kit": "^0.2.13", "@agoric/store": "^0.4.14", "@agoric/swingset-vat": "^0.17.2", - "@agoric/zoe": "^0.15.7" + "@agoric/zoe": "^0.16.0" }, "devDependencies": { "@agoric/install-ses": "^0.5.13", From b07a981b4132dff32837c4e928e9b770d78bbfd5 Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Wed, 16 Jun 2021 16:41:50 -0700 Subject: [PATCH 07/11] chore: review suggestions dependency reduction support instance and installation rather than handle support NAT type which must be a bigint rename publicFacet to params --- packages/governance/jsconfig.json | 2 +- packages/governance/package.json | 21 +--- .../src/{param-manager.js => paramManager.js} | 41 ++++--- packages/governance/src/types.js | 31 +++-- .../governance/test/test-param-manager.js | 111 ++++++++---------- 5 files changed, 100 insertions(+), 106 deletions(-) rename packages/governance/src/{param-manager.js => paramManager.js} (74%) diff --git a/packages/governance/jsconfig.json b/packages/governance/jsconfig.json index 195554cb5e5..b3b497b681f 100644 --- a/packages/governance/jsconfig.json +++ b/packages/governance/jsconfig.json @@ -14,5 +14,5 @@ "strictNullChecks": true, "moduleResolution": "node", }, - "include": ["src/**/*.js", "test/**/*.js", "exported.js", "globals.d.ts"], + "include": ["src/**/*.js", "test/**/*.js"], } diff --git a/packages/governance/package.json b/packages/governance/package.json index 57bf30646f1..f762c55bfbd 100644 --- a/packages/governance/package.json +++ b/packages/governance/package.json @@ -5,9 +5,9 @@ "parsers": { "js": "mjs" }, - "main": "src/missing.js", + "main": "src/paramManager.js", "engines": { - "node": ">=11.0" + "node": ">=14.15.0" }, "scripts": { "build": "exit 0", @@ -31,29 +31,19 @@ "homepage": "https://github.com/Agoric/agoric-sdk#readme", "dependencies": { "@agoric/assert": "^0.3.0", - "@agoric/bundle-source": "^1.3.7", - "@agoric/captp": "^1.7.13", - "@agoric/deploy-script-support": "^0.2.9", "@agoric/ertp": "^0.11.2", - "@agoric/eventual-send": "^0.13.14", - "@agoric/marshal": "^0.4.11", "@agoric/nat": "^4.0.0", "@agoric/notifier": "^0.3.14", - "@agoric/promise-kit": "^0.2.13", - "@agoric/store": "^0.4.14", - "@agoric/swingset-vat": "^0.17.2", + "@agoric/store": "^0.4.15", "@agoric/zoe": "^0.16.0" }, "devDependencies": { "@agoric/install-ses": "^0.5.13", "ava": "^3.12.1", - "esm": "^3.2.25", - "ses": "^0.12.7" + "esm": "^3.2.25" }, "files": [ - "bundles/", "src/", - "exported.js", "NEWS.md" ], "ava": { @@ -70,9 +60,6 @@ "@agoric" ] }, - "eslintIgnore": [ - "bundle-*.js" - ], "prettier": { "trailingComma": "all", "singleQuote": true diff --git a/packages/governance/src/param-manager.js b/packages/governance/src/paramManager.js similarity index 74% rename from packages/governance/src/param-manager.js rename to packages/governance/src/paramManager.js index bbaf468fd4e..045113942da 100644 --- a/packages/governance/src/param-manager.js +++ b/packages/governance/src/paramManager.js @@ -2,16 +2,26 @@ import { makeStore } from '@agoric/store'; import { assert, details as X } from '@agoric/assert'; -import { Nat } from '@agoric/nat'; import { assertIsRatio } from '@agoric/zoe/src/contractSupport'; import { AmountMath, looksLikeBrand } from '@agoric/ertp'; - +/** + * @type {{ + * AMOUNT: 'amount', + * ANY: 'any', + * BRAND: 'brand', + * INSTANCE: 'instance', + * INSTALLATION: 'installation', + * NAT: 'nat', + * RATIO: 'ratio', + * STRING: 'string', + * }} + */ const ParamType = { AMOUNT: 'amount', ANY: 'any', - BIGINT: 'bigint', BRAND: 'brand', - HANDLE: 'handle', + INSTANCE: 'instance', + INSTALLATION: 'installation', NAT: 'nat', RATIO: 'ratio', STRING: 'string', @@ -26,9 +36,7 @@ const assertType = (type, value, name) => { switch (type) { case ParamType.AMOUNT: - // TODO(hibbert): is there a clean way to assert something is an amount? - // An alternate approach would be to say the contract knows the brand and - // the managed parameter only needs to supply the value. + // It would be nice to have a clean way to assert something is an amount. assert( AmountMath.isEqual(value, value), X`value for ${name} must be an Amount, was ${value}`, @@ -36,23 +44,28 @@ const assertType = (type, value, name) => { break; case ParamType.ANY: break; - case ParamType.BIGINT: - assert.typeof(value, 'bigint'); - break; case ParamType.BRAND: assert( looksLikeBrand(value), X`value for ${name} must be a brand, was ${value}`, ); break; - case ParamType.HANDLE: + case ParamType.INSTALLATION: + // TODO(3344): add a better assertion once Zoe validates installations + assert( + typeof value === 'object' && !Object.getOwnPropertyNames(value).length, + X`value for ${name} must be an empty object, was ${value}`, + ); + break; + case ParamType.INSTANCE: + // TODO(3344): add a better assertion once Zoe validates instances assert( typeof value === 'object' && !Object.getOwnPropertyNames(value).length, X`value for ${name} must be an empty object, was ${value}`, ); break; case ParamType.NAT: - Nat(value); + assert.typeof(value, 'bigint'); break; case ParamType.RATIO: assertIsRatio(value); @@ -82,7 +95,7 @@ const parse = paramDesc => { const buildParamManager = paramDesc => { const { bindings, types } = parse(paramDesc); - const publicFacet = { + const params = { lookup: name => bindings.get(name), getDetails: name => ({ name, @@ -99,7 +112,7 @@ const buildParamManager = paramDesc => { }, }; - return { publicFacet, manager }; + return { params, manager }; }; harden(buildParamManager); diff --git a/packages/governance/src/types.js b/packages/governance/src/types.js index 0521a569f59..0260e79ed22 100644 --- a/packages/governance/src/types.js +++ b/packages/governance/src/types.js @@ -1,27 +1,38 @@ // @ts-check /** - * @typedef {'nat' | 'bigint' | 'string' | 'ratio' | 'amount' | 'brand' } ParamType + * @typedef { 'amount' | 'any' | 'brand' | 'installation' | 'instance' | 'nat' | 'ratio' | 'string' } ParamType + */ + +/** + * @typedef { Amount | Brand | Instance| Installation | bigint | Ratio | string | any } ParamValue */ /** * @typedef {Object} ParamManager - * @property {(name: string, value: any) => void} update + * @property {(name: string, value: ParamValue) => void} update */ /** - * @typedef {Object} ParamManagerPublic - * @property {(name: string) => any} lookup + * @typedef {Object} ParamDetails + * @property {string} name + * @property {ParamValue} value + * @property {ParamType} type */ /** - * @typedef {{name: string, - * value: any, - * type: string, - * }} ParamDescription + * @typedef {Object} ParamManagerPublic + * @property {(name: string) => ParamValue} lookup + * @property {(name: string) => ParamDetails} getDetails + * @property {() => string[]} definedNames */ -// type: string above should be type: ParamType +/** + * @typedef {Object} ParamDescription + * @property {string} name + * @property {ParamValue} value + * @property {ParamType} type + */ /** * @typedef {Array} ParamDescriptions @@ -30,5 +41,5 @@ /** * @callback BuildParamManager * @param {ParamDescriptions} paramDesc - * @returns {{publicFacet: ParamManagerPublic, manager: ParamManager }} + * @returns {{params: ParamManagerPublic, manager: ParamManager }} */ diff --git a/packages/governance/test/test-param-manager.js b/packages/governance/test/test-param-manager.js index a48b76e31be..7fac8e49f7e 100644 --- a/packages/governance/test/test-param-manager.js +++ b/packages/governance/test/test-param-manager.js @@ -5,22 +5,21 @@ import '@agoric/zoe/exported'; import { AmountMath, AssetKind, makeIssuerKit } from '@agoric/ertp'; import { makeRatio } from '@agoric/zoe/src/contractSupport'; -import { makeHandle } from '@agoric/zoe/src/makeHandle'; -import { buildParamManager, ParamType } from '../src/param-manager'; +import { buildParamManager, ParamType } from '../src/paramManager'; const BASIS_POINTS = 10_000; test('params one Nat', async t => { - const { publicFacet, manager } = buildParamManager([ + const { params, manager } = buildParamManager([ { name: 'number', - value: 13, + value: 13n, type: ParamType.NAT, }, ]); - t.is(publicFacet.lookup('number'), 13); - manager.update('number', 42); - t.is(publicFacet.lookup('number'), 42); + t.is(params.lookup('number'), 13n); + manager.update('number', 42n); + t.is(params.lookup('number'), 42n); t.throws( () => manager.update('string', 'foo'), @@ -32,23 +31,30 @@ test('params one Nat', async t => { t.throws( () => manager.update('number', 18.1), { - message: '18.1 not a safe integer', + message: '18.1 must be a bigint', }, 'value should be a nat', ); + t.throws( + () => manager.update('number', 13), + { + message: '13 must be a bigint', + }, + 'must be bigint', + ); }); test('params one String', async t => { - const { publicFacet, manager } = buildParamManager([ + const { params, manager } = buildParamManager([ { name: 'string', value: 'foo', type: ParamType.STRING, }, ]); - t.is(publicFacet.lookup('string'), 'foo'); + t.is(params.lookup('string'), 'foo'); manager.update('string', 'bar'); - t.is(publicFacet.lookup('string'), 'bar'); + t.is(params.lookup('string'), 'bar'); t.throws( () => manager.update('number', 'foo'), @@ -68,16 +74,16 @@ test('params one String', async t => { test('params one Amount', async t => { const { brand } = makeIssuerKit('roses', AssetKind.SET); - const { publicFacet, manager } = buildParamManager([ + const { params, manager } = buildParamManager([ { name: 'amount', value: AmountMath.makeEmpty(brand), type: ParamType.AMOUNT, }, ]); - t.deepEqual(publicFacet.lookup('amount'), AmountMath.makeEmpty(brand)); + t.deepEqual(params.lookup('amount'), AmountMath.makeEmpty(brand)); manager.update('amount', AmountMath.make(brand, [13])); - t.deepEqual(publicFacet.lookup('amount'), AmountMath.make(brand, [13])); + t.deepEqual(params.lookup('amount'), AmountMath.make(brand, [13])); t.throws( () => manager.update('number', 13), @@ -98,16 +104,16 @@ test('params one Amount', async t => { }); test('params one BigInt', async t => { - const { publicFacet, manager } = buildParamManager([ + const { params, manager } = buildParamManager([ { name: 'bigint', value: 314159n, - type: ParamType.BIGINT, + type: ParamType.NAT, }, ]); - t.deepEqual(publicFacet.lookup('bigint'), 314159n); + t.deepEqual(params.lookup('bigint'), 314159n); manager.update('bigint', 271828182845904523536n); - t.deepEqual(publicFacet.lookup('bigint'), 271828182845904523536n); + t.deepEqual(params.lookup('bigint'), 271828182845904523536n); t.throws( () => manager.update('bigint', 18.1), @@ -120,16 +126,16 @@ test('params one BigInt', async t => { test('params one ratio', async t => { const { brand } = makeIssuerKit('roses', AssetKind.SET); - const { publicFacet, manager } = buildParamManager([ + const { params, manager } = buildParamManager([ { name: 'ratio', value: makeRatio(7, brand), type: ParamType.RATIO, }, ]); - t.deepEqual(publicFacet.lookup('ratio'), makeRatio(7, brand)); + t.deepEqual(params.lookup('ratio'), makeRatio(7, brand)); manager.update('ratio', makeRatio(701, brand, BASIS_POINTS)); - t.deepEqual(publicFacet.lookup('ratio'), makeRatio(701, brand, BASIS_POINTS)); + t.deepEqual(params.lookup('ratio'), makeRatio(701, brand, BASIS_POINTS)); t.throws( () => manager.update('ratio', 18.1), @@ -143,16 +149,16 @@ test('params one ratio', async t => { test('params one brand', async t => { const { brand: roseBrand } = makeIssuerKit('roses', AssetKind.SET); const { brand: thornBrand } = makeIssuerKit('thorns'); - const { publicFacet, manager } = buildParamManager([ + const { params, manager } = buildParamManager([ { name: 'brand', value: roseBrand, type: ParamType.BRAND, }, ]); - t.deepEqual(publicFacet.lookup('brand'), roseBrand); + t.deepEqual(params.lookup('brand'), roseBrand); manager.update('brand', thornBrand); - t.deepEqual(publicFacet.lookup('brand'), thornBrand); + t.deepEqual(params.lookup('brand'), thornBrand); t.throws( () => manager.update('brand', 18.1), @@ -163,70 +169,47 @@ test('params one brand', async t => { ); }); -test('params one handle', async t => { - const fooHandle = makeHandle('foo'); - const barHandle = makeHandle('bar'); - const { publicFacet, manager } = buildParamManager([ - { - name: 'handle', - value: fooHandle, - type: ParamType.HANDLE, - }, - ]); - t.deepEqual(publicFacet.lookup('handle'), fooHandle); - manager.update('handle', barHandle); - t.deepEqual(publicFacet.lookup('handle'), barHandle); - - t.throws( - () => manager.update('handle', 18.1), - { - message: 'value for "handle" must be an empty object, was 18.1', - }, - 'value for "handle" must be an empty object, was 18.1', - ); -}); - test('params one any', async t => { - const fooHandle = makeHandle('foo'); - const { publicFacet, manager } = buildParamManager([ + const { brand: stiltonBrand } = makeIssuerKit('stilton', AssetKind.SET); + const { params, manager } = buildParamManager([ { name: 'stuff', - value: fooHandle, + value: stiltonBrand, type: ParamType.ANY, }, ]); - t.deepEqual(publicFacet.lookup('stuff'), fooHandle); + t.deepEqual(params.lookup('stuff'), stiltonBrand); manager.update('stuff', 18.1); - t.deepEqual(publicFacet.lookup('stuff'), 18.1); + t.deepEqual(params.lookup('stuff'), 18.1); }); test('params keys', async t => { - const fooHandle = makeHandle('foo'); - const { publicFacet, manager } = buildParamManager([ + const { brand: parmesanBrand } = makeIssuerKit('parmesan', AssetKind.SET); + const { params, manager } = buildParamManager([ { name: 'stuff', - value: fooHandle, + value: parmesanBrand, type: ParamType.ANY, }, { - name: 'bigint', + name: 'nat', value: 314159n, - type: ParamType.BIGINT, + type: ParamType.NAT, }, ]); - t.deepEqual(publicFacet.lookup('stuff'), fooHandle); + t.deepEqual(params.lookup('stuff'), parmesanBrand); manager.update('stuff', 18.1); - t.deepEqual(publicFacet.lookup('stuff'), 18.1); + t.deepEqual(params.lookup('stuff'), 18.1); - t.deepEqual(publicFacet.getDetails('stuff'), { + t.deepEqual(params.getDetails('stuff'), { name: 'stuff', value: 18.1, type: ParamType.ANY, }); - t.deepEqual(publicFacet.getDetails('bigint'), { - name: 'bigint', + t.deepEqual(params.getDetails('nat'), { + name: 'nat', value: 314159n, - type: ParamType.BIGINT, + type: ParamType.NAT, }); - t.deepEqual(publicFacet.definedNames(), ['stuff', 'bigint']); + t.deepEqual(params.definedNames(), ['stuff', 'nat']); }); From bf2dc9e2ed38777041738a1e4fe04428eea5d69a Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Thu, 17 Jun 2021 09:34:36 -0700 Subject: [PATCH 08/11] refactor: paramManager separates each param updater change 'any' to 'unknown' drop an unneeded guard clause a single getParams() describes all parameters --- packages/governance/package.json | 1 + packages/governance/src/paramManager.js | 82 +++--- packages/governance/src/types.js | 24 +- .../governance/test/test-param-manager.js | 263 +++++++++--------- yarn.lock | 33 ++- 5 files changed, 227 insertions(+), 176 deletions(-) diff --git a/packages/governance/package.json b/packages/governance/package.json index f762c55bfbd..ef6aaf421ac 100644 --- a/packages/governance/package.json +++ b/packages/governance/package.json @@ -32,6 +32,7 @@ "dependencies": { "@agoric/assert": "^0.3.0", "@agoric/ertp": "^0.11.2", + "@agoric/marshal": "^0.4.13", "@agoric/nat": "^4.0.0", "@agoric/notifier": "^0.3.14", "@agoric/store": "^0.4.15", diff --git a/packages/governance/src/paramManager.js b/packages/governance/src/paramManager.js index 045113942da..ac1093160c9 100644 --- a/packages/governance/src/paramManager.js +++ b/packages/governance/src/paramManager.js @@ -1,13 +1,15 @@ // @ts-check -import { makeStore } from '@agoric/store'; import { assert, details as X } from '@agoric/assert'; import { assertIsRatio } from '@agoric/zoe/src/contractSupport'; import { AmountMath, looksLikeBrand } from '@agoric/ertp'; +import { Far } from '@agoric/marshal'; +import { assertKeywordName } from '@agoric/zoe/src/cleanProposal'; + /** * @type {{ * AMOUNT: 'amount', - * ANY: 'any', + * UNKNOWN: 'unknown', * BRAND: 'brand', * INSTANCE: 'instance', * INSTALLATION: 'installation', @@ -18,22 +20,17 @@ import { AmountMath, looksLikeBrand } from '@agoric/ertp'; */ const ParamType = { AMOUNT: 'amount', - ANY: 'any', BRAND: 'brand', INSTANCE: 'instance', INSTALLATION: 'installation', NAT: 'nat', RATIO: 'ratio', STRING: 'string', + UNKNOWN: 'unknown', }; harden(ParamType); const assertType = (type, value, name) => { - if (!type) { - // undefined type means don't verify. Did we omit an interesting type? - return; - } - switch (type) { case ParamType.AMOUNT: // It would be nice to have a clean way to assert something is an amount. @@ -42,8 +39,6 @@ const assertType = (type, value, name) => { X`value for ${name} must be an Amount, was ${value}`, ); break; - case ParamType.ANY: - break; case ParamType.BRAND: assert( looksLikeBrand(value), @@ -73,46 +68,65 @@ const assertType = (type, value, name) => { case ParamType.STRING: assert.typeof(value, 'string'); break; + case ParamType.UNKNOWN: + break; default: assert.fail(X`unknown type guard ${type}`); } }; const parse = paramDesc => { - const bindings = makeStore('name'); - const types = makeStore('name'); + const values = {}; + // manager has an updateFoo() for each Foo param. It will be returned. + const manager = {}; + // getParams() uses describers to generate descriptions of each param. + const describers = []; paramDesc.forEach(({ name, value, type }) => { + assert( + !values[name], + X`each parameter name must be unique: ${name} duplicated`, + ); assertType(type, value, name); - bindings.init(name, value); - types.init(name, type); + // we want to create function names like updateFeeRatio(), so we insist that + // the name has Keyword-nature. + assertKeywordName(name); + + values[name] = { type, value }; + manager[`update${name}`] = newValue => { + assertType(type, newValue, name); + values[name].value = newValue; + }; + + const describer = () => ({ + name, + type, + value: values[name].value, + }); + describers.push(describer); }); - return { bindings, types }; + /** @type {() => Record} */ + const getParams = () => { + const descriptions = {}; + describers.forEach(d => { + const description = d(); + descriptions[description.name] = description; + }); + return descriptions; + }; + + return { getParams, manager }; }; /** @type {BuildParamManager} */ const buildParamManager = paramDesc => { - const { bindings, types } = parse(paramDesc); - - const params = { - lookup: name => bindings.get(name), - getDetails: name => ({ - name, - value: bindings.get(name), - type: types.get(name), - }), - definedNames: () => bindings.keys(), - }; - - const manager = { - update(name, value) { - assertType(types.get(name), value, name); - bindings.set(name, value); - }, - }; + const { getParams, manager } = parse(paramDesc); - return { params, manager }; + return Far('param manager', { + getParams, + ...manager, + }); }; harden(buildParamManager); diff --git a/packages/governance/src/types.js b/packages/governance/src/types.js index 0260e79ed22..994ab8f8509 100644 --- a/packages/governance/src/types.js +++ b/packages/governance/src/types.js @@ -1,16 +1,11 @@ // @ts-check /** - * @typedef { 'amount' | 'any' | 'brand' | 'installation' | 'instance' | 'nat' | 'ratio' | 'string' } ParamType + * @typedef { 'amount' | 'unknown' | 'brand' | 'installation' | 'instance' | 'nat' | 'ratio' | 'string' } ParamType */ /** - * @typedef { Amount | Brand | Instance| Installation | bigint | Ratio | string | any } ParamValue - */ - -/** - * @typedef {Object} ParamManager - * @property {(name: string, value: ParamValue) => void} update + * @typedef { Amount | Brand | Instance| Installation | bigint | Ratio | string | unknown } ParamValue */ /** @@ -20,13 +15,6 @@ * @property {ParamType} type */ -/** - * @typedef {Object} ParamManagerPublic - * @property {(name: string) => ParamValue} lookup - * @property {(name: string) => ParamDetails} getDetails - * @property {() => string[]} definedNames - */ - /** * @typedef {Object} ParamDescription * @property {string} name @@ -34,6 +22,12 @@ * @property {ParamType} type */ +/** + * @typedef {Object} ParamManagerPublic + * ParamManagerPublic also has updateFoo methods for each defined parameter. + * @property {() => Record} getParams + */ + /** * @typedef {Array} ParamDescriptions */ @@ -41,5 +35,5 @@ /** * @callback BuildParamManager * @param {ParamDescriptions} paramDesc - * @returns {{params: ParamManagerPublic, manager: ParamManager }} + * @returns {ParamManagerPublic} */ diff --git a/packages/governance/test/test-param-manager.js b/packages/governance/test/test-param-manager.js index 7fac8e49f7e..28fc49e8177 100644 --- a/packages/governance/test/test-param-manager.js +++ b/packages/governance/test/test-param-manager.js @@ -10,33 +10,26 @@ import { buildParamManager, ParamType } from '../src/paramManager'; const BASIS_POINTS = 10_000; test('params one Nat', async t => { - const { params, manager } = buildParamManager([ - { - name: 'number', - value: 13n, - type: ParamType.NAT, - }, - ]); - t.is(params.lookup('number'), 13n); - manager.update('number', 42n); - t.is(params.lookup('number'), 42n); + const numberKey = 'Number'; + const numberDescription = { + name: numberKey, + value: 13n, + type: ParamType.NAT, + }; + const { getParams, updateNumber } = buildParamManager([numberDescription]); + t.deepEqual(getParams()[numberKey], numberDescription); + updateNumber(42n); + t.is(getParams()[numberKey].value, 42n); t.throws( - () => manager.update('string', 'foo'), - { - message: '"name" not found: "string"', - }, - '"string" was not a registered name', - ); - t.throws( - () => manager.update('number', 18.1), + () => updateNumber(18.1), { message: '18.1 must be a bigint', }, 'value should be a nat', ); t.throws( - () => manager.update('number', 13), + () => updateNumber(13), { message: '13 must be a bigint', }, @@ -45,26 +38,19 @@ test('params one Nat', async t => { }); test('params one String', async t => { - const { params, manager } = buildParamManager([ - { - name: 'string', - value: 'foo', - type: ParamType.STRING, - }, - ]); - t.is(params.lookup('string'), 'foo'); - manager.update('string', 'bar'); - t.is(params.lookup('string'), 'bar'); + const stringKey = 'String'; + const stringDescription = { + name: stringKey, + value: 'foo', + type: ParamType.STRING, + }; + const { getParams, updateString } = buildParamManager([stringDescription]); + t.deepEqual(getParams()[stringKey], stringDescription); + updateString('bar'); + t.is(getParams()[stringKey].value, 'bar'); t.throws( - () => manager.update('number', 'foo'), - { - message: '"name" not found: "number"', - }, - '"number" was not a registered name', - ); - t.throws( - () => manager.update('string', 18.1), + () => updateString(18.1), { message: '18.1 must be a string', }, @@ -73,28 +59,20 @@ test('params one String', async t => { }); test('params one Amount', async t => { + const amountKey = 'Amount'; const { brand } = makeIssuerKit('roses', AssetKind.SET); - const { params, manager } = buildParamManager([ - { - name: 'amount', - value: AmountMath.makeEmpty(brand), - type: ParamType.AMOUNT, - }, - ]); - t.deepEqual(params.lookup('amount'), AmountMath.makeEmpty(brand)); - manager.update('amount', AmountMath.make(brand, [13])); - t.deepEqual(params.lookup('amount'), AmountMath.make(brand, [13])); + const amountDescription = { + name: amountKey, + value: AmountMath.makeEmpty(brand), + type: ParamType.AMOUNT, + }; + const { getParams, updateAmount } = buildParamManager([amountDescription]); + t.deepEqual(getParams()[amountKey], amountDescription); + updateAmount(AmountMath.make(brand, [13])); + t.deepEqual(getParams()[amountKey].value, AmountMath.make(brand, [13])); t.throws( - () => manager.update('number', 13), - { - message: '"name" not found: "number"', - }, - '"number" was not a registered name', - ); - - t.throws( - () => manager.update('amount', 18.1), + () => updateAmount(18.1), { message: "The amount 18.1 doesn't look like an amount. Did you pass a value instead?", @@ -104,19 +82,19 @@ test('params one Amount', async t => { }); test('params one BigInt', async t => { - const { params, manager } = buildParamManager([ - { - name: 'bigint', - value: 314159n, - type: ParamType.NAT, - }, - ]); - t.deepEqual(params.lookup('bigint'), 314159n); - manager.update('bigint', 271828182845904523536n); - t.deepEqual(params.lookup('bigint'), 271828182845904523536n); + const bigintKey = 'Bigint'; + const bigIntDescription = { + name: bigintKey, + value: 314159n, + type: ParamType.NAT, + }; + const { getParams, updateBigint } = buildParamManager([bigIntDescription]); + t.deepEqual(getParams()[bigintKey], bigIntDescription); + updateBigint(271828182845904523536n); + t.deepEqual(getParams()[bigintKey].value, 271828182845904523536n); t.throws( - () => manager.update('bigint', 18.1), + () => updateBigint(18.1), { message: '18.1 must be a bigint', }, @@ -125,20 +103,20 @@ test('params one BigInt', async t => { }); test('params one ratio', async t => { + const ratioKey = 'Ratio'; const { brand } = makeIssuerKit('roses', AssetKind.SET); - const { params, manager } = buildParamManager([ - { - name: 'ratio', - value: makeRatio(7, brand), - type: ParamType.RATIO, - }, - ]); - t.deepEqual(params.lookup('ratio'), makeRatio(7, brand)); - manager.update('ratio', makeRatio(701, brand, BASIS_POINTS)); - t.deepEqual(params.lookup('ratio'), makeRatio(701, brand, BASIS_POINTS)); + const ratioDescription = { + name: ratioKey, + value: makeRatio(7, brand), + type: ParamType.RATIO, + }; + const { getParams, updateRatio } = buildParamManager([ratioDescription]); + t.deepEqual(getParams()[ratioKey], ratioDescription); + updateRatio(makeRatio(701, brand, BASIS_POINTS)); + t.deepEqual(getParams()[ratioKey].value, makeRatio(701, brand, BASIS_POINTS)); t.throws( - () => manager.update('ratio', 18.1), + () => updateRatio(18.1), { message: 'Ratio 18.1 must be a record with 2 fields.', }, @@ -147,69 +125,104 @@ test('params one ratio', async t => { }); test('params one brand', async t => { + const brandKey = 'Brand'; const { brand: roseBrand } = makeIssuerKit('roses', AssetKind.SET); const { brand: thornBrand } = makeIssuerKit('thorns'); - const { params, manager } = buildParamManager([ - { - name: 'brand', - value: roseBrand, - type: ParamType.BRAND, - }, - ]); - t.deepEqual(params.lookup('brand'), roseBrand); - manager.update('brand', thornBrand); - t.deepEqual(params.lookup('brand'), thornBrand); + const brandDescription = { + name: brandKey, + value: roseBrand, + type: ParamType.BRAND, + }; + const { getParams, updateBrand } = buildParamManager([brandDescription]); + t.deepEqual(getParams()[brandKey], brandDescription); + updateBrand(thornBrand); + t.deepEqual(getParams()[brandKey].value, thornBrand); t.throws( - () => manager.update('brand', 18.1), + () => updateBrand(18.1), { - message: 'value for "brand" must be a brand, was 18.1', + message: 'value for "Brand" must be a brand, was 18.1', }, 'value should be a brand', ); }); -test('params one any', async t => { +test('params one unknown', async t => { + const stuffKey = 'Stuff'; const { brand: stiltonBrand } = makeIssuerKit('stilton', AssetKind.SET); - const { params, manager } = buildParamManager([ - { - name: 'stuff', - value: stiltonBrand, - type: ParamType.ANY, - }, - ]); - t.deepEqual(params.lookup('stuff'), stiltonBrand); - manager.update('stuff', 18.1); - t.deepEqual(params.lookup('stuff'), 18.1); + const stuffDescription = { + name: stuffKey, + value: stiltonBrand, + type: ParamType.UNKNOWN, + }; + const { getParams, updateStuff } = buildParamManager([stuffDescription]); + t.deepEqual(getParams()[stuffKey], stuffDescription); + updateStuff(18.1); + t.deepEqual(getParams()[stuffKey].value, 18.1); }); -test('params keys', async t => { - const { brand: parmesanBrand } = makeIssuerKit('parmesan', AssetKind.SET); - const { params, manager } = buildParamManager([ - { - name: 'stuff', - value: parmesanBrand, - type: ParamType.ANY, - }, - { - name: 'nat', - value: 314159n, - type: ParamType.NAT, +test('params duplicate entry', async t => { + const stuffKey = 'Stuff'; + const { brand: stiltonBrand } = makeIssuerKit('stilton', AssetKind.SET); + t.throws( + () => + buildParamManager([ + { + name: stuffKey, + value: 37n, + type: ParamType.NAT, + }, + { + name: stuffKey, + value: stiltonBrand, + type: ParamType.UNKNOWN, + }, + ]), + { + message: `each parameter name must be unique: "Stuff" duplicated`, }, - ]); - t.deepEqual(params.lookup('stuff'), parmesanBrand); - manager.update('stuff', 18.1); - t.deepEqual(params.lookup('stuff'), 18.1); + ); +}); - t.deepEqual(params.getDetails('stuff'), { - name: 'stuff', - value: 18.1, - type: ParamType.ANY, +test('params unknown type', async t => { + const stuffKey = 'Stuff'; + const stuffDescription = { + name: stuffKey, + value: 'It was the best of times, it was the worst of times', + // @ts-ignore illegal value for testing + type: 'quote', + }; + t.throws(() => buildParamManager([stuffDescription]), { + message: 'unknown type guard "quote"', }); - t.deepEqual(params.getDetails('nat'), { - name: 'nat', +}); + +test('params multiple values', t => { + const stuffKey = 'Stuff'; + const natKey = 'Nat'; + const { brand: parmesanBrand } = makeIssuerKit('parmesan', AssetKind.SET); + const cheeseDescription = { + name: stuffKey, + value: parmesanBrand, + type: ParamType.UNKNOWN, + }; + const piDescription = { + name: natKey, value: 314159n, type: ParamType.NAT, - }); - t.deepEqual(params.definedNames(), ['stuff', 'nat']); + }; + const { getParams, updateNat: _updateNat, updateStuff } = buildParamManager([ + cheeseDescription, + piDescription, + ]); + t.deepEqual(getParams()[stuffKey], cheeseDescription); + updateStuff(18.1); + const floatDescription = { + name: stuffKey, + value: 18.1, + type: ParamType.UNKNOWN, + }; + t.deepEqual(getParams()[stuffKey], floatDescription); + t.deepEqual(getParams()[natKey], piDescription); + t.deepEqual(getParams(), { Nat: piDescription, Stuff: floatDescription }); }); diff --git a/yarn.lock b/yarn.lock index 37b444a015b..f82194120e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@agoric/assert@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@agoric/assert/-/assert-0.3.1.tgz#6173aa8d61cb9e928b86e2cd981be1c941375698" + integrity sha512-xpAxPLq3zXk7fnJEcGgjdZrioh1A72AnmMumm2wZLFfcz5UkQuVM8K3V6KOygLcQP8lZvuVX3H2ApywpskQy+g== + dependencies: + ses "^0.13.2" + "@agoric/babel-parser@^7.6.4": version "7.6.4" resolved "https://registry.yarnpkg.com/@agoric/babel-parser/-/babel-parser-7.6.4.tgz#8dd5d36554cc758c29042713b5aa57dc58ee5273" @@ -12,11 +19,33 @@ resolved "https://registry.yarnpkg.com/@agoric/babel-standalone/-/babel-standalone-7.14.3.tgz#1bf201417481d37d2797dd3283590dcbef775b4d" integrity sha512-Rdlxts19kvxHsqTjTrhGJv0yKgCyjCSVgXoLBZf9dZ7lyo/j+6xFQBiWjP03bXve3X74wUvA1QU55wVey8DEiQ== -"@agoric/nat@^4.1.0": +"@agoric/eventual-send@^0.13.16": + version "0.13.16" + resolved "https://registry.yarnpkg.com/@agoric/eventual-send/-/eventual-send-0.13.16.tgz#be4204f19dc2c77d2f589fc29793d685e16a3971" + integrity sha512-lLjPFqezGnG3moX+Idf4moDFLcvubS4LWcANyBBnziMOXD6spLC9riRjxM/4JBBZH71FYKmM+TYZ15gpRDrvvQ== + +"@agoric/marshal@^0.4.13": + version "0.4.13" + resolved "https://registry.yarnpkg.com/@agoric/marshal/-/marshal-0.4.13.tgz#f8e7ccf0ed5c0ed64f6357468224a71f8ad8743a" + integrity sha512-SsaWAb69VasZWGlvi4N8ofT/8K70QzJVwozLIitzwA0DsyR7uU2kO8lAGgufll6DdgszORrRnMjycU6JJqSVyg== + dependencies: + "@agoric/assert" "^0.3.1" + "@agoric/eventual-send" "^0.13.16" + "@agoric/nat" "^4.1.0" + "@agoric/promise-kit" "^0.2.15" + +"@agoric/nat@^4.0.0", "@agoric/nat@^4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@agoric/nat/-/nat-4.1.0.tgz#102794e033ffc183a20b0f86031a2e76d204b9f6" integrity sha512-2oMoh3DMn0Fx8HChPPiH8irBNdT/33ttxAZJohhd3nU3gyBRQ1u+eEoOQWfSkrE6M02iMkQM7GE9MzGmjQ6bHg== +"@agoric/promise-kit@^0.2.15": + version "0.2.15" + resolved "https://registry.yarnpkg.com/@agoric/promise-kit/-/promise-kit-0.2.15.tgz#eb877b37880aeb764a3456e28abaf10eb1b7a5fa" + integrity sha512-0MqVJresAD/j7Us8aODxf0xfNwzef3afLn4rMK8x81FDsFJZ/KT3vLULtVm88JsyKxugceCvYZKDu8flZ3j73Q== + dependencies: + "@agoric/eventual-send" "^0.13.16" + "@babel/cli@^7.12.13": version "7.13.10" resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.13.10.tgz#3a9254cbe806639c8ca4ebd49ebe54b4267b88c9" @@ -5747,7 +5776,7 @@ eslint@^7.23.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -esm@agoric-labs/esm#Agoric-built: +esm@^3.2.25, esm@agoric-labs/esm#Agoric-built: version "3.2.25" resolved "https://codeload.github.com/agoric-labs/esm/tar.gz/3603726ad4636b2f865f463188fcaade6375638e" From 842a5f17727c311c508763f2275d3d42ab99fbd0 Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Thu, 17 Jun 2021 10:47:37 -0700 Subject: [PATCH 09/11] chore: typescript corrections Thanks to Michael Fig. --- packages/governance/src/paramManager.js | 2 +- packages/governance/src/types.js | 6 ++++-- packages/governance/test/test-param-manager.js | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/governance/src/paramManager.js b/packages/governance/src/paramManager.js index ac1093160c9..a7422dbb8c8 100644 --- a/packages/governance/src/paramManager.js +++ b/packages/governance/src/paramManager.js @@ -106,8 +106,8 @@ const parse = paramDesc => { describers.push(describer); }); - /** @type {() => Record} */ const getParams = () => { + /** @type {Record} */ const descriptions = {}; describers.forEach(d => { const description = d(); diff --git a/packages/governance/src/types.js b/packages/governance/src/types.js index 994ab8f8509..c035b352c75 100644 --- a/packages/governance/src/types.js +++ b/packages/governance/src/types.js @@ -23,9 +23,11 @@ */ /** - * @typedef {Object} ParamManagerPublic - * ParamManagerPublic also has updateFoo methods for each defined parameter. + * @typedef {Object} ParamManagerBase * @property {() => Record} getParams + * + * @typedef {{ [updater: string]: (arg: any) => void }} ParamManagerUpdaters + * @typedef {ParamManagerBase & ParamManagerUpdaters} ParamManagerPublic */ /** diff --git a/packages/governance/test/test-param-manager.js b/packages/governance/test/test-param-manager.js index 28fc49e8177..ed6e9e06f9f 100644 --- a/packages/governance/test/test-param-manager.js +++ b/packages/governance/test/test-param-manager.js @@ -189,9 +189,9 @@ test('params unknown type', async t => { const stuffDescription = { name: stuffKey, value: 'It was the best of times, it was the worst of times', - // @ts-ignore illegal value for testing type: 'quote', }; + // @ts-ignore illegal value for testing t.throws(() => buildParamManager([stuffDescription]), { message: 'unknown type guard "quote"', }); From edf7daccec9d830d407a6e2638d7309381387823 Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Thu, 17 Jun 2021 16:17:53 -0700 Subject: [PATCH 10/11] chore: review cleanups dependency trimming better test for AMOUNT. improve some error messages narrow some type declarations add tests for INSTANCE and INSTALLATION --- packages/governance/package.json | 2 +- packages/governance/src/paramManager.js | 50 ++++++------ packages/governance/src/types.js | 17 ++-- .../governance/test/test-param-manager.js | 79 ++++++++++++++++--- yarn.lock | 31 +------- 5 files changed, 97 insertions(+), 82 deletions(-) diff --git a/packages/governance/package.json b/packages/governance/package.json index ef6aaf421ac..8c5c4386a9c 100644 --- a/packages/governance/package.json +++ b/packages/governance/package.json @@ -33,7 +33,7 @@ "@agoric/assert": "^0.3.0", "@agoric/ertp": "^0.11.2", "@agoric/marshal": "^0.4.13", - "@agoric/nat": "^4.0.0", + "@agoric/nat": "^4.1.0", "@agoric/notifier": "^0.3.14", "@agoric/store": "^0.4.15", "@agoric/zoe": "^0.16.0" diff --git a/packages/governance/src/paramManager.js b/packages/governance/src/paramManager.js index a7422dbb8c8..c1a9a1a0d1e 100644 --- a/packages/governance/src/paramManager.js +++ b/packages/governance/src/paramManager.js @@ -9,13 +9,13 @@ import { assertKeywordName } from '@agoric/zoe/src/cleanProposal'; /** * @type {{ * AMOUNT: 'amount', - * UNKNOWN: 'unknown', * BRAND: 'brand', * INSTANCE: 'instance', * INSTALLATION: 'installation', * NAT: 'nat', * RATIO: 'ratio', * STRING: 'string', + * UNKNOWN: 'unknown', * }} */ const ParamType = { @@ -34,10 +34,7 @@ const assertType = (type, value, name) => { switch (type) { case ParamType.AMOUNT: // It would be nice to have a clean way to assert something is an amount. - assert( - AmountMath.isEqual(value, value), - X`value for ${name} must be an Amount, was ${value}`, - ); + AmountMath.coerce(value.brand, value); break; case ParamType.BRAND: assert( @@ -49,14 +46,14 @@ const assertType = (type, value, name) => { // TODO(3344): add a better assertion once Zoe validates installations assert( typeof value === 'object' && !Object.getOwnPropertyNames(value).length, - X`value for ${name} must be an empty object, was ${value}`, + X`value for ${name} must be an Installation, was ${value}`, ); break; case ParamType.INSTANCE: // TODO(3344): add a better assertion once Zoe validates instances assert( typeof value === 'object' && !Object.getOwnPropertyNames(value).length, - X`value for ${name} must be an empty object, was ${value}`, + X`value for ${name} must be an Instance, was ${value}`, ); break; case ParamType.NAT: @@ -68,52 +65,49 @@ const assertType = (type, value, name) => { case ParamType.STRING: assert.typeof(value, 'string'); break; + // This is an escape hatch for types we haven't added yet. If you need to + // use it, please file an issue and ask us to support the new type. case ParamType.UNKNOWN: break; default: - assert.fail(X`unknown type guard ${type}`); + assert.fail(X`unrecognized type ${type}`); } }; const parse = paramDesc => { - const values = {}; + const typesAndValues = {}; // manager has an updateFoo() for each Foo param. It will be returned. const manager = {}; - // getParams() uses describers to generate descriptions of each param. - const describers = []; paramDesc.forEach(({ name, value, type }) => { + // we want to create function names like updateFeeRatio(), so we insist that + // the name has Keyword-nature. + assertKeywordName(name); + assert( - !values[name], + !typesAndValues[name], X`each parameter name must be unique: ${name} duplicated`, ); assertType(type, value, name); - // we want to create function names like updateFeeRatio(), so we insist that - // the name has Keyword-nature. - assertKeywordName(name); - values[name] = { type, value }; + typesAndValues[name] = { type, value }; manager[`update${name}`] = newValue => { assertType(type, newValue, name); - values[name].value = newValue; + typesAndValues[name].value = newValue; }; - - const describer = () => ({ - name, - type, - value: values[name].value, - }); - describers.push(describer); }); const getParams = () => { /** @type {Record} */ const descriptions = {}; - describers.forEach(d => { - const description = d(); - descriptions[description.name] = description; + Object.getOwnPropertyNames(typesAndValues).forEach(name => { + descriptions[name] = { + name, + type: typesAndValues[name].type, + value: typesAndValues[name].value, + }; }); - return descriptions; + return harden(descriptions); }; return { getParams, manager }; diff --git a/packages/governance/src/types.js b/packages/governance/src/types.js index c035b352c75..6cbf3324fd4 100644 --- a/packages/governance/src/types.js +++ b/packages/governance/src/types.js @@ -1,18 +1,11 @@ // @ts-check /** - * @typedef { 'amount' | 'unknown' | 'brand' | 'installation' | 'instance' | 'nat' | 'ratio' | 'string' } ParamType + * @typedef { 'amount' | 'brand' | 'installation' | 'instance' | 'nat' | 'ratio' | 'string' | 'unknown' } ParamType */ /** - * @typedef { Amount | Brand | Instance| Installation | bigint | Ratio | string | unknown } ParamValue - */ - -/** - * @typedef {Object} ParamDetails - * @property {string} name - * @property {ParamValue} value - * @property {ParamType} type + * @typedef { Amount | Brand | Installation | Instance | bigint | Ratio | string | unknown } ParamValue */ /** @@ -26,8 +19,8 @@ * @typedef {Object} ParamManagerBase * @property {() => Record} getParams * - * @typedef {{ [updater: string]: (arg: any) => void }} ParamManagerUpdaters - * @typedef {ParamManagerBase & ParamManagerUpdaters} ParamManagerPublic + * @typedef {{ [updater: string]: (arg: ParamValue) => void }} ParamManagerUpdaters + * @typedef {ParamManagerBase & ParamManagerUpdaters} ParamManagerFull */ /** @@ -37,5 +30,5 @@ /** * @callback BuildParamManager * @param {ParamDescriptions} paramDesc - * @returns {ParamManagerPublic} + * @returns {ParamManagerFull} */ diff --git a/packages/governance/test/test-param-manager.js b/packages/governance/test/test-param-manager.js index ed6e9e06f9f..cbdb95f9fe9 100644 --- a/packages/governance/test/test-param-manager.js +++ b/packages/governance/test/test-param-manager.js @@ -5,6 +5,7 @@ import '@agoric/zoe/exported'; import { AmountMath, AssetKind, makeIssuerKit } from '@agoric/ertp'; import { makeRatio } from '@agoric/zoe/src/contractSupport'; +import { makeHandle } from '@agoric/zoe/src/makeHandle'; import { buildParamManager, ParamType } from '../src/paramManager'; const BASIS_POINTS = 10_000; @@ -19,7 +20,7 @@ test('params one Nat', async t => { const { getParams, updateNumber } = buildParamManager([numberDescription]); t.deepEqual(getParams()[numberKey], numberDescription); updateNumber(42n); - t.is(getParams()[numberKey].value, 42n); + t.deepEqual(getParams()[numberKey].value, 42n); t.throws( () => updateNumber(18.1), @@ -47,7 +48,7 @@ test('params one String', async t => { const { getParams, updateString } = buildParamManager([stringDescription]); t.deepEqual(getParams()[stringKey], stringDescription); updateString('bar'); - t.is(getParams()[stringKey].value, 'bar'); + t.deepEqual(getParams()[stringKey].value, 'bar'); t.throws( () => updateString(18.1), @@ -74,8 +75,7 @@ test('params one Amount', async t => { t.throws( () => updateAmount(18.1), { - message: - "The amount 18.1 doesn't look like an amount. Did you pass a value instead?", + message: 'The brand "[undefined]" doesn\'t look like a brand.', }, 'value should be a amount', ); @@ -161,6 +161,58 @@ test('params one unknown', async t => { t.deepEqual(getParams()[stuffKey].value, 18.1); }); +test('params one instance', async t => { + const instanceKey = 'Instance'; + // this is sufficient for the current type check. When we add + // isInstance() (#3344), we'll need to make a mockZoe. + const instanceHandle = makeHandle('Instance'); + const instanceDescription = { + name: instanceKey, + value: instanceHandle, + type: ParamType.INSTANCE, + }; + const { getParams, updateInstance } = buildParamManager([ + instanceDescription, + ]); + t.deepEqual(getParams()[instanceKey], instanceDescription); + t.throws( + () => updateInstance(18.1), + { + message: 'value for "Instance" must be an Instance, was 18.1', + }, + 'value should be an Instance', + ); + const handle2 = makeHandle('another Instance'); + updateInstance(handle2); + t.deepEqual(getParams()[instanceKey].value, handle2); +}); + +test('params one installation', async t => { + const installationKey = 'Installation'; + // this is sufficient for the current type check. When we add + // isInstallation() (#3344), we'll need to make a mockZoe. + const installationHandle = makeHandle('installation'); + const installationDescription = { + name: installationKey, + value: installationHandle, + type: ParamType.INSTALLATION, + }; + const { getParams, updateInstallation } = buildParamManager([ + installationDescription, + ]); + t.deepEqual(getParams()[installationKey], installationDescription); + t.throws( + () => updateInstallation(18.1), + { + message: 'value for "Installation" must be an Installation, was 18.1', + }, + 'value should be an installation', + ); + const handle2 = makeHandle('another installation'); + updateInstallation(handle2); + t.deepEqual(getParams()[installationKey].value, handle2); +}); + test('params duplicate entry', async t => { const stuffKey = 'Stuff'; const { brand: stiltonBrand } = makeIssuerKit('stilton', AssetKind.SET); @@ -193,7 +245,7 @@ test('params unknown type', async t => { }; // @ts-ignore illegal value for testing t.throws(() => buildParamManager([stuffDescription]), { - message: 'unknown type guard "quote"', + message: 'unrecognized type "quote"', }); }); @@ -206,14 +258,14 @@ test('params multiple values', t => { value: parmesanBrand, type: ParamType.UNKNOWN, }; - const piDescription = { + const constantDescription = { name: natKey, - value: 314159n, + value: 602214076000000000000000n, type: ParamType.NAT, }; - const { getParams, updateNat: _updateNat, updateStuff } = buildParamManager([ + const { getParams, updateNat, updateStuff } = buildParamManager([ cheeseDescription, - piDescription, + constantDescription, ]); t.deepEqual(getParams()[stuffKey], cheeseDescription); updateStuff(18.1); @@ -223,6 +275,11 @@ test('params multiple values', t => { type: ParamType.UNKNOWN, }; t.deepEqual(getParams()[stuffKey], floatDescription); - t.deepEqual(getParams()[natKey], piDescription); - t.deepEqual(getParams(), { Nat: piDescription, Stuff: floatDescription }); + t.deepEqual(getParams()[natKey], constantDescription); + t.deepEqual(getParams(), { + Nat: constantDescription, + Stuff: floatDescription, + }); + updateNat(299792458n); + t.deepEqual(getParams()[natKey].value, 299792458n); }); diff --git a/yarn.lock b/yarn.lock index f82194120e5..ac5ef805cce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,13 +2,6 @@ # yarn lockfile v1 -"@agoric/assert@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@agoric/assert/-/assert-0.3.1.tgz#6173aa8d61cb9e928b86e2cd981be1c941375698" - integrity sha512-xpAxPLq3zXk7fnJEcGgjdZrioh1A72AnmMumm2wZLFfcz5UkQuVM8K3V6KOygLcQP8lZvuVX3H2ApywpskQy+g== - dependencies: - ses "^0.13.2" - "@agoric/babel-parser@^7.6.4": version "7.6.4" resolved "https://registry.yarnpkg.com/@agoric/babel-parser/-/babel-parser-7.6.4.tgz#8dd5d36554cc758c29042713b5aa57dc58ee5273" @@ -19,33 +12,11 @@ resolved "https://registry.yarnpkg.com/@agoric/babel-standalone/-/babel-standalone-7.14.3.tgz#1bf201417481d37d2797dd3283590dcbef775b4d" integrity sha512-Rdlxts19kvxHsqTjTrhGJv0yKgCyjCSVgXoLBZf9dZ7lyo/j+6xFQBiWjP03bXve3X74wUvA1QU55wVey8DEiQ== -"@agoric/eventual-send@^0.13.16": - version "0.13.16" - resolved "https://registry.yarnpkg.com/@agoric/eventual-send/-/eventual-send-0.13.16.tgz#be4204f19dc2c77d2f589fc29793d685e16a3971" - integrity sha512-lLjPFqezGnG3moX+Idf4moDFLcvubS4LWcANyBBnziMOXD6spLC9riRjxM/4JBBZH71FYKmM+TYZ15gpRDrvvQ== - -"@agoric/marshal@^0.4.13": - version "0.4.13" - resolved "https://registry.yarnpkg.com/@agoric/marshal/-/marshal-0.4.13.tgz#f8e7ccf0ed5c0ed64f6357468224a71f8ad8743a" - integrity sha512-SsaWAb69VasZWGlvi4N8ofT/8K70QzJVwozLIitzwA0DsyR7uU2kO8lAGgufll6DdgszORrRnMjycU6JJqSVyg== - dependencies: - "@agoric/assert" "^0.3.1" - "@agoric/eventual-send" "^0.13.16" - "@agoric/nat" "^4.1.0" - "@agoric/promise-kit" "^0.2.15" - -"@agoric/nat@^4.0.0", "@agoric/nat@^4.1.0": +"@agoric/nat@^4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@agoric/nat/-/nat-4.1.0.tgz#102794e033ffc183a20b0f86031a2e76d204b9f6" integrity sha512-2oMoh3DMn0Fx8HChPPiH8irBNdT/33ttxAZJohhd3nU3gyBRQ1u+eEoOQWfSkrE6M02iMkQM7GE9MzGmjQ6bHg== -"@agoric/promise-kit@^0.2.15": - version "0.2.15" - resolved "https://registry.yarnpkg.com/@agoric/promise-kit/-/promise-kit-0.2.15.tgz#eb877b37880aeb764a3456e28abaf10eb1b7a5fa" - integrity sha512-0MqVJresAD/j7Us8aODxf0xfNwzef3afLn4rMK8x81FDsFJZ/KT3vLULtVm88JsyKxugceCvYZKDu8flZ3j73Q== - dependencies: - "@agoric/eventual-send" "^0.13.16" - "@babel/cli@^7.12.13": version "7.13.10" resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.13.10.tgz#3a9254cbe806639c8ca4ebd49ebe54b4267b88c9" From 569a01ef4507d7aa79c398f9cb9d0f7666a4bd17 Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Thu, 17 Jun 2021 17:18:24 -0700 Subject: [PATCH 11/11] chore: correct esm import --- packages/governance/package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/governance/package.json b/packages/governance/package.json index 8c5c4386a9c..d30f97062fa 100644 --- a/packages/governance/package.json +++ b/packages/governance/package.json @@ -41,7 +41,7 @@ "devDependencies": { "@agoric/install-ses": "^0.5.13", "ava": "^3.12.1", - "esm": "^3.2.25" + "esm": "agoric-labs/esm#Agoric-built" }, "files": [ "src/", diff --git a/yarn.lock b/yarn.lock index ac5ef805cce..37b444a015b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5747,7 +5747,7 @@ eslint@^7.23.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -esm@^3.2.25, esm@agoric-labs/esm#Agoric-built: +esm@agoric-labs/esm#Agoric-built: version "3.2.25" resolved "https://codeload.github.com/agoric-labs/esm/tar.gz/3603726ad4636b2f865f463188fcaade6375638e"