-
Notifications
You must be signed in to change notification settings - Fork 253
refactor(run-protocol): move config of charging and recording periods to vault factory #4394
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
Conversation
packages/assert/src/assert.js
Outdated
* @param {string} [message] | ||
* @returns {T} | ||
*/ | ||
export function assertDefined(val, message) { |
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.
@erights WDYT of this? similar to Nat
but for a nullish check. See below for an example in action.
18cd189
to
a914f32
Compare
IMO the problem here is that I don't disagree that an |
packages/assert/src/assert.js
Outdated
/** | ||
* @template T | ||
* @param {T | null | undefined} val | ||
* @param {string} [message] | ||
* @returns {T} | ||
*/ | ||
export function assertDefined(val, message) { | ||
if (val != null) { | ||
return val; | ||
} | ||
throw Error(message !== undefined ? message : `unexpected ${val}`); | ||
} |
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 like the idea of it, but have some questions. The assert module is migrating from agoric-sdk to endo anyway. But wherever it is, it should be written in our normal assertFoo
style. The following is how I might write it.
Also, please don't write function
functions. We have essentially adopted an arrow-only style. We have not yet taken the time to convert old code. But new code should be in arrow-only style unless there's a good stated reason otherwise.
Also, you're exporting a non-hardened value.
/** | |
* @template T | |
* @param {T | null | undefined} val | |
* @param {string} [message] | |
* @returns {T} | |
*/ | |
export function assertDefined(val, message) { | |
if (val != null) { | |
return val; | |
} | |
throw Error(message !== undefined ? message : `unexpected ${val}`); | |
} | |
/** | |
* @template T | |
* @param {T | null | undefined} val | |
* @param {string} [optDetails] | |
* @returns {T} | |
*/ | |
export const assertDefined = (val, optDetails = X`unexpected ${q(val)}`) => { | |
if (val != null) { | |
// This `!= null` idiom checks that `val` is not `null` nor `undefined`. | |
return val; | |
} | |
assert.fail(optDetails); | |
}; | |
harden(assertDefined); |
Also, I'm not sure I like "defined" as the opposite of "nullish". But I cannot think of a better one.
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.
Apropos naming, is there a better term than "assert"? In SES, global assert mostly return void but this one returns the argument.
I could see someone being surprised by one or the other. For consistency, would it be better to return the argument when asserting a type or to have a different verb for this version that returns its argument? cc @kriskowal
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 is a good point. I agree that we should not have a function named assertFoo
that returns its argument. This is indeed inconsistent with both precedents: The assertFoo
functions we have don't return their argument, and the validating or coercing functions we have that do return their argument, or a coerced-to-validated form of their argument, like Nat
, and written simply naming the property they assure about their return result. This one at least is written with an initial upper case, mirroring similar usage of String
, BigInt
etc.
How about simply NotNullish
?
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.
Went with slight tweak, NonNullish
, similar to https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullabletype
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 have in hobby projects found it useful to distinguish assert*
(returns void) from assume*
(returns argument), though one could argue that all assume
functions could just be assert
and ignore the return.
https://github.com/borkshop/js/blob/main/cube/assert.js
Not having to name an intermediate variable in an expression like this is useful:
const location = assumeDefined(locations.get(entityId), X`No entity for identifier ${q(entityId)}`);
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.
With some refactoring I don't need this anymore but I still think it would be useful. Pulling out to #4422 and removing you from reviewers for this PR.
import { | ||
CHARGING_PERIOD, | ||
RECORDING_PERIOD, | ||
} from '@agoric/zoe/src/contracts/loan'; | ||
|
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.
That's an example contract that, according to #1656, should move out of Zoe. Let's not use that as the source of truth for this.
a914f32
to
5537785
Compare
the NonNullish utility for which changes were requested has been pulled out (#4422)
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 see a test for the fix / feature / design change. I suggest a test that changes the recording period and checks that it affects vaults of multiple collateral brands.
@@ -49,6 +51,8 @@ const handleParamGovernance = (zcf, paramManager) => { | |||
...originalPublicFacet, | |||
getSubscription: () => paramManager.getSubscription(), | |||
getContractGovernor: () => electionManager, | |||
/** @type {GetGovernedVaultParams} */ | |||
// @ts-expect-error we know this ParamManagerFull is really a GetGovernedVaultParams |
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.
Not for this PR, but...
I suspect there's a way to avoid type conflicts like this by parameterizing types such as ParamManagerFull
.
It looks like I didn't file an issue, but I did some related work in https://github.com/Agoric/agoric-sdk/commits/claims-registar-dc-review esp 88b28e9 .
/** | ||
* @param {bigint} 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.
In the interest of vertical code density, for single-parameter functions, I usually do:
/** | |
* @param {bigint} value | |
*/ | |
/** @param {bigint} value */ |
This reduces consistency somewhat. And if the function later takes more than one parameter, there is some churn. So it's a matter of taste.
// @ts-ignore It's a VaultParamManager | ||
/** | ||
* @param {LoanTiming} initialValues | ||
* @returns {ParamManagerFull & { |
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.
}; | ||
|
||
/** | ||
* XXX maybe call this "loan terms"? |
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.
to whom is this XXX
comment directed? Why call it "loan terms"? Is there something wrong with the current name? if so, what?
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 XXX is directed at whoever is reading this code, but I think this one can be resolved before merging.
I thought "terms" instead of "rates" because while it includes interestRate
it also has initialMargin
, liquidationMargin
and loanFee
. The latter don't seem like rates to me but they are part of the terms of the loan.
I didn't make the change because I thought maybe the charging and recording period could be considered terms of the loan… but since those are parameters of the whole vault factory they aren't part of any particular loan.
So I think Terms is better than Rates. But I'm not as sure about the "Loan" term (pun intended) because vaults, while they share some mechanics with loans, are explicitly not loans. Maybe ChargingTerms?
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 have some hesitation about changing this name, as it's not required to address #4185 . It's a bit of a "drive-by." Plus, I feel a little like when my spouse asks me whether I like the new paint color; I just don't have an opinion.
OTOH, @dtribble did ask you to look into naming issues such as this. See if you can grab him briefly?
For somewhat arbitrary issues like this, I'm kinda inclined to fall back on an executive hierarchy (#3382); that is: talk about it with @Chris-Hibbert .
I guess if it's between you and me: I'll agree to a change if you think it's sufficiently worthwhile to add a test :)
Is it part of the package's external API? If so, that makes it a breaking change, yes? So it would need its own conventional commit to get it in the CHANGELOG. (or do we use NEWS.md in this package?)
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 call that it's out of scope. I've cut it and will look into it separately.
Good question about breaking change… changing the TS type wouldn't break API but this refactoring does change how debts are calculated. However I don't think it breaks any external assumptions because Agoric controls the governance of both the vault factory and vault managers (the destination and source for timing governance)
packages/governance/src/types.js
Outdated
*/ | ||
|
||
/** | ||
* @typedef {Object} ParamManagerBase | ||
* @property {GetParams} getParams | ||
* @property {() => Record<Keyword,ParamShortDescription>} 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.
* @property {() => Record<Keyword,ParamShortDescription>} getParams | |
* @property {() => Record<Keyword, ParamShortDescription>} 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.
Thanks. Among the downside of type defs being in jsdoc comments. In .ts file Prettier would autoformat.
We have 95 Record
with space and 18 without it.
/** | ||
* @param {Amount} electorateInvitationAmount | ||
*/ |
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.
again, please consider a more dense/concise form:
/** | |
* @param {Amount} electorateInvitationAmount | |
*/ | |
/** @param {Amount} electorateInvitationAmount */ |
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 convinced.
As you said above, there's a trade-off with comment churn when another param is added. But on balance I think it's better to have the concise form. Comments have less need for git blame
.
@@ -16,7 +16,7 @@ | |||
*/ | |||
|
|||
/** | |||
* @typedef {Object} Rates | |||
* @typedef {Object} Rates - XXX loan terms? |
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.
another XXX. I'm not sure what to do with these.
If they are intended to land on master, ideally they would have corresponding issue #s.
*/ | ||
|
||
/** | ||
* @callback MakeVaultParamManager |
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 riddance to the use of @callback
for something that isn't actually passed around as a callback.
* 'ChargingPeriod': ParamRecord<'relativeTime'> & { value: RelativeTime }, | ||
* 'RecordingPeriod': ParamRecord<'relativeTime'> & { value: RelativeTime }, |
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.
again: why quote these keys?
* 'ChargingPeriod': ParamRecord<'relativeTime'> & { value: RelativeTime }, | |
* 'RecordingPeriod': ParamRecord<'relativeTime'> & { value: RelativeTime }, | |
* ChargingPeriod: ParamRecord<'relativeTime'> & { value: RelativeTime }, | |
* RecordingPeriod: ParamRecord<'relativeTime'> & { value: RelativeTime }, |
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.
vestiges of refactoring I guess. will remove.
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.
Doesn't seem to have been cleaned up before merge?
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.
mea culpa. I'll include in another PR
fc86778
to
1c04948
Compare
Good suggestion, @dckc . Given the state of swingset testing in run-protocol, I discussed with Dean in standup and we agreed to punt to a more comprehensive look at test coverage #4432 PTAAL |
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.
postponing testing is very much not my style, but let's give it a try (#4432).
* @callback GetParams - getParams() retrieves a Record containing | ||
* keyword pairs with descriptions of parameters under governance. | ||
* @returns {Record<Keyword,ParamShortDescription>} | ||
* @callback GetGovernedVaultParams |
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.
@turadg governance shouldn't know about vaults.
This looks like it's actually about Vaults, so I'd like to move it. Is there a reason it needs to be 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.
This was a best effort to get the types consistent. Feel free to improve!
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 sorta moved it back in #4437
@@ -539,7 +544,7 @@ | |||
* @typedef {Object} GovernedPublicFacet | |||
* @property {() => Subscription<ParamDescription>} getSubscription | |||
* @property {VoteOnParamChange} getContractGovernor | |||
* @property {GetParams} getGovernedParams - get descriptions of | |||
* @property {GetGovernedVaultParams} getGovernedParams - get descriptions of |
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 may be the case that the only actual use of this is in Vaults, but the support in Governance should be more generic. Is there a way to have a generic GetParams here, and override it with something more specific in Vaults?
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, if in the vaults we use something more specific instead of GovernedPublicFacet
. Happy to work together on the specifics.
* 'ChargingPeriod': ParamRecord<'relativeTime'> & { value: RelativeTime }, | ||
* 'RecordingPeriod': ParamRecord<'relativeTime'> & { value: RelativeTime }, |
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.
Doesn't seem to have been cleaned up before merge?
closes: #4185
Description
Moves the loan calculation periods (charging and recording) from governance params on each vault manager (collateral type) to the vault factory as a whole.
Security Considerations
See #4185
Documentation Considerations
Needs documenting
Testing Considerations
Period governance probably needs testing. Will be addressed in #4432