-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Manage parameters for a contract #3208
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't have actions against these changes or notification of the changes. I need to see the context to comment further.
STRING: 'string', | ||
RATIO: 'ratio', | ||
AMOUNT: 'amount', | ||
BRAND: 'brand', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need an "instance" or "installation" reference? We could just use boardID for that, but might want direct support for "boardID" usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
based on @katelynsills' comments, I think these will be handles.
I'll add a case for handles and one for untyped ANY.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should only ever use boardIds
where we can't pass objects. So anything on-chain should not be using a boardId
and should use the handle instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added instance
and installation
as (currently unverified) types. No sign of boardIDs.
const types = makeStore('name'); | ||
|
||
paramDesc.forEach(({ name, value, type }) => { | ||
assert.typeof(name, 'string'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems unnecessary given that looking it up will do the same assert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dropped.
912ec10
to
df28867
Compare
964877b
to
9ffd163
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some small suggestions, most of which are optional. Looks really good!
packages/governance/package.json
Outdated
"parsers": { | ||
"js": "mjs" | ||
}, | ||
"main": "src/missing.js", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add the actual file here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll update it to param-manager.js
for now, but it should eventually be the registrar or something else. This won't be the most important thing for long.
packages/governance/package.json
Outdated
}, | ||
"main": "src/missing.js", | ||
"engines": { | ||
"node": ">=11.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be "node": ">=14.15.0", since 11 won't actually work, as far as I know.
"node": ">=11.0" | |
"node": ">=14.15.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done. Both treasury and zoe still have 11.0. I didn't check anywhere else.
packages/governance/package.json
Outdated
"@agoric/notifier": "^0.3.14", | ||
"@agoric/promise-kit": "^0.2.13", | ||
"@agoric/store": "^0.4.14", | ||
"@agoric/swingset-vat": "^0.17.2", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is a dependency. Could you check the rest to make sure they are used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed everything that isn't currently in use. I'll add them individually as I introduce dependencies.
packages/governance/package.json
Outdated
"dependencies": { | ||
"@agoric/assert": "^0.3.0", | ||
"@agoric/bundle-source": "^1.3.7", | ||
"@agoric/captp": "^1.7.13", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is a dependency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dropped.
packages/governance/package.json
Outdated
"@agoric/install-ses": "^0.5.13", | ||
"ava": "^3.12.1", | ||
"esm": "^3.2.25", | ||
"ses": "^0.12.7" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a dependency? I don't see it used anywhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gone
}, | ||
}; | ||
|
||
return { publicFacet, manager }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm torn on this name, since it's potentially confused with the contract instance publicFacet
. But on the other hand, it might be nice for people to be familiar with the pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was confused by it, worrying that it would need to be accessed async. So I advocate read
or params
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed to params.
packages/governance/src/types.js
Outdated
|
||
/** | ||
* @typedef {Object} ParamManager | ||
* @property {(name: string, value: any) => void} update |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we restrict types, we could tighten up this any
to be the types we support. This would help developers a lot because they could find bugs statically before deploying (or testing locally, I suppose).
* @property {(name: string, value: any) => void} update | |
* @property {(name: string, value: ParamValue) => void} update |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I thought we had gotten everything that devs might want to put in a contract, I would be in favor of this, but I think devs are going to need an escape hatch. Having the explicit ParamType.ANY
lets them clearly escape our limits. We should try to be welcoming to new suggestions, but there's clearly going to be a release cycle before we can get them support for new types.
packages/governance/src/types.js
Outdated
|
||
/** | ||
* @typedef {Object} ParamManagerPublic | ||
* @property {(name: string) => any} lookup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @property {(name: string) => any} lookup | |
* @property {(name: string) => ParamValue} lookup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
packages/governance/src/types.js
Outdated
* }} ParamDescription | ||
*/ | ||
|
||
// type: string above should be type: ParamType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, why not just use ParamType as the type rather than string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typescript was fighting with me. I got it this time.
packages/governance/src/types.js
Outdated
|
||
/** | ||
* @typedef {{name: string, | ||
* value: any, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* value: any, | |
* value: ParamValue, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think publicFacet
needs to be changed, but the rest of discussion.
ANY: 'any', | ||
BIGINT: 'bigint', | ||
BRAND: 'brand', | ||
HANDLE: 'handle', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those seems plausible, assuming Zoe is the manager of such things. It does make the test async, though, which introduces a lot of complexity.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. We should stick with Amounts, and just e.g., assert that they are of a particular Brand if that's relevant.
// 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), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer the non-allocaating version in asserts :). a coerce
often allocates
}, | ||
}; | ||
|
||
return { publicFacet, manager }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was confused by it, worrying that it would need to be accessed async. So I advocate read
or params
.
type: ParamType.NAT, | ||
}, | ||
]); | ||
t.is(publicFacet.lookup('number'), 13); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah params
looks like a good name for that thing :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Adding my feedback from the discussion this morning based on what @dtribble brought up:
During the meeting, we discussed a few ways to do this. The first option was return one const manager = {
updateFeeRatio: value => ...,
updateContractName: value => ...,
} Then in the documentation we can explain how to attenuate: const attenuatedManager = {
updateFeeRatio: manager.updateFeeRatio,
};
publicFacet.getParams();
// returns
{
myName: {
name: 'myName',
type: 'string',
value: 'Alice',
},
anotherName: {
.... rather than |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't remove ParamType.ANY
. LMK if we don't need to leave this escape hatch for 3rd party devs.
packages/governance/jsconfig.json
Outdated
"strictNullChecks": true, | ||
"moduleResolution": "node", | ||
}, | ||
"include": ["src/**/*.js", "test/**/*.js", "exported.js", "globals.d.ts"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, good catch.
packages/governance/package.json
Outdated
"parsers": { | ||
"js": "mjs" | ||
}, | ||
"main": "src/missing.js", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll update it to param-manager.js
for now, but it should eventually be the registrar or something else. This won't be the most important thing for long.
packages/governance/package.json
Outdated
}, | ||
"main": "src/missing.js", | ||
"engines": { | ||
"node": ">=11.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done. Both treasury and zoe still have 11.0. I didn't check anywhere else.
packages/governance/package.json
Outdated
"@agoric/notifier": "^0.3.14", | ||
"@agoric/promise-kit": "^0.2.13", | ||
"@agoric/store": "^0.4.14", | ||
"@agoric/swingset-vat": "^0.17.2", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed everything that isn't currently in use. I'll add them individually as I introduce dependencies.
packages/governance/package.json
Outdated
"ses": "^0.12.7" | ||
}, | ||
"files": [ | ||
"bundles/", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dropped
}, | ||
}; | ||
|
||
return { publicFacet, manager }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed to params.
packages/governance/src/types.js
Outdated
|
||
/** | ||
* @typedef {Object} ParamManagerPublic | ||
* @property {(name: string) => any} lookup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
packages/governance/src/types.js
Outdated
|
||
/** | ||
* @typedef {{name: string, | ||
* value: any, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
STRING: 'string', | ||
RATIO: 'ratio', | ||
AMOUNT: 'amount', | ||
BRAND: 'brand', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added instance
and installation
as (currently unverified) types. No sign of boardIDs.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated comment
harden(ParamType); | ||
|
||
const assertType = (type, value, name) => { | ||
if (!type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just pointing to this directly because I think the comment got lost.
I think this is unnecessary since we already have the ParamType.ANY which is handled below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep.
One last comment - instead of ParamType.ANY, should it be UNKNOWN? https://stackoverflow.com/a/57356103 A JSDoc/TypeScript type of |
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?
dependency reduction support instance and installation rather than handle support NAT type which must be a bigint rename publicFacet to params
change 'any' to 'unknown' drop an unneeded guard clause a single getParams() describes all parameters
Thanks to Michael Fig.
83fe828
to
842a5f1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The most important changes are changing the dependencies, moving the keyword check up, and not creating new describer functions.
yarn.lock
Outdated
@@ -2,6 +2,13 @@ | |||
# yarn lockfile v1 | |||
|
|||
|
|||
"@agoric/assert@^0.3.1": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, most of the changes in this yarn.lock shouldn't be happening. Before we merge this, can we make sure we've gotten the package dependencies right? For instance, an old version of Nat is being installed, and multiple Agoric packages are being added to the root yarn.lock even though they are already widely used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
}; | ||
// @ts-ignore illegal value for testing | ||
t.throws(() => buildParamManager([stuffDescription]), { | ||
message: 'unknown type guard "quote"', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error message is kind of strange. Do we mean "unrecognized type"?
message: 'unknown type guard "quote"', | |
message: 'unrecognized type "quote"', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
value: 314159n, | ||
type: ParamType.NAT, | ||
}; | ||
const { getParams, updateNat: _updateNat, updateStuff } = buildParamManager([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const { getParams, updateNat: _updateNat, updateStuff } = buildParamManager([ | |
const { getParams, updateStuff } = buildParamManager([ |
Seems to be unused. Is this intentional? If so, let's add a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unused, but I wanted it to be visible that updateNat
is defined. Perhaps I'll just use it instead of making a big deal of it.
packages/governance/src/types.js
Outdated
*/ | ||
|
||
/** | ||
* @typedef {Object} ParamDetails |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type doesn't seem to be used at all. Seems like ParamDescription is the same thing and is the one used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
packages/governance/src/types.js
Outdated
* @typedef {Object} ParamManagerBase | ||
* @property {() => Record<Keyword,ParamDescription>} getParams | ||
* | ||
* @typedef {{ [updater: string]: (arg: any) => void }} ParamManagerUpdaters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be:
* @typedef {{ [updater: string]: (arg: any) => void }} ParamManagerUpdaters | |
* @typedef {{ [updater: string]: (arg: ParamValue) => void }} ParamManagerUpdaters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep. Done
case ParamType.AMOUNT: | ||
// It would be nice to have a clean way to assert something is an amount. | ||
assert( | ||
AmountMath.isEqual(value, value), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to use isEqual
? AmountMath.coerce
is the clean way to do it. We just don't have a brand to test against objectively, so the call becomes:
AmountMath.isEqual(value, value), | |
AmountMath.coerce(value.brand, value), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
INSTANCE: 'instance', | ||
INSTALLATION: 'installation', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we test INSTANCE and INSTALLATION?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
assertType(type, value, name); | ||
// we want to create function names like updateFeeRatio(), so we insist that | ||
// the name has Keyword-nature. | ||
assertKeywordName(name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Can we move this up to line 86? I think we don't want to use the name
as a property accessor into values
until after this check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
const describer = () => ({ | ||
name, | ||
type, | ||
value: values[name].value, | ||
}); | ||
describers.push(describer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems very strange to have a function per value for making descriptions. Is there a reason we need this? Or could we have a single function that knows how to turn values
into what should be returned from getParams
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
describers.forEach(d => { | ||
const description = d(); | ||
descriptions[description.name] = description; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't need describers
and can just iterate over values
directly. This is making and using a ton of functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point. Done
dependency trimming better test for AMOUNT. improve some error messages narrow some type declarations add tests for INSTANCE and INSTALLATION
717eba1
to
edf7dac
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved, but please change esm
to use the Agoric version before merging. Looks great!
yarn.lock
Outdated
esm@agoric-labs/esm#Agoric-built: | ||
esm@^3.2.25, esm@agoric-labs/esm#Agoric-built: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should only be esm@agoric-labs/esm#Agoric-built
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
packages/governance/package.json
Outdated
"devDependencies": { | ||
"@agoric/install-ses": "^0.5.13", | ||
"ava": "^3.12.1", | ||
"esm": "^3.2.25" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"esm": "^3.2.25" | |
"esm": "agoric-labs/esm#Agoric-built", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
closes #3186
outstanding issues:
the brand to the managed contract?