diff --git a/main/guides/coreeval/permissions.md b/main/guides/coreeval/permissions.md index 402c67f52..27237a5cf 100644 --- a/main/guides/coreeval/permissions.md +++ b/main/guides/coreeval/permissions.md @@ -34,9 +34,10 @@ export const main = startSellConcertTicketsContract; In the top level promise space, we have: -- **agoricNames**: read-only access to the [agoricNames](../integration/name-services.md#agoricnames-agoricnamesadmin-well-known-names) name service. +- **agoricNames**: read-only access to the [agoricNames](../integration/name-services#agoricnames-agoricnamesadmin-well-known-names) name service. -- **agoricNamesAdmin**: admin / update access to **agoricNames** and the name hubs it contains. +- **agoricNamesAdmin**: admin / update access to [agoricNames](../integration/name-services#agoricnames-agoricnamesadmin-well-known-names) and the name hubs it contains. + **Warning: this includes access to over-write existing bindings to instances, brands, etc.** **Warning: this includes the right to over-write existing bindings to instances, brands, etc.** - **bankManager**: to manage reflection of cosmos @@ -45,14 +46,14 @@ In the top level promise space, we have: - **board**: the [board](../integration/name-services.md#the-board-publishing-under-arbitrary-names) name service. **Note: the board only grows; no mechanism to reclaim storage has been established.** -- **chainStorage**: to make storage nodes to write to vstorage. - **Warning: this includes the right to over-write previously allocated storage nodes.** +- **chainStorage**: to make storage nodes to [write to vstorage](../zoe/pub-to-storage). + **Warning: this includes access to over-write previously allocated storage nodes.** -- **chainTimerService**: for getting the current timer and setting timer wake-ups; for example, at the conclusion of a governance vote. - **Note: this includes the right to schedule infinitely repeating events.** +- **chainTimerService**: for getting the current [timer](../../reference/repl/timerServices) and setting timer wake-ups; for example, at the conclusion of a governance vote. + **Note: this includes access to schedule infinitely repeating events.** - **priceAuthority**: access to get price quotes and triggers; see [Price Authority Guide](../zoe/price-authority). - **priceAuthorityAdmin**: access to add and replace sources of price quotes using [E(priceAuthorityAdmin).registerPriceAuthority()](../../reference/zoe-api/price-authority-admin#e-priceauthorityregistryadmin-registerpriceauthority-priceauthority-brandin-brandout-force) -- **zoe**: the Zoe service +- **zoe**: the [Zoe service](../../reference/zoe-api//zoe) diff --git a/main/guides/governance/index.md b/main/guides/governance/index.md index 7ea23e49c..1a0e65cce 100644 --- a/main/guides/governance/index.md +++ b/main/guides/governance/index.md @@ -46,7 +46,7 @@ Adding parameter governance to a contract consists mainly of using `handleParamG We pass it `zcf` so that it can `getTerms()` for initial parameter values, and we pass `paramTypes` to specify governed parameters and their types. `initialPoserInvitation` is necessary to set up replacing the electorate. `storageNode` and `marshaller` are used -to publish values of the parameters to vstorage. +to [publish values of the parameters to vstorage](../zoe/pub-to-storage). ```js import { handleParamGovernance } from '@agoric/governance/src/contractHelper.js'; diff --git a/main/guides/zoe/pub-to-storage.md b/main/guides/zoe/pub-to-storage.md new file mode 100644 index 000000000..e210c7744 --- /dev/null +++ b/main/guides/zoe/pub-to-storage.md @@ -0,0 +1,159 @@ +# Publishing to chainStorage + +Contracts can use [notifiers and subscriptions](../js-programming/notifiers) +to publish to clients. To publish data visible to [vstorage queries](../getting-started/contract-rpc#querying-vstorage), contracts should connect +a subscriber to a `chainStorage` node. + +## Deployment Capabilities for Publishing to chainStorage + +In [Adding Parameter Governance to a Contract](../governance/#adding-parameter-governance-to-a-contract), +`storageNode` and `marshaller` are passed to the contract in its `privateArgs` so it can publish to chainStorage. + +In [dapp-agoric-basics](https://github.com/Agoric/dapp-agoric-basics), the `startSwapContract` uses 2 [permitted deployment capabilities](../coreeval/permissions), `chainStorage` and `board` and uses them to make the `privateArgs`: + +```js +const marshaller = await E(board).getPublishingMarshaller(); +const storageNode = await E(chainStorage).makeChildNode(contractName); +``` + +A `Marshaller` is parameterized by functions for mapping unforgeable object identities to plain data slot references and back. Using the [board](../integration/name-services#the-board-publishing-under-arbitrary-names) name service gives consistent slot references across contracts. +As discussed in [Marshalling Amounts and Instances](../getting-started/contract-rpc#marshalling-amounts-and-instances), this lets +off-chain clients use the same `@endo/marshal` API. + +The `chainStorage` node corresponds to the `published` key in the +[vstorage hierarchy](/reference/vstorage-ref). +Using `E(chainStorage).makeChildNode(contractName)` gives the contract +access to write to the `published.swaparoo` key and all keys under it. + +The `swaparoo` contract delegates the rest of publishing governance parameters to the `@agoric/governance` package. + +## Publishing structured data to chainStorage + +Let's look at the Inter Protocol [assetReserve.js](https://github.com/Agoric/agoric-sdk/blob/agoric-upgrade-13/packages/inter-protocol/src/reserve/assetReserve.js) contract to get more of the details. It publishes to [published.reserve.metrics](https://github.com/Agoric/agoric-sdk/blob/agoric-upgrade-13/packages/inter-protocol/test/reserve/snapshots/test-reserve.js.md) data of the form + +```js +/** + * @typedef {object} MetricsNotification + * @property {AmountKeywordRecord} allocations + * @property {Amount<'nat'>} shortfallBalance shortfall from liquidation that + * has not yet been compensated. + * @property {Amount<'nat'>} totalFeeMinted total Fee tokens minted to date + * @property {Amount<'nat'>} totalFeeBurned total Fee tokens burned to date + */ +``` + +For example: + +```js + { + allocations: { + Fee: { + brand: Object @Alleged: IST brand {}, + value: 64561373455n, + }, + ATOM: { + brand: Object @Alleged: ATOM brand {}, + value: 6587020n + }, + }, + shortfallBalance: { + brand: Object @Alleged: IST brand {}, + value: 5747205025n, + }, + totalFeeBurned: { + brand: Object @Alleged: IST brand {}, + value: n, + }, + totalFeeMinted: { + brand: Object @Alleged: IST brand {}, + value: 0n, + }, + }, +``` + +The method that writes this data is: + +```js + writeMetrics() { + const { state } = this; + const metrics = harden({ + allocations: state.collateralSeat.getCurrentAllocation(), + shortfallBalance: state.shortfallBalance, + totalFeeMinted: state.totalFeeMinted, + totalFeeBurned: state.totalFeeBurned, + }); + void state.metricsKit.recorder.write(metrics); + }, +``` + +The `metricsKit` is made with a `makeRecorderKit` function: + +```js + metricsKit: makeRecorderKit( + metricsNode, + /** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedMatcher} */ ( + M.any() + ), + ), +``` + +We "prepare" (in the [exo](https://endojs.github.io/endo/modules/_endo_exo.html) sense) that function for making +a `RecorderKit` using [prepareRecorderKitMakers](/reference/zoe-api/zoe-helpers#preparerecorderkitmakers-baggage-marshaller). + +```js +const { makeRecorderKit } = prepareRecorderKitMakers( + baggage, + privateArgs.marshaller, +); +``` + +The contract gets `baggage`, along with `privateArgs` when it starts in +[the usual way for upgradable contracts](./contract-upgrade.html#upgradable-declaration): + +```js +/** + * Asset Reserve holds onto assets for the Inter Protocol, and ... + * + * @param {{ + * ... + * marshaller: ERef, + * storageNode: ERef, + * }} privateArgs + * @param {Baggage} baggage + */ +export const prepare = async (zcf, privateArgs, baggage) => { + ... +}; +``` + +The reserve uses its `StorageNode` and makes a child to get `metricsNode`: + +```js +const metricsNode = await E(storageNode).makeChildNode('metrics'); +``` + +The `marshaller` is used to serialize data structures such as `MetricsNotification` above. + +### Deployment Capabilities for the reserve + +To start `assetReserve`, the [setupReserve](https://github.com/Agoric/agoric-sdk/blob/agoric-upgrade-13/packages/inter-protocol/src/proposals/econ-behaviors.js#L76) function again supplies +the two relevant `privateArgs`, `marshaller` and `storageNode`: + +```js +const STORAGE_PATH = 'reserve'; +const storageNode = await E(storageNode).makeChildNode(STORAGE_PATH); +const marshaller = await E(board).getReadonlyMarshaller(); +``` + +The `setupReserve` function gets `chainStorage` and `board` deployment capabilities passed in: + +```js +export const setupReserve = async ({ + consume: { + board, + chainStorage, + ... + }, +... +}) => { ... }; +``` diff --git a/main/reference/vstorage-ref.md b/main/reference/vstorage-ref.md new file mode 100644 index 000000000..7fd3b4bfa --- /dev/null +++ b/main/reference/vstorage-ref.md @@ -0,0 +1,373 @@ +# VStorage Reference + +See also: + +- [Querying VStorage](/guides/getting-started/contract-rpc#querying-vstorage) +- [Publishing to chainStorage](../guides/zoe/pub-to-storage) +- [x/vstorage module](https://github.com/Agoric/agoric-sdk/tree/003f0c2232815a8d64a3f9a5b05521a10160ce34/golang/cosmos/x/vstorage#readme) + +## vstorage: top level keys + +The `published` and `bundles` keys are the most relevant to dapp development. + +```js + { + activityhash: 'historical', + beansOwing: 'swingset execution fee accounting', + bundles: 'MsgInstallBundle outcome', + egress: 'reserved for future use', + highPrioritySenders: 'a priority mechanism', + mailbox: 'reserved for future use', + published: 'for the chainStorage API; see below', + } +``` + +## vstorage: published.\* keys + +The following keys appear under `published`. +see also [Inter Protocol data](https://github.com/Agoric/agoric-sdk/tree/agoric-upgrade-13/packages/inter-protocol#reading-data-off-chain). + +```js + { + agoricNames: 'name service controlled by chain governance', + auction: 'see Inter Protocol', + boardAux: 'auxiliary data for brands etc. keyed by boardId (since #49 2023-09-21)', + committees: 'see Inter Protocol', + crabble: 'reserved by chain governance proposal #64 decided 2023-12-18', + kread: 'reserved by chain governance proposal #53 decided 2023-10-01', + priceFeed: 'see Inter Protocol', + provisionPool: 'provideds initial IST during smart wallet provisioning', + psm: 'see Inter Protocol', + reserve: 'see Inter Protocol', + vaultFactory: 'see Inter Protocol', + wallet: 'smart wallet status', + } +``` + +## vstorage: agoricNames hubs + +agoricNames contains several other NameHubs. +See also [agoricNames](https://docs.agoric.com/guides/integration/name-services.html#agoricnames-agoricnamesadmin-well-known-names). + +```js +['brand', 'installation', 'instance', 'issuer', 'oracleBrand', 'vbankAsset']; +``` + +## vstorage: well known contracts + +`published.agoricNames.installation` contains _Installations_ representing code of important contracts. The data at this key are the entries of the NameHub. Here we show the object comprised +of those entries. +See also [agoricNames in vstorage](https://docs.agoric.com/guides/integration/name-services.html#agoricnames-in-vstorage) +regarding un-marshalling the data using board IDs. + +```js + { + VaultFactory: Object @Alleged: BundleIDInstallation#board05815 {}, + auctioneer: Object @Alleged: BundleIDInstallation#board04016 {}, + binaryVoteCounter: Object @Alleged: BundleIDInstallation#board02314 {}, + centralSupply: Object @Alleged: BundleIDInstallation#board0188 {}, + committee: Object @Alleged: BundleIDInstallation#board00613 {}, + contractGovernor: Object @Alleged: BundleIDInstallation#board02810 {}, + econCommitteeCharter: Object @Alleged: BundleIDInstallation#board01422 {}, + feeDistributor: Object @Alleged: BundleIDInstallation#board00917 {}, + kreadCommitteeCharter: Object @Alleged: BundleIDInstallation#board01679 {}, + kreadKit: Object @Alleged: BundleIDInstallation#board04980 {}, + mintHolder: Object @Alleged: BundleIDInstallation#board02733 {}, + priceAggregator: Object @Alleged: BundleIDInstallation#board02021 {}, + provisionPool: Object @Alleged: BundleIDInstallation#board05311 {}, + psm: Object @Alleged: BundleIDInstallation#board05432 {}, + reserve: Object @Alleged: BundleIDInstallation#board00218 {}, + scaledPriceAuthority: Object @Alleged: BundleIDInstallation#board04719 {}, + walletFactory: Object @Alleged: BundleIDInstallation#board04312 {}, + } +``` + +`published.agoricNames.instance` contains _instances_ of important contracts. +The data at this key are the entries of the NameHub. Here we show the object comprised of those entries. + +```js + { + 'ATOM-USD price feed': Object @Alleged: InstanceHandle#board02963 {}, + Crabble: Object @Alleged: InstanceHandle#board04395 {}, + CrabbleCommittee: Object @Alleged: InstanceHandle#board02393 {}, + CrabbleGovernor: Object @Alleged: InstanceHandle#board05396 {}, + VaultFactory: Object @Alleged: InstanceHandle#board00360 {}, + VaultFactoryGovernor: Object @Alleged: InstanceHandle#board03773 {}, + auctioneer: Object @Alleged: InstanceHandle#board01759 {}, + econCommitteeCharter: Object @Alleged: InstanceHandle#board04661 {}, + economicCommittee: Object @Alleged: InstanceHandle#board04149 {}, + feeDistributor: Object @Alleged: InstanceHandle#board05262 {}, + kread: Object @Alleged: InstanceHandle#board04783 {}, + kreadCommittee: Object @Alleged: InstanceHandle#board01985 {}, + kreadCommitteeCharter: Object @Alleged: InstanceHandle#board06284 {}, + provisionPool: Object @Alleged: InstanceHandle#board01664 {}, + 'psm-IST-DAI_axl': Object @Alleged: InstanceHandle#board01867 {}, + 'psm-IST-DAI_grv': Object @Alleged: InstanceHandle#board02568 {}, + 'psm-IST-USDC_axl': Object @Alleged: InstanceHandle#board05669 {}, + 'psm-IST-USDC_grv': Object @Alleged: InstanceHandle#board05970 {}, + 'psm-IST-USDT_axl': Object @Alleged: InstanceHandle#board02271 {}, + 'psm-IST-USDT_grv': Object @Alleged: InstanceHandle#board01272 {}, + reserve: Object @Alleged: InstanceHandle#board06458 {}, + reserveGovernor: Object @Alleged: InstanceHandle#board03365 {}, + 'scaledPriceAuthority-stATOM': Object @Alleged: InstanceHandle#board05892 {}, + 'stATOM-USD price feed': Object @Alleged: InstanceHandle#board04091 {}, + walletFactory: Object @Alleged: InstanceHandle#board06366 {}, + } +``` + +## vstorage: well-known assets + +`published.agoricNames.issuer` has Issuers of well-known assets. + +```js + { + ATOM: Object @Alleged: ATOM issuer#board02656 {}, + BLD: Object @Alleged: BLD issuer#board0592 {}, + DAI_axl: Object @Alleged: DAI_axl issuer#board02437 {}, + DAI_grv: Object @Alleged: DAI_grv issuer#board05039 {}, + IST: Object @Alleged: IST issuer#board0223 {}, + Invitation: Object @Alleged: Zoe Invitation issuer#board0371 {}, + KREAdCHARACTER: Object @Alleged: KREAdCHARACTER issuer#board01386 {}, + KREAdITEM: Object @Alleged: KREAdITEM issuer#board03687 {}, + USDC_axl: Object @Alleged: USDC_axl issuer#board05141 {}, + USDC_grv: Object @Alleged: USDC_grv issuer#board00443 {}, + USDT_axl: Object @Alleged: USDT_axl issuer#board06445 {}, + USDT_grv: Object @Alleged: USDT_grv issuer#board01547 {}, + stATOM: Object @Alleged: stATOM issuer#board00689 {}, + } +``` + +`published.agoricNames.brand` has the well-known Brands. + +```js + { + ATOM: Object @Alleged: ATOM brand#board05557 {}, + BLD: Object @Alleged: BLD brand#board0566 {}, + DAI_axl: Object @Alleged: DAI_axl brand#board05736 {}, + DAI_grv: Object @Alleged: DAI_grv brand#board03138 {}, + IST: Object @Alleged: IST brand#board0257 {}, + Invitation: Object @Alleged: Zoe Invitation brand#board0074 {}, + KREAdCHARACTER: Object @Alleged: KREAdCHARACTER brand#board03281 {}, + KREAdITEM: Object @Alleged: KREAdITEM brand#board00282 {}, + USDC_axl: Object @Alleged: USDC_axl brand#board03040 {}, + USDC_grv: Object @Alleged: USDC_grv brand#board04542 {}, + USDT_axl: Object @Alleged: USDT_axl brand#board01744 {}, + USDT_grv: Object @Alleged: USDT_grv brand#board03446 {}, + stATOM: Object @Alleged: stATOM brand#board00990 {}, + timer: Object @Alleged: timerBrand#board0425 {}, + } +``` + +`published.agoricNames.oracleBrand` has the well-known oracle brands. + +```js + { + ATOM: Object @Alleged: Brand#board03935 {}, + USD: Object @Alleged: Brand#board01034 {}, + stATOM: Object @Alleged: Brand#board04388 {}, + } +``` + +`published.agoricNames.vbankAsset` shows denoms registered with the vbank. + +```js + { +... + 'ibc/42225F147137DDEB5FEF0F1D0A92F2AD57557AFA2C4D6F30B21E0D983001C002': { + brand: Object @Alleged: stATOM brand#board00990 {}, + denom: 'ibc/42225F147137DDEB5FEF0F1D0A92F2AD57557AFA2C4D6F30B21E0D983001C002', + displayInfo: { + assetKind: 'nat', + decimalPlaces: 6, + }, + issuer: Object @Alleged: stATOM issuer#board00689 {}, + issuerName: 'stATOM', + proposedName: 'stATOM', + }, +... + 'ibc/BA313C4A19DFBF943586C0387E6B11286F9E416B4DD27574E6909CABE0E342FA': { + brand: Object @Alleged: ATOM brand#board05557 {}, + denom: 'ibc/BA313C4A19DFBF943586C0387E6B11286F9E416B4DD27574E6909CABE0E342FA', + displayInfo: { + assetKind: 'nat', + decimalPlaces: 6, + }, + issuer: Object @Alleged: ATOM issuer#board02656 {}, + issuerName: 'ATOM', + proposedName: 'ATOM', + }, +... + ubld: { + brand: Object @Alleged: BLD brand#board0566 {}, + denom: 'ubld', + displayInfo: { + assetKind: 'nat', + decimalPlaces: 6, + }, + issuer: Object @Alleged: BLD issuer#board0592 {}, + issuerName: 'BLD', + proposedName: 'Agoric staking token', + }, + uist: { + brand: Object @Alleged: IST brand#board0257 {}, + denom: 'uist', + displayInfo: { + assetKind: 'nat', + decimalPlaces: 6, + }, + issuer: Object @Alleged: IST issuer#board0223 {}, + issuerName: 'IST', + proposedName: 'Agoric stable token', + }, + } +``` + +## boardAux + +The keys under `published.boardAux` are board IDs. +Here we show a handful. + +```js +['board00282', 'board0074', 'board01744']; +``` + +The data are auxiliary info about objects in the board; +for example, displayInfo of brands, including assetKind. + +```js + { + board0074: { + allegedName: 'Zoe Invitation', + displayInfo: { + assetKind: 'set', + }, + }, + board01744: { + allegedName: 'USDT_axl', + displayInfo: { + assetKind: 'nat', + decimalPlaces: 6, + }, + }, + } +``` + +## vstorage: provisionPool + +`published.provisionPool.governance` gives current values of governed params. +See similar data in [Inter Protocol data](https://github.com/Agoric/agoric-sdk/tree/agoric-upgrade-13/packages/inter-protocol#reading-data-off-chain). + +```js + { + current: { + Electorate: { + type: 'invitation', + value: { + brand: Object @Alleged: Zoe Invitation brand#board0074 {}, + value: [ + { + description: 'questionPoser', + handle: Object @Alleged: InvitationHandle#board00848 {}, + installation: Object @Alleged: BundleIDInstallation#board00613 {}, + instance: Object @Alleged: InstanceHandle#board04149 {}, + }, + ], + }, + }, + PerAccountInitialAmount: { + type: 'amount', + value: { + brand: Object @Alleged: IST brand#board0257 {}, + value: 250000n, + }, + }, + }, + } +``` + +`published.provisionPool.metrics` + +```js + { + totalMintedConverted: { + brand: Object @Alleged: IST brand#board0257 {}, + value: 20000000n, + }, + totalMintedProvided: { + brand: Object @Alleged: IST brand#board0257 {}, + value: 2750000n, + }, + walletsProvisioned: 11n, + } +``` + +## vstorage: wallet + +The address of each provisioned smart wallet is a key under `published.wallet`. +Here we show a handful. +See also: [Smart Wallet VStorage Topics](/guides/getting-started/contract-rpc#smart-wallet-vstorage-topics) + +```js +[ + 'agoric1890064p6j3xhzzdf8daknd6kpvhw766ds8flgw', + 'agoric1ee9hr0jyrxhy999y755mp862ljgycmwyp4pl7q', + 'agoric1enwuyn2hzyyvt39x87tk9rhlkpqtyv9haj7mgs', +]; +``` + +The `.current` child has current wallet status. For example: + +```js + { + liveOffers: [], + offerToPublicSubscriberPaths: [], + offerToUsedInvitation: [], + purses: [ + { + balance: { + brand: Object @Alleged: Zoe Invitation brand#board0074 {}, + value: [ + { + description: 'Voter0', + handle: Object @Alleged: InvitationHandle#null {}, + installation: Object @Alleged: BundleIDInstallation#board00613 {}, + instance: Object @Alleged: InstanceHandle#null {}, + }, + { + description: 'charter member invitation', + handle: Object @Alleged: InvitationHandle#null {}, + installation: Object @Alleged: BundleIDInstallation#board01679 {}, + instance: Object @Alleged: InstanceHandle#null {}, + }, + ], + }, + brand: Object @Alleged: Zoe Invitation brand#board0074 {}, + }, + ], + } +``` + +The `published.wallet.${address}` key has wallet's last update. For example: + +```js + { + currentAmount: { + brand: Object @Alleged: Zoe Invitation brand#board0074 {}, + value: [ + { + description: 'Voter0', + handle: Object @Alleged: InvitationHandle#null {}, + installation: Object @Alleged: BundleIDInstallation#board00613 {}, + instance: Object @Alleged: InstanceHandle#null {}, + }, + { + description: 'charter member invitation', + handle: Object @Alleged: InvitationHandle#null {}, + installation: Object @Alleged: BundleIDInstallation#board01679 {}, + instance: Object @Alleged: InstanceHandle#null {}, + }, + ], + }, + updated: 'balance', + } +``` diff --git a/main/reference/zoe-api/zoe-helpers.md b/main/reference/zoe-api/zoe-helpers.md index 3502c7525..beba1e8c7 100644 --- a/main/reference/zoe-api/zoe-helpers.md +++ b/main/reference/zoe-api/zoe-helpers.md @@ -8,61 +8,65 @@ directly from **@agoric/zoe/src/contractSupport/index.js**. For example, the following imports the two ZoeHelper functions **[assertIssuerKeywords()](#assertissuerkeywords-zcf-expected)** and **[assertProposalShape()](#assertproposalshape-seat-expected)**: - ```js import { assertIssuerKeywords, - assertProposalShape + assertProposalShape, } from '@agoric/zoe/src/contractSupport/index.js'; ``` ## atomicRearrange(zcf, transfers) -- **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** + +- **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **transfers**: **Array<[TransferPart](./zoe-data-types#transferpart)>** - Returns: None. Asks Zoe to rearrange the **[Allocations](./zoe-data-types#allocation)** among the seats mentioned in -*transfers*. *transfers* are a set of changes to **Allocations** that must satisfy several +_transfers_. _transfers_ are a set of changes to **Allocations** that must satisfy several constraints. If these constraints are all met, then the reallocation happens atomically. Otherwise an error is thrown and none of the propossed changes has any effect. The constraints are as follows. - * All the mentioned seats are still live. - * There aren't any outstanding stagings for any of the mentioned seats. - - Stagings are a reallocation mechanism that has been - deprecated in favor of this **atomicRearrange()** function. - To prevent confusion, each reallocation can only be - expressed in the old way or the new way, but not a mixture. - * Overall conservation must be maintained. In other words, the reallocated - **[Amounts](/reference/ertp-api/ertp-data-types#amount)** must balance out. - * Offer Safety is preserved for each seat. That means reallocations can only take assets from a seat - as long as either it gets the assets described in the want section of its proposal, or it retains - all of the assets specified in the give section of the proposal. This constraint applies to each - seat across the entire atomicRearrangement, not to the individual **TransferParts**. - -Note that you can construct the **TransferParts** that make up the *transfers* array manually, or for +- All the mentioned seats are still live. +- There aren't any outstanding stagings for any of the mentioned seats. + + Stagings are a reallocation mechanism that has been + deprecated in favor of this **atomicRearrange()** function. + To prevent confusion, each reallocation can only be + expressed in the old way or the new way, but not a mixture. + +- Overall conservation must be maintained. In other words, the reallocated + **[Amounts](/reference/ertp-api/ertp-data-types#amount)** must balance out. +- Offer Safety is preserved for each seat. That means reallocations can only take assets from a seat + as long as either it gets the assets described in the want section of its proposal, or it retains + all of the assets specified in the give section of the proposal. This constraint applies to each + seat across the entire atomicRearrangement, not to the individual **TransferParts**. + +Note that you can construct the **TransferParts** that make up the _transfers_ array manually, or for transfers that only include one seat, you can use the helper functions **[fromOnly()](#fromonly-fromseat-fromamounts)** and **[toOnly()](#toonly-toseat-toamounts)** to create **TransferParts** that only use a subset of the fields. ## fromOnly(fromSeat, fromAmounts) + - **fromSeat**: **[ZCFSeat](./zcfseat)** - **fromAmounts**: **[AmountKeywordRecord](./zoe-data-types#keywordrecord)** - Returns: **[TransferPart](./zoe-data-types#transferpart)** -Returns a **TransferPart** which only takes **fromAmounts** from *fromSeat*. **TransferParts** are used -as part of the *transfer* argument of the **[atomicRearrange()](#atomicrearrange-zcf-transfers)** +Returns a **TransferPart** which only takes **fromAmounts** from _fromSeat_. **TransferParts** are used +as part of the _transfer_ argument of the **[atomicRearrange()](#atomicrearrange-zcf-transfers)** function. ## toOnly(toSeat, toAmounts) + - **toSeat**: **[ZCFSeat](./zcfseat)** - **toAmounts**: **[AmountKeywordRecord](./zoe-data-types#keywordrecord)** - Returns: **[TransferPart](./zoe-data-types#transferpart)** -Returns a **TransferPart** which only gives **toAmount** to *toSeat*. **TransferParts** are used as part -of the *transfer* argument of the **[atomicRearrange()](#atomicrearrange-zcf-transfers)** function. +Returns a **TransferPart** which only gives **toAmount** to _toSeat_. **TransferParts** are used as part +of the _transfer_ argument of the **[atomicRearrange()](#atomicrearrange-zcf-transfers)** function. ## atomicTransfer(zcf, fromSeat, toSeat, fromAmounts, toAmounts?) + - **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **fromSeat**: **[ZCFSeat](./zcfseat)** - Optional. - **toSeat**: **ZCFSeat** - Optional. @@ -71,61 +75,63 @@ of the *transfer* argument of the **[atomicRearrange()](#atomicrearrange-zcf-tra - Returns: None. Asks Zoe to rearrange the **[Allocations](./zoe-data-types#allocation)** among the seats mentioned in -*fromSeat* and *toSeat*. The reallocations must satisfy several constraints. If these constraints are all +_fromSeat_ and _toSeat_. The reallocations must satisfy several constraints. If these constraints are all met, then the reallocation happens atomically. Otherwise an error is thrown and none of the proposed changes has any effect. The constraints are as follows. - * All the mentioned seats are still live. - * There aren't any outstanding stagings for any of the mentioned seats. +- All the mentioned seats are still live. +- There aren't any outstanding stagings for any of the mentioned seats. - Stagings are a reallocation mechanism that has been - deprecated in favor of this **atomicRearrange()** function. - To prevent confusion, each reallocation can only be - expressed in the old way or the new way, but not a mixture. - * Overall conservation must be maintained. In other words, the reallocated - **[Amounts](/reference/ertp-api/ertp-data-types#amount)** must balance out. - * Offer Safety is preserved for each seat. That means reallocations can only take assets from a seat - as long as either it gets the assets described in the want section of its proposal, or it retains - all of the assets specified in the give section of the proposal. This constraint applies to each - seat across the entire atomicRearrangement, not to the individual **TransferParts**. + Stagings are a reallocation mechanism that has been -When you don't specify *toAmounts*, it means that the *fromAmount* will be taken from *fromSeat* and -given to *toSeat*. + deprecated in favor of this **atomicRearrange()** function. + To prevent confusion, each reallocation can only be + expressed in the old way or the new way, but not a mixture. + +- Overall conservation must be maintained. In other words, the reallocated + **[Amounts](/reference/ertp-api/ertp-data-types#amount)** must balance out. +- Offer Safety is preserved for each seat. That means reallocations can only take assets from a seat + as long as either it gets the assets described in the want section of its proposal, or it retains + all of the assets specified in the give section of the proposal. This constraint applies to each + seat across the entire atomicRearrangement, not to the individual **TransferParts**. + +When you don't specify _toAmounts_, it means that the _fromAmount_ will be taken from _fromSeat_ and +given to _toSeat_. ## assertIssuerKeywords(zcf, expected) -- **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** + +- **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **expected**: **Array<String>** - Returns: None. -Checks that the **[Keywords](./zoe-data-types#keyword)** in the *expected* argument match what the contract expects. +Checks that the **[Keywords](./zoe-data-types#keyword)** in the _expected_ argument match what the contract expects. The function throws an error if incorrect or extra **Keywords** are passed in, or if there are **Keywords** missing. The **Keyword** order is irrelevant. ```js -import { - assertIssuerKeywords -} from '@agoric/zoe/src/contractSupport/index.js'; +import { assertIssuerKeywords } from '@agoric/zoe/src/contractSupport/index.js'; // Proposals for this contract instance use keywords 'Asset' and 'Price' assertIssuerKeywords(zcf, harden(['Asset', 'Price'])); ``` ## satisfies(zcf, seat, update) + - **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **seat**: **[ZCFSeat](./zcfseat)** - **update**: **[AmountKeywordRecord](./zoe-data-types#keywordrecord)** -- Returns: **Boolean** +- Returns: **Boolean** Returns **true** if an update to a **seat**'s **currentAllocation** satisfies its -**proposal.want**. Note this is half of the offer safety check; +**proposal.want**. Note this is half of the offer safety check; it does not check if the **[Allocation](./zoe-data-types#allocation)** constitutes a refund. The update is merged with **currentAllocation** such that -*update*'s values prevail if the **[Keywords](./zoe-data-types#keyword)** are the same. If they +_update_'s values prevail if the **[Keywords](./zoe-data-types#keyword)** are the same. If they are not the same, the **Keyword** and **value** is just added to the **currentAllocation**. The following example code uses **satisfies()** to define a **satisfiedBy()** comparison -function between two **seats**. It checks if the second **seat** argument's *currentAllocation* -satisfies the first **seat** argument's **proposal.want**. +function between two **seats**. It checks if the second **seat** argument's _currentAllocation_ +satisfies the first **seat** argument's **proposal.want**. It then calls **satisfiedBy()** on both orders of the two **seats**. If both satisfy each other, it does a swap on them. @@ -142,6 +148,7 @@ if (satisfiedBy(offer, seat) && satisfiedBy(seat, offer)) { ``` ## swap(zcf, leftSeat, rightSeat) + - **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **leftSeat**: **[ZCFSeat](./zcfseat)** - **rightSeat**: **ZCFSeat** @@ -150,19 +157,20 @@ if (satisfiedBy(offer, seat) && satisfiedBy(seat, offer)) { For both **seats**, everything a **seat** wants is given to it, having been taken from the other **seat**. **swap()** exits both **seats**. Use **swap()** when all of these are true: - - Both **seats** use the same **[Keywords](./zoe-data-types#keyword)**. - - The **seats**' wants can be fulfilled from the other **seat**. - - No further **seat** interaction is desired. + +- Both **seats** use the same **[Keywords](./zoe-data-types#keyword)**. +- The **seats**' wants can be fulfilled from the other **seat**. +- No further **seat** interaction is desired. If the two **seats** can trade, they swap their compatible assets, -exiting both **seats**. It returns the message **The offer has been accepted. +exiting both **seats**. It returns the message **The offer has been accepted. Once the contract has been completed, please check your payout**. -Any surplus remains with whichever **seat** has the surplus. -For example if **seat** A gives 5 Quatloos and **seat** B only +Any surplus remains with whichever **seat** has the surplus. +For example if **seat** A gives 5 Quatloos and **seat** B only wants 3 Quatloos, **seat** A retains 2 Quatloos. -If the swap fails, no assets transfer, and both *leftSeat* and *rightSeat* are exited. +If the swap fails, no assets transfer, and both _leftSeat_ and _rightSeat_ are exited. ```js import { swap } from '@agoric/zoe/src/contractSupport.js'; @@ -171,6 +179,7 @@ swap(zcf, firstSeat, secondSeat); ``` ## swapExact(zcf, leftSeat, rightSeat) + - **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **leftSeat**: **[ZCFSeat](./zcfseat)** - **rightSeat**: **ZCFSeat** @@ -179,10 +188,11 @@ swap(zcf, firstSeat, secondSeat); For both seats, everything a seat wants is given to it, having been taken from the other seat. **swapExact()** exits both seats. Use **swapExact()** when both of these are true: - - The **seats**' wants can be fulfilled from the other **seat**. - - No further **seat** interaction is desired. -Note that unlike the **swap()** function, *leftSeat* and *rightSeat* don't necessarily use the same **[Keywords](./zoe-data-types#keyword)**. +- The **seats**' wants can be fulfilled from the other **seat**. +- No further **seat** interaction is desired. + +Note that unlike the **swap()** function, _leftSeat_ and _rightSeat_ don't necessarily use the same **[Keywords](./zoe-data-types#keyword)**. **swapExact()** is a special case of **swap()** such that it is successful only if both seats gain everything they want and lose everything they were willing to give. @@ -191,10 +201,10 @@ seat wants everything that the other seat has. The benefit of using this method is that the **Keywords** of each seat do not matter. If the two **seats** can trade, they swap their compatible assets, -exiting both **seats**. It returns the message **The offer has been accepted. +exiting both **seats**. It returns the message **The offer has been accepted. Once the contract has been completed, please check your payout**. -If the swap fails, no assets transfer, and both *leftSeat* and *rightSeat* are exited. +If the swap fails, no assets transfer, and both _leftSeat_ and _rightSeat_ are exited. ```js import { swapExact } from '@agoric/zoe/src/contractSupport/index.js'; @@ -203,28 +213,30 @@ const swapMsg = swapExact(zcf, zcfSeatA, zcfSeatB); ``` ## fitProposalShape(seat, proposalShape) + - **seat**: **[ZCFSeat](./zcfseat)** - **proposalShape**: **[Pattern](https://github.com/endojs/endo/tree/master/packages/patterns#readme)** - Returns: None. -Checks the seat's proposal against the *proposalShape* argument. If the proposal does not match *proposalShape*, the seat will be exited and all **[Payments](/reference/ertp-api/payment)** will be refunded. +Checks the seat's proposal against the _proposalShape_ argument. If the proposal does not match _proposalShape_, the seat will be exited and all **[Payments](/reference/ertp-api/payment)** will be refunded. ## assertProposalShape(seat, expected) + - **seat**: **[ZCFSeat](./zcfseat)** - **expected**: **ExpectedRecord** - Returns: None. -Checks the seat's proposal against an *expected* record that says +Checks the seat's proposal against an _expected_ record that says what shape of proposal is acceptable. - -By "shape", we mean the **give**, **want**, and **exit** rule **[Keywords](./zoe-data-types#keyword)** of the proposal must be equal to -those in *expected*. Note that **exit** rule **Keywords** are optional in *expected*. Also, none of the + +By "shape", we mean the **give**, **want**, and **exit** rule **[Keywords](./zoe-data-types#keyword)** of the proposal must be equal to +those in _expected_. Note that **exit** rule **Keywords** are optional in _expected_. Also, none of the values of those **Keywords** are checked. This **ExpectedRecord** is like a **Proposal**, but the amounts in **want** and **give** should be **null**; the **exit** clause should specify a rule with **null** contents. If the client submits a **Proposal** which does not match -these expectations, that **proposal** is rejected (and refunded). +these expectations, that **proposal** is rejected (and refunded). ```js import { assertProposalShape } from '@agoric/zoe/src/contractSupport/index.js'; @@ -241,11 +253,12 @@ const sell = seat => { ``` ## assertNatAssetKind(zcf, brand) + - **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **brand**: **[Brand](/reference/ertp-api/brand)** - Returns: **Boolean** -Asserts that the *brand* is [AssetKind.NAT](/reference/ertp-api/ertp-data-types#assetkind). +Asserts that the _brand_ is [AssetKind.NAT](/reference/ertp-api/ertp-data-types#assetkind). This means the corresponding **[Mint](/reference/ertp-api/mint)** creates fungible assets. If **false** throws with message **brand must be AssetKind.NAT**. @@ -257,6 +270,7 @@ assertNatAssetKind(zcf, quatloosBrand); ``` ## depositToSeat(zcf, recipientSeat, amounts, payments) + - **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **recipientSeat**: **[ZCFSeat](./zcfseat)** - **amounts**: **[AmountKeywordRecord](./zoe-data-types#allocation)** @@ -271,13 +285,20 @@ If the seat has exited, aborts with the message **The recipientSeat cannot have On success, returns the exported and settable **depositToSeatSuccessMsg** which defaults to **Deposit and reallocation successful.** + ```js import { depositToSeat } from '@agoric/zoe/src/contractSupport/index.js'; -await depositToSeat(zcf, zcfSeat, { Dep: quatloos(2n) }, { Dep: quatloosPayment }); +await depositToSeat( + zcf, + zcfSeat, + { Dep: quatloos(2n) }, + { Dep: quatloosPayment }, +); ``` ## withdrawFromSeat(zcf, seat, amounts) + - **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **seat**: **[ZCFSeat](./zcfseat)** - **amounts**: **[AmountKeywordRecord](./zoe-data-types#allocation)** @@ -290,13 +311,17 @@ the payments must not and cannot violate offer safety for the seat. The If the seat has exited, aborts with the message **The seat cannot have exited.** Unlike **depositToSeat()**, a **PaymentPKeywordRecord** is returned, not a success message. + ```js import { withdrawFromSeat } from '@agoric/zoe/src/contractSupport/index.js'; -const paymentKeywordRecord = await withdrawFromSeat(zcf, zcfSeat, { With: quatloos(2n) }); +const paymentKeywordRecord = await withdrawFromSeat(zcf, zcfSeat, { + With: quatloos(2n), +}); ``` ## saveAllIssuers(zcf, issuerKeywordRecord) + - **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **issuerKeywordRecord**: **IssuerKeywordRecord** - Returns: **Promise<PaymentPKeywordRecord>** @@ -314,6 +339,7 @@ await saveAllIssuers(zcf, { G: gIssuer, D: dIssuer, P: pIssuer }); ``` ## offerTo(zcf, invitation, keywordMapping, proposal, fromSeat, toSeat, offerArgs) + - **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **invitation**: **ERef<[Invitation](./zoe-data-types#invitation)>** - **keywordMapping**: **KeywordRecord** @@ -325,23 +351,24 @@ await saveAllIssuers(zcf, { G: gIssuer, D: dIssuer, P: pIssuer }); **offerTo()** makes an offer from your current contract instance (which we'll call "contractA") to another contract instance (which we'll call -"contractB"). It withdraws offer payments from the *fromSeat* in -contractA and deposits any payouts in the *toSeat*, also a contractA -seat. Note that *fromSeat* and *toSeat* may be the same seat, which is -the default condition (i.e. *toSeat* is an optional parameter -defaulting to *fromSeat*'s value). **offerTo()** can be used to make an +"contractB"). It withdraws offer payments from the _fromSeat_ in +contractA and deposits any payouts in the _toSeat_, also a contractA +seat. Note that _fromSeat_ and _toSeat_ may be the same seat, which is +the default condition (i.e. _toSeat_ is an optional parameter +defaulting to _fromSeat_'s value). **offerTo()** can be used to make an offer from any contract instance to any other contract instance, as -long as the *fromSeat* allows the withdrawal without violating +long as the _fromSeat_ allows the withdrawal without violating offer-safety. To be clear, this does mean that contractA and contractB -do not have to be instances of the same contract. +do not have to be instances of the same contract. -*zcf* is contractA's Zoe contract facet. The *invitation* parameter is an **Invitation** -to contractB. The *proposal* parameter is the proposal part of the offer made to contractB. +_zcf_ is contractA's Zoe contract facet. The _invitation_ parameter is an **Invitation** +to contractB. The _proposal_ parameter is the proposal part of the offer made to contractB. -*keywordMapping* is a record of the **[Keywords](./zoe-data-types#keyword)** used in contractA mapped to the +_keywordMapping_ is a record of the **[Keywords](./zoe-data-types#keyword)** used in contractA mapped to the **Keywords** for contractB. Note that the pathway to deposit the payout back to contractA reverses this mapping. It looks like this, where the **Keywords** are from the contracts indicated by using "A" or "B" in the **Keyword** name. + ```js // Map the keywords in contractA to the keywords in contractB const keywordMapping = harden({ @@ -350,23 +377,24 @@ const keywordMapping = harden({ }); ``` -*offerArgs* is an object that can be used to pass +_offerArgs_ is an object that can be used to pass additional arguments to the **offerHandler** of contractB's contract code. -Which arguments should be included within *offerArgs* is determined by the +Which arguments should be included within _offerArgs_ is determined by the contract in question; each contract can define whatever additional arguments it requires. If no -additional arguments are defined for a particular contract, then the *offerArgs* argument can be +additional arguments are defined for a particular contract, then the _offerArgs_ argument can be omitted entirely. It is up to the contract code how it chooses to handle any unexpected or missing -arguments within *offerArgs*. +arguments within _offerArgs_. -Contract code should be careful interacting with *offerArgs*. These values need input validation +Contract code should be careful interacting with _offerArgs_. These values need input validation before being used by the contract code since they are coming directly from the user and may have malicious behavior. The **OfferToReturns** return value is a promise for an object containing -the **userSeat** for the offer to the other contract, and a promise (**deposited**) -that resolves when the payout for the offer has been deposited to the **toSeat**. +the **userSeat** for the offer to the other contract, and a promise (**deposited**) +that resolves when the payout for the offer has been deposited to the **toSeat**. Its two properties are: -- **userSeatPromise**: **Promise<UserSeat>** + +- **userSeatPromise**: **Promise<UserSeat>** - **deposited**: **Promise<AmountKeywordRecord>** ```js @@ -378,3 +406,23 @@ const { userSeatPromise: AMMUserSeat, deposited } = zcf.offerTo( lenderSeat, ); ``` + +## prepareRecorderKitMakers(baggage, marshaller) + +Convenience wrapper for DurablePublishKit and Recorder kinds. + +::: tip + +This defines two durable kinds. Must be called at most once per baggage. + +::: + +- `makeRecorderKit` is suitable for making a durable `RecorderKit` which can be held in Exo state. +- `makeERecorderKit` is for closures that must return a `subscriber` synchronously but can defer the `recorder`. + +```js +@param {import('@agoric/vat-data').Baggage} baggage +@param {ERef} marshaller +``` + +Source: [@agoric/zoe/src/contractSupport/recorder.js#L215](https://github.com/Agoric/agoric-sdk/blob/5a6cdeb0c18ae9700d706445acf402f8d1e873c3/packages/zoe/src/contractSupport/recorder.js#L215)