Skip to content

Commit

Permalink
feat: manage parameters for a contract
Browse files Browse the repository at this point in the history
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?
  • Loading branch information
Chris-Hibbert committed Jun 17, 2021
1 parent e02286c commit d32e1bd
Show file tree
Hide file tree
Showing 8 changed files with 397 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"packages/bundle-source",
"packages/import-bundle",
"packages/eventual-send",
"packages/governance",
"packages/promise-kit",
"packages/tame-metering",
"packages/transform-metering",
Expand Down
5 changes: 5 additions & 0 deletions packages/governance/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.

Empty file added packages/governance/NEWS.md
Empty file.
18 changes: 18 additions & 0 deletions packages/governance/jsconfig.json
Original file line number Diff line number Diff line change
@@ -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"],
}
83 changes: 83 additions & 0 deletions packages/governance/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
93 changes: 93 additions & 0 deletions packages/governance/src/param-manager.js
Original file line number Diff line number Diff line change
@@ -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 };
34 changes: 34 additions & 0 deletions packages/governance/src/types.js
Original file line number Diff line number Diff line change
@@ -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<ParamDescription>} ParamDescriptions
*/

/**
* @callback BuildParamManager
* @param {ParamDescriptions} paramDesc
* @returns {{publicFacet: ParamManagerPublic, manager: ParamManager }}
*/
Loading

0 comments on commit d32e1bd

Please sign in to comment.