diff --git a/packages/ERTP/src/amountMath.js b/packages/ERTP/src/amountMath.js index 1a91db2c47d..b241991131a 100644 --- a/packages/ERTP/src/amountMath.js +++ b/packages/ERTP/src/amountMath.js @@ -86,12 +86,7 @@ const helpers = { /** * @template {AmountValue} V - * @type {(value: V) => - * V extends NatValue ? 'nat' : - * V extends SetValue ? 'set' : - * V extends CopySetValue ? 'copySet' : - * V extends CopyBagValue ? 'copyBag' : - * never} + * @type {(value: V) => AssetKindForValue} */ const assertValueGetAssetKind = value => { const passStyle = passStyleOf(value); @@ -148,10 +143,10 @@ const optionalBrandCheck = (allegedBrand, brand) => { }; /** - * @template {AmountValue} [V=AmountValue] - * @param {Amount} leftAmount - * @param {Amount} rightAmount - * @param {Brand | undefined} brand + * @template {AssetKind} [K=AssetKind] + * @param {Amount} leftAmount + * @param {Amount} rightAmount + * @param {Brand | undefined} brand * @returns {MathHelpers<*>} */ const checkLRAndGetHelpers = (leftAmount, rightAmount, brand = undefined) => { @@ -179,11 +174,11 @@ const checkLRAndGetHelpers = (leftAmount, rightAmount, brand = undefined) => { }; /** - * @template {AmountValue} V - * @param {MathHelpers} h - * @param {Amount} leftAmount - * @param {Amount} rightAmount - * @returns {[V, V]} + * @template {AssetKind} K + * @param {MathHelpers} h + * @param {Amount} leftAmount + * @param {Amount} rightAmount + * @returns {[K, K]} */ const coerceLR = (h, leftAmount, rightAmount) => { // @ts-ignore cast (ignore b/c erroring in CI but not my IDE) @@ -203,10 +198,10 @@ const AmountMath = { /** * Make an amount from a value by adding the brand. * - * @template {AmountValue} [V=AmountValue] - * @param {Brand} brand - * @param {V extends NatValue ? NatValue : V extends SetValue ? SetValue : V extends CopySetValue ? CopySetValue : V extends CopyBagValue ? CopyBagValue : never} allegedValue - * @returns {Amount} + * @template {AssetKind} [K=AssetKind] + * @param {Brand} brand + * @param {AssetValueForKind} allegedValue + * @returns {Amount} */ // allegedValue has a conditional expression for type widening, to prevent V being bound to a a literal like 1n make: (brand, allegedValue) => { @@ -220,10 +215,10 @@ const AmountMath = { * Make sure this amount is valid enough, and return a corresponding * valid amount if so. * - * @template {AmountValue} [V=AmountValue] + * @template {AssetKind} [K=AssetKind] * @param {Brand} brand - * @param {Amount} allegedAmount - * @returns {Amount} + * @param {Amount} allegedAmount + * @returns {Amount} */ coerce: (brand, allegedAmount) => { assertRemotable(brand, 'brand'); @@ -240,10 +235,10 @@ const AmountMath = { /** * Extract and return the value. * - * @template {AmountValue} [V=AmountValue] - * @param {Brand} brand - * @param {Amount} amount - * @returns {V} + * @template {AssetKind} [K=AssetKind] + * @param {Brand} brand + * @param {Amount} amount + * @returns {AssetValueForKind} */ getValue: (brand, amount) => AmountMath.coerce(brand, amount).value, /** @@ -251,9 +246,9 @@ const AmountMath = { * identity element for MathHelpers.add and MatHelpers.subtract. * * @template {AssetKind} K - * @param {Brand} brand - * @param {K=} [assetKind='nat'] - * @returns {Amount} + * @param {Brand} brand + * @param {K} [assetKind] + * @returns {Amount} */ // @ts-expect-error TS/jsdoc things 'nat' can't be assigned to K subclassing AssetKind // If we were using TypeScript we'd simply overload the function definition for each case. @@ -268,9 +263,9 @@ const AmountMath = { * Return the amount representing an empty amount, using another * amount as the template for the brand and assetKind. * - * @template {AmountValue} V - * @param {Amount} amount - * @returns {Amount} + * @template {AssetKind} K + * @param {Amount} amount + * @returns {Amount} */ makeEmptyFromAmount: amount => { assertRecord(amount, 'amount'); @@ -302,10 +297,10 @@ const AmountMath = { * whether rectangle A is greater than rectangle B depends on whether rectangle * A includes rectangle B as defined by the logic in MathHelpers. * - * @template {AmountValue} [V=AmountValue] - * @param {Amount} leftAmount - * @param {Amount} rightAmount - * @param {Brand=} brand + * @template {AssetKind} [K=AssetKind] + * @param {Amount} leftAmount + * @param {Amount} rightAmount + * @param {Brand=} brand * @returns {boolean} */ isGTE: (leftAmount, rightAmount, brand = undefined) => { @@ -316,10 +311,10 @@ const AmountMath = { * Returns true if the leftAmount equals the rightAmount. We assume * that if isGTE is true in both directions, isEqual is also true * - * @template {AmountValue} [V=AmountValue] - * @param {Amount} leftAmount - * @param {Amount} rightAmount - * @param {Brand=} brand + * @template {AssetKind} [K=AssetKind] + * @param {Amount} leftAmount + * @param {Amount} rightAmount + * @param {Brand=} brand * @returns {boolean} */ isEqual: (leftAmount, rightAmount, brand = undefined) => { @@ -333,11 +328,11 @@ const AmountMath = { * amount, it usually means including all of the elements from both * left and right. * - * @template {AmountValue} [V=AmountValue] - * @param {Amount} leftAmount - * @param {Amount} rightAmount - * @param {Brand=} brand - * @returns {Amount} + * @template {AssetKind} [K=AssetKind] + * @param {Amount} leftAmount + * @param {Amount} rightAmount + * @param {Brand=} brand + * @returns {Amount} */ add: (leftAmount, rightAmount, brand = undefined) => { const h = checkLRAndGetHelpers(leftAmount, rightAmount, brand); @@ -352,11 +347,11 @@ const AmountMath = { * left amount must include the right amount, this is NOT equivalent * to set subtraction. * - * @template {AmountValue} [V=AmountValue] - * @param {Amount} leftAmount - * @param {Amount} rightAmount - * @param {Brand=} brand - * @returns {Amount} + * @template {AssetKind} [K=AssetKind] + * @param {Amount} leftAmount + * @param {Amount} rightAmount + * @param {Brand=} brand + * @returns {Amount} */ subtract: (leftAmount, rightAmount, brand = undefined) => { const h = checkLRAndGetHelpers(leftAmount, rightAmount, brand); @@ -366,21 +361,21 @@ const AmountMath = { /** * Returns the min value between x and y using isGTE * - * @template {AmountValue} [V=AmountValue] - * @param {Amount} x - * @param {Amount} y - * @param {Brand=} brand - * @returns {Amount} + * @template {AssetKind} [K=AssetKind] + * @param {Amount} x + * @param {Amount} y + * @param {Brand=} brand + * @returns {Amount} */ min: (x, y, brand = undefined) => (AmountMath.isGTE(x, y, brand) ? y : x), /** * Returns the max value between x and y using isGTE * - * @template {AmountValue} [V=AmountValue] - * @param {Amount} x - * @param {Amount} y - * @param {Brand=} brand - * @returns {Amount} + * @template {AssetKind} [K=AssetKind] + * @param {Amount} x + * @param {Amount} y + * @param {Brand=} brand + * @returns {Amount} */ max: (x, y, brand = undefined) => (AmountMath.isGTE(x, y, brand) ? x : y), }; diff --git a/packages/ERTP/src/issuerKit.js b/packages/ERTP/src/issuerKit.js index 59ccb6898a1..1878f5e7c25 100644 --- a/packages/ERTP/src/issuerKit.js +++ b/packages/ERTP/src/issuerKit.js @@ -11,10 +11,38 @@ import { makePaymentLedger } from './paymentLedger.js'; import './types.js'; /** - * @type {MakeIssuerKit} + * @template {AssetKind} K + * The allegedName becomes part of the brand in asset descriptions. The + * allegedName doesn't have to be a string, but it will only be used for + * its value. The allegedName is useful for debugging and double-checking + * assumptions, but should not be trusted. + * + * The assetKind will be used to import a specific mathHelpers + * from the mathHelpers library. For example, natMathHelpers, the + * default, is used for basic fungible tokens. + * + * `displayInfo` gives information to the UI on how to display the amount. + * + * @param {string} allegedName + * @param {K} [assetKind=AssetKind.NAT] + * @param {AdditionalDisplayInfo} [displayInfo={}] + * @param {ShutdownWithFailure=} optShutdownWithFailure If this issuer fails + * in the middle of an atomic action (which btw should never happen), it + * potentially leaves its ledger in a corrupted state. If this function was + * provided, then the failed atomic action will call it, so that some + * larger unit of computation, like the enclosing vat, can be shutdown + * before anything else is corrupted by that corrupted state. + * See https://github.com/Agoric/agoric-sdk/issues/3434 + * @returns {{ + * mint: Mint, + * issuer: Issuer, + * brand: Brand, + * displayInfo: DisplayInfo, + * }} */ const makeIssuerKit = ( allegedName, + // @ts-expect-error K could be instantiated with a different subtype of AssetKind assetKind = AssetKind.NAT, displayInfo = harden({}), optShutdownWithFailure = undefined, @@ -61,3 +89,5 @@ const makeIssuerKit = ( harden(makeIssuerKit); export { makeIssuerKit }; + +/** @typedef {ReturnType} IssuerKit */ diff --git a/packages/ERTP/src/paymentLedger.js b/packages/ERTP/src/paymentLedger.js index 2b5d5783e22..6e82e00a3a9 100644 --- a/packages/ERTP/src/paymentLedger.js +++ b/packages/ERTP/src/paymentLedger.js @@ -16,12 +16,13 @@ import '@agoric/store/exported.js'; * Make the paymentLedger, the source of truth for the balances of * payments. All minting and transfer authority originates here. * + * @template {AssetKind} [K=AssetKind] * @param {string} allegedName * @param {Brand} brand * @param {AssetKind} assetKind * @param {DisplayInfo} displayInfo * @param {ShutdownWithFailure=} optShutdownWithFailure - * @returns {{ issuer: Issuer, mint: Mint }} + * @returns {{ issuer: Issuer, mint: Mint }} */ export const makePaymentLedger = ( allegedName, @@ -248,7 +249,12 @@ export const makePaymentLedger = ( }); }; - /** @type {MintPayment} */ + /** + * Creates a new Payment containing newly minted amount. + * + * @param {Amount} newAmount + * @returns {Payment} + */ const mintPayment = newAmount => { newAmount = coerce(newAmount); const payment = makePayment(allegedName, brand); @@ -331,7 +337,7 @@ export const makePaymentLedger = ( withdraw, }; - /** @type {Issuer} */ + /** @type {Issuer} */ const issuer = Far(`${allegedName} issuer`, { isLive, getAmountOf, @@ -348,7 +354,7 @@ export const makePaymentLedger = ( makePurse(allegedName, assetKind, brand, purseMethods), }); - /** @type {Mint} */ + /** @type {Mint} */ const mint = Far(`${allegedName} mint`, { getIssuer: () => issuer, mintPayment, diff --git a/packages/ERTP/src/types.js b/packages/ERTP/src/types.js index 7d75d60698e..19dffe82c9d 100644 --- a/packages/ERTP/src/types.js +++ b/packages/ERTP/src/types.js @@ -6,7 +6,7 @@ */ /** - * @template {AmountValue} [V=AmountValue] + * @template {AssetKind} [K=AssetKind] * @typedef {object} Amount * Amounts are descriptions of digital assets, answering the questions * "how much" and "of what kind". Amounts are values labeled with a brand. @@ -17,8 +17,8 @@ * relies heavily on polymorphic MathHelpers, which manipulate the unbranded * portion. * - * @property {Brand} brand - * @property {V} value + * @property {Brand} brand + * @property {AssetValueForKind} value */ /** @@ -58,6 +58,26 @@ */ /** + * @template {AssetKind} K + * @typedef {K extends 'nat' ? NatValue : + * K extends 'set' ? SetValue : + * K extends 'copySet' ? CopySetValue: + * K extends 'copyBag' ? CopyBagValue : + * never + * } AssetValueForKind + */ + +/** + * @template {AmountValue} V + * @typedef {V extends NatValue ? 'nat' : + * V extends SetValue ? 'set' : + * V extends CopySetValue ? 'copySet' : + * V extends CopyBagValue ? 'copyBag' : + * never} AssetKindForValue + */ + +/** + * @template {AssetKind} [K=AssetKind] * @typedef {Object} DisplayInfo * @property {number=} decimalPlaces Tells the display software how * many decimal places to move the decimal over to the left, or in @@ -69,12 +89,13 @@ * assets, should not be specified. The decimalPlaces property * should be used for *display purposes only*. Any other use is an * anti-pattern. - * @property {AssetKind} assetKind - the kind of asset, either + * @property {K} assetKind - the kind of asset, either * AssetKind.NAT (fungible) or * AssetKind.SET or AssertKind.COPY_SET (non-fungible) */ /** + * @template {AssetKind} [K=AssetKind] * @typedef {Object} Brand * The brand identifies the kind of issuer, and has a function to get the * alleged name for the kind of asset described. The alleged name (such @@ -197,6 +218,7 @@ */ /** + * @template {AssetKind} [K=AssetKind] * @typedef {Object} Issuer * * The issuer cannot mint a new amount, but it can create empty purses @@ -206,7 +228,7 @@ * source and then relied upon as the decider of whether an untrusted * payment is valid. * - * @property {() => Brand} getBrand Get the Brand for this Issuer. The + * @property {() => Brand} getBrand Get the Brand for this Issuer. The * Brand indicates the type of digital asset and is shared by the * mint, the issuer, and any purses and payments of this particular * kind. The brand is not closely held, so this function should not be @@ -260,55 +282,17 @@ */ /** - * @callback MakeIssuerKit - * @param {string} allegedName - * @param {AssetKind} [assetKind=AssetKind.NAT] - * @param {AdditionalDisplayInfo} [displayInfo={}] - * @param {ShutdownWithFailure=} optShutdownWithFailure If this issuer fails - * in the middle of an atomic action (which btw should never happen), it - * potentially leaves its ledger in a corrupted state. If this function was - * provided, then it the failed atomic action will call it, so that some - * larger unit of computation, like the enclosing vat, can be shutdown - * before anything else is corrupted by that corrupted state. - * See https://github.com/Agoric/agoric-sdk/issues/3434 - * @returns {IssuerKit} - * - * The allegedName becomes part of the brand in asset descriptions. The - * allegedName doesn't have to be a string, but it will only be used for - * its value. The allegedName is useful for debugging and double-checking - * assumptions, but should not be trusted. - * - * The assetKind will be used to import a specific mathHelpers - * from the mathHelpers library. For example, natMathHelpers, the - * default, is used for basic fungible tokens. - * - * `displayInfo` gives information to UI on how to display the amount. - * - * @typedef {Object} IssuerKit - * The return value of makeIssuerKit - * - * @property {Mint} mint - * @property {Issuer} issuer - * @property {Brand} brand - * @property {DisplayInfo} displayInfo - */ - -/** - * @callback MintPayment - * - * Creates a new Payment containing newly minted amount. - * - * @param {Amount} newAmount - * @returns {Payment} + * @typedef {import('./issuerKit').IssuerKit} IssuerKit */ /** + * @template {AssetKind} [K=AssetKind] * @typedef {Object} Mint * Holding a Mint carries the right to issue new digital assets. These * assets all have the same kind, which is called a Brand. * - * @property {() => Issuer} getIssuer Gets the Issuer for this mint. - * @property {MintPayment} mintPayment + * @property {() => Issuer} getIssuer Gets the Issuer for this mint. + * @property {MintPayment} mintPayment */ /** @@ -393,8 +377,8 @@ */ /** - * @template {AmountValue} V - * @typedef {Object} MathHelpers + * @template {AssetKind} K + * @typedef {Object} MathHelpers * All of the difference in how digital asset amount are manipulated can be * reduced to the behavior of the math on values. We extract this * custom logic into mathHelpers. MathHelpers are about value diff --git a/packages/run-protocol/src/interest-math.js b/packages/run-protocol/src/interest-math.js index 625147bc5ab..70b35441cce 100644 --- a/packages/run-protocol/src/interest-math.js +++ b/packages/run-protocol/src/interest-math.js @@ -27,10 +27,10 @@ const calculateRelativeCompounding = ( /** * - * @param {Amount} debtSnapshot + * @param {Amount<'nat'>} debtSnapshot * @param {Ratio} interestSnapshot as coefficient * @param {Ratio} currentCompoundedInterest as coefficient - * @returns {Amount} + * @returns {Amount<'nat'>} */ export const calculateCurrentDebt = ( debtSnapshot, @@ -51,9 +51,9 @@ export const calculateCurrentDebt = ( /** * - * @param {Amount} debt + * @param {Amount<'nat'>} debt * @param {Ratio} interestApplied - * @returns {Amount} + * @returns {Amount<'nat'>} */ export const reverseInterest = (debt, interestApplied) => { return floorDivideBy(debt, interestApplied); diff --git a/packages/run-protocol/src/interest.js b/packages/run-protocol/src/interest.js index 83576e1cbe9..abe4e0eb7a2 100644 --- a/packages/run-protocol/src/interest.js +++ b/packages/run-protocol/src/interest.js @@ -143,9 +143,9 @@ const validatedBrand = async (mint, debt) => { * @param {{ * latestInterestUpdate: bigint, * compoundedInterest: Ratio, - * totalDebt: Amount}} prior + * totalDebt: Amount<'nat'>}} prior * @param {bigint} accruedUntil - * @returns {Promise<{compoundedInterest: Ratio, latestInterestUpdate: bigint, totalDebt: Amount }>} + * @returns {Promise<{compoundedInterest: Ratio, latestInterestUpdate: bigint, totalDebt: Amount<'nat'> }>} */ export const chargeInterest = async (powers, params, prior, accruedUntil) => { const brand = await validatedBrand(powers.mint, prior.totalDebt); diff --git a/packages/run-protocol/src/vaultFactory/prioritizedVaults.js b/packages/run-protocol/src/vaultFactory/prioritizedVaults.js index 069aa915e89..58dd4dd6a95 100644 --- a/packages/run-protocol/src/vaultFactory/prioritizedVaults.js +++ b/packages/run-protocol/src/vaultFactory/prioritizedVaults.js @@ -10,8 +10,8 @@ import { toVaultKey } from './storeUtils.js'; /** * - * @param {Amount} debtAmount - * @param {Amount} collateralAmount + * @param {Amount<'nat'>} debtAmount + * @param {Amount<'nat'>} collateralAmount * @returns {Ratio} */ const calculateDebtToCollateral = (debtAmount, collateralAmount) => { @@ -111,8 +111,8 @@ export const makePrioritizedVaults = reschedulePriceCheck => { /** * - * @param {Amount} oldDebt - * @param {Amount} oldCollateral + * @param {Amount<'nat'>} oldDebt + * @param {Amount<'nat'>} oldCollateral * @param {string} vaultId */ const removeVaultByAttributes = (oldDebt, oldCollateral, vaultId) => { @@ -159,8 +159,8 @@ export const makePrioritizedVaults = reschedulePriceCheck => { } /** - * @param {Amount} oldDebt - * @param {Amount} oldCollateral + * @param {Amount<'nat'>} oldDebt + * @param {Amount<'nat'>} oldCollateral * @param {string} vaultId */ const refreshVaultPriority = (oldDebt, oldCollateral, vaultId) => { diff --git a/packages/run-protocol/src/vaultFactory/storeUtils.js b/packages/run-protocol/src/vaultFactory/storeUtils.js index 36cdf7f3ac7..acba7870a70 100644 --- a/packages/run-protocol/src/vaultFactory/storeUtils.js +++ b/packages/run-protocol/src/vaultFactory/storeUtils.js @@ -20,8 +20,8 @@ const dbEntryKeyToNumber = makeDecodeKey(/** @type {any} */ (null)); * Overcollateralized are greater than one. * The more undercollaterized the smaller in [0-1]. * - * @param {Amount} normalizedDebt normalized (not actual) total debt - * @param {Amount} collateral + * @param {Amount<'nat'>} normalizedDebt normalized (not actual) total debt + * @param {Amount<'nat'>} collateral * @returns {number} */ const collateralizationRatio = (normalizedDebt, collateral) => { @@ -35,8 +35,8 @@ const collateralizationRatio = (normalizedDebt, collateral) => { /** * Sorts by ratio in descending debt. Ordering of vault id is undefined. * - * @param {Amount} normalizedDebt normalized (not actual) total debt - * @param {Amount} collateral + * @param {Amount<'nat'>} normalizedDebt normalized (not actual) total debt + * @param {Amount<'nat'>} collateral * @param {VaultId} vaultId * @returns {string} lexically sortable string in which highest debt-to-collateral is earliest */ diff --git a/packages/run-protocol/src/vaultFactory/vault.js b/packages/run-protocol/src/vaultFactory/vault.js index 962027f0317..fc3ea604c0e 100644 --- a/packages/run-protocol/src/vaultFactory/vault.js +++ b/packages/run-protocol/src/vaultFactory/vault.js @@ -61,8 +61,8 @@ const validTransitions = { * @typedef {VaultPhase[keyof typeof VaultPhase]} OuterPhase * * @typedef {Object} VaultUIState - * @property {Amount} locked Amount of Collateral locked - * @property {{run: Amount, interest: Ratio}} debtSnapshot Debt of 'run' at the point the compounded interest was 'interest' + * @property {Amount<'nat'>} locked Amount of Collateral locked + * @property {{run: Amount<'nat'>, interest: Ratio}} debtSnapshot Debt of 'run' at the point the compounded interest was 'interest' * @property {Ratio} interestRate Annual interest rate charge * @property {Ratio} liquidationRatio * @property {OuterPhase} vaultState @@ -96,7 +96,7 @@ const validTransitions = { * interestSnapshot: Ratio, * outerUpdater: IterationObserver | null, * phase: InnerPhase, - * debtSnapshot: Amount, + * debtSnapshot: Amount<'nat'>, * }} MutableState */ @@ -118,6 +118,7 @@ export const makeInnerVault = ( ) => { // CONSTANTS const collateralBrand = manager.getCollateralBrand(); + /** @type {{brand: Brand<'nat'>}} */ const { brand: debtBrand } = mint.getIssuerRecord(); /** @@ -144,7 +145,6 @@ export const makeInnerVault = ( // Two values from the same moment interestSnapshot: manager.getCompoundedInterest(), - /** @type {any} cast */ debtSnapshot: AmountMath.makeEmpty(debtBrand), }; @@ -184,7 +184,6 @@ export const makeInnerVault = ( */ const updateDebtSnapshot = newDebt => { // update local state - // @ts-expect-error newDebt is actually Amount state.debtSnapshot = newDebt; state.interestSnapshot = manager.getCompoundedInterest(); }; @@ -212,7 +211,7 @@ export const makeInnerVault = ( * what interest has compounded since this vault record was written. * * @see getNormalizedDebt - * @returns {Amount} + * @returns {Amount<'nat'>} */ const getCurrentDebt = () => { return calculateCurrentDebt( @@ -229,7 +228,7 @@ export const makeInnerVault = ( * the interest accrues. * * @see getActualDebAmount - * @returns {Amount} as if the vault was open at the launch of this manager, before any interest accrued + * @returns {Amount<'nat'>} as if the vault was open at the launch of this manager, before any interest accrued */ const getNormalizedDebt = () => { return reverseInterest(state.debtSnapshot, state.interestSnapshot); @@ -272,7 +271,7 @@ export const makeInnerVault = ( /** * - * @returns {Amount} + * @returns {Amount<'nat'>} */ const getCollateralAmount = () => { const { vaultSeat } = state; diff --git a/packages/run-protocol/src/vaultFactory/vaultManager.js b/packages/run-protocol/src/vaultFactory/vaultManager.js index 02302e79254..40ca3d2ca2c 100644 --- a/packages/run-protocol/src/vaultFactory/vaultManager.js +++ b/packages/run-protocol/src/vaultFactory/vaultManager.js @@ -39,7 +39,7 @@ const trace = makeTracer('VM'); * compoundedInterest: Ratio, * interestRate: Ratio, * latestInterestUpdate: bigint, - * totalDebt: Amount, + * totalDebt: Amount<'nat'>, * }} AssetState */ /** @@ -49,7 +49,7 @@ const trace = makeTracer('VM'); * the collateral is provided in exchange for borrowed RUN. * * @param {ContractFacet} zcf - * @param {ZCFMint} debtMint + * @param {ZCFMint<'nat'>} debtMint * @param {Brand} collateralBrand * @param {ERef} priceAuthority * @param {{ @@ -75,6 +75,7 @@ export const makeVaultManager = ( liquidationStrategy, startTimeStamp, ) => { + /** @type {{brand: Brand<'nat'>}} */ const { brand: debtBrand } = debtMint.getIssuerRecord(); /** @type {GetVaultParams} */ @@ -116,7 +117,7 @@ export const makeVaultManager = ( /** @type {MutableQuote=} */ let outstandingQuote; - /** @type {Amount} */ + /** @type {Amount<'nat'>} */ let totalDebt = AmountMath.makeEmpty(debtBrand, 'nat'); /** @type {Ratio}} */ let compoundedInterest = makeRatio(100n, debtBrand); // starts at 1.0, no interest @@ -296,8 +297,8 @@ export const makeVaultManager = ( /** * Update total debt of this manager given the change in debt on a vault * - * @param {Amount} oldDebtOnVault - * @param {Amount} newDebtOnVault + * @param {Amount<'nat'>} oldDebtOnVault + * @param {Amount<'nat'>} newDebtOnVault */ // TODO https://github.com/Agoric/agoric-sdk/issues/4599 const applyDebtDelta = (oldDebtOnVault, newDebtOnVault) => { @@ -313,8 +314,8 @@ export const makeVaultManager = ( }; /** - * @param {Amount} oldDebt - * @param {Amount} oldCollateral + * @param {Amount<'nat'>} oldDebt + * @param {Amount<'nat'>} oldCollateral * @param {VaultId} vaultId */ const updateVaultPriority = (oldDebt, oldCollateral, vaultId) => { diff --git a/packages/run-protocol/test/test-interest-math.js b/packages/run-protocol/test/test-interest-math.js index 912180170e9..d64b1236bf4 100644 --- a/packages/run-protocol/test/test-interest-math.js +++ b/packages/run-protocol/test/test-interest-math.js @@ -14,7 +14,7 @@ const runBrand = makeIssuerKit('run').brand; * @param {bigint} result */ function checkDebt(t, input, result) { - /** @type {Amount} */ + /** @type {Amount<'nat'>} */ const debtSnapshot = AmountMath.make(runBrand, input[0]); const interestSnapshot = makeRatio(100n + input[1], runBrand); const currentCompoundedInterest = makeRatio(100n + input[2], runBrand); @@ -51,7 +51,7 @@ for (const [input, result] of /** @type {const} */ ([ } function checkReverse(t, input, result) { - /** @type {Amount} */ + /** @type {Amount<'nat'>} */ const debt = AmountMath.make(runBrand, input[0]); const interestApplied = makeRatio(100n + input[1], runBrand); t.deepEqual(reverseInterest(debt, interestApplied).value, result); diff --git a/packages/run-protocol/test/test-interest.js b/packages/run-protocol/test/test-interest.js index dd43defcdd4..8c8c6162b11 100644 --- a/packages/run-protocol/test/test-interest.js +++ b/packages/run-protocol/test/test-interest.js @@ -506,7 +506,7 @@ test('chargeInterest when no time elapsed', async t => { const prior = { latestInterestUpdate: now, compoundedInterest: makeRatio(100n, brand), - /** @type {Amount} */ + /** @type {Amount<'nat'>} */ totalDebt: AmountMath.make(brand, 10_000n), }; const results = await chargeInterest(powers, params, prior, now); diff --git a/packages/zoe/src/contractFacet/types.js b/packages/zoe/src/contractFacet/types.js index 85b113991d0..e12f3b7b940 100644 --- a/packages/zoe/src/contractFacet/types.js +++ b/packages/zoe/src/contractFacet/types.js @@ -101,14 +101,6 @@ * @returns {Promise>} */ -/** - * @callback MakeZCFMint - * @param {Keyword} keyword - * @param {AssetKind=} assetKind - * @param {AdditionalDisplayInfo=} displayInfo - * @returns {Promise} - */ - /** * @callback ZCFRegisterFeeMint * @param {Keyword} keyword @@ -144,8 +136,9 @@ */ /** + * @template {AssetKind} [K=AssetKind] * @typedef {Object} ZCFMint - * @property {() => IssuerRecord} getIssuerRecord + * @property {() => IssuerRecord} getIssuerRecord * @property {ZCFMintMintGains} mintGains * All the amounts in gains must be of this ZCFMint's brand. * The gains' keywords are in the namespace of that seat. diff --git a/packages/zoe/src/contractFacet/zcfZygote.js b/packages/zoe/src/contractFacet/zcfZygote.js index e305e6b987c..0d92ed77fcc 100644 --- a/packages/zoe/src/contractFacet/zcfZygote.js +++ b/packages/zoe/src/contractFacet/zcfZygote.js @@ -206,9 +206,16 @@ export const makeZCFZygote = ( return zcfMint; }; - /** @type {MakeZCFMint} */ + /** + * @template {AssetKind} [K='nat'] + * @param {Keyword} keyword + * @param {K} [assetKind] + * @param {AdditionalDisplayInfo=} displayInfo + * @returns {Promise} + */ const makeZCFMint = async ( keyword, + // @ts-expect-error possible different subtype assetKind = AssetKind.NAT, displayInfo, ) => { diff --git a/packages/zoe/src/contractSupport/types.js b/packages/zoe/src/contractSupport/types.js index eedab76df98..6edbcdd6b54 100644 --- a/packages/zoe/src/contractSupport/types.js +++ b/packages/zoe/src/contractSupport/types.js @@ -81,13 +81,13 @@ /** * @typedef {Object} Ratio - * @property {Amount} numerator - * @property {Amount} denominator + * @property {Amount<'nat'>} numerator + * @property {Amount<'nat'>} denominator */ /** * @callback ScaleAmount * @param {Amount} amount * @param {Ratio} ratio - * @returns {Amount} + * @returns {Amount<'nat'>} */ diff --git a/packages/zoe/src/types.js b/packages/zoe/src/types.js index 77a740618bc..5238ec26f42 100644 --- a/packages/zoe/src/types.js +++ b/packages/zoe/src/types.js @@ -31,10 +31,11 @@ * @property {Terms} terms - contract parameters * + * @template {AssetKind} [K=AssetKind] * @typedef {Object} IssuerRecord - * @property {Brand} brand - * @property {Issuer} issuer - * @property {AssetKind} assetKind + * @property {Brand} brand + * @property {Issuer} issuer + * @property {K} assetKind * @property {any} [displayInfo] * * @typedef {AmountKeywordRecord} Allocation