From 9d02dfab2cc2c24ed9b15a6aa8bc5fba7d6c9fe0 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Wed, 12 Jun 2024 06:48:40 -0700 Subject: [PATCH 1/2] feat(types): ContractMeta --- .../test/upgrade-contract/fixed-contract.js | 2 +- packages/boot/test/bootstrapTests/zcfProbe.js | 2 +- packages/governance/src/committee.js | 2 +- packages/governance/src/contractGovernor.js | 2 +- .../src/econCommitteeCharter.js | 2 +- packages/inter-protocol/src/feeDistributor.js | 2 +- .../src/reserve/assetReserve.js | 2 +- .../src/examples/stakeIca.contract.js | 1 + .../src/examples/swapExample.contract.js | 2 +- packages/vats/src/mintHolder.js | 2 +- .../zoe/src/contractFacet/types-ambient.d.ts | 12 ++++-- .../coveredCall-durable-V3.js | 2 +- packages/zoe/test/types.test-d.ts | 37 ++++++++++++++++++- 13 files changed, 56 insertions(+), 14 deletions(-) diff --git a/packages/agoric-cli/test/upgrade-contract/fixed-contract.js b/packages/agoric-cli/test/upgrade-contract/fixed-contract.js index 9140419297e..cf19defe953 100644 --- a/packages/agoric-cli/test/upgrade-contract/fixed-contract.js +++ b/packages/agoric-cli/test/upgrade-contract/fixed-contract.js @@ -1,7 +1,7 @@ import { AmountMath } from '@agoric/ertp'; import { makeDurableZone } from '@agoric/zone/durable.js'; -/** @type {ContractMeta} */ +/** @type {ContractMeta} */ export const meta = { upgradability: 'canUpgrade', }; diff --git a/packages/boot/test/bootstrapTests/zcfProbe.js b/packages/boot/test/bootstrapTests/zcfProbe.js index 5089ebdd659..bec8d63684c 100644 --- a/packages/boot/test/bootstrapTests/zcfProbe.js +++ b/packages/boot/test/bootstrapTests/zcfProbe.js @@ -17,7 +17,7 @@ const ZcfProbeI = M.interface('ZCF Probe', { makeFaucetInvitation: M.call().returns(M.promise()), }); -// /** @type {ContractMeta} */ +// /** @type {ContractMeta} */ // export const meta = { upgradability: 'canUpgrade' }; // harden(meta); diff --git a/packages/governance/src/committee.js b/packages/governance/src/committee.js index 4fd70deafa9..8eb967d75fb 100644 --- a/packages/governance/src/committee.js +++ b/packages/governance/src/committee.js @@ -28,7 +28,7 @@ const { ceilDivide } = natSafeMath; * }} CommitteeElectorateCreatorFacet */ -/** @type {ContractMeta} */ +/** @type {ContractMeta} */ export const meta = { privateArgsShape: { storageNode: StorageNodeShape, diff --git a/packages/governance/src/contractGovernor.js b/packages/governance/src/contractGovernor.js index 8708ecbe055..90575ef2fdf 100644 --- a/packages/governance/src/contractGovernor.js +++ b/packages/governance/src/contractGovernor.js @@ -15,7 +15,7 @@ const { Fail } = assert; const trace = makeTracer('CGov', false); -/** @type {ContractMeta} */ +/** @type {ContractMeta} */ export const meta = { upgradability: 'canUpgrade', }; diff --git a/packages/inter-protocol/src/econCommitteeCharter.js b/packages/inter-protocol/src/econCommitteeCharter.js index 7c5913a91e9..b718e4d9337 100644 --- a/packages/inter-protocol/src/econCommitteeCharter.js +++ b/packages/inter-protocol/src/econCommitteeCharter.js @@ -38,7 +38,7 @@ const ParamChangesOfferArgsShape = M.splitRecord( }, ); -/** @type {ContractMeta} */ +/** @type {ContractMeta} */ export const meta = { customTermsShape: { binaryVoteCounterInstallation: InstallationShape, diff --git a/packages/inter-protocol/src/feeDistributor.js b/packages/inter-protocol/src/feeDistributor.js index 0818efe0724..5871f9c50dd 100644 --- a/packages/inter-protocol/src/feeDistributor.js +++ b/packages/inter-protocol/src/feeDistributor.js @@ -9,7 +9,7 @@ import { KeywordShape } from '@agoric/zoe/src/typeGuards.js'; const KeywordSharesShape = M.recordOf(KeywordShape, M.nat()); -/** @type {ContractMeta} */ +/** @type {ContractMeta} */ export const meta = { customTermsShape: { keywordShares: KeywordSharesShape, diff --git a/packages/inter-protocol/src/reserve/assetReserve.js b/packages/inter-protocol/src/reserve/assetReserve.js index f34c2de3bcf..322172e0e0f 100644 --- a/packages/inter-protocol/src/reserve/assetReserve.js +++ b/packages/inter-protocol/src/reserve/assetReserve.js @@ -10,7 +10,7 @@ import { prepareAssetReserveKit } from './assetReserveKit.js'; const trace = makeTracer('AR', true); -/** @type {ContractMeta} */ +/** @type {ContractMeta} */ export const meta = { upgradability: 'canUpgrade', }; diff --git a/packages/orchestration/src/examples/stakeIca.contract.js b/packages/orchestration/src/examples/stakeIca.contract.js index e1093857d8f..8f4562220a4 100644 --- a/packages/orchestration/src/examples/stakeIca.contract.js +++ b/packages/orchestration/src/examples/stakeIca.contract.js @@ -17,6 +17,7 @@ const trace = makeTracer('StakeAtom'); * @import {ICQConnection, OrchestrationService} from '../types.js'; */ +/** @type {ContractMeta} */ export const meta = harden({ customTermsShape: { chainId: M.string(), diff --git a/packages/orchestration/src/examples/swapExample.contract.js b/packages/orchestration/src/examples/swapExample.contract.js index 9c138c393ae..a7ba4c8db2e 100644 --- a/packages/orchestration/src/examples/swapExample.contract.js +++ b/packages/orchestration/src/examples/swapExample.contract.js @@ -21,7 +21,7 @@ import { prepareLocalChainAccountKit } from '../exos/local-chain-account-kit.js' * @import {NameHub} from '@agoric/vats'; */ -/** @type {ContractMeta} */ +/** @type {ContractMeta} */ export const meta = { privateArgsShape: { agoricNames: M.remotable('agoricNames'), diff --git a/packages/vats/src/mintHolder.js b/packages/vats/src/mintHolder.js index c9a9b3c176d..3041c807f4d 100644 --- a/packages/vats/src/mintHolder.js +++ b/packages/vats/src/mintHolder.js @@ -25,7 +25,7 @@ function provideIssuerKit(zcf, baggage) { return prepareIssuerKit(baggage, keyword, assetKind, displayInfo); } -/** @type {ContractMeta} */ +/** @type {ContractMeta} */ export const meta = { upgradability: 'canUpgrade', }; diff --git a/packages/zoe/src/contractFacet/types-ambient.d.ts b/packages/zoe/src/contractFacet/types-ambient.d.ts index f9c6d9b479d..219e97e864d 100644 --- a/packages/zoe/src/contractFacet/types-ambient.d.ts +++ b/packages/zoe/src/contractFacet/types-ambient.d.ts @@ -217,9 +217,15 @@ type OfferHandler = | { handle: HandleOffer; }; -type ContractMeta = { - customTermsShape?: import('@endo/pass-style').CopyRecord | undefined; - privateArgsShape?: import('@endo/pass-style').CopyRecord | undefined; +type ContractMeta< + SF extends // import inline to maintain ambient mode + import('../zoeService/utils').ContractStartFunction = import('../zoeService/utils').ContractStartFunction, +> = { + customTermsShape?: Record< + Parameters[0] extends ZCF ? keyof CT : never, + Pattern + >; + privateArgsShape?: { [K in keyof Parameters[1]]: Pattern }; upgradability?: 'none' | 'canBeUpgraded' | 'canUpgrade' | undefined; }; /** diff --git a/packages/zoe/test/swingsetTests/upgradeCoveredCall/coveredCall-durable-V3.js b/packages/zoe/test/swingsetTests/upgradeCoveredCall/coveredCall-durable-V3.js index 9664cec2d00..b44f6dc3d37 100644 --- a/packages/zoe/test/swingsetTests/upgradeCoveredCall/coveredCall-durable-V3.js +++ b/packages/zoe/test/swingsetTests/upgradeCoveredCall/coveredCall-durable-V3.js @@ -12,7 +12,7 @@ const { details: X } = assert; const sellSeatExpiredMsg = 'The covered call option is expired.'; -/** @type {ContractMeta} */ +/** @type {ContractMeta} */ export const meta = { upgradability: 'canUpgrade', }; diff --git a/packages/zoe/test/types.test-d.ts b/packages/zoe/test/types.test-d.ts index cb4098079fe..0301025a531 100644 --- a/packages/zoe/test/types.test-d.ts +++ b/packages/zoe/test/types.test-d.ts @@ -7,7 +7,7 @@ import { E, RemoteFunctions } from '@endo/eventual-send'; import { expectNotType, expectType } from 'tsd'; -import type { Key } from '@endo/patterns'; +import { M, type Key } from '@endo/patterns'; // 'prepare' is deprecated but still supported import type { prepare as scaledPriceAuthorityStart } from '../src/contracts/scaledPriceAuthority.js'; import type { Instance } from '../src/zoeService/utils.js'; @@ -104,3 +104,38 @@ const mock = null as any; // @ts-expect-error pf2.notInPublicFacet; } + +{ + const start = async ( + zcf: ZCF<{ anchorBrand: Brand<'nat'> }>, + privateArgs: { + storageNode: StorageNode; + marshaller: Marshaller; + feeMintAccess?: FeeMintAccess; + }, + ) => ({}); + + const meta: ContractMeta = { + // XXX not detected + extrakey: 'bad', + privateArgsShape: { + // @ts-expect-error extra key + extraKey: 'bad', + marshaller: mock, + storageNode: mock, + }, + // @ts-expect-error invalid upgradability value + upgradability: 'invalid', + }; + + const metaWithSplitRecord: ContractMeta = { + // XXX not detected + extrakey: 'bad', + // @ts-expect-error Matcher not assignable + privateArgsShape: M.splitRecord({ + extraKey: 'bad', + marshaller: mock, + storageNode: mock, + }), + }; +} From c843758c3a294fabe399d44ce794da1d90379231 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Wed, 12 Jun 2024 08:28:00 -0700 Subject: [PATCH 2/2] docs: upgradability meta --- packages/zoe/src/contractFacet/types-ambient.d.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/zoe/src/contractFacet/types-ambient.d.ts b/packages/zoe/src/contractFacet/types-ambient.d.ts index 219e97e864d..168fdca74be 100644 --- a/packages/zoe/src/contractFacet/types-ambient.d.ts +++ b/packages/zoe/src/contractFacet/types-ambient.d.ts @@ -226,6 +226,11 @@ type ContractMeta< Pattern >; privateArgsShape?: { [K in keyof Parameters[1]]: Pattern }; + /** + * - `none` means that the contract is not upgradable. + * - `canUpgrade` means this code can perform an upgrade + * - `canBeUpgraded` means that the contract stores kinds durably such that the next version can upgrade + */ upgradability?: 'none' | 'canBeUpgraded' | 'canUpgrade' | undefined; }; /**