From f56340b96a259498c240a4625b93981c7b08a32b Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Thu, 24 Sep 2026 19:54:57 +0000 Subject: [PATCH 01/21] docs: refresh getting-started onboarding cluster for current agoric-sdk Node.js requirement was pinned to the EOL v18.18.0; bump to v22.11.0 to match agoric-sdk's engines range (^22.11 || ^24.14). The Yarn install step still described Yarn 1 with a corepack pin of 1.22.5, but the default dapp-offer-up template pins Yarn Berry 4.7.0; update the guide to match. Fix a bigint literal bug in the sell-concert-tickets code sample (bare `n` where `1n`/`10n` bigints are required). Retire deploying.md, which described the retired ag-solo `agoric deploy` model (home object, contract/deploy.js + api/deploy.js, REPL) that no longer matches any current dapp template; the current core-eval flow is already documented accurately in explainer-deploying-a-smart-contact.md, so redirect the old path there and fix its one inbound link plus a stale zoe.install() code sample in eventual-send.md. Fix "Smart Contact" title typo. Soften a swaparoo doc's dated "will be addressed in an upcoming release" promise about a namesByAddressAdmin bug that is still unfixed upstream. Bump one ui-tutorial dependency pin (@interchain-ui/react 1.22.11 -> 1.23.11) to match what agoric-labs/ui-tutorial's checkpoint branches actually pin. Verified against live agoric-sdk (engines, CLI defaults), the dapp-offer-up and dapp-agoric-basics template repos, and the agoric-labs/ui-tutorial checkpoint-1..5 branches: the seven ui-tutorial pages' code samples and dependency pins (@agoric/react-components, @agoric/web-components, @agoric/rpc, @agoric/store, cosmos-kit) match the actual checkpoint branches exactly, despite lagging the unreleased tip of Agoric/ui-kit, whose API has since diverged in breaking ways (AgoricProvider props, useAgoric's package). Bumping those pins to ui-kit's latest would break the tutorial rather than fix it, since agoric-labs/ui-tutorial has not itself been updated; left as-is. contract-rpc.md's mainnet1B source permalinks were also re-verified line-by-line against that tag and found accurate, contrary to an earlier suspicion of drift. yarn docs:build (including the internal link checker) passes locally. --- _redirects | 5 +- main/guides/getting-started/deploying.md | 100 ------------------ .../explainer-deploying-a-smart-contact.md | 4 +- main/guides/getting-started/index.md | 8 +- ...sell-concert-tickets-contract-explainer.md | 4 +- .../swaparoo-how-to-swap-assets-explainer.md | 2 +- .../ui-tutorial/agoric-provider.md | 2 +- main/guides/js-programming/eventual-send.md | 16 +-- 8 files changed, 22 insertions(+), 119 deletions(-) delete mode 100644 main/guides/getting-started/deploying.md diff --git a/_redirects b/_redirects index 1d99c0875..11c32f71e 100644 --- a/_redirects +++ b/_redirects @@ -36,8 +36,11 @@ /getting-started/start-a-project.html /guides/getting-started/ /getting-started/start-a-project/* /guides/getting-started/start-a-project/:splat /guides/agoric-cli/commands /guides/agoric-cli/ -/guides/agoric-cli/commands.html /guides/agoric-cli/ +/guides/agoric-cli/commands.html /guides/agoric-cli/ /guides/agoric-cli/commands/* /guides/agoric-cli/:splat +/guides/getting-started/deploying /guides/getting-started/explainer-deploying-a-smart-contact +/guides/getting-started/deploying.html /guides/getting-started/explainer-deploying-a-smart-contact +/guides/getting-started/deploying/* /guides/getting-started/explainer-deploying-a-smart-contact:splat /guides/js-programming/ses/lockdown https://github.com/endojs/endo/blob/HEAD/packages/ses/docs/lockdown.md /guides/js-programming/ses/lockdown.html https://github.com/endojs/endo/blob/HEAD/packages/ses/docs/lockdown.md /guides/js-programming/ses/ses-guide https://github.com/endojs/endo/blob/HEAD/packages/ses/docs/guide.md diff --git a/main/guides/getting-started/deploying.md b/main/guides/getting-started/deploying.md deleted file mode 100644 index b5a7445d8..000000000 --- a/main/guides/getting-started/deploying.md +++ /dev/null @@ -1,100 +0,0 @@ -# Deploying Smart Contracts - -The `agoric deploy` command in the [Agoric command line tool](/guides/agoric-cli/index#agoric-deploy) supports deploying contracts and off-chain web applications that talk to those contracts. The command has two primary uses: - -- Deploy smart contract source code onto the blockchain. -- Deploy and set up an application program on a local server running an Agoric process. - -Use the `agoric deploy` command to run your dapp's `contract/deploy.js` -and `api/deploy.js` scripts. You can use the deploy scripts copied from an existing -Dapp as they are, or you can modify them as suggested later in this document. - -Remember, your Dapp has three primary subdirectories: - -- `contract/` contains files defining your on-chain smart contract. -- `api/` contains files enabling the UI frontend to communicate via HTTP/WebSocket to an on-chain backend contract instance and start your Dapp contract instance and backend. -- `ui/` contains files relating to your contract's browser user interface. - -## How It Works - -All deployment happens via the local running Agoric process. This is usually the **ag-solo** process, -sometimes described as an Agoric VM or a local server. - -`ag-solo` communicates with either a locally running or remote chain. -The local process has a `home` object, which contains references to services on-chain -that can be used to call associated API commands. -Such references include `zoe`, the `board` for sharing objects, and the application user's `wallet`. - -Each `deploy.js` runs in its own temporary process connected to `ag-solo`, through which it can reach the chain. -It first uploads bundled contract source code to `ag-solo`, -then goes through the `home` object to access `zoe` and uses that to install the code on-chain. - -All on-chain commands that deployment scripts use to deploy contracts and Dapps -are also available to developers via the REPL associated with their wallet. - -## Contract Deployment - -First, let's look at _contract deployment_. `contract/deploy.js` bundles up a contract's source code -(which may consist of multiple files and modules) and "installs" -it on the blockchain as source code, using `Zoe`. -This does _not_ execute contract code; it just makes the code available on-chain. - -The contract deployment process uses [`zoe.install()`](/reference/zoe-api/zoe#e-zoe-install-bundle) -to install the contract source code on-chain. This returns an _installation_ associated with the -source code. In a typical contract deployment, the deploy script adds the installation -to the default shared board so it is broadly accessible on the chain. The script then writes -the board id to a config file in the Dapp's `ui` directory as shown below. - -By default, when you run `agoric init`, your dapp gets -the [`dapp-fungible-faucet` `contract/deploy.js` file](https://github.com/Agoric/dapp-fungible-faucet/blob/HEAD/contract/deploy.js), -which is our example of a typical contract deploy script. - -Deploying the `dapp-fungible-faucet` contract (e.g., with `agoric deploy contract/deploy.js` after `agoric init` -copied it into a local directory) installs it on chain, and generates the -file `ui/public/conf/installationConstants.js` with contents like: - -```js -// GENERATED FROM dapp-fungible-faucet/contract/deploy.js -export default { - CONTRACT_NAME: 'fungibleFaucet', - INSTALLATION_BOARD_ID: '1456154132' -}; -``` - -The board provides a unique ID per object, in this case -`"1456154132"`, so it is different for each contract deployment. - -## Application Service Deployment and Setup - -Next, let's look at _application deployment and setup_. As compared to contract deployment, -you need to customize the Agoric API server deployment and setup much more -for your particular application and contract. Some Dapps use a singleton contract instance -which presumes that it will be installed once and serve all customers (as opposed to an auction -or swap contract, which is installed once, but instantiated separately for each sale it manages). -A singleton may need to: - -- Be instantiated -- Find and connect to on-chain resources such as issuers for specific currencies -- Create new on-chain resources like new currencies or NFTs -- Create new Purses for the application to use -- Seed the on-chain contract instance with initial orders or configuration. - -These example contract `api/deploy.js` scripts show some of the -range of the above custom setup actions: - -- [`dapp-fungible-faucet`](https://github.com/Agoric/dapp-fungible-faucet/blob/HEAD/api/deploy.js) -- [`dapp-card-store`](https://github.com/Agoric/dapp-card-store/blob/HEAD/api/deploy.js) -- [`dapp-simple-exchange`](https://github.com/Agoric/dapp-simple-exchange/blob/HEAD/api/deploy.js) - -Application deployment steps may include: - -- Bundle the `api/` code and deploy it to the running local `ag-solo` -- Include the contract installation configuration information in the bundle -- Create new currencies and add them to the application's wallet - -Steps for contracts that use a singleton instance for all clients may further include: - -- Instantiate a contract instance using the installation created by contract deployment -- Use the invitation from that instance creation to configure the new instance -- Register the contract instance's `instance` with the Board -- Record the contract instance's Board ID in a configuration file diff --git a/main/guides/getting-started/explainer-deploying-a-smart-contact.md b/main/guides/getting-started/explainer-deploying-a-smart-contact.md index 223b9138c..b0f38b746 100644 --- a/main/guides/getting-started/explainer-deploying-a-smart-contact.md +++ b/main/guides/getting-started/explainer-deploying-a-smart-contact.md @@ -1,6 +1,6 @@ -# Deploying a Smart Contact +# Deploying a Smart Contract -In the `dapp-offer-up` tutorial you just went through you saw how quick and easy it was to deploy a contact on Agoric using the `yarn start:contract` command. Let's take a look at how this command works and what's going on behind the scenes. +In the `dapp-offer-up` tutorial you just went through you saw how quick and easy it was to deploy a contract on Agoric using the `yarn start:contract` command. Let's take a look at how this command works and what's going on behind the scenes. ## How it Works diff --git a/main/guides/getting-started/index.md b/main/guides/getting-started/index.md index d5291f553..b1ecdc3fa 100644 --- a/main/guides/getting-started/index.md +++ b/main/guides/getting-started/index.md @@ -89,7 +89,7 @@ source $(brew --prefix nvm)/nvm.sh Then, install Node.js. ```sh -nvm install v18.18.0 +nvm install v22.11.0 ``` Finally, verify the Node.js version. @@ -102,17 +102,17 @@ node --version ### Installing Yarn -This will install yarn, and verify it is installed correctly. Install yarn by either running `npm install --global yarn`, or visit https://classic.yarnpkg.com/en/docs/install for more information. See below, `corepack enable` will add the Corepack shims to the install directories, and `yarn --version` will verify yarn is installed correctly. +This will install yarn, and verify it is installed correctly. `corepack enable` will add the Corepack shims to the install directories, and `yarn --version` will verify yarn is installed correctly. ```sh corepack enable yarn --version # for verification ``` -This app uses Yarn 1, so running the above command will show a version in the format `1.x.x`. If you are using a different version of `yarn`, you can use `yarn set version ` to switch like in the example below. +The sample dapp pins Yarn Berry (`"packageManager": "yarn@4.7.0"` in its `package.json`), so once you're inside the `demo` directory (see [Creating Your Dapp From a Template](#creating-your-dapp-from-a-template) below), Corepack will pick up that version automatically. If it does not, you can set it explicitly: ```sh -yarn set version 1.22.5 +yarn set version 4.7.0 ``` ### Installing Docker diff --git a/main/guides/getting-started/sell-concert-tickets-contract-explainer.md b/main/guides/getting-started/sell-concert-tickets-contract-explainer.md index 407a36f71..4f23a14df 100644 --- a/main/guides/getting-started/sell-concert-tickets-contract-explainer.md +++ b/main/guides/getting-started/sell-concert-tickets-contract-explainer.md @@ -30,8 +30,8 @@ const inventory = { maxTickets: 5n }, backRow: { - tradePrice: AmountMath.make(istBrand, n), - maxTickets: n + tradePrice: AmountMath.make(istBrand, 1n), + maxTickets: 10n } }; ``` diff --git a/main/guides/getting-started/swaparoo-how-to-swap-assets-explainer.md b/main/guides/getting-started/swaparoo-how-to-swap-assets-explainer.md index df3a18429..84bd946cf 100644 --- a/main/guides/getting-started/swaparoo-how-to-swap-assets-explainer.md +++ b/main/guides/getting-started/swaparoo-how-to-swap-assets-explainer.md @@ -2,7 +2,7 @@ This smart contract is designed to allow two parties to swap assets between themselves, with a fee charged to one of the parties. The contract is started with a `feeAmount` and a `namesByAddressAdmin` object, which is used to retrieve a deposit facet for the second party. -**NOTE:** _`namesByAddressAdmin` is actually excess authority in this scenario. Normally read-only access can be attained via `namesByAddress`. The use of `namesByAddressAdmin` in this example is due to a bug, which will be addressed in an upcoming release._ +**NOTE:** _`namesByAddressAdmin` is actually excess authority in this scenario. Normally read-only access can be attained via `namesByAddress`. The use of `namesByAddressAdmin` in this example is due to a bug that has not yet been fixed upstream; treat it as a known rough edge rather than something a template consumer needs to work around._ Let's take a look at how this contract works: diff --git a/main/guides/getting-started/ui-tutorial/agoric-provider.md b/main/guides/getting-started/ui-tutorial/agoric-provider.md index 67ba73764..5a878d612 100644 --- a/main/guides/getting-started/ui-tutorial/agoric-provider.md +++ b/main/guides/getting-started/ui-tutorial/agoric-provider.md @@ -14,7 +14,7 @@ This makes it easy to handle all the platform-specific implementation details, s Install the following dependencies: ``` -yarn add -D @agoric/react-components@0.2.0 cosmos-kit@2.8.5 @interchain-ui/react@1.22.11 +yarn add -D @agoric/react-components@0.2.0 cosmos-kit@2.8.5 @interchain-ui/react@1.23.11 ``` The `cosmos-kit` dependency is used to provide different wallets in the wallet connection modal. diff --git a/main/guides/js-programming/eventual-send.md b/main/guides/js-programming/eventual-send.md index de965f27a..9c8f8ba9a 100644 --- a/main/guides/js-programming/eventual-send.md +++ b/main/guides/js-programming/eventual-send.md @@ -7,18 +7,18 @@ In web browsers, a common pattern of remote communication is using the In the Agoric platform, communicating with remote objects is similar, using the `E()` wrapper. For example, -a [deploy script](../getting-started/deploying) may want to use the -[Zoe Service API](/reference/zoe-api/zoe) to install a contract on a blockchain. -But the deploy script cannot call `zoe.install(bundle)`, because it does not have local -access to the `zoe` object. However, the deploy -script is given a `zoe` _remote presence_. To call methods on the -actual Zoe object, the deploy script can do: +a [core-eval script](../getting-started/explainer-deploying-a-smart-contact) may want to use the +[Zoe Service API](/reference/zoe-api/zoe) to install a contract on the chain. +But the script cannot call `zoe.installBundleID(bundleId)` directly, because it does not have local +access to the `zoe` object. However, the script +is given a `zoe` _remote presence_ among its permitted powers. To call methods on the +actual Zoe object, the script can do: ```js import { E } from '@endo/eventual-send'; -E(zoe).install(bundle) - .then(installationHandle => { ... }) +E(zoe).installBundleID(bundleId) + .then(installation => { ... }) .catch(err => { ... }); ``` From 41850eb4ba402891360a038b07a094e7045f44a9 Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Thu, 24 Sep 2026 21:11:53 +0000 Subject: [PATCH 02/21] docs: fill Zoe API gaps and wire orphaned pages into nav - zoe-contract-facet: document registerFeeMint and setTestJig, fix makeZCFMint's 4th options param and makeEmptySeatKit's exit param. - zoe: fix "auction w ill" typo and getBundleIDFromInstallation, which is a real method, not reserved for future use. - zoe-helpers: satisfies returns 0|1, not Boolean; flag the atomicRearrange helper as deprecated in favor of zcf.atomicRearrange. - ratio-math: document ratioToNumber. - zoe-data-types: add PriceQuote, MutableQuote, ExitRule, and InvitationDetails entries, closing price-authority.md's broken #pricequote/#mutablequote cross-anchors. - price-authority: point at the new zoe-data-types entries instead of duplicating them. - mutable-quote: publish it (drop the "not included" banner) since its object-method docs aren't covered elsewhere. - index.md and the sidebar: wire price-authority, price-authority-admin, and mutable-quote in, and move price-authority off its previous unrelated home under "Deployed Zoe Contracts". - price-authority-admin: refresh the source permalink to a live commit. --- main/.vitepress/config.mjs | 16 +++-- main/reference/zoe-api/index.md | 5 ++ main/reference/zoe-api/mutable-quote.md | 10 +--- .../zoe-api/price-authority-admin.md | 2 +- main/reference/zoe-api/price-authority.md | 38 ++---------- main/reference/zoe-api/ratio-math.md | 15 +++++ main/reference/zoe-api/zoe-contract-facet.md | 51 ++++++++++++++-- main/reference/zoe-api/zoe-data-types.md | 60 +++++++++++++++++++ main/reference/zoe-api/zoe-helpers.md | 9 ++- main/reference/zoe-api/zoe.md | 9 ++- 10 files changed, 160 insertions(+), 55 deletions(-) diff --git a/main/.vitepress/config.mjs b/main/.vitepress/config.mjs index 89fd8414d..698600b79 100644 --- a/main/.vitepress/config.mjs +++ b/main/.vitepress/config.mjs @@ -349,6 +349,18 @@ export default defineConfig({ text: 'Zoe Data Types', link: '/reference/zoe-api/zoe-data-types', }, + { + text: 'PriceAuthority Object', + link: '/reference/zoe-api/price-authority', + }, + { + text: 'PriceAuthority Admin Object', + link: '/reference/zoe-api/price-authority-admin', + }, + { + text: 'MutableQuote Object', + link: '/reference/zoe-api/mutable-quote', + }, ], }, { @@ -494,10 +506,6 @@ export default defineConfig({ text: 'PSM Contract', link: '/guides/zoe/actual-contracts/PSM', }, - { - text: 'PriceAuthority Object', - link: '/reference/zoe-api/price-authority', - }, ], }, diff --git a/main/reference/zoe-api/index.md b/main/reference/zoe-api/index.md index 877a815e7..9677ea62c 100644 --- a/main/reference/zoe-api/index.md +++ b/main/reference/zoe-api/index.md @@ -19,6 +19,9 @@ The Zoe API supports the following objects: | [Zoe Contract Facet](./zoe-contract-facet) | Accesses a running contract instance. | | [ZCFSeat](./zcfseat) | Used within contracts to access or manipulate offers. | | [ZCFMint](./zcfmint) | Used by a contract to issue digital assets. | +| [PriceAuthority](./price-authority) | Gives reliable price quotes for pairs of currencies. | +| [PriceAuthority Admin](./price-authority-admin) | Registers and deletes **PriceAuthorities**. | +| [MutableQuote](./mutable-quote) | Returned by **PriceAuthority**'s **mutableQuoteWhen\*()** methods; lets you update the trigger level of an outstanding quote. | The Zoe API provides the following libraries: @@ -38,6 +41,8 @@ The Zoe API introduces and uses the following data types: | [Invitation](./zoe-data-types#invitation) | A non-fungible eright that can be held in **[Payments](/reference/ertp-api/payment)** or **[Purses](/reference/ertp-api/purse)**, just like any other eright. | | [InvitationIssuer](./zoe-data-types#invitationissuer) | An **[Issuer](/reference/ertp-api/issuer)** for **[Invitations](./zoe-data-types#invitation)**, which grant the right to participate in a contract. | | [Keyword](./zoe-data-types#keyword) | An ASCII identifier string that must begin with an upper case letter. | +| [MutableQuote](./zoe-data-types#mutablequote) | A **[PriceQuote](./zoe-data-types#pricequote)**-yielding **Promise** whose trigger level can be changed after it's created. | | [ParsableNumber](./zoe-data-types#parsablenumber) | Defined as a **bigint**, **number**, or **string**. | +| [PriceQuote](./zoe-data-types#pricequote) | A statement from a **[PriceAuthority](./price-authority)** as to the current price level at a particular time. | | [Ratio](./zoe-data-types#ratio) | Pass-by-value record that consists of a _numerator_ **[Amount](/reference/ertp-api/ertp-data-types#amount)** and a _denominator_ **Amount**. | | [TransferPart](./zoe-data-types#transferpart) | **[Allocation](./zoe-data-types#allocation)** changes for one or two existing **[ZCFSeats](./zcfseat)**. **TransferParts** are the individual elements of the _transfer_ array passed into the **[atomicRearrange()](./zoe-helpers#atomicrearrange-zcf-transfers)** function. | diff --git a/main/reference/zoe-api/mutable-quote.md b/main/reference/zoe-api/mutable-quote.md index c1d21dbac..28e197997 100644 --- a/main/reference/zoe-api/mutable-quote.md +++ b/main/reference/zoe-api/mutable-quote.md @@ -1,12 +1,8 @@ -# NOT CURRENTLY INCLUDED IN THE PUBLISHED DOCS; PLEASE IGNORE - # MutableQuote Object -Use a **MutableQuote** when you expect to make multiple calls, replacing the trigger -value. If you just need a single quote, and won't change the trigger level, then use -a non-mutable quote. - -There are four _mutable quote_ methods, which return a **MutableQuote** object with the methods: +A **[MutableQuote](./zoe-data-types#mutablequote)** is what the +**[E(PriceAuthority).mutableQuoteWhen\*()](./price-authority#e-priceauthority-mutablequotewhengt-amountin-amountoutlimit)** +methods resolve to. It has the following methods: ## aMutableQuote.cancel(e) diff --git a/main/reference/zoe-api/price-authority-admin.md b/main/reference/zoe-api/price-authority-admin.md index 5bc35623d..6959886fc 100644 --- a/main/reference/zoe-api/price-authority-admin.md +++ b/main/reference/zoe-api/price-authority-admin.md @@ -12,7 +12,7 @@ If the pair is already registered, throw unless `force` is `true`. #### Defined in -[priceAuthorityRegistry.js:27](https://github.com/Agoric/agoric-sdk/blob/a8c322206/packages/vats/src/priceAuthorityRegistry.js#L27) +[priceAuthorityRegistry.js:189](https://github.com/Agoric/agoric-sdk/blob/1db3919939eacd3194c4f07baf507612900ec754/packages/vats/src/priceAuthorityRegistry.js#L189) ## E(Deleter).delete() diff --git a/main/reference/zoe-api/price-authority.md b/main/reference/zoe-api/price-authority.md index cd2811aa6..d9d43c677 100644 --- a/main/reference/zoe-api/price-authority.md +++ b/main/reference/zoe-api/price-authority.md @@ -219,37 +219,7 @@ const quote = E(PriceAuthority).mutableQuoteWhenLTE( ); ``` -## MutableQuote - -A **MutableQuote** represents a statement from a **[PriceAuthority](./price-authority)** as to the -current price level at a particular time. The significant content (prices -and time) is packaged in the **[Amount](/reference/ertp-api/ertp-data-types#amount)**, and repeated -in the **[Payment](/reference/ertp-api/payment)** for veracity. - -**MutableQuotes** should be used when you expect to make multiple calls, replacing the trigger -value. If you just need a single quote, and won't change the trigger level, you should use -**PriceQuotes**. - -A **MutableQuote** is an **Amount**-**Payment** pair, where the **Amount** is also the current -balance of the **Payment**. - -## PriceQuote - -A **PriceQuote** represents a statement from a **[PriceAuthority](./price-authority)** as to the -current price level at a particular time. The significant content (prices -and time) is packaged in the **[Amount](/reference/ertp-api/ertp-data-types#amount)** and repeated -in the **[Payment](/reference/ertp-api/payment)** for veracity. -A **PriceQuote** is an **Amount**-**Payment** pair, where the **Amount** is also the current -balance of the **Payment**. - -```js -const { quoteAmount, quotePayment } = priceQuote; -``` - -**PriceQuotes** are returned in two forms: - -- **PriceDescription** - - Always includes **amountIn**, **amountOut**, the quote's **Timestamp**, - and the **TimerService** the **Timestamp** is relative to. -- **PriceDescription** wrapped as a **QuoteAuthority** issued payment. - - This lets quotes be shared in a format letting others verify the time and values. +See the **[PriceQuote](./zoe-data-types#pricequote)** and **[MutableQuote](./zoe-data-types#mutablequote)** +data type entries for the shape of the values these methods return. The object a +**mutableQuoteWhen\*()** call resolves to has its own **cancel()**, **getPromise()**, and +**updateLevel()** methods, documented on the **[MutableQuote object](./mutable-quote)** page. diff --git a/main/reference/zoe-api/ratio-math.md b/main/reference/zoe-api/ratio-math.md index da626357b..260ddfcbd 100644 --- a/main/reference/zoe-api/ratio-math.md +++ b/main/reference/zoe-api/ratio-math.md @@ -397,6 +397,21 @@ Creates and returns a new **Ratio** that's equivalent to the _ratio_ argument, b Creates a **Ratio** from the _numeric_ argument, and returns that **Ratio**. +## ratioToNumber(ratio) + +- **ratio**: **[Ratio](./zoe-data-types#ratio)** +- Returns: **Number** + +Converts a **Ratio** to a JavaScript **number** by dividing its numerator's value by its +denominator's value. Since **numbers** don't have the precision of **BigInts**, only use this for +approximations, such as for display purposes; don't use it for further exact computation. + +```js +const halfRatio = makeRatio(1n, quatloosBrand, 2n); +// 0.5 +const half = ratioToNumber(halfRatio); +``` + ## assertParsableNumber(specimen) - **specimen**: **Object** diff --git a/main/reference/zoe-api/zoe-contract-facet.md b/main/reference/zoe-api/zoe-contract-facet.md index 3aa33e69f..4669fd2c2 100644 --- a/main/reference/zoe-api/zoe-contract-facet.md +++ b/main/reference/zoe-api/zoe-contract-facet.md @@ -34,11 +34,12 @@ transfers that only include one seat, you can use the helper functions **[toOnly()](./zoe-helpers#toonly-toseat-toamounts)** to create **TransferParts** that only use a subset of the fields. -## zcf.makeZCFMint(keyword, assetKind?, displayInfo?) +## zcf.makeZCFMint(keyword, assetKind?, displayInfo?, options?) - **keyword**: **[Keyword](./zoe-data-types#keyword)** - **assetKind**: **[AssetKind](/reference/ertp-api/ertp-data-types#assetkind)** - Optional, defaults to **AssetKind.NAT**. - **displayInfo**: **[DisplayInfo](/reference/ertp-api/ertp-data-types#displayinfo)** - Optional, defaults to **undefined**. +- **options**: **IssuerOptionsRecord** - Optional, defaults to **undefined**. - Returns: **Promise<[ZCFMint](./zcfmint)>** Creates a synchronous Zoe mint, allowing users to mint and reallocate digital assets synchronously @@ -47,6 +48,10 @@ The optional _displayInfo_ parameter takes values like **decimalPlaces: 16** that tell the UI how to display values associated with the created mint's brand. It defaults to undefined. +The optional _options_ parameter is an **IssuerOptionsRecord**. Its only currently supported field is +**elementShape**, which constrains the shape of each element when _assetKind_ is one of the set-like +kinds (**AssetKind.SET**, **AssetKind.COPY_SET**, **AssetKind.COPY_BAG**). + **Important**: **ZCFMints** do **not** have the same methods as an ERTP **Mint**. Do not try to use ERTP methods on a **ZCFMint** or vice versa. @@ -65,6 +70,40 @@ const { brand, issuer } = mySynchronousMint.getIssuerRecord(); mySynchronousMint.mintGains({ myKeyword: amount }, seat); ``` +## zcf.registerFeeMint(keyword, feeMintAccess) + +- **keyword**: **[Keyword](./zoe-data-types#keyword)** +- **feeMintAccess**: **FeeMintAccess** +- Returns: **Promise<[ZCFMint](./zcfmint)>** + +Registers the contract's synchronous access to the fee mint, allowing the contract to mint and +reallocate assets of the fee **[Brand](/reference/ertp-api/brand)** (currently **IST**) synchronously, +the same way **[zcf.makeZCFMint()](#zcf-makezcfmint-keyword-assetkind-displayinfo-options)** does for +a mint the contract creates itself. Unlike **makeZCFMint()**, this reuses the existing fee issuer +instead of minting a new asset kind. + +_feeMintAccess_ is a credential only obtainable by contracts explicitly granted permission to mint fees; +most contracts never receive one, and calling this method without a valid _feeMintAccess_ fails. + +```js +const feeZCFMint = await zcf.registerFeeMint('Fee', feeMintAccess); +``` + +## zcf.setTestJig(testFn?) + +- **testFn**: **() => Object** - Optional. +- Returns: None. + +Provides a jig object for testing purposes only. The supplied _testFn_ callback is only ever called +in a testing context (specifically, only if a **testJigSetter** was supplied when the contract's vat +was set up), never in production. If no _testFn_ is supplied, an empty jig is used. Whatever object +_testFn_ returns has a **zcf** property appended, set to the contract's current **ZCF**, overriding +any **zcf** property _testFn_ may have provided. + +```js +zcf.setTestJig(() => ({ someState })); +``` + ## zcf.getInvitationIssuer() - Returns: **Promise<[InvitationIssuer](./zoe-data-types#invitationissuer)>** @@ -208,16 +247,20 @@ interface PatternMatchers { } ``` -## zcf.makeEmptySeatKit() +## zcf.makeEmptySeatKit(exit?) -- Returns: **[ZCFSeat](./zcfseat), Promise<[UserSeat](./user-seat)>** +- **exit**: **[ExitRule](./zoe-data-types#exitrule)** - Optional. +- Returns: **{ zcfSeat: [ZCFSeat](./zcfseat), userSeat: Promise<[UserSeat](./user-seat)> }** -Returns an empty **ZCFSeat** and a **Promise** for a **UserSeat** +Returns an empty **ZCFSeat** and a **Promise** for a **UserSeat**. Zoe uses **seats** to represent offers, and has two seat facets (a particular view or API of an object; there may be multiple such facets per object) a **ZCFSeat** and a **UserSeat**. +The optional _exit_ argument is an **ExitRule**, the same shape used in a **Proposal**'s **exit** +clause; it defaults to **{ onDemand: null }**. + ```js const { zcfSeat: mySeat } = zcf.makeEmptySeatKit(); ``` diff --git a/main/reference/zoe-api/zoe-data-types.md b/main/reference/zoe-api/zoe-data-types.md index ce11fc578..42ce39207 100644 --- a/main/reference/zoe-api/zoe-data-types.md +++ b/main/reference/zoe-api/zoe-data-types.md @@ -16,6 +16,19 @@ For example, if a seat expected to be paid 5 _Quatloos_ and 3 _Widgets_ after su } ``` +## ExitRule + +An **ExitRule** specifies how and when a seat can exit a contract, voluntarily or otherwise. It's +one of: + +- **{ onDemand: null }** - The default. The seat can exit whenever it wants by calling + **[zcfSeat.exit()](./zcfseat#zcfseat-exit-completion)**. +- **{ waived: null }** - The seat gives up its right to exit; only the contract can exit it. +- **{ afterDeadline: { timer, deadline } }** - The seat is exited automatically when _timer_ reaches + _deadline_. + - **timer**: **TimerService** + - **deadline**: **Timestamp** + ## Handle **Handles** are **Far** objects without any methods whose only useful property are their @@ -38,6 +51,17 @@ You can get information about the contract instance via these methods: An **Invitation** is a non-fungible asset created by the **[InvitationIssuer](#invitationissuer)**. An **Invitation Payment** is a **[Payment](/reference/ertp-api/payment)** holding an **Invitation**. +## InvitationDetails + +**InvitationDetails** is the value carried by an **[Invitation](#invitation)**'s +**[Amount](/reference/ertp-api/ertp-data-types#amount)**. It consists of: + +- **installation**: **Installation** - The **Installation** the **Invitation**'s **Instance** was started from. +- **instance**: **Instance** - The contract **Instance** the **Invitation** is for. +- **handle**: **Handle** - A unique **Handle** identifying this **Invitation**. +- **description**: **String** - The description passed to **[zcf.makeInvitation()](./zoe-contract-facet#zcf-makeinvitation-offerhandler-description-customdetails-proposalshape)**. +- **customDetails**: **Object** - Optional. The _customDetails_ passed to **zcf.makeInvitation()**, if any. + ## InvitationIssuer The **InvitationIssuer** is an **[Issuer](/reference/ertp-api/issuer)** that plays a @@ -87,10 +111,46 @@ const paymentKeywordRecord = { }; ``` +## MutableQuote + +A **MutableQuote** is a **[PriceQuote](#pricequote)**-yielding **Promise** whose trigger levels can be +changed after it's created, instead of needing a new call for each new trigger. It's returned by the +**[E(PriceAuthority).mutableQuoteWhen*()](./price-authority#e-priceauthority-mutablequotewhengt-amountin-amountoutlimit)** +methods, and has its own **cancel()**, **getPromise()**, and **updateLevel()** methods, documented on +the **[MutableQuote object](./mutable-quote)** page. + +Use a **MutableQuote** when you expect to make multiple calls that just replace the trigger value. If +you only need a single quote and won't change the trigger level, use a plain **PriceQuote**. + ## ParsableNumber A **ParsableNumber** is defined as a **bigint**, **number**, or **string**. +## PriceQuote + +A **PriceQuote** represents a statement from a **[PriceAuthority](./price-authority)** as to the +current price level at a particular time. The significant content (prices and time) is packaged in +the **[Amount](/reference/ertp-api/ertp-data-types#amount)** and repeated in the +**[Payment](/reference/ertp-api/payment)** for veracity. A **PriceQuote** is a +**quoteAmount**/**quotePayment** pair, where **quoteAmount** is also the current balance of +**quotePayment**: + +```js +const { quoteAmount, quotePayment } = priceQuote; +``` + +- **quoteAmount**: **[Amount](/reference/ertp-api/ertp-data-types#amount)** whose value is a + one-element array holding a **PriceDescription**. +- **quotePayment**: **ERef<[Payment](/reference/ertp-api/payment)>** wrapping **quoteAmount**. + +A **PriceDescription** consists of: + +- **amountIn**: **[Amount](/reference/ertp-api/ertp-data-types#amount)** - The amount supplied to a trade. +- **amountOut**: **Amount** - The quoted result of trading _amountIn_. +- **timer**: **TimerService** - The service that gave the _timestamp_. +- **timestamp**: **Timestamp** - A timestamp according to _timer_ for the quote. +- **conditions**: **Object** - Optional. Additional conditions for the quote. + ## Ratio **Ratios** are pass-by-value records that consist of a diff --git a/main/reference/zoe-api/zoe-helpers.md b/main/reference/zoe-api/zoe-helpers.md index bfc107a86..ff07a188f 100644 --- a/main/reference/zoe-api/zoe-helpers.md +++ b/main/reference/zoe-api/zoe-helpers.md @@ -21,6 +21,9 @@ import { - **transfers**: **Array<[TransferPart](./zoe-data-types#transferpart)>** - Returns: None. +**Deprecated**: use **[zcf.atomicRearrange()](./zoe-contract-facet#zcf-atomicrearrange-transfers)** +directly instead of this helper. + 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 constraints. If these constraints are all met, then the reallocation happens atomically. Otherwise an @@ -105,10 +108,10 @@ assertIssuerKeywords(zcf, harden(['Asset', 'Price'])); - **zcf**: **[ZoeContractFacet](./zoe-contract-facet)** - **seat**: **[ZCFSeat](./zcfseat)** - **update**: **[AmountKeywordRecord](./zoe-data-types#keywordrecord)** -- Returns: **Boolean** +- Returns: **0 | 1** -Returns **true** if an update to a **seat**'s **currentAllocation** satisfies its -**proposal.want**. Note this is half of the offer safety check; +Returns **1** if an update to a **seat**'s **currentAllocation** satisfies its +**proposal.want**, and **0** otherwise. 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 diff --git a/main/reference/zoe-api/zoe.md b/main/reference/zoe-api/zoe.md index eb002c62b..13c1d6bfa 100644 --- a/main/reference/zoe-api/zoe.md +++ b/main/reference/zoe-api/zoe.md @@ -267,7 +267,7 @@ to **[Issuers](/reference/ertp-api/issuer)**, such as **FirstCurrency: quatlooIs Parties to the contract will use the **Keywords** to index their proposal and their payments. The **terms** are values used by this contract instance, such as the -number of bids an auction w ill wait for before closing. These values may +number of bids an auction will wait for before closing. These values may be different for different instances of the same contract, but the contract defines what variables need their values passed in as **terms**. @@ -426,4 +426,9 @@ Each contract can define the properties it supports and which are required. - **installation**: **Installation** - Returns: **Promise<BundleId>** -Reserved for future use. +Returns the **BundleId** of the contract bundle the _installation_ argument was installed from. +Throws if _installation_ isn't a valid, currently-known **Installation**. + +```js +const bundleId = await E(zoe).getBundleIDFromInstallation(installation); +``` From f0d0c581bcf526745ef5a02af1ef20c963ac618d Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Thu, 24 Sep 2026 22:20:26 +0000 Subject: [PATCH 03/21] docs(zoe): refresh contract catalog and rebuild actual-contracts as a current inventory Inter Protocol (PSM, vaultFactory, auctioneer, assetReserve, fluxAggregator, the constant-product AMM) was removed from agoric-sdk in Agoric/agoric-sdk#12744; the AMM alone had already been removed years earlier in Agoric/agoric-sdk#7074. Every "View the code" link into packages/inter-protocol was dead. Mark those pages historical with a pinned last-good commit, and rebuild actual-contracts/index.md around what the chain actually deploys today: the bootstrap contracts in @agoric/vats and @agoric/governance (where the economic committee and charter machinery relocated), plus Fast USDC, the YMax portfolio contract, and the orchestration examples. Across the ~19 demo pages in contracts/*, drop the obsolete beta banner, un-pin 2020-2022 commit SHAs to plain master links, refresh the legacy assert(cond, details`...`) idiom to the current cond || Fail`...` form, fix non-BigInt numeric literals, and fix outright bugs: second-price-auction.md's dead source path and Ask/Bid/Price keyword mismatch, simple-exchange.md's missing AmountMath.make() call, and mislabeled links on escrow-to-vote.md and use-obj-example.md (both are test fixtures, not src/contracts demos). Add a durable-variant pointer to covered-call.md and correct loan.md's stale AMM liquidation description to the surviving autoswap.js demo. Verified with yarn lint:check-links and yarn docs:build (VitePress) locally; every contract path and API described was checked against the current agoric-sdk source, not just the doc's own prior claims. --- main/guides/zoe/actual-contracts/PSM.md | 16 +++- main/guides/zoe/actual-contracts/index.md | 83 +++++++++++++----- main/guides/zoe/contracts/atomic-swap.md | 36 ++++---- main/guides/zoe/contracts/automatic-refund.md | 4 +- main/guides/zoe/contracts/barter-exchange.md | 4 +- .../zoe/contracts/constantProductAMM.md | 19 +++-- main/guides/zoe/contracts/covered-call.md | 21 +++-- main/guides/zoe/contracts/escrow-to-vote.md | 6 +- main/guides/zoe/contracts/fundedCallSpread.md | 6 +- main/guides/zoe/contracts/index.md | 57 ++++++++----- main/guides/zoe/contracts/loan.md | 27 +++--- .../zoe/contracts/mint-and-sell-nfts.md | 10 +-- main/guides/zoe/contracts/mint-payments.md | 4 +- main/guides/zoe/contracts/oracle.md | 4 +- main/guides/zoe/contracts/otc-desk.md | 6 +- main/guides/zoe/contracts/pricedCallSpread.md | 4 +- .../zoe/contracts/second-price-auction.md | 85 ++++++++++--------- main/guides/zoe/contracts/sell-items.md | 4 +- main/guides/zoe/contracts/simple-exchange.md | 15 ++-- main/guides/zoe/contracts/use-obj-example.md | 6 +- main/guides/zoe/contracts/vault.md | 43 ++++++---- 21 files changed, 269 insertions(+), 191 deletions(-) diff --git a/main/guides/zoe/actual-contracts/PSM.md b/main/guides/zoe/actual-contracts/PSM.md index 90f165e7e..222316bd2 100644 --- a/main/guides/zoe/actual-contracts/PSM.md +++ b/main/guides/zoe/actual-contracts/PSM.md @@ -1,8 +1,18 @@ # PSM Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/inter-protocol/src/psm/psm.js) (Last updated: Aug 15, 2022) +::: warning Removed from agoric-sdk +`@agoric/inter-protocol`, including the PSM, was removed from `agoric-sdk` in +[Agoric/agoric-sdk#12744](https://github.com/Agoric/agoric-sdk/pull/12744) (merged June 18, +2026); Inter Protocol is no longer supported and there is no current package to install a +fresh PSM instance from. Instances started before that change keep running on mainnet, and +the API below is accurate for them, but the source is only reachable at the historical commit +linked next. +::: + +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/cbcea8c2415f2c9c4bc1ea9ff90730f2773bafaa/packages/inter-protocol/src/psm/psm.js) (last commit before removal: June 2026) + +See [Deployed Zoe Contracts](./) for where the PSM's governance machinery (the economic +committee and its charter) ended up after the removal. The Parity Stability Module (PSM) contract allows users to convert Inter Stable Tokens (ISTs) to external stable tokens at a specified fixed ratio, and vice versa. diff --git a/main/guides/zoe/actual-contracts/index.md b/main/guides/zoe/actual-contracts/index.md index b3113a361..fa99471b4 100644 --- a/main/guides/zoe/actual-contracts/index.md +++ b/main/guides/zoe/actual-contracts/index.md @@ -1,27 +1,72 @@ # Deployed Zoe Contracts -In the [mainnet-1B release of agoric-sdk](https://github.com/Agoric/agoric-sdk/releases/tag/mainnet1B-rc3), the chain is configured to automatically deploy the following Zoe contracts. A [community post on Inter Protocol Vaults Contract Implementations](https://community.agoric.com/t/inter-protocol-vaults-contract-implementations/261) has a high level description. - -| Contract | Description | -| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| centralSupply | used to initialize the vbank IST purse balance based on supply reported from the cosmos x/bank module | -| mintHolder | use to hold mints for BLD as well as inter-chain assets such as ATOM, USDC, and USDT | -| committee | represents the Economic Committee that governs Inter Protocol parameters | -| binaryVoteCounter | instantiated once for each question that a committee votes on | -| econCommitteeCharter | controls what questions can be put to the economic committee | -| contractGovernor | each governed contract is started by starting its governor | -| [PSM](./PSM) | The Parity Stability Module (PSM) supports efficiently minting and burning Inter Stable Tokens (ISTs) in exchange for approved external stable tokens. | -| vaultFactory | allows users to mint IST backed by collateral such as ATOM; hands off vaults to auctioneer when value of collateral in a vault falls below a governed threshold | -| auctioneer | auctions collateral from liquidated vaults | -| fluxAggregator | a [Price Authority](../price-authority) that aggregates prices from oracle oeprators | -| scaledPriceAuthoriy | provides prices for tradeable assets such as ATOM in terms of idealized "oracle ATOM" prices from oracle operators | -| feeDistributor | collects fees from Inter Protocol contracts and distributes to reserve and/or stakers | -| assetReserve | holds assets in reserve to back IST | -| walletFactory | executes Zoe offers on behalf of users | +The chain's bootstrap sequence still installs and starts a small set of Zoe contracts from +`agoric-sdk` itself. Everything else that runs in production today (Fast USDC, the YMax +portfolio contract, the orchestration examples) ships from its own package, either inside +`agoric-sdk` or in a sibling repository, and is deployed with a +[core-eval proposal](/guides/coreeval/) after the chain is already live. + +## Inter Protocol was removed from agoric-sdk + +Earlier revisions of this page described Inter Protocol (the [PSM](./PSM), `vaultFactory`, +`auctioneer`, `assetReserve`, `fluxAggregator`, `feeDistributor`, and the constant-product +AMM) as the chain's flagship deployed contracts. All of that source was deleted from +`agoric-sdk` in [Agoric/agoric-sdk#12744](https://github.com/Agoric/agoric-sdk/pull/12744) +(merged June 18, 2026): Inter Protocol is no longer supported, and there is no current +package to link to. The instances that were already running on mainnet before that change +keep running (the PR removed repository *source*, not the *on-chain instances*), but nobody +can install a fresh copy from `agoric-sdk` anymore. + +Two pieces of the surrounding governance machinery survived the removal, relocated rather +than deleted: + +- `startEconomicCommittee` and the committee/charter invitation behaviors moved to + [`@agoric/vats`](https://github.com/Agoric/agoric-sdk/blob/master/packages/vats/src/proposals/start-econ-committee.js). +- The `econCommitteeCharter` contract moved to + [`@agoric/governance`](https://github.com/Agoric/agoric-sdk/blob/master/packages/governance/src/econCommitteeCharter.js) + (kept under its old name for on-chain continuity). + +If you need the last Inter Protocol source for reference, browse the tree at the commit +before removal: +[`packages/inter-protocol` at `cbcea8c2`](https://github.com/Agoric/agoric-sdk/tree/cbcea8c2415f2c9c4bc1ea9ff90730f2773bafaa/packages/inter-protocol). +Treat it as historical: it will not build against current `agoric-sdk` packages. + +## Contracts started during chain bootstrap + +| Contract | Package | Description | +| --------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| centralSupply | [`@agoric/vats`](https://github.com/Agoric/agoric-sdk/blob/master/packages/vats/src/centralSupply.js) | initializes the vbank IST purse balance from the supply reported by the Cosmos `x/bank` module | +| mintHolder | [`@agoric/vats`](https://github.com/Agoric/agoric-sdk/blob/master/packages/vats/src/mintHolder.js) | holds mints for BLD and interchain assets such as ATOM, USDC, and USDT | +| provisionPool | [`@agoric/vats`](https://github.com/Agoric/agoric-sdk/blob/master/packages/vats/src/provisionPool.js) | funds new smart-wallet accounts; governed by the economic committee | +| committee | [`@agoric/governance`](https://github.com/Agoric/agoric-sdk/blob/master/packages/governance/src/committee.js) | represents the economic committee that governs parameters of governed contracts | +| binaryVoteCounter | [`@agoric/governance`](https://github.com/Agoric/agoric-sdk/blob/master/packages/governance/src/binaryVoteCounter.js) | instantiated once per yes/no question the committee votes on | +| econCommitteeCharter | [`@agoric/governance`](https://github.com/Agoric/agoric-sdk/blob/master/packages/governance/src/econCommitteeCharter.js) | controls what questions can be put to the economic committee | +| contractGovernor | [`@agoric/governance`](https://github.com/Agoric/agoric-sdk/blob/master/packages/governance/src/contractGovernor.js) | each governed contract is started alongside its own governor instance | +| walletFactory | [`@agoric/smart-wallet`](https://github.com/Agoric/agoric-sdk/blob/master/packages/smart-wallet/src/walletFactory.js) | creates and upgrades each user's [smart wallet](/guides/integration/name-services), and executes their Zoe offers | + +## Product contracts deployed on top of the chain + +These ship as core-eval proposals after bootstrap, each from its own package rather than +`agoric-sdk`'s bootstrap vats. + +| Contract | Package | Description | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | +| Fast USDC | [`@agoric/fast-usdc-contract`](https://github.com/Agoric/agoric-sdk/blob/master/packages/fast-usdc-contract/src/fast-usdc.contract.ts) | advances USDC to a recipient on Agoric ahead of a slower Circle CCTP transfer settling | +| Portfolio (YMax) | [`@agoric/portfolio-contract`](https://github.com/Agoric/agoric-sdk/blob/master/packages/portfolio-contract/src/portfolio.contract.ts) | manages a multi-chain yield portfolio using orchestration accounts | + +## Orchestration examples + +[`@agoric/orchestration`](https://github.com/Agoric/agoric-sdk/tree/master/packages/orchestration/src/examples) +ships a set of `*.contract.js` example contracts that exercise the orchestration API +(chain accounts, `vowTools`, `orchestrationKit`). They aren't all installed by default on +mainnet, but they're the best current worked examples of a Zoe contract that drives +interchain accounts: `stake-bld`, `stake-ica`, `send-anywhere`, `swap-anything`, `swap`, +`unbond`, `auto-stake-it`, and `staking-combinations`. See each file's header comment for +what it demonstrates. ## Deployed Vat Services -Other services run in vats that are not contracts. +Other services run in vats that are not Zoe contracts. | vat | services | | -------------- | -------------------------------------------------------------------------------------- | diff --git a/main/guides/zoe/contracts/atomic-swap.md b/main/guides/zoe/contracts/atomic-swap.md index bc2341e2d..48c51095e 100644 --- a/main/guides/zoe/contracts/atomic-swap.md +++ b/main/guides/zoe/contracts/atomic-swap.md @@ -1,8 +1,6 @@ # Atomic Swap Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/f29591519809dbadf19db0a26f38704d87429b89/packages/zoe/src/contracts/atomicSwap.js) (Last updated: Sep 12, 2020) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/atomicSwap.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) @@ -52,10 +50,10 @@ In this case, Alice's exit rule is `onDemand`, meaning she can exit the contract instance at any time. ```js -const threeMoola = AmountMath.make(moolaBrand, 3); +const threeMoola = AmountMath.make(moolaBrand, 3n); const aliceProposal = harden({ give: { Asset: threeMoola }, - want: { Price: AmountMath.make(simoleanBrand, 7) }, + want: { Price: AmountMath.make(simoleanBrand, 7n) }, exit: { onDemand: null } }); @@ -85,27 +83,25 @@ Bob examines the invitation's details to see if they match Alice's claims about it. ```js secondary style2 -const { installation: bobInstallation, instance } = - E(zoe).getInvitationDetails(invitationP); -const bobIssuers = E(zoe).getIssuers(instance); +const invitationIssuer = E(zoe).getInvitationIssuer(); +const { installation: bobInstallation, instance } = await E( + zoe +).getInvitationDetails(invitationP); +const bobIssuers = await E(zoe).getIssuers(instance); -const bobExclusiveInvitation = await invitationIssuer.claim(invitationP); +const bobExclusiveInvitation = await E(invitationIssuer).claim(invitationP); const bobInvitationValue = await E(zoe).getInvitationDetails( bobExclusiveInvitation ); // Bob verifies the invitation. -assert(bobInstallation === atomicSwapInstallation, details`wrong contract`); -assert(bobIssuers.Asset === moolaIssuer, details`unexpected Asset issuer`); -assert(bobIssuers.Price === simoleanIssuer, details`unexpected Price issuer`); -assert( - AmountMath.isEqual(bobInvitationValue.asset, moola(3)), - details`wrong asset` -); -assert( - AmountMath.isEqual(bobInvitationValue.price, simoleans(7)), - details`wrong price` -); +bobInstallation === atomicSwapInstallation || Fail`wrong contract`; +bobIssuers.Asset === moolaIssuer || Fail`unexpected Asset issuer`; +bobIssuers.Price === simoleanIssuer || Fail`unexpected Price issuer`; +AmountMath.isEqual(bobInvitationValue.customDetails.asset, moola(3n)) || + Fail`wrong asset`; +AmountMath.isEqual(bobInvitationValue.customDetails.price, simoleans(7n)) || + Fail`wrong price`; ``` Bob decides to exercise the invitation, and to escrow his payments. He then diff --git a/main/guides/zoe/contracts/automatic-refund.md b/main/guides/zoe/contracts/automatic-refund.md index e9f74810c..d5684ee8e 100644 --- a/main/guides/zoe/contracts/automatic-refund.md +++ b/main/guides/zoe/contracts/automatic-refund.md @@ -1,8 +1,6 @@ # Automatic Refund Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/src/contracts/automaticRefund.js) (Last updated: Jan 31, 2022) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/automaticRefund.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) diff --git a/main/guides/zoe/contracts/barter-exchange.md b/main/guides/zoe/contracts/barter-exchange.md index 121f17b9c..4ab93771b 100644 --- a/main/guides/zoe/contracts/barter-exchange.md +++ b/main/guides/zoe/contracts/barter-exchange.md @@ -1,8 +1,6 @@ # Barter Exchange Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/a564c6081976d7b66b3cdf54e0ba8903c8f1ee6d/packages/zoe/src/contracts/barterExchange.js) (Last updated: Sep 14, 2020) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/barterExchange.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) diff --git a/main/guides/zoe/contracts/constantProductAMM.md b/main/guides/zoe/contracts/constantProductAMM.md index 02181aef3..3a75d6af8 100644 --- a/main/guides/zoe/contracts/constantProductAMM.md +++ b/main/guides/zoe/contracts/constantProductAMM.md @@ -1,10 +1,19 @@ # ConstantProduct AMM Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/7d141a47b311363f099f496d4ed9b4d0f28c8fff/packages/inter-protocol/src/vpool-xyk-amm/multipoolMarketMaker.js) (Last updated: Aug 15, 2022) - -##### [View contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) +::: warning Removed from agoric-sdk +This contract was part of `@agoric/inter-protocol` and was removed from `agoric-sdk` in +[Agoric/agoric-sdk#7074](https://github.com/Agoric/agoric-sdk/pull/7074) (closed March 1, +2023), years before the rest of Inter Protocol followed in +[Agoric/agoric-sdk#12744](https://github.com/Agoric/agoric-sdk/pull/12744). Vault liquidation +moved to a descending-clock `auctioneer` at the same time; nothing in current `agoric-sdk` +replaces this AMM's multi-pool trading role. The much simpler `autoswap.js` demo (single +fixed pair, no multi-pool routing) is the closest thing still in the repository; see +[the example contracts index](./). Treat everything below as historical. +::: + +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/70ba9b0ce1bf20c815e3d63ac98cc7086a813984/packages/inter-protocol/src/vpool-xyk-amm/multipoolMarketMaker.js) (last commit before removal: 2023) + +##### [View current demo contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) The Constant Product AMM is an automated market maker (AMM) that supports multiple liquidity pools and direct exchanges across pools. It's called the "Constant diff --git a/main/guides/zoe/contracts/covered-call.md b/main/guides/zoe/contracts/covered-call.md index 52d75b90c..6ff6659f5 100644 --- a/main/guides/zoe/contracts/covered-call.md +++ b/main/guides/zoe/contracts/covered-call.md @@ -1,8 +1,6 @@ # Covered Call Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/f29591519809dbadf19db0a26f38704d87429b89/packages/zoe/src/contracts/coveredCall.js) (Last updated: Sep 12, 2020) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/coveredCall.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) @@ -25,7 +23,7 @@ to deposit assets. When they do so, the offer result is another invitation that serves as the call option. The invitation includes details of the transaction for the benefit of the counter-party. Their assured presence in the invitation allows the recipient of the invitation to verify what has -been escrowed: `{ expirationDate, timerAuthority, underlyingAsset, +been escrowed: `{ expirationDate, timeAuthority, underlyingAssets, strikePrice }`. ## The Contract's API @@ -188,9 +186,9 @@ const { installation: daveSwapInstall, instance } = const daveSwapIssuers = await E(zoe).getIssuers(instance); // Dave does some checks -assert(daveSwapInstall === swapInstallation, details`wrong installation`); -assert(daveIssuers.Asset === moolaIssuer, details`unexpected Asset issuer`); -assert(daveIssuers.Price === simoleanIssuer, details`unexpected Price issuer`); +daveSwapInstall === swapInstallation || Fail`wrong installation`; +daveSwapIssuers.Asset === moolaIssuer || Fail`unexpected Asset issuer`; +daveSwapIssuers.Price === simoleanIssuer || Fail`unexpected Price issuer`; ``` Dave can safely proceed with the swap because he knows that if Bob has lied @@ -239,3 +237,12 @@ const daveCallSeat = await E(zoe).offer( const daveMoolaPayout = await daveCallSeat.getPayout('UnderlyingAsset'); await daveMoolaPurse.deposit(daveMoolaPayout); ``` + +## Durable Variant + +The walkthrough above describes the plain, heap-based +[`coveredCall.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/coveredCall.js), whose in-memory state does not survive a contract upgrade. Agoric also +ships [`coveredCall-durable.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/coveredCall-durable.js), the same contract rebuilt with baggage and +`prepareExoClass` so its exerciser and creator facet persist across an +upgrade. See [Contract Upgrade](../contract-upgrade) for background on +durability and how upgrade works. diff --git a/main/guides/zoe/contracts/escrow-to-vote.md b/main/guides/zoe/contracts/escrow-to-vote.md index 80b32dc8d..a5a102a14 100644 --- a/main/guides/zoe/contracts/escrow-to-vote.md +++ b/main/guides/zoe/contracts/escrow-to-vote.md @@ -1,10 +1,10 @@ # Escrow To Vote Contract - +This contract is a test fixture, not a deployed demo contract under `src/contracts`. -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/test/unitTests/contracts/escrowToVote.js) (Last updated: Jan 31, 2022) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/test/unitTests/contracts/escrowToVote.js) -##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) +##### [View other test-fixture contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/test/unitTests/contracts/) This contract implements coin voting. There are two roles: the Secretary, who can determine the question (a string), make voting diff --git a/main/guides/zoe/contracts/fundedCallSpread.md b/main/guides/zoe/contracts/fundedCallSpread.md index e25b1d110..3a2e5d245 100644 --- a/main/guides/zoe/contracts/fundedCallSpread.md +++ b/main/guides/zoe/contracts/fundedCallSpread.md @@ -1,8 +1,6 @@ # Funded Call Spread Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/src/contracts/callSpread/fundedCallSpread.js) (Last updated: Feb 20, 2022) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/callSpread/fundedCallSpread.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) @@ -95,5 +93,5 @@ neither waits for the other to exercise. <<< @/../snippets/zoe/contracts/test-callSpread.js#bobExercise There is a -[unit test](https://github.com/Agoric/agoric-sdk/blob/0b44d486390768fbf828e64ce52c99192f67ada0/packages/zoe/test/unitTests/contracts/test-callSpread.js#L440) +[unit test](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/test/unitTests/contracts/callSpread.test.js#L465) showing how you could offer these options for sale using the SimpleExchange contract. diff --git a/main/guides/zoe/contracts/index.md b/main/guides/zoe/contracts/index.md index b4ce17a15..3f5f7bdf7 100644 --- a/main/guides/zoe/contracts/index.md +++ b/main/guides/zoe/contracts/index.md @@ -1,10 +1,15 @@ # Example Zoe Contracts - - While Zoe provides the means to build custom smart contracts, there is a good chance you will -want to use one that follows a commonly-used structure. Therefore, we currently provide several -pre-built example contracts that can be imported and run on Zoe. Note that none of the contracts described below are automatically deployed on-chain. +want to use one that follows a commonly-used structure. `agoric-sdk` currently ships the demo +contracts below in +[`packages/zoe/src/contracts`](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts). +None of them are automatically deployed on-chain; for what actually runs in production, see +[Deployed Zoe Contracts](../actual-contracts/). + +The economy contracts that used to be listed here (PSM, Vault, the constant-product AMM) were +removed from `agoric-sdk`; see [Vault](./vault) and [ConstantProduct AMM](./constantProductAMM) +for where that history went. ## Oracle Contracts @@ -18,48 +23,60 @@ pre-built example contracts that can be imported and run on Zoe. Note that none These contracts create various sorts of financial instruments. | Contract | Description | -| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Vault](./vault) | The Vault is the primary mechanism for making IST (the Agoric stable-value currency) available to participants in the economy. It does this by issuing loans against supported types of collateral. The creator of the contract can add new types of collateral. (This is expected to be under the control of on-chain governance after the initial currencies are defined when the contract starts up.) | -| [Loan](./loan) | A basic collateralized loan contract. | +| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Loan](./loan) | A basic collateralized loan contract. Demo-only: the production loan path was the (now-removed) Inter Protocol `vaultFactory`. | | [Funded Call Spread](./fundedCallSpread) | Creates a pair of fully collateralized call spread options. They are ERTP assets and can be used as such in other contracts. This contract has two variants, which affect how invitations are created. This version is fully funded by the creator, who receives a matching pair of call spread options. They can be traded or sold separately. | | [Priced Call Spread](./pricedCallSpread) | Creates a pair of fully collateralized call spread options. They are ERTP assets and can be used as such in other contracts. This contract has two variants, which affect how invitations are created. In this version, the creator requests a pair of invitations. Each one lets the holder obtain one of the positions by providing a started portion of the collateral. This version is useful for a market maker who finds pairs of participants with matching interests. | | [Covered Call](./covered-call) | Creates a call option, which is the right to buy an underlying asset. | -| [OTC Desk](./otc-desk) | A contract for giving quotes that can be exercised. The quotes are guaranteed to be exercisable because they are actually options with escrowed underlying assets. | +| [OTC Desk](./otc-desk) | A contract for giving quotes that can be exercised. The quotes are guaranteed to be exercisable because they are actually options with escrowed underlying assets. | + +## Removed from agoric-sdk -## AMM (Automatic Market Maker) Contract +| Contract | Status | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [Vault](./vault) | The production collateralized-loan contract; part of Inter Protocol, removed from `agoric-sdk`. The page covers where its parts went. | +| [ConstantProduct AMM](./constantProductAMM) | The production automated market maker; part of Inter Protocol, removed from `agoric-sdk`. The page covers its history and the surviving demo `autoswap.js`. | -| Contract | Description | -| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [ConstantProduct AMM](./constantProductAMM) | An automated market maker with multiple liquidity pools that can trade between any pair of funded currencies. It charges a poolFee (added to the liquidity pools) and a protocolFee (set aside for the benefit of the Agoric economy). These fees are subject to change by votes controlled by and made visible by the governance system. | +## Orchestration Example Contracts + +[`@agoric/orchestration`](https://github.com/Agoric/agoric-sdk/tree/master/packages/orchestration/src/examples) +ships current `*.contract.js` examples of Zoe contracts that drive interchain accounts through +`vowTools` and `orchestrationKit`: `stake-bld`, `stake-ica`, `send-anywhere`, `swap-anything`, +`swap`, `unbond`, `auto-stake-it`, and `staking-combinations`. They're a better current +reference for a production-style contract than the demos on this page. See +[Deployed Zoe Contracts](../actual-contracts/) for what's actually running on mainnet. ## Generic Sales/Trading Contracts These contracts involve trading or selling ERTP digital assets. | Contract | Description | -| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Sell Items](./sell-items) | A generic sales contract, mostly used for selling NFTs for money. | | [Atomic Swap](./atomic-swap) | A basic trade of digital assets between two parties. | | [Barter Exchange](./barter-exchange) | An exchange with an order book letting all kinds of goods to be offered for explicit barter swaps. | | [Second-Price Auction](./second-price-auction) | An auction in which the highest bidder wins and pays the second-highest bid. This version doesn't conceal the bids (an essential aspect of second price auctions). Therefore, **it should not be used in production**. | | [Simple Exchange](./simple-exchange) | A basic exchange with an order book for one asset, priced in a second asset. | -## Governance Contract +## Test-fixture Contracts + +These live under `packages/zoe/test/unitTests/contracts/`, not `packages/zoe/src/contracts/`; +they exist to exercise Zoe's test suite, not as contracts you'd reuse directly. | Contract | Description | -| ---------------------------------- | ------------------------------------------------------------------------------------- | +| ----------------------------------- | ------------------------------------------------------------------------------------- | | [Escrow To Vote](./escrow-to-vote) | A coin voting contract in which votes are weighted by the escrowed governance tokens. | +| [Use Object](./use-obj-example) | An example of how you might associate the ability to take an action with ownership of a particular digital asset. In this case, you can color a pixel if you own the NFT for the pixel. | ## Minting Contracts | Contract | Description | -| ------------------------------------------ | ---------------------------------------------------------------------------- | +| ------------------------------------------- | ---------------------------------------------------------------------------- | | [Mint Payments](./mint-payments) | An example of minting fungible tokens. | | [Mint and Sell NFTs](./mint-and-sell-nfts) | A contract that mints NFTs and sells them through a separate sales contract. | ## Miscellaneous Contracts -| Contract | Description | -| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Use Object](./use-obj-example) | An example of how you might associate the ability to take an action with ownership of a particular digital asset. In this case, you can color a pixel if you own the NFT for the pixel. | -| [Automatic Refund](./automatic-refund) | A trivial contract that gives the user back what they put in. | +| Contract | Description | +| ---------------------------------------- | --------------------------------------------------------------- | +| [Automatic Refund](./automatic-refund) | A trivial contract that gives the user back what they put in. | diff --git a/main/guides/zoe/contracts/loan.md b/main/guides/zoe/contracts/loan.md index a754274b2..3010d2a1f 100644 --- a/main/guides/zoe/contracts/loan.md +++ b/main/guides/zoe/contracts/loan.md @@ -1,11 +1,13 @@ # Loan Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/src/contracts/loan/index.js) (Last updated: Nov 23, 2021) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/loan/index.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) +This is a demo loan contract that still ships in `agoric-sdk`; it is not the production +lending path, which was the Inter Protocol `vaultFactory`, removed from `agoric-sdk` (see +[Deployed Zoe Contracts](../actual-contracts/) for what is actually deployed today). + The basic loan contract has two parties, a _lender_ and a _borrower_. It lets the borrower add collateral of a particular brand and get a loan of another brand. The collateral (also known as margin) must be a @@ -30,10 +32,11 @@ loaned amount and interest must be of the same (separate) brand. drops below `mmr`, liquidation can occur. - [`priceAuthority`](/guides/zoe/price-authority) - used for getting the current value of collateral and setting liquidation triggers. -- `autoswapInstance` - The running contract instance for - [AMM](./constantProductAMM) installation. The `publicFacet` - of the instance is used to make an invitation to sell the - collateral on liquidation. +- `autoswapInstance` - The running contract instance of an + [`autoswap.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/autoswap.js) + installation, the single-pair demo AMM that is the surviving contract of this shape in + `agoric-sdk` (see [the example contracts index](./)). The `publicFacet` of the instance is + used to make an invitation to sell the collateral on liquidation. - `periodNotifier` - the [notifier](/guides/js-programming/notifiers) used for notifications that a period has passed, on which compound interest will be calculated using the `interestRate`. @@ -58,7 +61,7 @@ further actions. The loan is ongoing until it is paid back entirely or liquidated, at which point the lender receives a payout. This means the lender's payout will be in Loan-branded digital assets, not Collateral-brand. (The only exception is if the scheduling -of liquidation triggers with the `priceAuthority` results in a error. In +of liquidation triggers with the `priceAuthority` results in an error. In that case, we must give the collateral to the lender. The borrower has already exited with their loan.) @@ -137,7 +140,7 @@ want a reminder to add collateral. ## Liquidating -Actual liquidation is done through an AMM -regardless of its current price. -Even if the price is worse or better than what our `priceAuthority` -quoted, we still liquidate. +Actual liquidation is done by trading all the collateral into the +[`autoswap.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/autoswap.js) +instance named by `autoswapInstance`, regardless of its current price. Even if the price is +worse or better than what our `priceAuthority` quoted, we still liquidate. diff --git a/main/guides/zoe/contracts/mint-and-sell-nfts.md b/main/guides/zoe/contracts/mint-and-sell-nfts.md index 94a780b8d..349ffb849 100644 --- a/main/guides/zoe/contracts/mint-and-sell-nfts.md +++ b/main/guides/zoe/contracts/mint-and-sell-nfts.md @@ -1,8 +1,6 @@ # Mint and Sell NFTs Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/src/contracts/mintAndSellNFT.js) (Last updated: Jan 31, 2022) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/mintAndSellNFT.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) @@ -17,12 +15,12 @@ specification of what is being sold, such as: customValueProperties: { ...arbitrary }, count: 3, moneyIssuer: moolaIssuer, - sellItemsInstallationHandle, + sellItemsInstallation, pricePerItem: AmountMath.make(moolaBrand, 20n), } ``` The `offerResult` is a record with useful properties such as the `creatorFacet` for the sales contract. You can reuse the -`creatorFacet` of this contract to mint more batches of NFTs (e.g. -more tickets for a separate show.) +`creatorFacet` of this contract to mint more batches of NFTs, for +example more tickets for a separate show. diff --git a/main/guides/zoe/contracts/mint-payments.md b/main/guides/zoe/contracts/mint-payments.md index 3b878cd34..f3efc0f80 100644 --- a/main/guides/zoe/contracts/mint-payments.md +++ b/main/guides/zoe/contracts/mint-payments.md @@ -1,8 +1,6 @@ # Mint Payments Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/src/contracts/mintPayments.js) (Last updated: Jan 31, 2022) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/mintPayments.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) diff --git a/main/guides/zoe/contracts/oracle.md b/main/guides/zoe/contracts/oracle.md index baecf0d60..f58d73521 100644 --- a/main/guides/zoe/contracts/oracle.md +++ b/main/guides/zoe/contracts/oracle.md @@ -1,8 +1,6 @@ # Oracle Query Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4c4da6a7ae76aebbff2af48613008978eb04462b/packages/zoe/src/contracts/oracle.js) (Last updated: Jan 31, 2022) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/oracle.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) diff --git a/main/guides/zoe/contracts/otc-desk.md b/main/guides/zoe/contracts/otc-desk.md index 7db0f7641..24106fe24 100644 --- a/main/guides/zoe/contracts/otc-desk.md +++ b/main/guides/zoe/contracts/otc-desk.md @@ -1,8 +1,6 @@ # OTC Desk Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/src/contracts/otcDesk.js) (Last updated: Mar 1, 2022) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/otcDesk.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) @@ -25,7 +23,7 @@ The OTC Desk contract is based on an idea by Haseeb Qureshi in In this OTC Desk Contract: -- Trades are atomic and “trustless” +- Trades are atomic and "trustless" - Creator keeps all profits - Can use any pricing mechanism - Can stop quoting when the market is crazy diff --git a/main/guides/zoe/contracts/pricedCallSpread.md b/main/guides/zoe/contracts/pricedCallSpread.md index 41717f0b5..6f9fa04de 100644 --- a/main/guides/zoe/contracts/pricedCallSpread.md +++ b/main/guides/zoe/contracts/pricedCallSpread.md @@ -1,8 +1,6 @@ # Priced Call Spread Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/src/contracts/callSpread/pricedCallSpread.js) (Last updated: Feb 20, 2022) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/callSpread/pricedCallSpread.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) diff --git a/main/guides/zoe/contracts/second-price-auction.md b/main/guides/zoe/contracts/second-price-auction.md index ac6c3d586..d4003f221 100644 --- a/main/guides/zoe/contracts/second-price-auction.md +++ b/main/guides/zoe/contracts/second-price-auction.md @@ -1,8 +1,6 @@ # Second-Price Auction Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/a564c6081976d7b66b3cdf54e0ba8903c8f1ee6d/packages/zoe/src/contracts/auction/secondPriceAuction.js) (Last updated: Sep 14, 2020) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/auction/index.js) (winner-selection logic: [`secondPriceLogic.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/auction/secondPriceLogic.js)) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) @@ -14,59 +12,66 @@ used in production for real valuables. It's a demonstration that auctions un Zoe can enforce different rules about how prices are calculated, or how winners are selected. -An auction contract is which the seller offers an Asset for sale, and states a -minimum price. The auction closes at the deadline specified by the timeAuthority and -closesAfter parameters in the terms provided by the creator of the contract -instance. The second price rule is followed, so the highest bidder pays the amount -bid by the second highest bidder. +This is one winner-price option of a shared `auction` contract; the other, +`first-price`, is implemented by the sibling +[`firstPriceLogic.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/auction/firstPriceLogic.js). +An auction contract is one in which the seller offers an Asset for sale, and states a +minimum price. The auction closes when `bidDuration` has elapsed on the `timeAuthority` +timer passed in as a term. The second-price rule is followed, so the highest bidder pays +the amount bid by the second-highest bidder. -`startInstance()` specifies the issuers and the terms. An invitation for the seller is -returned as the creatorInvitation. The seller's offer should look like +`startInstance()` is given issuers for the `Asset` and `Ask` keywords, and terms +`{ timeAuthority, bidDuration, winnerPriceOption }` (`winnerPriceOption` defaults to +`'second-price'`). An invitation for the seller is returned as the creatorInvitation. +The seller's offer should look like ```js -{ give: { Asset: asset }, want: { Ask: minimumBidAmount}} +{ give: { Asset: asset }, want: { Ask: minimumBidAmount } } ``` The asset can be non-fungible, but the Ask amount should be of a fungible brand. Make the bidder invitations by calling `makeBidInvitation()` on the object returned from the seller's -offer. Each bidder can submit an offer: `js { give: { Bid: null } -want: { Asset: null } }. ` +offer. Each bidder can submit an offer: + +```js +{ give: { Bid: null }, want: { Asset: null } } +``` ## Public Second-Price Auction -In this particular "public" second-price auction, anyone who has access to the -auction instance can make a bid by submitting a proposal. +In this particular "public" second-price auction, anyone who has access to a bid +invitation can make a bid by submitting a proposal. -Alice can create an auction from an existing second-price auction -installation. (`installation` is the unique, unforgeable identifier for the -installation.) +Alice can create an auction from an existing auction installation, passing a timer and +how long bidding should stay open. (`installation` is the unique, unforgeable identifier +for the installation.) ```js const issuerKeywordRecord = harden({ Asset: moolaIssuer, - Bid: simoleanIssuer + Ask: simoleanIssuer, }); -const terms = harden({ numBidsAllowed: 3 }); +const terms = harden({ timeAuthority, bidDuration: 1n }); const { creatorInvitation } = await E(zoe).startInstance( installation, issuerKeywordRecord, - terms + terms, ); ``` She can put something up for auction by escrowing it with Zoe, so she provides a payment for what she wants to sell, and makes a `proposal`. The proposal's terms will be enforced by Zoe and will protect Alice from misbehavior by the smart contract and -other participants. If no `exit` rule is given, as in this example, the default (`{ -onDemand: null }`) is used. +other participants. The seller can't exit early; the auction only closes when the timer +fires. ```js const aliceProposal = harden({ give: { Asset: AmountMath.make(moolaBrand, 1n) }, - want: { Bid: AmountMath.make(simoleanBrand, 3n) }, - exit: { waived: null } + want: { Ask: AmountMath.make(simoleanBrand, 3n) }, + exit: { waived: null }, }); const alicePayments = { Asset: aliceMoolaPayment }; @@ -74,10 +79,10 @@ const alicePayments = { Asset: aliceMoolaPayment }; const aliceSeat = await E(zoe).offer( creatorInvitation, aliceProposal, - alicePayments + alicePayments, ); -const invitationMaker = await E(aliceSeat).getOfferResult(); -const bobInvitation = E(invitationMaker).makeBidInvitation(); +const offerResult = await E(aliceSeat).getOfferResult(); +const bobInvitation = E(offerResult).makeBidInvitation(); ``` Now Alice can share the counterparty invitation with her friends and see if there are @@ -91,15 +96,12 @@ const invitationIssuer = await E(zoe).getInvitationIssuer(); const bobExclusiveInvitation = await invitationIssuer.claim(bobInvitation); const { installation: bobInstallation, instance } = await E( - zoe + zoe, ).getInvitationDetails(bobExclusiveInvitation); const bobIssuers = await E(zoe).getIssuers(instance); -assert( - bobInstallation === secondPriceAuctionInstallation, - details`wrong installation` -); -assert(bobIssuers.Asset === moolaIssuer, details`wrong issuer`); +bobInstallation === auctionInstallation || Fail`wrong installation`; +bobIssuers.Asset === moolaIssuer || Fail`wrong issuer`; ``` Bob decides to join the contract and makes an offer: @@ -107,7 +109,7 @@ Bob decides to join the contract and makes an offer: ```js const bobProposal = harden({ give: { Bid: AmountMath.make(simoleanBrand, 11n) }, - want: { Asset: AmountMath.make(moolaBrand, 1n) } + want: { Asset: AmountMath.make(moolaBrand, 1n) }, }); const bobPayments = { Bid: bobSimoleanPayment }; @@ -115,7 +117,7 @@ const bobPayments = { Bid: bobSimoleanPayment }; const bobSeat = await E(zoe).offer( bobExclusiveInvitation, bobProposal, - bobPayments + bobPayments, ); ``` @@ -131,16 +133,17 @@ simoleans (11-7), and Carol and Dave get a full refund. const aliceAssetPayout = await aliceSeat.getPayout('Asset'); const moolaRefundAmount = aliceMoolaPurse.deposit(aliceAssetPayout); -const alicePricePayout = await aliceSeat.getPayout('Price'); -const simoleanGainAmount = aliceSimPurse.deposit(alicePricePayout); +const aliceAskPayout = await aliceSeat.getPayout('Ask'); +const simoleanGainAmount = aliceSimPurse.deposit(aliceAskPayout); ``` -Bob's payouts are also available. +Bob's payouts are also available, keyed by `Asset` (what he won) and `Bid` (his refund, +since bidders never use the `Ask` keyword): ```js const bobAssetPayout = await bobSeat.getPayout('Asset'); const bobMoolaGainAmount = bobMoolaPurse.deposit(bobAssetPayout); -const bobPricePayout = await bobSeat.getPayout('Price'); -const bobSimoleanRefundAmount = bobSimoleanPurse.deposit(bobPricePayout); +const bobBidPayout = await bobSeat.getPayout('Bid'); +const bobSimoleanRefundAmount = bobSimoleanPurse.deposit(bobBidPayout); ``` diff --git a/main/guides/zoe/contracts/sell-items.md b/main/guides/zoe/contracts/sell-items.md index 86f53d62a..30ba075ce 100644 --- a/main/guides/zoe/contracts/sell-items.md +++ b/main/guides/zoe/contracts/sell-items.md @@ -1,8 +1,6 @@ # Sell Items Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/src/contracts/sellItems.js) (Last updated: Feb 4, 2022) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/sellItems.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) diff --git a/main/guides/zoe/contracts/simple-exchange.md b/main/guides/zoe/contracts/simple-exchange.md index 528f03ad5..831c31d3f 100644 --- a/main/guides/zoe/contracts/simple-exchange.md +++ b/main/guides/zoe/contracts/simple-exchange.md @@ -1,8 +1,6 @@ # Simple Exchange Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/f29591519809dbadf19db0a26f38704d87429b89/packages/zoe/src/contracts/simpleExchange.js) (Last updated: Sep 12, 2020) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/simpleExchange.js) ##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) @@ -99,12 +97,9 @@ installation he gets from the invitation with a canonical link he found in a public directory he trusts. ```js -assert( - installation === simpleExchangeInstallation, - details`wrong installation` -); -assert(bobIssuers.Asset === moolaIssuer, details`wrong Asset issuer`); -assert(bobIssuers.Price === simoleanIssuer, details`wrong Price issuer`); +installation === simpleExchangeInstallation || Fail`wrong installation`; +bobIssuers.Asset === moolaIssuer || Fail`wrong Asset issuer`; +bobIssuers.Price === simoleanIssuer || Fail`wrong Price issuer`; ``` Bob has checked that everything is in order, so he fulfills the buy order: @@ -117,7 +112,7 @@ const bobBuyOrderProposal = harden({ }); const bobSimPayment = await E(bobSimoleanPurse).withdraw( - AmountMath(simoleanBrand, 7n) + AmountMath.make(simoleanBrand, 7n) ); const bobPayments = { Price: bobSimPayment }; diff --git a/main/guides/zoe/contracts/use-obj-example.md b/main/guides/zoe/contracts/use-obj-example.md index b2f6a5814..4a7bc7407 100644 --- a/main/guides/zoe/contracts/use-obj-example.md +++ b/main/guides/zoe/contracts/use-obj-example.md @@ -1,10 +1,10 @@ # Use Object Contract - +This contract is a test fixture, not a deployed demo contract under `src/contracts`. -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/test/unitTests/contracts/useObjExample.js) (Last updated: Jan 31, 2022) +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/test/unitTests/contracts/useObjExample.js) -##### [View all contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) +##### [View other test-fixture contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/test/unitTests/contracts/) This contract is an example of associating a particular ability with ownership of a non-fungible token (NFT). In this case, ownership diff --git a/main/guides/zoe/contracts/vault.md b/main/guides/zoe/contracts/vault.md index a873a6aab..d9884ff44 100644 --- a/main/guides/zoe/contracts/vault.md +++ b/main/guides/zoe/contracts/vault.md @@ -1,10 +1,20 @@ # Vault Contract - - -##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/7d141a47b311363f099f496d4ed9b4d0f28c8fff/packages/inter-protocol/src/vaultFactory/vaultFactory.js) (Last updated: Aug 15, 2022) - -##### [View contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) +::: warning Removed from agoric-sdk +The `vaultFactory`, including this Vault contract, was part of `@agoric/inter-protocol`, +removed from `agoric-sdk` in [Agoric/agoric-sdk#12744](https://github.com/Agoric/agoric-sdk/pull/12744) +(merged June 18, 2026). Inter Protocol is no longer supported; there is no current package +to link to. Vaults opened before that change keep running on mainnet, and the description +below is accurate for them, but you can't start a new `vaultFactory` instance from +`agoric-sdk` anymore. See [Deployed Zoe Contracts](../actual-contracts/) for what replaced +its surrounding governance machinery, and [ConstantProduct AMM](./constantProductAMM) for +the liquidation path this contract used to depend on (superseded years earlier by the +descending-clock auctioneer). +::: + +##### [View the code on Github](https://github.com/Agoric/agoric-sdk/blob/cbcea8c2415f2c9c4bc1ea9ff90730f2773bafaa/packages/inter-protocol/src/vaultFactory/vaultFactory.js) (last commit before removal: June 2026) + +##### [View current demo contracts on Github](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts) The Vault is the primary mechanism for making `IST` (the Agoric stable-value currency) available to participants in the economy. It does this by issuing @@ -64,11 +74,12 @@ interest rate and required collateralization ratio. The `liquidationMargin` is the `collateralizationRatio` required to open a vault and keep it open. If the ratio of current value of collateral (according to the -`priceAuthority`, currently driven by the AMM) to the outstanding debt falls -below `liquidationMargin`, the collateral will be sold off, the debt repaid, and -any remainder returned to the borrower. So it's prudent for borrowers to -over-collateralize so that price volatility and interest charges don't quickly -drive their loans into default. +`priceAuthority`) to the outstanding debt falls below `liquidationMargin`, the +collateral will be sold off, the debt repaid, and any remainder returned to the +borrower. By the time of the removal described above, liquidation ran through a +descending-clock `auctioneer`, not the AMM this page originally described. So +it's prudent for borrowers to over-collateralize so that price volatility and +interest charges don't quickly drive their loans into default. The `loanFee` (in basis points) is charged on the amount of `IST` issued when opening a loan or increasing the amount of a loan. The `interestRate` is an @@ -104,9 +115,9 @@ governance, liquidation takes place in a separate vat. #### makeLoan -The Vault's public API includes `makeVaultInvitation()` and -`getCollaterals()`, as well as `getAMM()` and `getRunIssuer()`. -`getCollaterals()` returns a list of the collateral types that are accepted. -`getAmm()` returns the public facet of the AMM. `getRunIssuer()` provides access -to the issuer of `IST` so anyone can hold, spend and recognize IST. -`makeVaultInvitation()` is described above under [Borrowers](#borrowers) +The Vault's public API included `makeVaultInvitation()` and `getCollaterals()`, +as well as `getAMM()` and `getRunIssuer()` at the time this page was originally +written; both of those method names predate the `RUN`-to-`IST` rename and the +AMM's removal (see the warning above), so treat them as historical rather than +current. `getCollaterals()` returns a list of the collateral types that are +accepted. `makeVaultInvitation()` is described above under [Borrowers](#borrowers). From 7a3a8d1d3947660e1d087d222d440a21a6a1ff33 Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Thu, 24 Sep 2026 19:59:49 +0000 Subject: [PATCH 04/21] docs(zoe): refresh core guides to the durable start/meta idiom Aligns the Zoe concept guides with contract-upgrade.md/contract-details.md: - pub-to-storage.md: replace the deprecated `prepare` entrypoint and the vanished inter-protocol assetReserve.js citation with `start`+baggage and a current recorder-kit example (stake-bld.contract.js). - contract-requirements.md: fix the zoeHelpers.js deep-path import and the @agoric/notifier mislink, document the 3rd `baggage` argument and the `meta`/`upgradability` export. - contract-upgrade.md: fix the orchestration vowTools maker names (prepareLocalOrchestrationAccountKit, not prepareLocalChainAccountKit) and add pointers to a worked durable-contract example and to the new moving-assets.md page. - offer-enforcement.md: refresh the inlined atomicSwap/automaticRefund excerpts to current source and un-pin the 2020/2022 commit SHAs. - price-authority.md: fix the broken quoteAmount destructuring snippet and cite the current scaledPriceAuthority/priceAggregator production path. - index.md: drop the stale "Beta Features" mainnet warning and the AMM link to a contract no longer in the repo. - moving-assets.md (new): teach zcf.atomicRearrange/atomicTransfer/ fromOnly/toOnly, the primitives that replaced the durability-incompatible stage()/reallocate() seat API, since no guide covered them. Every source claim (contractSupport/index.js exports, atomicTransfer.js, zcfSeat.js, priceQuote.js, orchestration exos) was checked against a fresh agoric-sdk clone. Verified: `yarn lint:check-links`, the markdown JS-snippet linter, prettier, and a full `vitepress build` all pass locally. --- main/.vitepress/config.mjs | 327 ++++++++++++----------- main/guides/zoe/contract-details.md | 2 +- main/guides/zoe/contract-requirements.md | 29 +- main/guides/zoe/contract-upgrade.md | 56 +++- main/guides/zoe/index.md | 13 +- main/guides/zoe/moving-assets.md | 125 +++++++++ main/guides/zoe/offer-enforcement.md | 19 +- main/guides/zoe/price-authority.md | 15 +- main/guides/zoe/pub-to-storage.md | 105 ++------ 9 files changed, 419 insertions(+), 272 deletions(-) create mode 100644 main/guides/zoe/moving-assets.md diff --git a/main/.vitepress/config.mjs b/main/.vitepress/config.mjs index 698600b79..6ab199d8c 100644 --- a/main/.vitepress/config.mjs +++ b/main/.vitepress/config.mjs @@ -13,7 +13,7 @@ export default defineConfig({ head: [ [ 'meta', - { name: 'viewport', content: 'width=device-width, initial-scale=1' }, + { name: 'viewport', content: 'width=device-width, initial-scale=1' } ], ['link', { rel: 'icon', href: '/favicon-full.ico' }], [ @@ -28,19 +28,19 @@ export default defineConfig({ } a[href^='#'] { font-style: italic; - }`, + }` ], [ 'script', { src: 'https://www.googletagmanager.com/gtag/js?id=UA-118217811-1', - async: '', - }, + async: '' + } ], [ 'script', {}, - "window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-118217811-1'); ", + "window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-118217811-1'); " ], [ 'script', @@ -77,8 +77,8 @@ export default defineConfig({ // console.log('fixups are done'); } }, 500); - `, - ], + ` + ] ], ignoreDeadLinks: [ // ignore all localhost links @@ -87,10 +87,10 @@ export default defineConfig({ /^.\/packages\/*/, './MAINTAINERS', './CONTRIBUTING', - './LICENSE', + './LICENSE' ], sitemap: { - hostname: 'https://docs.agoric.com', + hostname: 'https://docs.agoric.com' }, plugins: [], /* --- ROUTE REWRITES / REDIRECTS --- */ @@ -103,8 +103,8 @@ export default defineConfig({ formatOptions: { dateStyle: 'medium', timeStyle: 'long', - timeZone: 'Etc/UTC', - }, + timeZone: 'Etc/UTC' + } }, logo: '/agoric-logo-red.svg', /* --- NAVBAR (top) --- */ @@ -126,15 +126,15 @@ export default defineConfig({ items: [ { text: 'What is Agoric Orchestration?', - link: '/guides/orchestration/', + link: '/guides/orchestration/' }, { text: 'Transactional vs Portfolio', - link: '/guides/orchestration/txvsportfolio', + link: '/guides/orchestration/txvsportfolio' }, { text: 'Key Concepts and APIs', - link: '/guides/orchestration/key-concepts', + link: '/guides/orchestration/key-concepts' }, { text: 'Contract Walkthroughs', @@ -142,11 +142,11 @@ export default defineConfig({ items: [ { text: 'Send Anywhere Example', - link: '/guides/orchestration/contract-walkthroughs/send-anywhere', + link: '/guides/orchestration/contract-walkthroughs/send-anywhere' }, { text: 'Cross-Chain Unbond Example', - link: '/guides/orchestration/contract-walkthroughs/cross-chain-unbond', + link: '/guides/orchestration/contract-walkthroughs/cross-chain-unbond' } ] }, @@ -156,22 +156,22 @@ export default defineConfig({ items: [ { text: 'Installation and Deployment', - link: '/guides/orchestration/orchestration-basics/installation', + link: '/guides/orchestration/orchestration-basics/installation' }, { text: 'Orca Contract walkthrough', - link: '/guides/orchestration/orchestration-basics/contract', + link: '/guides/orchestration/orchestration-basics/contract' }, { text: 'UI Walkthrough', - link: '/guides/orchestration/orchestration-basics/ui', + link: '/guides/orchestration/orchestration-basics/ui' } ] }, { text: 'How Orchestration Works', - link: '/guides/orchestration/how-orch-works', - }, + link: '/guides/orchestration/how-orch-works' + } ] }, { @@ -184,20 +184,17 @@ export default defineConfig({ items: [ { text: 'Takeaway 1: Starting a Local Chain', - link: - '/guides/getting-started/explainer-how-to-start-a-local-chain', + link: '/guides/getting-started/explainer-how-to-start-a-local-chain' }, { text: 'Takeaway 2: Deploying a Smart Contract', - link: - '/guides/getting-started/explainer-deploying-a-smart-contact', + link: '/guides/getting-started/explainer-deploying-a-smart-contact' }, { text: 'Takeaway 3: Making an Offer', - link: - '/guides/getting-started/explainer-how-to-make-an-offer', - }, - ], + link: '/guides/getting-started/explainer-how-to-make-an-offer' + } + ] }, { text: 'Smart Contract Basics', @@ -206,39 +203,67 @@ export default defineConfig({ items: [ { text: 'Hello World Smart Contract', - link: '/guides/zoe/contract-hello', + link: '/guides/zoe/contract-hello' + }, + { + text: 'Contract Requirements', + link: '/guides/zoe/contract-requirements' }, { text: 'State Smart Contract', - link: '/guides/zoe/contract-state', + link: '/guides/zoe/contract-state' }, { text: 'Access Control Smart Contract', - link: '/guides/zoe/contract-access-control', + link: '/guides/zoe/contract-access-control' + }, + { + text: 'The Structure of Offers', + link: '/guides/zoe/proposal' + }, + { + text: 'Offer Safety', + link: '/guides/zoe/offer-safety' + }, + { + text: 'Offer-Safety Enforcement', + link: '/guides/zoe/offer-enforcement' }, { text: 'Complete Contract Walk-Through', - link: '/guides/zoe/contract-walkthru', + link: '/guides/zoe/contract-walkthru' }, { text: 'Durable Contract Details', - link: '/guides/zoe/contract-details', + link: '/guides/zoe/contract-details' }, { text: 'Contract Upgrade', - link: '/guides/zoe/contract-upgrade', + link: '/guides/zoe/contract-upgrade' + }, + { + text: 'Moving Assets Between Seats', + link: '/guides/zoe/moving-assets' }, - { text: 'Contract Governance', link: '/guides/governance/' }, - ], + { + text: 'Price Authority', + link: '/guides/zoe/price-authority' + }, + { + text: 'Publishing to chainStorage', + link: '/guides/zoe/pub-to-storage' + }, + { text: 'Contract Governance', link: '/guides/governance/' } + ] }, { text: 'UI Component Library', - link: '/guides/UIComponentLibrary/', + link: '/guides/UIComponentLibrary/' }, { text: 'Building Client Dapps', - link: '/guides/getting-started/contract-rpc', + link: '/guides/getting-started/contract-rpc' }, { text: 'Permissioned Contract Deployment', @@ -248,17 +273,17 @@ export default defineConfig({ items: [ { text: 'Write Code to Deploy a Contract', - link: '/guides/coreeval/proposal', + link: '/guides/coreeval/proposal' }, { text: 'Declare Required Capabilities', - link: '/guides/coreeval/permissions', + link: '/guides/coreeval/permissions' }, { text: 'Submit Transactions', - link: '/guides/coreeval/local-testnet', - }, - ], + link: '/guides/coreeval/local-testnet' + } + ] }, { text: 'Integrating with Agoric Network', @@ -267,13 +292,13 @@ export default defineConfig({ items: [ { text: 'Name Services: agoricNames, namesByAddress, board', - link: '/guides/integration/name-services', + link: '/guides/integration/name-services' }, { text: 'SubQuery Indexing', - link: '/guides/subquery-indexing', - }, - ], + link: '/guides/subquery-indexing' + } + ] }, { text: 'Agoric CLI', @@ -283,17 +308,17 @@ export default defineConfig({ { text: 'Agoric CLI Reference', link: '/guides/agoric-cli/' }, { text: 'Using agd to make queries and transactions', - link: '/guides/agoric-cli/agd-query-tx', - }, - ], + link: '/guides/agoric-cli/agd-query-tx' + } + ] }, { - text: 'Agoric API Reference', - link: 'https://agoric-sdk.pages.dev/' + text: 'Agoric API Reference', + link: 'https://agoric-sdk.pages.dev/' }, { - text: 'Endo API Reference', - link: 'https://endojs.github.io/endo/' + text: 'Endo API Reference', + link: 'https://endojs.github.io/endo/' }, { @@ -308,17 +333,17 @@ export default defineConfig({ { text: 'Purse Object', link: '/reference/ertp-api/purse' }, { text: 'Payment Object', - link: '/reference/ertp-api/payment', + link: '/reference/ertp-api/payment' }, { text: 'AmountMath Object', - link: '/reference/ertp-api/amount-math', + link: '/reference/ertp-api/amount-math' }, { text: 'ERTP Data Types', - link: '/reference/ertp-api/ertp-data-types', - }, - ], + link: '/reference/ertp-api/ertp-data-types' + } + ] }, { text: 'Zoe API', @@ -329,39 +354,39 @@ export default defineConfig({ { text: 'Zoe Service', link: '/reference/zoe-api/zoe' }, { text: 'UserSeat Object', - link: '/reference/zoe-api/user-seat', + link: '/reference/zoe-api/user-seat' }, { text: 'Zoe Contract Facet (ZCF)', - link: '/reference/zoe-api/zoe-contract-facet', + link: '/reference/zoe-api/zoe-contract-facet' }, { text: 'ZCFSeat Object', link: '/reference/zoe-api/zcfseat' }, { text: 'ZCFMint Object', link: '/reference/zoe-api/zcfmint' }, { text: 'ZoeHelper Functions', - link: '/reference/zoe-api/zoe-helpers', + link: '/reference/zoe-api/zoe-helpers' }, { text: 'Ratio Math Functions', - link: '/reference/zoe-api/ratio-math', + link: '/reference/zoe-api/ratio-math' }, { text: 'Zoe Data Types', - link: '/reference/zoe-api/zoe-data-types', + link: '/reference/zoe-api/zoe-data-types' }, { text: 'PriceAuthority Object', - link: '/reference/zoe-api/price-authority', + link: '/reference/zoe-api/price-authority' }, { text: 'PriceAuthority Admin Object', - link: '/reference/zoe-api/price-authority-admin', + link: '/reference/zoe-api/price-authority-admin' }, { text: 'MutableQuote Object', - link: '/reference/zoe-api/mutable-quote', - }, - ], + link: '/reference/zoe-api/mutable-quote' + } + ] }, { text: 'Example Zoe Contracts', @@ -371,85 +396,85 @@ export default defineConfig({ items: [ { text: 'Example Zoe Contracts', - link: '/guides/zoe/contracts/', + link: '/guides/zoe/contracts/' }, { text: 'Oracle Query Contract', - link: '/guides/zoe/contracts/oracle', + link: '/guides/zoe/contracts/oracle' }, { text: 'Vault Contract', - link: '/guides/zoe/contracts/vault', + link: '/guides/zoe/contracts/vault' }, { text: 'Loan Contract', link: '/guides/zoe/contracts/loan' }, { text: 'Funded Call Spread Contract', - link: '/guides/zoe/contracts/fundedCallSpread', + link: '/guides/zoe/contracts/fundedCallSpread' }, { text: 'Priced Call Spread Contract', - link: '/guides/zoe/contracts/pricedCallSpread', + link: '/guides/zoe/contracts/pricedCallSpread' }, { text: 'Covered Call Contract', - link: '/guides/zoe/contracts/covered-call', + link: '/guides/zoe/contracts/covered-call' }, { text: 'OTC Desk Contract', - link: '/guides/zoe/contracts/otc-desk', + link: '/guides/zoe/contracts/otc-desk' }, { text: 'ConstantProduct AMM Contract', - link: '/guides/zoe/contracts/constantProductAMM', + link: '/guides/zoe/contracts/constantProductAMM' }, { text: 'Sell Items Contract', - link: '/guides/zoe/contracts/sell-items', + link: '/guides/zoe/contracts/sell-items' }, { text: 'Atomic Swap Contract', - link: '/guides/zoe/contracts/atomic-swap', + link: '/guides/zoe/contracts/atomic-swap' }, { text: 'Barter Exchange Contract', - link: '/guides/zoe/contracts/barter-exchange', + link: '/guides/zoe/contracts/barter-exchange' }, { text: 'Second-Price Auction Contract', - link: '/guides/zoe/contracts/second-price-auction', + link: '/guides/zoe/contracts/second-price-auction' }, { text: 'Simple Exchange Contract', - link: '/guides/zoe/contracts/simple-exchange', + link: '/guides/zoe/contracts/simple-exchange' }, { text: 'Escrow To Vote Contract', - link: '/guides/zoe/contracts/escrow-to-vote', + link: '/guides/zoe/contracts/escrow-to-vote' }, { text: 'Mint Payments Contract', - link: '/guides/zoe/contracts/mint-payments', + link: '/guides/zoe/contracts/mint-payments' }, { text: 'Mint and Sell NFTs Contract', - link: '/guides/zoe/contracts/mint-and-sell-nfts', + link: '/guides/zoe/contracts/mint-and-sell-nfts' }, { text: 'Use Object Contract', - link: '/guides/zoe/contracts/use-obj-example', + link: '/guides/zoe/contracts/use-obj-example' }, { text: 'Automatic Refund Contract', - link: '/guides/zoe/contracts/automatic-refund', - }, - ], + link: '/guides/zoe/contracts/automatic-refund' + } + ] }, { text: 'End-to-End Testing', ariaLabel: 'End-to-End Testing', - link: '/e2e-testing', - }, - ], + link: '/e2e-testing' + } + ] }, { text: 'Learn', @@ -457,17 +482,17 @@ export default defineConfig({ items: [ { text: 'What is Agoric?', - link: '/what-is-agoric', + link: '/what-is-agoric' }, { text: 'Agoric Platform', link: '/guides/platform/', collapsed: true, - items: [], + items: [] }, { text: 'Zoe Smart Contract Framework', - link: '/guides/zoe/', + link: '/guides/zoe/' }, { text: 'ERTP', @@ -477,23 +502,23 @@ export default defineConfig({ items: [ { text: 'Amounts, Values, and Brands', - link: '/guides/ertp/amounts', + link: '/guides/ertp/amounts' }, { text: 'AmountMath', link: '/guides/ertp/amount-math' }, { text: 'Issuers and Mints', - link: '/guides/ertp/issuers-and-mints', + link: '/guides/ertp/issuers-and-mints' }, { text: 'Purses and Payments', - link: '/guides/ertp/purses-and-payments', - }, - ], + link: '/guides/ertp/purses-and-payments' + } + ] }, { text: 'JavaScript Framework', ariaLabel: 'JavaScript Framework', - link: '/guides/js-programming/', + link: '/guides/js-programming/' }, { @@ -504,23 +529,23 @@ export default defineConfig({ items: [ { text: 'PSM Contract', - link: '/guides/zoe/actual-contracts/PSM', - }, - ], + link: '/guides/zoe/actual-contracts/PSM' + } + ] }, { text: 'Glossary', ariaLabel: 'Glossary Menu', - link: '/glossary/', + link: '/glossary/' }, { text: 'Papers', ariaLabel: 'Papers Page Link', - link: 'https://agoric.com/papers/', - }, - ], + link: 'https://agoric.com/papers/' + } + ] }, { text: 'Tutorials', @@ -528,7 +553,7 @@ export default defineConfig({ items: [ { text: 'Tutorial: Dapp with Agoric', - link: '/guides/getting-started/tutorial/', + link: '/guides/getting-started/tutorial/' }, { text: 'dapp-agoric-basics', @@ -536,23 +561,19 @@ export default defineConfig({ items: [ { text: 'Takeaway 1: Sell Concert Tickets Contract Overview', - link: - '/guides/getting-started/sell-concert-tickets-contract-explainer', + link: '/guides/getting-started/sell-concert-tickets-contract-explainer' }, { text: 'Takeaway 2: Swaparoo Contract Overview', - link: - '/guides/getting-started/swaparoo-how-to-swap-assets-explainer', + link: '/guides/getting-started/swaparoo-how-to-swap-assets-explainer' }, { - text: - 'Takeaway 3: Sending Invitation Payments using an Address', - link: - '/guides/getting-started/swaparoo-making-a-payment-explainer', - }, - ], + text: 'Takeaway 3: Sending Invitation Payments using an Address', + link: '/guides/getting-started/swaparoo-making-a-payment-explainer' + } + ] }, { @@ -561,31 +582,31 @@ export default defineConfig({ items: [ { text: '1. Starting', - link: '/guides/getting-started/ui-tutorial/starting', + link: '/guides/getting-started/ui-tutorial/starting' }, { text: '2. Agoric Provider', - link: '/guides/getting-started/ui-tutorial/agoric-provider', + link: '/guides/getting-started/ui-tutorial/agoric-provider' }, { text: '3. Connect Wallet', - link: '/guides/getting-started/ui-tutorial/connect-wallet', + link: '/guides/getting-started/ui-tutorial/connect-wallet' }, { text: '4. Querying Vstorage', - link: '/guides/getting-started/ui-tutorial/querying-vstorage', + link: '/guides/getting-started/ui-tutorial/querying-vstorage' }, { text: '5. Making an Offer', - link: '/guides/getting-started/ui-tutorial/making-an-offer', + link: '/guides/getting-started/ui-tutorial/making-an-offer' }, { text: '6. Conclusion', - link: '/guides/getting-started/ui-tutorial/conclusion', - }, - ], - }, - ], + link: '/guides/getting-started/ui-tutorial/conclusion' + } + ] + } + ] }, { text: 'Support', @@ -594,37 +615,37 @@ export default defineConfig({ { text: 'Agoric', ariaLabel: 'Agoric Homepage Link', - link: 'https://agoric.com/', + link: 'https://agoric.com/' }, { text: 'Discord', - link: 'https://agoric.com/discord', + link: 'https://agoric.com/discord' }, { text: 'Discussions (Q&A)', - link: 'https://github.com/Agoric/agoric-sdk/discussions', + link: 'https://github.com/Agoric/agoric-sdk/discussions' }, { text: 'Office Hours', - link: 'https://github.com/Agoric/agoric-sdk/wiki/Office-Hours', + link: 'https://github.com/Agoric/agoric-sdk/wiki/Office-Hours' }, { text: 'Twitter', - link: 'https://twitter.com/agoric', + link: 'https://twitter.com/agoric' }, { text: 'YouTube', ariaLabel: 'Agoric YouTube Channel Page Link', - link: 'https://www.youtube.com/channel/UCpY91oQLh_Lp0mitdZ5bYWg/', + link: 'https://www.youtube.com/channel/UCpY91oQLh_Lp0mitdZ5bYWg/' }, { text: 'Github', ariaLabel: 'Agoric Github Link', - link: 'https://github.com/Agoric/', - }, - ], - }, - ], + link: 'https://github.com/Agoric/' + } + ] + } + ] }, docsRepo: 'Agoric/documentation', // if your docs are not at the root of the repo: @@ -634,7 +655,7 @@ export default defineConfig({ // custom text for edit link. Defaults to "Edit this page" editLink: { pattern: 'https://github.com/Agoric/documentation/edit/main/main/:path', - text: 'Help us improve this page!', + text: 'Help us improve this page!' }, zoeVersion: 'v0.24.0', @@ -659,7 +680,7 @@ export default defineConfig({ */ searchOptions: { /* ... */ - }, + } /** * @param {string} src * @param {import('vitepress').MarkdownEnv} env @@ -667,33 +688,33 @@ export default defineConfig({ */ // _render(src, env, md) { // }, - }, - }, + } + } }, footer: { - copyright: `© ${new Date().getFullYear()} Agoric Systems Operating Company. All Rights Reserved.`, + copyright: `© ${new Date().getFullYear()} Agoric Systems Operating Company. All Rights Reserved.` }, socialLinks: [ { icon: 'discord', ariaLabel: 'Discord', - link: 'https://agoric.com/discord', + link: 'https://agoric.com/discord' }, { icon: 'github', ariaLabel: 'GitHub', - link: 'https://github.com/Agoric/agoric-sdk', + link: 'https://github.com/Agoric/agoric-sdk' }, { icon: 'twitter', ariaLabel: 'Twitter', - link: 'https://twitter.com/agoric', + link: 'https://twitter.com/agoric' }, { icon: 'youtube', ariaLabel: 'YouTube', - link: 'https://www.youtube.com/@Agoric', - }, - ], - }, + link: 'https://www.youtube.com/@Agoric' + } + ] + } }); diff --git a/main/guides/zoe/contract-details.md b/main/guides/zoe/contract-details.md index fc6113e14..d2770d0d1 100644 --- a/main/guides/zoe/contract-details.md +++ b/main/guides/zoe/contract-details.md @@ -81,7 +81,7 @@ or to pass to separate recipients. These objects and facets are designed to be durable and shareable across address space boundaries. Since code in different vats might not be mutually trusting, code needs to be defensive about parameters received from -remote callers. Interface Guards let us express in code what parameters each method expects and can handle +remote callers. [Interface Guards](https://endojs.github.io/endo/modules/_endo_patterns.html) let us express in code what parameters each method expects and can handle safely. If a caller provides a parameter that doesn't match the template specified in the guard, SwingSet returns an exception to the caller without notifying the receiver. If the return value doesn't match, the function returns an exception to the caller. diff --git a/main/guides/zoe/contract-requirements.md b/main/guides/zoe/contract-requirements.md index 50ea34b5a..74796d7bf 100644 --- a/main/guides/zoe/contract-requirements.md +++ b/main/guides/zoe/contract-requirements.md @@ -13,11 +13,11 @@ and may import other code, including: for testing whether something is a natural number (natural numbers are recommended for currency-related programming in order to avoid rounding issues) and throwing an error if not. -- [@agoric/notifier](https://www.npmjs.com/package/@agoric/zoe): A package that provides updates through +- [@agoric/notifier](https://www.npmjs.com/package/@agoric/notifier): A package that provides updates through smartly resolving promises rather than polling. - [@agoric/zoe](https://www.npmjs.com/package/@agoric/zoe): Zoe has helpers that contracts can use by importing - `@agoric/zoe/src/contractSupport/zoeHelpers.js`. + `@agoric/zoe/src/contractSupport/index.js`. A Zoe contract will be bundled up, so you should feel free to divide your contract into multiple files (perhaps putting helper functions in a @@ -28,14 +28,23 @@ JavaScript code is incompatible with Hardened JavaScript, because Lockdown freez JavaScript objects you start out with (the primordials, such as `Object`), and some legacy code tries to mutate these. -If you add this type annotation, TypeScript-aware tools +If you add JSDoc type annotations, TypeScript-aware tools (IDEs like vsCode and WebStorm) will inform the developer about parameters and return values for your contract and `zcf` methods and warn about mismatches. -Put it right before the start of your contract code. +Current contracts import their types with an `@import` tag and annotate +`start`'s parameters directly, rather than typing the whole function as a +`ContractStartFn`: ```js /** - * @type {ContractStartFn} + * @import {Baggage} from '@agoric/vat-data'; + * @import {ZCF} from '@agoric/zoe'; + */ + +/** + * @param {ZCF} zcf + * @param {object} privateArgs + * @param {Baggage} baggage */ ``` @@ -46,9 +55,12 @@ The second argument, `privateArgs`, is used by the caller of `startInstance` to pass in any arguments that should not be part of the public terms. `privateArgs` is an object with keys and values as decided by the caller of `startInstance`. If no private arguments are passed, `privateArgs` is undefined. +The third argument, `baggage`, is a durable `MapStore` the kernel preserves +across upgrades of the contract's vat; see [Durability](./contract-upgrade.md#durability) +for how contracts use it to keep state and behavior between incarnations. ```js -const start = (zcf, privateArgs) => { +const start = (zcf, privateArgs, baggage) => { // ... // your code here return harden({ creatorFacet, creatorInvitation, publicFacet }); @@ -57,6 +69,11 @@ harden(start); export { start }; ``` +A contract that wants to declare whether it supports upgrade also exports a +`meta` record alongside `start`, with an `upgradability` field of `none`, +`canUpgrade`, or `canBeUpgraded`. See [Upgradable Declaration](./contract-upgrade.md#upgradable-declaration) +for details; a `prepare` export is no longer used for this purpose. + The contract must return a record with any (or none) of the following: - **creatorFacet**: An object, usually with admin authority. It is only given to the entity diff --git a/main/guides/zoe/contract-upgrade.md b/main/guides/zoe/contract-upgrade.md index 5a8b0ad59..bb2138b73 100644 --- a/main/guides/zoe/contract-upgrade.md +++ b/main/guides/zoe/contract-upgrade.md @@ -251,20 +251,54 @@ See [Vow](/glossary/#vow); These tools handle promises and asynchronous operatio ```js const vowTools = prepareVowTools(zone.subZone('vows')); +const chainHub = makeChainHub( + zone.subZone('chainHub'), + privateArgs.agoricNames, + vowTools +); // ... -const makeLocalOrchestrationAccountKit = prepareLocalChainAccountKit( - zone, - makeRecorderKit, - zcf, - privateArgs.timerService, - vowTools, - makeChainHub(privateArgs.agoricNames) +const makeLocalOrchestrationAccountKit = prepareLocalOrchestrationAccountKit( + zone.subZone('orchestration'), + { + makeRecorderKit, + makeProgressTracker, + zcf, + timerService, + vowTools, + chainHub, + localchain, + zoeTools + } ); // ... const makeCosmosOrchestrationAccount = prepareCosmosOrchestrationAccount( - zone, - makeRecorderKit, - vowTools, - zcf + zone.subZone('orchestration'), + { + chainHub, + makeProgressTracker, + makeRecorderKit, + timerService, + vowTools, + zcf + } ); ``` + +_See [`start-helper.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/orchestration/src/utils/start-helper.js) for the full wiring these makers depend on._ + +### Moving Assets Between Seats + +Upgradable contracts still need to reallocate assets between seats, but the +old `stage()`/`reallocate()` seat API isn't compatible with durability. +Use `zcf.atomicRearrange(transfers)` instead; see [Moving Assets Between +Seats](./moving-assets.md) for the primitive and its helpers (`atomicTransfer`, +`fromOnly`, `toOnly`). + +### Worked Examples + +- [`coveredCall-durable.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/coveredCall-durable.js): + a durable variant of the covered-call contract, using `prepareExoClass`/`prepareExo` + directly against `baggage` so the exercise-option invitation survives upgrade. +- [`valueVow.contract.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/valueVow.contract.js): + a minimal contract that exports `meta = { upgradability: 'canUpgrade' }` and + uses `zone.makeOnce()` to keep a durable Vow across incarnations. diff --git a/main/guides/zoe/index.md b/main/guides/zoe/index.md index 651b0d7c3..635fb062d 100644 --- a/main/guides/zoe/index.md +++ b/main/guides/zoe/index.md @@ -38,7 +38,11 @@ Note that in this flow, _assets are not sent to the contract_; only information ## Building and Using Contracts - [Zoe Smart Contract Basics](./contract-basics.md) +- [Contract Requirements](./contract-requirements.md) +- [The Structure of Offers](./proposal.md) +- [Offer Safety](./offer-safety.md) - [A Complete Contract Walk-Through: offer-up](./contract-walkthru) +- [Moving Assets Between Seats](./moving-assets.md) ## Live Coding and Example Contracts @@ -51,16 +55,7 @@ Note that in this flow, _assets are not sent to the contract_; only information Agoric has written [a number of example contracts that you can use](./contracts/index), including: -- an [Automated Market Maker (AMM) - implementation](./contracts/constantProductAMM) - a [covered call option contract](./contracts/covered-call) - an [OTC Desk market maker contract](./contracts/otc-desk) - contracts for [minting fungible](./contracts/mint-payments) and [non-fungible tokens](./contracts/mint-and-sell-nfts) - -::: warning Beta Features - -These contracts may depend on features from our Beta release -that are not available in mainnet. - -::: diff --git a/main/guides/zoe/moving-assets.md b/main/guides/zoe/moving-assets.md new file mode 100644 index 000000000..3432a3c92 --- /dev/null +++ b/main/guides/zoe/moving-assets.md @@ -0,0 +1,125 @@ +# Moving Assets Between Seats + +A contract's business logic decides how the assets escrowed in its seats +should end up allocated. It never touches the assets directly; instead it +tells `zcf` to change the allocations, and Zoe checks the result for +[offer safety](./offer-safety.md) and overall conservation before applying it. + +The older way to express a reallocation was to `stage()` proposed changes on +each seat and then call `reallocate()` with the staged seats. That API isn't +compatible with contract [durability](./contract-upgrade.md#durability), so +current contracts use `zcf.atomicRearrange(transfers)` instead, and a +reallocation can only be expressed one way or the other, never a mixture of +both, for a given contract instance. + +## `zcf.atomicRearrange(transfers)` + +`transfers` is an array of `TransferPart`s. Each `TransferPart` is a 4-tuple: + +```js +[fromSeat, toSeat, fromAmounts, toAmounts]; +``` + +- `fromSeat` and `toSeat` are `ZCFSeat`s, or `undefined`. +- `fromAmounts` and `toAmounts` are `AmountKeywordRecord`s, or `undefined`. +- If `fromSeat` is given, `fromAmounts` is deducted from its allocation (it + defaults to `toAmounts` if omitted). +- If `toSeat` is given, `toAmounts` is added to its allocation (it defaults + to `fromAmounts` if omitted). + +If all the `TransferPart`s in the array are individually valid, and the +overall transfer still balances (conserves the total value of every keyword) +and preserves offer safety for every seat mentioned, the whole reallocation +happens atomically. Otherwise none of it happens. + +Here's the [`swap`](/reference/zoe-api/zoe-helpers#swap-zcf-leftseat-rightseat) +helper's own implementation, exchanging what each seat wants for what the +other seat is giving: + +```js +export const swap = (zcf, leftSeat, rightSeat) => { + try { + zcf.atomicRearrange( + harden([ + [rightSeat, leftSeat, leftSeat.getProposal().want], + [leftSeat, rightSeat, rightSeat.getProposal().want] + ]) + ); + } catch (err) { + leftSeat.fail(err); + rightSeat.fail(err); + throw err; + } + + leftSeat.exit(); + rightSeat.exit(); + return defaultAcceptanceMsg; +}; +``` + +## `fromOnly` and `toOnly` + +Some transfers only need to say what comes from a seat, or only what goes to +a seat, leaving the rest of the array to balance it out. Writing +`[fromSeat, undefined, fromAmounts]` and `[undefined, toSeat, undefined, +toAmounts]` by hand is easy to get wrong, so +[`contractSupport`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contractSupport/atomicTransfer.js) +provides `fromOnly(fromSeat, fromAmounts)` and `toOnly(toSeat, toAmounts)` to +express those cases clearly. The `swapExact` helper uses both to move each +seat's full `give` out and full `want` in: + +```js +export const swapExact = (zcf, leftSeat, rightSeat) => { + try { + zcf.atomicRearrange( + harden([ + fromOnly(rightSeat, rightSeat.getProposal().give), + fromOnly(leftSeat, leftSeat.getProposal().give), + + toOnly(leftSeat, leftSeat.getProposal().want), + toOnly(rightSeat, rightSeat.getProposal().want) + ]) + ); + } catch (err) { + leftSeat.fail(err); + rightSeat.fail(err); + throw err; + } + + leftSeat.exit(); + rightSeat.exit(); + return defaultAcceptanceMsg; +}; +``` + +## `atomicTransfer` + +For the common case of a single one-way transfer, `atomicTransfer` avoids +wrapping the arguments in an array: + +```js +import { atomicTransfer } from '@agoric/zoe/src/contractSupport/index.js'; + +atomicTransfer(zcf, fromSeat, toSeat, fromAmounts, toAmounts); +``` + +which is exactly: + +```js +zcf.atomicRearrange(harden([[fromSeat, toSeat, fromAmounts, toAmounts]])); +``` + +::: tip Import from `contractSupport/index.js` + +`fromOnly`, `toOnly`, and `atomicTransfer` are helpers, imported from +`@agoric/zoe/src/contractSupport/index.js` alongside `swap` and `swapExact`. +There is also an `atomicRearrange` helper with the same signature as +`zcf.atomicRearrange`, but it's deprecated in favor of calling the `zcf` +method directly. + +::: + +## API Reference + +See [`ZCF.atomicRearrange`](/reference/zoe-api/zoe-contract-facet#zcf-atomicrearrange-transfers) +and [`TransferPartShape`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contractSupport/atomicTransfer.js). diff --git a/main/guides/zoe/offer-enforcement.md b/main/guides/zoe/offer-enforcement.md index 8c8ccd5e0..7b630a413 100644 --- a/main/guides/zoe/offer-enforcement.md +++ b/main/guides/zoe/offer-enforcement.md @@ -67,7 +67,7 @@ the swap contract behaves badly, we both get a refund, and at best, we get what we each wanted. Let's look at the basic [Atomic Swap contract](/guides/zoe/contracts/atomic-swap) -(link includes [real contract code](https://github.com/Agoric/agoric-sdk/blob/f29591519809dbadf19db0a26f38704d87429b89/packages/zoe/src/contracts/atomicSwap.js)). +(link includes [real contract code](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/atomicSwap.js)). Here's a high-level overview of what happens: @@ -94,18 +94,22 @@ Here's a high-level overview of what happens: Writing smart contracts that run on Zoe is easy. Let's look at a simple contract like [Automatic Refund](/guides/zoe/contracts/automatic-refund) (link includes [real contract -code](https://github.com/Agoric/agoric-sdk/blob/4e0aece631d8310c7ab8ef3f46fad8981f64d208/packages/zoe/src/contracts/automaticRefund.js)). +code](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/automaticRefund.js)). It only does one thing, and it's pretty useless—it gives you back what you put in. ```js const start = zcf => { + let offersCount = 0n; + const refund = seat => { + offersCount += 1n; seat.exit(); return `The offer was accepted`; }; const makeRefundInvitation = () => zcf.makeInvitation(refund, 'getRefund'); const publicFacet = Far('publicFacet', { + getOffersCount: () => offersCount, makeInvitation: makeRefundInvitation }); @@ -139,11 +143,12 @@ several optional properties: ## Diving Deeper Let's dive back into the [Atomic Swap contract](/guides/zoe/contracts/atomic-swap) -(link includes [real contract code](https://github.com/Agoric/agoric-sdk/blob/f29591519809dbadf19db0a26f38704d87429b89/packages/zoe/src/contracts/atomicSwap.js)). +(link includes [real contract code](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/atomicSwap.js)). The contract first confirms that `issuers` are setup for the `Asset` and `Price` keywords. Those are the two items that will be swapped. -The following uses the [`assertIssuerKeywords` helper function](/reference/zoe-api/zoe-helpers#assertissuerkeywords-zcf-expected). It +The following uses the [`assertIssuerKeywords` helper function](/reference/zoe-api/zoe-helpers#assertissuerkeywords-zcf-expected), imported +along with `swap` from `@agoric/zoe/src/contractSupport/index.js`. It checks properties of the running contract instance's terms. ```js @@ -186,12 +191,14 @@ handler is responsible for the final step. It uses the [`swap` helper function](/reference/zoe-api/zoe-helpers#swap-zcf-leftseat-rightseat) to attempt asset reallocation between the two seats as described above and then (whether or not the attempt succeeds) exits both seats, making payouts available to -both parties. Finally, `matchingSeatOfferHandler()` shuts down the contract. +both parties. Finally, `matchingSeatOfferHandler()` shuts down the contract. Under the +hood, `swap` reallocates with [`zcf.atomicRearrange`](./moving-assets.md), the +current replacement for the deprecated `stage()`/`reallocate()` seat API. ```js const matchingSeatOfferHandler = matchingSeat => { const swapResult = swap(zcf, firstSeat, matchingSeat); - zcf.shutdown(); + zcf.shutdown('Swap completed.'); return swapResult; }; ``` diff --git a/main/guides/zoe/price-authority.md b/main/guides/zoe/price-authority.md index 37ac1a530..494c81bc0 100644 --- a/main/guides/zoe/price-authority.md +++ b/main/guides/zoe/price-authority.md @@ -6,7 +6,15 @@ various time and price conditions. ## Examples -To see a `priceAuthority` in use, see the [Loan +The production path for price feeds composes +[`priceAggregator.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/priceAggregator.js), +which combines quotes from multiple oracles into a median price, with +[`scaledPriceAuthority.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/zoe/src/contracts/scaledPriceAuthority.js), +which rescales a source `priceAuthority` (for example, to change units) +without adding any durable state of its own. + +For simpler, single-file demos that use a `priceAuthority` in their terms, +see the [Loan contract](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts/loan) and the [Call Spread contracts](https://github.com/Agoric/agoric-sdk/tree/master/packages/zoe/src/contracts/callSpread). @@ -35,10 +43,11 @@ const verifiedQuoteAmount = await E(quoteIssuer).getAmountOf(quotePayment); ``` Once you have a `quoteAmount` (or a `verifiedQuoteAmount`), you can extract the -quoted amounts: +quoted amounts. `quoteAmount.value` is a one-element array holding the quote's +`PriceDescription` record: ```js -const [{ value: { amountIn, amountOut, timestamp, timer }] = quoteAmount; +const [{ amountIn, amountOut, timestamp, timer }] = quoteAmount.value; ``` This means that the `priceAuthority` asserts that when `timestamp` according to diff --git a/main/guides/zoe/pub-to-storage.md b/main/guides/zoe/pub-to-storage.md index f77407428..3303140c4 100644 --- a/main/guides/zoe/pub-to-storage.md +++ b/main/guides/zoe/pub-to-storage.md @@ -29,76 +29,36 @@ The `swaparoo` contract delegates the rest of publishing governance parameters t ## 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 +Let's work through the details of writing a notification. A contract that +manages a durable resource often wants to publish a metrics notification +whenever that resource changes: ```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 + * @property {Amount<'nat'>} totalMinted total tokens minted 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: +A method that writes this data using a `RecorderKit` looks like: ```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); + const metrics = harden({ totalMinted: state.totalMinted }); + void state.metricsRecorder.write(metrics); }, ``` -The `metricsKit` is made with a `makeRecorderKit` function: +The `metricsRecorder` comes from a `RecorderKit` made with `makeRecorderKit`: ```js - metricsKit: makeRecorderKit( - metricsNode, - /** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedMatcher} */ ( - M.any() - ), - ), + metricsRecorder: makeRecorderKit(metricsNode, M.any()).recorder, ``` -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). +`makeRecorderKit` itself is made by "preparing" (in the [exo](https://endojs.github.io/endo/modules/_endo_exo.html) sense) +[`prepareRecorderKitMakers`](/reference/zoe-api/zoe-helpers#preparerecorderkitmakers-baggage-marshaller) +against the contract's `baggage`: ```js const { makeRecorderKit } = prepareRecorderKitMakers( @@ -107,53 +67,32 @@ const { makeRecorderKit } = prepareRecorderKitMakers( ); ``` -The contract gets `baggage`, along with `privateArgs` when it starts in -[the usual way for upgradable contracts](./contract-upgrade.html#upgradable-declaration): +The contract gets `baggage`, along with `privateArgs`, as the standard `start` +arguments described in [Durability](./contract-upgrade.md#durability): ```js /** - * Asset Reserve holds onto assets for the Inter Protocol, and ... - * + * @param {ZCF} zcf * @param {{ - * ... * marshaller: ERef, * storageNode: ERef, * }} privateArgs * @param {Baggage} baggage */ -export const prepare = async (zcf, privateArgs, baggage) => { +export const start = async (zcf, privateArgs, baggage) => { // ... }; ``` -The reserve uses its `StorageNode` and makes a child to get `metricsNode`: +The contract uses its `storageNode` and makes a child node to get `metricsNode`: ```js -const metricsNode = await E(storageNode).makeChildNode('metrics'); +const metricsNode = await E(privateArgs.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, -// ... - }, -// ... -}) => { ... }; -``` +For a real, current contract that wires up `prepareRecorderKitMakers`, +`storageNode`, and `marshaller` this way (as part of a larger orchestration +setup), see +[`stake-bld.contract.js`](https://github.com/Agoric/agoric-sdk/blob/master/packages/orchestration/src/examples/stake-bld.contract.js). From db5c6663bbed6ec271eff5c5c182162359ac1212 Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Thu, 24 Sep 2026 20:19:19 +0000 Subject: [PATCH 05/21] docs(ertp): refresh guides and API reference for current AssetKind/Issuer surface Live AssetKind set is NAT, COPY_SET, COPY_BAG (SET is deprecated); update the guides and reference pages away from the old NAT/SET-only framing. claim, combine, split, and splitMany are no longer Issuer methods -- they moved to legacy-payment-helpers.js with a recoveryPurse-first signature, documented on a new Legacy Payment Helpers page. makeIssuerKit's 5th parameter is an options record ({ elementShape, recoverySetsOption }), not a positional elementShape, and IssuerKit now has five properties (issuer, mint, brand, mintRecoveryPurse, displayInfo). Add a Durable Issuers reference page for prepareIssuerKit/makeDurableIssuerKit/ upgradeIssuerKit and RecoverySetsOption. Document Brand.getAmountShape, AmountMath.min/max, and Purse.getRecoverySet/recoverAll; flag getDisplayInfo/DisplayInfo as deprecated. Verified against agoric-sdk packages/ERTP/src/{amountMath,issuerKit, types,legacy-payment-helpers,index}.js. All snippets/ertp/guide/*.js tests pass, yarn lint:check-links passes, and the VitePress build succeeds. --- main/.vitepress/config.mjs | 8 + main/guides/ertp/amount-math.md | 19 +- main/guides/ertp/amounts.md | 4 +- main/guides/ertp/index.md | 14 +- main/guides/ertp/issuers-and-mints.md | 45 +++-- main/guides/ertp/purses-and-payments.md | 35 +++- main/reference/ertp-api/brand.md | 4 + main/reference/ertp-api/durable-issuers.md | 98 +++++++++ main/reference/ertp-api/ertp-data-types.md | 8 +- main/reference/ertp-api/index.md | 10 +- main/reference/ertp-api/issuer.md | 189 ++++-------------- .../ertp-api/legacy-payment-helpers.md | 104 ++++++++++ main/reference/ertp-api/mint.md | 4 +- main/reference/ertp-api/payment.md | 19 +- main/reference/ertp-api/purse.md | 39 ++++ snippets/ertp/guide/test-amount-math.js | 61 ++++-- snippets/ertp/guide/test-issuers-and-mints.js | 4 +- snippets/ertp/guide/test-readme.js | 5 +- 18 files changed, 452 insertions(+), 218 deletions(-) create mode 100644 main/reference/ertp-api/durable-issuers.md create mode 100644 main/reference/ertp-api/legacy-payment-helpers.md diff --git a/main/.vitepress/config.mjs b/main/.vitepress/config.mjs index 6ab199d8c..e661374b1 100644 --- a/main/.vitepress/config.mjs +++ b/main/.vitepress/config.mjs @@ -339,6 +339,14 @@ export default defineConfig({ text: 'AmountMath Object', link: '/reference/ertp-api/amount-math' }, + { + text: 'Durable Issuers', + link: '/reference/ertp-api/durable-issuers', + }, + { + text: 'Legacy Payment Helpers', + link: '/reference/ertp-api/legacy-payment-helpers', + }, { text: 'ERTP Data Types', link: '/reference/ertp-api/ertp-data-types' diff --git a/main/guides/ertp/amount-math.md b/main/guides/ertp/amount-math.md index 987d521f0..bbcf82f35 100644 --- a/main/guides/ertp/amount-math.md +++ b/main/guides/ertp/amount-math.md @@ -7,13 +7,16 @@ Depositing and withdrawing assets from a all require adding and subtracting digital assets. ERTP uses the `AmountMath` library for all these operations. -The `AmountMath` library functions work for both fungible and nonfungible tokens. -There are two `AssetKinds`, each of which implements the same methods. Which kind is used +The `AmountMath` library functions work for fungible, non-fungible, and semi-fungible tokens. +There are three live `AssetKinds`, each of which implements the same methods. Which kind is used for a particular `brand` depends on what was specified when the `brand` and its `issuer` were created. They are: - `AssetKind.NAT` ("nat"): Used with fungible assets. Values are natural numbers using the JavaScript [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) type to avoid overflow risks from using the usual JavaScript `Number` type. -- `AssetKind.SET` ("set"): Used with non-fungible assets. Values are [copyArray](../js-programming/far#passstyleof-api)s such as hardened arrays of strings. +- `AssetKind.COPY_SET` ("copySet"): Used with non-fungible assets where there can't be duplicates, such as assigned seats in a stadium. Values are [CopySets](/reference/ertp-api/ertp-data-types#assetkind). +- `AssetKind.COPY_BAG` ("copyBag"): Used with semi-fungible assets where duplicates of the same element are fungible with each other, such as weapons in a computer game. Values are [CopyBags](/reference/ertp-api/ertp-data-types#assetkind). + +A fourth, `AssetKind.SET` ("set"), is deprecated; use `AssetKind.COPY_SET` instead. ## AmountMath Methods @@ -47,6 +50,12 @@ to add verification that the `brand` of "amount" argument(s) corresponds with th - Takes an `amount` and returns it if it's a valid `amount`. If invalid, it throws an error. - <<< @/../snippets/ertp/guide/test-amount-math.js#coerce + - [AmountMath.min(x, y, brand?)](/reference/ertp-api/amount-math#amountmath-min-x-y-brand) + - Returns the smaller of the `x` and `y` `amount` arguments, using `isGTE`. + - <<< @/../snippets/ertp/guide/test-amount-math.js#min + - [AmountMath.max(x, y, brand?)](/reference/ertp-api/amount-math#amountmath-max-x-y-brand) + - Returns the larger of the `x` and `y` `amount` arguments, using `isGTE`. + - <<< @/../snippets/ertp/guide/test-amount-math.js#max - **Manipulator Methods** - [AmountMath.add(leftAmount, rightAmount, brand?)](/reference/ertp-api/amount-math#amountmath-add-leftamount-rightamount-brand) - Returns an `amount` that is the union of the `leftAmount` and `rightAmount` @@ -73,7 +82,7 @@ to add verification that the `brand` of "amount" argument(s) corresponds with th - Returns an `amount` representing an empty `amount`, which is the identity element for the `AmountMath` `add()` and `subtract()` operations. Note that this value varies depending on the - `brand` and whether it is of kind `AssetKind.NAT` or `AssetKind.SET`. + `brand` and its `AssetKind`. - <<< @/../snippets/ertp/guide/test-amount-math.js#makeEmpty - [AmountMath.makeEmptyFromAmount(amount)](/reference/ertp-api/amount-math#amountmath-makeemptyfromamount-amount) - Returns an `amount` representing an empty `amount`, using another `amount` @@ -85,7 +94,7 @@ to add verification that the `brand` of "amount" argument(s) corresponds with th These methods return an **[AssetKind](/reference/ertp-api/ertp-data-types#assetkind)**: - [anIssuer.getAssetKind()](/reference/ertp-api/issuer#anissuer-getassetkind) - - Returns the `AssetKind` of the `issuer`'s `brand`. (`AssetKind.NAT` or `AssetKind.SET`). + - Returns the `AssetKind` of the `issuer`'s `brand`. - <<< @/../snippets/ertp/guide/test-amount-math.js#getAssetKind2 - [zcf.getAssetKind(brand)](/reference/zoe-api/zoe-contract-facet#zcf-getassetkind-brand) - Returns the `AssetKind` of the `brand` argument. diff --git a/main/guides/ertp/amounts.md b/main/guides/ertp/amounts.md index 411849e92..0a7b0639d 100644 --- a/main/guides/ertp/amounts.md +++ b/main/guides/ertp/amounts.md @@ -65,10 +65,12 @@ API Reference](/reference/ertp-api/). - [aBrand.getAllegedName()](/reference/ertp-api/brand#abrand-getallegedname) - Returns the `brand`'s alleged name, but should not be trusted as accurate. - <<< @/../snippets/ertp/guide/test-amounts.js#getAllegedName -- [aBrand.getDisplayInfo()](/reference/ertp-api/brand#abrand-getdisplayinfo) +- [aBrand.getDisplayInfo()](/reference/ertp-api/brand#abrand-getdisplayinfo) **(deprecated: look up in `boardAux` instead)** - Returns the `DisplayInfo` associated with the `brand`. The `DisplayInfo` tells the UI how to correctly display `values` associated with the `brand`. - <<< @/../snippets/ertp/guide/test-amounts.js#getDisplayInfo +- [aBrand.getAmountShape()](/reference/ertp-api/brand#abrand-getamountshape) + - Returns the `AmountShape` for a `brand` associated with a non-fungible asset. The following methods on other ERTP components also either operate on or return a `brand`. diff --git a/main/guides/ertp/index.md b/main/guides/ertp/index.md index b53abf4a5..e373e13a0 100644 --- a/main/guides/ertp/index.md +++ b/main/guides/ertp/index.md @@ -137,6 +137,11 @@ Here it also creates a new `mint` and formal `brand` for the argument, and returns all three new objects. The `mint`, `issuer`, and `brand` are all in unchangeable one-to-one relationships with each other. +`makeIssuerKit()` makes an `issuer` that does not survive an upgrade of the +vat holding it. A contract, which must keep working across upgrades, instead +calls `prepareIssuerKit()` in durable storage (`baggage`); see +[Durable Issuers](/reference/ertp-api/durable-issuers). + In this case, you used the string 'quatloos' to name the `brand`. <<< @/../snippets/ertp/guide/test-readme.js#seven @@ -253,12 +258,15 @@ for one performance of _Hamilton_. As before, you use `makeIssuerKit()` to create a `mint` that can create Agoric Theatre ticket assets. The difference from when you created a fungible asset is that you have to use a second argument, -in this case `AssetKind.SET`. +in this case `AssetKind.COPY_SET`. -There are two `AssetKinds`. Each one polymorphically implements the same set of methods. +There are three live `AssetKinds`. Each one polymorphically implements the same set of methods. - `AssetKind.NAT`: Works with natural number `values` and fungible assets. Default value for `makeIssuerKit()`. -- `AssetKind.SET`: Used with non-fungible assets, operates on an array of records (objects) with keys and values. +- `AssetKind.COPY_SET`: Used with non-fungible assets where there can't be duplicates, such as these theater tickets. +- `AssetKind.COPY_BAG`: Used with semi-fungible assets where duplicates of the same element are fungible with each other. + +A fourth, `AssetKind.SET`, is deprecated; use `AssetKind.COPY_SET` instead. <<< @/../snippets/ertp/guide/test-readme.js#ticketPayments diff --git a/main/guides/ertp/issuers-and-mints.md b/main/guides/ertp/issuers-and-mints.md index 22d7cba6d..20d0a76de 100644 --- a/main/guides/ertp/issuers-and-mints.md +++ b/main/guides/ertp/issuers-and-mints.md @@ -18,8 +18,7 @@ the `issuer` in the one-to-one relationship with the Quatloos `brand` can: - Create a new empty `purse` that can store Quatloos. -- Manipulate a `payment` in Quatloos to be claimed, split, combined, - burned, or have its amount received. +- Manipulate a `payment` in Quatloos to be burned or have its amount received. An `issuer` should be obtained from a trusted source and then relied upon as the authority as to whether an untrusted `payment` @@ -40,8 +39,11 @@ more detail, click the method's name to go to its entry in the [ERTP API Reference](/reference/ertp-api/). - **Create issuer operation** - - [makeIssuerKit()](/reference/ertp-api/issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-elementshape) + - [makeIssuerKit()](/reference/ertp-api/issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-issueroptionsrecord) - Create and return a new `issuer` and its associated `mint` and `brand`. + This `issuer` does not survive an upgrade of the vat holding it; a + contract instead uses `prepareIssuerKit()`. See + [Durable Issuers](/reference/ertp-api/durable-issuers). - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#import <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#makeIssuerKit - **Get information about the issuer operations** @@ -49,7 +51,7 @@ API Reference](/reference/ertp-api/). - Return the `allegedName` for the `issuer` (the non-trusted human-readable name of its associated `brand`). - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#getAllegedName - [anIssuer.getAssetKind()](/reference/ertp-api/issuer#anissuer-getassetkind) - - Return the kind of the `issuer`'s asset; either `AssetKind.NAT` ("nat") or `AssetKind.SET` ("set"). + - Return the kind of the `issuer`'s asset, such as `AssetKind.NAT` ("nat") or `AssetKind.COPY_SET` ("copySet"). - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#getAssetKind - [anIssuer.getBrand()](/reference/ertp-api/issuer#anissuer-getbrand) - Return the `brand` for the `issuer`. @@ -65,16 +67,29 @@ API Reference](/reference/ertp-api/). - [anIssuer.getAmountOf(payment)](/reference/ertp-api/issuer#anissuer-getamountof-payment) - Describe the `payment`'s balance as an Amount. - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#getAmountOf - - [anIssuer.isLive(payment)](/reference/ertp-api/issuer#anissuer-islive-payment) - Return `true` if the `payment` was created by the issuer and is available for use (has not been consumed or burned). - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#isLive - ::: warning DEPRECATED - - [anIssuer.split(payment, paymentAmountA)](/reference/ertp-api/issuer#anissuer-split-payment-paymentamounta) - - Split a single `payment` into two new Payments. - - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#split - - [anIssuer.splitMany(payment, paymentAmountArray)](/reference/ertp-api/issuer#anissuer-splitmany-payment-amountarray) - - Split a single `payment` into multiple Payments. - - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#splitMany -- [anIssuer.claim(payment, optAmount)](/reference/ertp-api/issuer#anissuer-claim-payment-optamount) - Transfer all digital assets from `payment` to a new Payment. - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#claim - - [anIssuer.combine(paymentsArray)](/reference/ertp-api/issuer#anissuer-combine-paymentsarray-opttotalamount) - Combine multiple Payments into one new Payment. - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#combine + - [anIssuer.isLive(payment)](/reference/ertp-api/issuer#anissuer-islive-payment) + - Return `true` if the `payment` was created by the issuer and is available for use (has not been consumed or burned). + - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#isLive + +`claim`, `combine`, `split`, and `splitMany` are no longer `Issuer` methods. +They remain available as deprecated, standalone helper functions with a +different, `recoveryPurse`-first signature; see +[Legacy Payment Helpers](/reference/ertp-api/legacy-payment-helpers). + +::: warning DEPRECATED + +- [claim(recoveryPurse, srcPaymentP, optAmountShape?)](/reference/ertp-api/legacy-payment-helpers#claim-recoverypurse-srcpaymentp-optamountshape) + - Transfer all digital assets from `srcPaymentP` to a new Payment. + - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#claim +- [combine(recoveryPurse, srcPaymentsPs, optTotalAmount?)](/reference/ertp-api/legacy-payment-helpers#combine-recoverypurse-srcpaymentsps-opttotalamount) + - Combine multiple Payments into one new Payment. + - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#combine +- [split(recoveryPurse, srcPaymentP, paymentAmountA)](/reference/ertp-api/legacy-payment-helpers#split-recoverypurse-srcpaymentp-paymentamounta) + - Split a single `payment` into two new Payments. + - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#split +- [splitMany(recoveryPurse, srcPaymentP, amounts)](/reference/ertp-api/legacy-payment-helpers#splitmany-recoverypurse-srcpaymentp-amounts) + - Split a single `payment` into multiple Payments. + - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#splitMany ::: **Related Methods:** @@ -122,6 +137,6 @@ API Reference](/reference/ertp-api/index). - [aMint.mintPayment()](/reference/ertp-api/mint#amint-mintpayment-newamount) - Create new digital assets of the `mint`'s associated `brand`. - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#mintMintPayment -- [makeIssuerKit()](/reference/ertp-api/issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-elementshape) +- [makeIssuerKit()](/reference/ertp-api/issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-issueroptionsrecord) - Create and return a new `issuer` and its associated `mint` and `brand`. - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#makeIssuerKitMint diff --git a/main/guides/ertp/purses-and-payments.md b/main/guides/ertp/purses-and-payments.md index bcfa14c86..4bcaac613 100644 --- a/main/guides/ertp/purses-and-payments.md +++ b/main/guides/ertp/purses-and-payments.md @@ -33,9 +33,10 @@ whatever assets already exist there. So a 3 Quatloos deposit into a `purse` with 8 Quatloos results in a `purse` with 11 Quatloos. When adding a `payment` to a `purse`, you must add the entire `payment`. To -only add part of a `payment`, you must first call [anIssuer.split()](/reference/ertp-api/issuer#anissuer-split-payment-paymentamounta) -or [anIssuer.splitMany()](/reference/ertp-api/issuer#anissuer-splitmany-payment-amountarray) -to split it into two or more new `payments`. +only add part of a `payment`, you must first call the deprecated +[split()](/reference/ertp-api/legacy-payment-helpers#split-recoverypurse-srcpaymentp-paymentamounta) +or [splitMany()](/reference/ertp-api/legacy-payment-helpers#splitmany-recoverypurse-srcpaymentp-amounts) +helper to split it into two or more new `payments`. `mints` create entirely new digital assets and put them in a new `payment`. You also create a `payment` by withdrawing assets from a `purse`, by splitting an @@ -100,6 +101,16 @@ API Reference](/reference/ertp-api/). - Return a deposit-only facet on the `purse`. Note that the command to add a `payment`'s assets via a `DepositFacet` is not `deposit()` but `receive()` as shown here. - <<< @/../snippets/ertp/guide/test-purses-and-payments.js#getDepositFacet +- [aPurse.getCurrentAmountNotifier()](/reference/ertp-api/purse#apurse-getcurrentamountnotifier) + - Return a lossy notifier for changes to this `purse`'s balance. +- [aPurse.getRecoverySet()](/reference/ertp-api/purse#apurse-getrecoveryset) + - Return the set of `payments` withdrawn from this `purse` that are still live and can + still be recovered by depositing them back into the `purse`. Empty if the `purse`'s + `issuer` does not maintain recovery sets. +- [aPurse.recoverAll()](/reference/ertp-api/purse#apurse-recoverall) + - Deposit every `payment` in this `purse`'s recovery set back into the `purse`, returning + the total `amount` recovered. Used to recover from an emergency, such as a vat crash + and upgrade. In addition, the method to create a new, empty, `purse` is called on an `issuer`: @@ -178,17 +189,23 @@ API Reference](/reference/ertp-api/index). - [aPurse.withdraw(amount)](/reference/ertp-api/purse#apurse-withdraw-amount) - Withdraw the `amount` of specified digital assets from `purse` into a new `payment`. - <<< @/../snippets/ertp/guide/test-purses-and-payments.js#withdraw - ::: warning DEPRECATED -- [anIssuer.combine(paymentsArray)](/reference/ertp-api/issuer#anissuer-combine-paymentsarray-opttotalamount) + +`combine`, `claim`, `splitMany`, and `split` are no longer `Issuer` methods; they +remain available as deprecated, standalone helper functions. See +[Legacy Payment Helpers](/reference/ertp-api/legacy-payment-helpers). + +::: warning DEPRECATED + +- [combine(recoveryPurse, srcPaymentsPs, optTotalAmount?)](/reference/ertp-api/legacy-payment-helpers#combine-recoverypurse-srcpaymentsps-opttotalamount) - Combine multiple Payments into one new Payment. - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#combine -- [anIissuer.claim(payment, optAmount)](/reference/ertp-api/issuer#anissuer-claim-payment-optamount) - - Transfer all digital assets from `payment` to a new Payment. +- [claim(recoveryPurse, srcPaymentP, optAmountShape?)](/reference/ertp-api/legacy-payment-helpers#claim-recoverypurse-srcpaymentp-optamountshape) + - Transfer all digital assets from `srcPaymentP` to a new Payment. - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#claim -- [anIssuer.splitMany(payment, amountArray)](/reference/ertp-api/issuer#anissuer-splitmany-payment-amountarray) +- [splitMany(recoveryPurse, srcPaymentP, amounts)](/reference/ertp-api/legacy-payment-helpers#splitmany-recoverypurse-srcpaymentp-amounts) - Split a single `payment` into multiple Payments. - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#splitManyConcise -- [anIssuer.split(payment, paymentAmountA)](/reference/ertp-api/issuer#anissuer-split-payment-paymentamounta) +- [split(recoveryPurse, srcPaymentP, paymentAmountA)](/reference/ertp-api/legacy-payment-helpers#split-recoverypurse-srcpaymentp-paymentamounta) - Split a single `payment` into two new Payments. - <<< @/../snippets/ertp/guide/test-issuers-and-mints.js#split ::: diff --git a/main/reference/ertp-api/brand.md b/main/reference/ertp-api/brand.md index c3757799d..d9847c5f4 100644 --- a/main/reference/ertp-api/brand.md +++ b/main/reference/ertp-api/brand.md @@ -55,6 +55,10 @@ const name = brand.getAllegedName(); ## aBrand.getDisplayInfo() +::: warning DEPRECATED +Look up display info in `boardAux` instead. +::: + - Returns: **[DisplayInfo](./ertp-data-types#displayinfo)** Returns the **DisplayInfo** associated with the **Brand**. diff --git a/main/reference/ertp-api/durable-issuers.md b/main/reference/ertp-api/durable-issuers.md new file mode 100644 index 000000000..b9697ef8b --- /dev/null +++ b/main/reference/ertp-api/durable-issuers.md @@ -0,0 +1,98 @@ +# Durable Issuers + +**[makeIssuerKit()](./issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-issueroptionsrecord)** +makes an issuer kit that does not survive an upgrade of the vat that holds +it. Contracts, which must keep working across upgrades, instead build their +issuer kit in **[Baggage](/glossary/#baggage)** with +`prepareIssuerKit()` or `makeDurableIssuerKit()`. Both take the same +arguments as `makeIssuerKit()`, except with a **Baggage** prepended. + +## prepareIssuerKit(issuerBaggage, name, assetKind?, displayInfo?, optShutdownWithFailure?, issuerOptionsRecord?) + +- **issuerBaggage**: **Baggage** +- **name**: **String** +- **assetKind**: **[AssetKind](./ertp-data-types#assetkind)** - Optional, defaults to **AssetKind.NAT**. +- **displayInfo**: **[DisplayInfo](./ertp-data-types#displayinfo)** - Optional, defaults to `{}`. +- **optShutdownWithFailure** - Optional, defaults to **undefined**. +- **issuerOptionsRecord** - Optional, defaults to `{}`. Same shape as for + **[makeIssuerKit()](./issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-issueroptionsrecord)**. +- Returns **IssuerKit** + +Revives a predecessor incarnation's issuer kit from _issuerBaggage_ if one +is already there, otherwise makes a new durable one and stores it in +_issuerBaggage_ for the next incarnation to revive. This is the method +most contracts should call; it makes the initial-versus-upgrade decision +for you. + +```js +import { prepareIssuerKit } from '@agoric/ertp'; + +const { issuer, mint, brand } = prepareIssuerKit( + issuerBaggage, + 'quatloos', + AssetKind.NAT +); +``` + +## makeDurableIssuerKit(issuerBaggage, name, assetKind?, displayInfo?, optShutdownWithFailure?, issuerOptionsRecord?) + +- Same parameters and return value as `prepareIssuerKit()`. + +Makes a _new_ durable issuer kit; the initial incarnation only. Throws if +_issuerBaggage_ already holds an issuer kit. Most callers should use +`prepareIssuerKit()` instead, since it also handles the upgrade case. + +## upgradeIssuerKit(issuerBaggage, optShutdownWithFailure?, recoverySetsOption?) + +- **issuerBaggage**: **Baggage** +- **optShutdownWithFailure** - Optional, defaults to **undefined**. +- **recoverySetsOption**: **[RecoverySetsOption](#recoverysetsoption)** - Optional. Defaults to the predecessor's state. +- Returns **IssuerKit** + +Revives a predecessor incarnation's issuer kit from _issuerBaggage_. +Throws if _issuerBaggage_ doesn't already hold one. Most callers should use +`prepareIssuerKit()` instead. + +## elementShape + +The **issuerOptionsRecord**'s _elementShape_ property may only be set for +a non-fungible or semi-fungible **Issuer** (an **AssetKind** of +**COPY_SET** or **COPY_BAG**). When present, it is a **Pattern** that +every element of this **Issuer**'s amounts must satisfy. For example, the +Zoe **Invitation** issuer uses an _elementShape_ describing the shape of +an individual invitation's details, so that every element of an +invitation-amount's **[CopySet](/glossary/#copyset)** is guaranteed to +match that shape. + +```js +const ticketShape = harden({ + seat: M.number(), + show: M.string(), + start: M.string() +}); + +const { issuer, mint, brand } = prepareIssuerKit( + issuerBaggage, + 'AgoricTheaterTickets', + AssetKind.COPY_SET, + undefined, + undefined, + { elementShape: ticketShape } +); +``` + +## RecoverySetsOption + +- `'hasRecoverySets'` (the default) or `'noRecoverySets'` + +Controls whether an issuer maintains a **[recovery set](./purse#apurse-getrecoveryset)** +per **Purse**: the set of **Payments** withdrawn from that purse that are +still live, kept so they can be recovered in an emergency (for example, +after a vat crash and upgrade) via **[recoverAll()](./purse#apurse-recoverall)**. + +Issuers first became durable with recovery sets mandatory. They were later +made optional via this option, but there is currently no support for +converting an issuer from one state to the other on upgrade: absence of a +stored `RecoverySetsOption` is equivalent to `'hasRecoverySets'`, and +`upgradeIssuerKit()` defaults to the predecessor's state if +_recoverySetsOption_ isn't passed. diff --git a/main/reference/ertp-api/ertp-data-types.md b/main/reference/ertp-api/ertp-data-types.md index 7e1b53a14..24c742368 100644 --- a/main/reference/ertp-api/ertp-data-types.md +++ b/main/reference/ertp-api/ertp-data-types.md @@ -25,7 +25,7 @@ An **AmountShape** is a description of non-fungible digital assets. Similar to * and a **ValueShape**, which is an object containing however many properties are required to describe this non-fungible asset. Note that an asset's **ValueShape** is defined by the _elementShape_ parameter when the asset's **[Issuer](./issuer)** is created via the -**[makeIssuerKit()](./issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-elementshape)** function. +**[makeIssuerKit()](./issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-issueroptionsrecord)** function. ```js someAmountShape: { @@ -57,7 +57,7 @@ There are several kinds of Assets. Even though very different mathematical processes are performed, **[AmountMath](./amount-math)** methods work for all kinds of assets. -Use **[makeIssuerKit()](./issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-elementshape)** to specify which **AssetKind** +Use **[makeIssuerKit()](./issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-issueroptionsrecord)** to specify which **AssetKind** your contract uses. See the **[Issuer](./issuer)** documentation for details on how to use this method. ```js @@ -68,6 +68,10 @@ makeIssuerKit('kitties', AssetKind.COPY_SET); // Defaults to undefined DisplayIn ## DisplayInfo +::: warning DEPRECATED +Look up display info in `boardAux` instead of `aBrand.getDisplayInfo()`. +::: + A **DisplayInfo** data type is associated with a **[Brand](./brand)** and gives information about how to display that **Brand**'s **[Amounts](#amount)**. **DisplayInfo** has one optional property, **decimalPlaces**, which takes a non-negative integer value. diff --git a/main/reference/ertp-api/index.md b/main/reference/ertp-api/index.md index 5df43c194..996604bce 100644 --- a/main/reference/ertp-api/index.md +++ b/main/reference/ertp-api/index.md @@ -10,11 +10,13 @@ The ERTP API supports the following objects: | [Purse](./purse) | Holds digital assets. | | [Payment](./payment) | Holds digital assets that are in transit. | -The ETRP API uses the following library: +The ERTP API uses the following library: -| Object | Description | -| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| [AmountMath](./amount-math) | The **AmountMath** object has several methods which can be used to manipulate and analyze **[Amounts](./ertp-data-types#amount)**. | +| Object | Description | +| -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| [AmountMath](./amount-math) | The **AmountMath** object has several methods which can be used to manipulate and analyze **[Amounts](./ertp-data-types#amount)**. | +| [Durable Issuers](./durable-issuers) | How contracts create an **Issuer** that survives vat upgrade. | +| [Legacy Payment Helpers](./legacy-payment-helpers) | Deprecated standalone replacements for the removed `Issuer` methods `claim`, `combine`, `split`, and `splitMany`. | The ERTP API introduces and uses the following data types: diff --git a/main/reference/ertp-api/issuer.md b/main/reference/ertp-api/issuer.md index 09c7de706..b0e10e7a6 100644 --- a/main/reference/ertp-api/issuer.md +++ b/main/reference/ertp-api/issuer.md @@ -3,8 +3,7 @@ An **Issuer** is the authority on what holds digital assets of its kind. While it cannot create new value by creating digital assets like a **[Mint](./mint)** can, it recognizes and identifies **[Purses](./purse)** and **[Payments](./payment)** that carry actual value. -It can create empty **Purses** and transform **Payments** (by splitting, -combining, burning, or exclusively claiming them). +It can create empty **Purses** and burn **Payments**. An **Issuer** has an unchangeable one-to-one relationship with the **Mint** and **[Brand](./brand)** that were created with it. For any **Brands** for which you will accept @@ -15,21 +14,31 @@ validate an untrusted **Payment** of that **Brand**. **Note**: You should not create an **Issuer** in a deploy script. Deploy scripts are ephemeral, so any object created there dies as soon as the script ends. -## makeIssuerKit(allegedName, assetKind?, displayInfo?, optShutdownWithFailure?, elementShape?) +## makeIssuerKit(allegedName, assetKind?, displayInfo?, optShutdownWithFailure?, issuerOptionsRecord?) - **allegedName**: **String** - **assetKind**: **[AssetKind](./ertp-data-types#assetkind)** - Optional, defaults to **AssetKind.NAT**. - **displayInfo**: **[DisplayInfo](./ertp-data-types#displayinfo)** - Optional, defaults to **undefined**. - **optShutdownWithFailure** - Optional, defaults to **undefined**. -- **elementShape** - Optional, defaults to **undefined**. -- Returns **IssuerKit**. This is an object with three properties: +- **issuerOptionsRecord** - Optional, defaults to `{}`. An object that may carry: + - **elementShape**: **Pattern** - Optional, defaults to **undefined**. + - **recoverySetsOption**: **[RecoverySetsOption](./durable-issuers#recoverysetsoption)** - Optional, defaults to **undefined**. +- Returns **IssuerKit**. This is an object with five properties: - **issuer**: **Issuer** - **mint**: **[Mint](./mint)** - **brand**: **[Brand](./brand)** + - **mintRecoveryPurse**: **[Purse](./purse)** + - **displayInfo**: **[DisplayInfo](./ertp-data-types#displayinfo)** Creates and returns a new **Issuer** and its associated **Mint** and **Brand**. All three are in unchangeable one-to-one relationships with each other. +`makeIssuerKit()` makes an issuer kit that is not durable; it does not +survive an upgrade of the vat that holds it. Contracts, which must +survive upgrade, instead use `prepareIssuerKit()` or `makeDurableIssuerKit()`, +which take a **Baggage** as their first argument and are otherwise +parameterized the same way. See **[Durable Issuers](./durable-issuers)**. + The _allegedName_ becomes part of the **Brand** in asset descriptions. It doesn't have to be a **String**, but it will only be used for its value. It is useful for debugging and double-checking assumptions, but should not be trusted. @@ -47,10 +56,13 @@ The optional _optShutdownWithFailure_ parameter should be used for mission-criti **Issuers**. This parameter is a function that will stop the vat hosting the **Issuer** if **Issuer** invariants are violated. -The optional _elementShape_ parameter is only used when creating an **Issuer** that -has a non-fungible asset associated with it. When used, the _elementShape_ parameter is an object -with however many properties are required to describe the asset. This object sets the -_valueShape's_ properties of the asset's **[AmountShape](./ertp-data-types#amountshape)**. +The optional _issuerOptionsRecord_ parameter's _elementShape_ property is only used +when creating an **Issuer** for a non-fungible or semi-fungible asset (an **AssetKind** +of **COPY_SET** or **COPY_BAG**). When present, it is a **Pattern** that every element +of this **Issuer**'s amounts must satisfy; for example, the Zoe **Invitation** issuer +uses an _elementShape_ describing the shape of an individual invitation's details. Its +_recoverySetsOption_ property controls whether the issuer maintains recovery sets; see +**[Durable Issuers](./durable-issuers)**. ```js import { AssetKind, makeIssuerKit } from '@agoric/ertp'; @@ -59,6 +71,9 @@ makeIssuerKit('title', AssetKind.COPY_SET); ``` ```js +import { AssetKind, AmountMath, makeIssuerKit } from '@agoric/ertp'; +import { makeCopySet } from '@endo/patterns'; + const { issuer: quatloosIssuer, mint: quatloosMint, @@ -71,14 +86,14 @@ const { issuer: titleIssuer, mint: titleMint, brand: titleBrand -} = makeIssuerKit('propertyTitle'); +} = makeIssuerKit('propertyTitle', AssetKind.COPY_SET); // These are merely amounts describing digital assets, not minting assets. -const cornerProperty = AmountMath.make(propertyTitleBrand, ['1292826']); -const adjacentProperty = AmountMath.make(propertyTitleBrand, ['1028393']); -const combinedProperty = AmountMath.make(propertyTitleBrand, [ - '1292826', - '1028393' -]); +const cornerProperty = AmountMath.make(titleBrand, makeCopySet(['1292826'])); +const adjacentProperty = AmountMath.make(titleBrand, makeCopySet(['1028393'])); +const combinedProperty = AmountMath.make( + titleBrand, + makeCopySet(['1292826', '1028393']) +); ``` ## anIssuer.getAllegedName() @@ -118,7 +133,7 @@ The **AssetKind** specifies what kind of values are used in **[Amounts](./ertp-d const { issuer: quatloosIssuer } = makeIssuerKit('quatloos'); quatloosIssuer.getAssetKind(); // Returns 'nat', also known as AssetKind.NAT, the default value. const { issuer: moolaIssuer } = makeIssuerKit('moola', AssetKind.COPY_SET); -moolaIssuer.getAssetKind(); // Returns 'copy_set', also known as 'AssetKind.COPY_SET' +moolaIssuer.getAssetKind(); // Returns 'copySet', also known as AssetKind.COPY_SET ``` ## anIssuer.getAmountOf(payment) @@ -210,139 +225,9 @@ Returns **true** if the _payment_ was created by the **Issuer** and is available If _payment_ is a promise, the method proceeds after it resolves to a **Payment**. -::: warning DEPRECATED - -## anIssuer.claim(payment, optAmount?) - -- **payment**: **[Payment](./payment)** -- **optAmount**: **[Amount](./ertp-data-types#amount)** - Optional. -- Returns: **Payment** - -Transfers all digital assets from _payment_ to a new **Payment** and consumes the -original **Payment**, making it unavailable for later use. - -If the _optAmount_ argument is passed into the method, _payment_'s balance must be -equal to _optAmount_, to prevent claiming the wrong **Payment**. -If _optAmount_ does not equal the balance in the original **Payment** an error is thrown, -and the original **Payment** is unmodified. - -If _payment_ is a promise, the operation proceeds after it resolves to a **Payment**. - -```js -const { - issuer: quatloosIssuer, - mint: quatloosMint, - brand: quatloosBrand -} = makeIssuerKit('quatloos'); -const amountExpectedToTransfer = AmountMath.make(quatloosBrand, 2n); -const originalPayment = quatloosMint.mintPayment(amountExpectedToTransfer); - -const newPayment = quatloosIssuer.claim(originalPayment, amountToTransfer); -``` - -## anIssuer.combine(paymentsArray, optTotalAmount?) - -- **paymentsArray**: **Array<[Payment](./payment)>** -- **optTotalAmount**: **[Amount](./ertp-data-types#amount)** - Optional. -- Returns: **Payment** - -Combines multiple **Payments** into one new **Payment**. If any item in _paymentsArray_ is -a promise, the operation proceeds after each such promise resolves to a **Payment**. -All **Payments** in _paymentsArray_ are consumed and made unavailable for later use. - -If the _optTotalAmount_ argument is passed into the method, -the total value of all **Payments** in _paymentsArray_ -must equal _optTotalAmount_. If they don't, the method throws an error, -and the original **Payment** is unmodified. - -Each **Payment** in _paymentsArray_ must be associated with the same **[Brand](./brand)** as the **Issuer**. - -```js -const { - issuer: quatloosIssuer, - mint: quatloosMint, - brand: quatloosBrand -} = makeIssuerKit('quatloos'); -// Create an array of 100 payments of 1 quatloo each -const payments = []; -for (let i = 0; i < 100; i += 1) { - payments.push(quatloosMint.mintPayment(AmountMath.make(quatloosBrand, 1n))); -} - -// combinedPayment equals 100 -const combinedPayment = quatloosIssuer.combine(payments); -``` - -## anIssuer.split(payment, paymentAmountA) - -- **payment**: **[Payment](./payment)** -- **paymentAmountA**: **[Amount](./ertp-data-types#amount)** -- Returns: **Array<Payment>** - -Splits a single **Payment** into two new **Payments**, A and B, according to _paymentAmountA_. -For example, if the **Payment** is for 10 _Quatloos_, and _paymentAmountA_ is 3 _Quatloos_, -the method returns an array of two **Payments** with balances of 3 _Quatloos_ and 7 _Quatloos_. - -The original **Payment** is consumed and made unavailable for later use. - -If _payment_ is a promise, the operation proceeds after it resolves to a **Payment**. - -_payment_ and _paymentAmountA_ must both be associated with the same **[Brand](./brand)** as the **Issuer**. - -```js -const { - issuer: quatloosIssuer, - mint: quatloosMint, - brand: quatloosBrand -} = makeIssuerKit('quatloos'); -const oldPayment = quatloosMint.mintPayment( - AmountMath.make(quatloosBrand, 20n) -); -// After the split, paymentA has 5 quatloos and paymentB has 15. -const [paymentA, paymentB] = quatloosIssuer.split( - oldPayment, - AmountMath.make(quatloosBrand, 5n) -); -``` - -## anIssuer.splitMany(payment, amountArray) - -- **payment**: **[Payment](./payment)** -- **amountArray**: **Array<[Amount](./ertp-data-types#amount)>** -- Returns: **Array<Payment>** - -Splits a single **Payment** into multiple **Payments**. -The returned array includes a **Payment** item corresponding to each **Amount** in the _amountArray_ parameter, in order. - -The original **Payment** is consumed and made unavailable for later use. - -If _payment_ is a promise, the operation proceeds after it resolves to a **Payment**. - -If the **Amounts** in _amountArray_ don't add up to the value of _payment_, the operation fails. -_payment_ and each **Amount** in _amountArray_ must be associated with the same **[Brand](./brand)** as **Issuer**. - -```js -const { - issuer: quatloosIssuer, - mint: quatloosMint, - brand: quatloosBrand -} = makeIssuerKit('quatloos'); -const oldPayment = quatloosMint.mintPayment( - AmountMath.make(quatloosBrand, 100n) -); -const goodAmounts = Array(10).fill(AmountMath.make(quatloosBrand, 10n)); - -const arrayOfNewPayments = quatloosIssuer.splitMany(oldPayment, goodAmounts); - -// The total amount in the amountArray must equal the original payment amount -// Set original amount to 1000n -const payment = quatloosMint.mintPayment(AmountMath.make(quatloosBrand, 1000n)); - -// Total amounts in badAmounts equal 20n, when it should equal 1000n -const badAmounts = Array(2).fill(AmountMath.make(quatloosBrand, 10n)); - -// 20n does not equal 1000n, so throws error -quatloosIssuer.splitMany(payment, badAmounts); -``` +## Removed methods -::: +`claim`, `combine`, `split`, and `splitMany` are no longer **Issuer** +methods. They live on as standalone, deprecated helper functions with a +different, `recoveryPurse`-first signature; see +**[Legacy Payment Helpers](./legacy-payment-helpers)**. diff --git a/main/reference/ertp-api/legacy-payment-helpers.md b/main/reference/ertp-api/legacy-payment-helpers.md new file mode 100644 index 000000000..a6ba7f892 --- /dev/null +++ b/main/reference/ertp-api/legacy-payment-helpers.md @@ -0,0 +1,104 @@ +# Legacy Payment Helpers + +::: warning DEPRECATED +`claim`, `combine`, `split`, and `splitMany` are deprecated. They are no +longer methods on **[Issuer](./issuer)**. They remain available as +standalone functions exported from +`@agoric/ertp/src/legacy-payment-helpers.js` (not re-exported from the +package's main entry point), each parameterized by a **recoveryPurse** +used to recover a **Payment** if the helper fails partway through. +::: + +Each helper first deposits its input **Payment**(s) into the _recoveryPurse_ +argument before withdrawing the result. If a helper fails after depositing +but before it can withdraw and return the result, no assets are lost: they +remain in _recoveryPurse_, and can also be recovered from that purse's +**[recovery set](./purse#apurse-getrecoveryset)** if the purse is itself +lost track of. + +`combine` is not failure-atomic in one respect: if it fails partway +through, some of the input **Payments** may already have been consumed. +Even then, no assets are lost; they end up in _recoveryPurse_. + +```js +import { + claim, + combine, + split, + splitMany +} from '@agoric/ertp/src/legacy-payment-helpers.js'; +``` + +## claim(recoveryPurse, srcPaymentP, optAmountShape?) + +- **recoveryPurse**: **[Purse](./purse)** +- **srcPaymentP**: **ERef<[Payment](./payment)>** +- **optAmountShape**: **Pattern** - Optional. +- Returns: **Promise<Payment>** + +Transfers all digital assets from _srcPaymentP_ to a new **Payment**, +consuming the original. If the _optAmountShape_ argument is passed, the +source **Payment**'s amount must match it, or the deposit throws and no +**Payment** is withdrawn. + +```js +const newPayment = await claim( + recoveryPurse, + originalPayment, + amountToTransfer +); +``` + +## combine(recoveryPurse, srcPaymentsPs, optTotalAmount?) + +- **recoveryPurse**: **[Purse](./purse)** +- **srcPaymentsPs**: **Array<ERef<[Payment](./payment)>>** +- **optTotalAmount**: **Pattern** - Optional. +- Returns: **Promise<Payment>** + +Combines multiple **Payments** into one new **Payment**, depositing each +into _recoveryPurse_ as its promise resolves. If _optTotalAmount_ is +passed, the combined total must match it before the result is withdrawn. + +```js +const combinedPayment = await combine(recoveryPurse, harden(payments)); +``` + +## split(recoveryPurse, srcPaymentP, paymentAmountA) + +- **recoveryPurse**: **[Purse](./purse)** +- **srcPaymentP**: **ERef<[Payment](./payment)>** +- **paymentAmountA**: **[Amount](./ertp-data-types#amount)** +- Returns: **Promise<Payment[]>** + +Splits a single **Payment** into two new **Payments**, A and B, according +to _paymentAmountA_, after depositing the source **Payment** into +_recoveryPurse_. + +```js +const [paymentA, paymentB] = await split( + recoveryPurse, + oldPayment, + AmountMath.make(quatloosBrand, 10n) +); +``` + +## splitMany(recoveryPurse, srcPaymentP, amounts) + +- **recoveryPurse**: **[Purse](./purse)** +- **srcPaymentP**: **ERef<[Payment](./payment)>** +- **amounts**: **Array<[Amount](./ertp-data-types#amount)>** +- Returns: **Promise<Payment[]>** + +Splits a single **Payment** into multiple **Payments**, one per entry in +_amounts_, after depositing the source **Payment** into _recoveryPurse_. If +_amounts_ doesn't add up to the source **Payment**'s amount, the operation +throws once the source has already been deposited into _recoveryPurse_. + +```js +const arrayOfNewPayments = await splitMany( + recoveryPurse, + oldPayment, + harden(goodAmounts) +); +``` diff --git a/main/reference/ertp-api/mint.md b/main/reference/ertp-api/mint.md index b15dfdd59..6659dd7fe 100644 --- a/main/reference/ertp-api/mint.md +++ b/main/reference/ertp-api/mint.md @@ -6,7 +6,7 @@ A **Mint** has a one-to-one relationship with both an **[Issuer](./issuer)** and So it can only mint new assets of that **Brand** and is the only **Mint** that can mint new assets of that **Brand**. -**Mints** are created by calling the **[makeIssuerKit()](./issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-elementshape)** function. See the **[Issuer](./issuer)** documentation for detailed information about how to use this function. +**Mints** are created by calling the **[makeIssuerKit()](./issuer#makeissuerkit-allegedname-assetkind-displayinfo-optshutdownwithfailure-issueroptionsrecord)** function. See the **[Issuer](./issuer)** documentation for detailed information about how to use this function. ## aMint.getIssuer() @@ -40,7 +40,7 @@ const { brand: quatloosBrand } = makeIssuerKit('quatloos'); -const quatloos1000 = amountMath.make(quatloosBrand, 1000n); +const quatloos1000 = AmountMath.make(quatloosBrand, 1000n); // newPayment will have a balance of 1000 Quatloos const newPayment = quatloosMint.mintPayment(quatloos1000); ``` diff --git a/main/reference/ertp-api/payment.md b/main/reference/ertp-api/payment.md index bc63f5544..dcb60b254 100644 --- a/main/reference/ertp-api/payment.md +++ b/main/reference/ertp-api/payment.md @@ -18,8 +18,8 @@ take out, say, only 3 _Quatloos_ from it. However, you can split a **Payment** into multiple **Payments**. For example, you could split a 10 _Quatloos_ **Payment** into two new **Payments** of 3 _Quatloos_ and 7 _Quatloos_ by calling the -**[anIssuer.split()](./issuer#anissuer-split-payment-paymentamounta)** method which consumes the -original 10 _Quatloos_ **Payment** and creates two new smaller **Payments**. +deprecated **[split()](./legacy-payment-helpers#split-recoverypurse-srcpaymentp-paymentamounta)** +helper, which consumes the original 10 _Quatloos_ **Payment** and creates two new smaller **Payments**. **Payments** are often received from other actors. Since they are not self-verifying, you cannot trust **Payments**. To get the verified balance of a **Payment**, call the **[anIssuer.getAmountOf()](./issuer#anissuer-getamountof-payment)** method. @@ -67,13 +67,16 @@ on or return a **Payment**. - Creates and returns a new deposit-only facet of the **Purse** that allows arbitrary other parties to deposit **Payments** into the **Purse**. - [**aPurse.withdraw()**](./purse#apurse-withdraw-amount) - Withdraws the _amount_ of specified digital assets from **Purse** into a new **Payment**. - ::: warning DEPRECATED -- [**anIssuer.split()**](./issuer#anissuer-split-payment-paymentamounta) + +::: warning DEPRECATED +The following standalone helpers, no longer **Issuer** methods, also operate on **Payments**. See [Legacy Payment Helpers](./legacy-payment-helpers). + +- [**split()**](./legacy-payment-helpers#split-recoverypurse-srcpaymentp-paymentamounta) - Splits a single **Payment** into two new **Payments**. -- [**anIssuer.splitMany()**](./issuer#anissuer-splitmany-payment-amountarray) +- [**splitMany()**](./legacy-payment-helpers#splitmany-recoverypurse-srcpaymentp-amounts) - Split a single **Payment** into multiple **Payments**. -- [**anIssuer.claim()**](./issuer#anissuer-claim-payment-optamount) - - Transfers all digital assets from _payment_ to a new **Payment**. -- [**anIssuer.combine()**](./issuer#anissuer-combine-paymentsarray-opttotalamount) +- [**claim()**](./legacy-payment-helpers#claim-recoverypurse-srcpaymentp-optamountshape) + - Transfers all digital assets from _srcPaymentP_ to a new **Payment**. +- [**combine()**](./legacy-payment-helpers#combine-recoverypurse-srcpaymentsps-opttotalamount) - Combines multiple **Payments** into one new **Payment**. ::: diff --git a/main/reference/ertp-api/purse.md b/main/reference/ertp-api/purse.md index 7a31c8492..ea39ba888 100644 --- a/main/reference/ertp-api/purse.md +++ b/main/reference/ertp-api/purse.md @@ -139,6 +139,45 @@ issuer.getAmountOf(withdrawalPayment); purse.getCurrentAmount(); ``` +## aPurse.getRecoverySet() + +- Returns: **CopySet<[Payment](./payment)>** + +Returns the set of **Payments** withdrawn from this **Purse** that are +still live: the **Payments** that can still be recovered in an emergency +by, for example, depositing them back into this **Purse**. It's like +canceling an outstanding check because you're tired of waiting for it; +once the cancellation is acknowledged, you can spend the assets at stake +on other things. If the recipient of the original check later tries to +deposit it, their deposit fails. + +Returns an empty **CopySet** if this **Purse**'s **[Issuer](./issuer)** +does not maintain recovery sets; see +**[RecoverySetsOption](./durable-issuers#recoverysetsoption)**. + +```js +const recoverySet = quatloosPurse.getRecoverySet(); +``` + +## aPurse.recoverAll() + +- Returns: **[Amount](./ertp-data-types#amount)** + +For use in emergencies, such as recovering from a crash and upgrade of the +vat holding this **Purse**. Deposits every **Payment** in this **Purse**'s +recovery set back into the **Purse** itself, and returns the total +**Amount** of assets recovered. + +Returns an empty **Amount** if this **Purse**'s **[Issuer](./issuer)** +does not maintain recovery sets; see +**[RecoverySetsOption](./durable-issuers#recoverysetsoption)**. + +```js +// Deposit every outstanding payment from quatloosPurse's recovery set +// back into quatloosPurse. +const recoveredAmount = quatloosPurse.recoverAll(); +``` + ## aPurse.getAllegedBrand() - Returns: **[Brand](./brand)** diff --git a/snippets/ertp/guide/test-amount-math.js b/snippets/ertp/guide/test-amount-math.js index 9ed0fa9b8..450669286 100644 --- a/snippets/ertp/guide/test-amount-math.js +++ b/snippets/ertp/guide/test-amount-math.js @@ -2,6 +2,7 @@ import { test } from '../../prepare-test-env-ava.js'; import { AmountMath, makeIssuerKit, AssetKind } from '@agoric/ertp'; +import { makeCopySet } from '@endo/patterns'; import { setupZCFTest } from '../../tools/setupZcfTest.js'; @@ -93,6 +94,30 @@ test('ertp guide AmountMath methods isEqual', async t => { t.falsy(AmountMath.isEqual(empty, quatloos1)); }); +test('ertp guide AmountMath methods min', async t => { + // #region min + const { brand: quatloosBrand } = makeIssuerKit('quatloos'); + const quatloos5 = AmountMath.make(quatloosBrand, 5n); + const quatloos10 = AmountMath.make(quatloosBrand, 10n); + + // Returns an amount equivalent to quatloos5 + const smaller = AmountMath.min(quatloos5, quatloos10); + // #endregion min + t.deepEqual(smaller, quatloos5); +}); + +test('ertp guide AmountMath methods max', async t => { + // #region max + const { brand: quatloosBrand } = makeIssuerKit('quatloos'); + const quatloos5 = AmountMath.make(quatloosBrand, 5n); + const quatloos10 = AmountMath.make(quatloosBrand, 10n); + + // Returns an amount equivalent to quatloos10 + const larger = AmountMath.max(quatloos5, quatloos10); + // #endregion max + t.deepEqual(larger, quatloos10); +}); + test('ertp guide AmountMath methods coerce', async t => { // #region coerce const { brand: quatloosBrand } = makeIssuerKit('quatloos'); @@ -104,25 +129,33 @@ test('ertp guide AmountMath methods coerce', async t => { test('ertp guide AmountMath methods add', async t => { // #region add - const { brand: myItemsBrand } = makeIssuerKit('myItems', 'set'); - const listAmountA = AmountMath.make(myItemsBrand, harden(['1', '2', '4'])); - const listAmountB = AmountMath.make(myItemsBrand, harden(['3'])); + const { brand: myItemsBrand } = makeIssuerKit('myItems', AssetKind.COPY_SET); + const listAmountA = AmountMath.make( + myItemsBrand, + makeCopySet(['1', '2', '4']), + ); + const listAmountB = AmountMath.make(myItemsBrand, makeCopySet(['3'])); // Returns an amount containing all of ['1', '2', '4', '3'] const combinedList = AmountMath.add(listAmountA, listAmountB); // #endregion add - t.deepEqual( - combinedList, - AmountMath.make(myItemsBrand, harden(['1', '2', '4', '3'])), + t.true( + AmountMath.isEqual( + combinedList, + AmountMath.make(myItemsBrand, makeCopySet(['1', '2', '4', '3'])), + ), ); }); test('ertp guide AmountMath methods subtract', async t => { // #region subtract - const { brand: myItemsBrand } = makeIssuerKit('myItems', 'set'); - const listAmountA = AmountMath.make(myItemsBrand, harden(['1', '2', '4'])); - const listAmountB = AmountMath.make(myItemsBrand, harden(['3'])); - const listAmountC = AmountMath.make(myItemsBrand, harden(['2'])); + const { brand: myItemsBrand } = makeIssuerKit('myItems', AssetKind.COPY_SET); + const listAmountA = AmountMath.make( + myItemsBrand, + makeCopySet(['1', '2', '4']), + ); + const listAmountB = AmountMath.make(myItemsBrand, makeCopySet(['3'])); + const listAmountC = AmountMath.make(myItemsBrand, makeCopySet(['2'])); // Returns ['1', '4'] const subtractedList = AmountMath.subtract(listAmountA, listAmountC); // Throws error @@ -130,9 +163,11 @@ test('ertp guide AmountMath methods subtract', async t => { message: /right element .* was not in left/, }); // #endregion subtract - t.deepEqual( - subtractedList, - AmountMath.make(myItemsBrand, harden(['1', '4'])), + t.true( + AmountMath.isEqual( + subtractedList, + AmountMath.make(myItemsBrand, makeCopySet(['1', '4'])), + ), ); }); diff --git a/snippets/ertp/guide/test-issuers-and-mints.js b/snippets/ertp/guide/test-issuers-and-mints.js index c5b1535c5..19529a83c 100644 --- a/snippets/ertp/guide/test-issuers-and-mints.js +++ b/snippets/ertp/guide/test-issuers-and-mints.js @@ -23,10 +23,10 @@ test('ertp guide issuers and mints makeIssuerKit', async t => { // It does not create new assets. const quatloos2 = AmountMath.make(quatloosBrand, 2n); // Non-fungible asset, which needs an AssetKind - // of AssetKind.SET + // of AssetKind.COPY_SET const { mint: titleMint, issuer: titleIssuer } = makeIssuerKit( 'alamedaCountyPropertyTitle', - AssetKind.SET, + AssetKind.COPY_SET, ); // #endregion makeIssuerKit diff --git a/snippets/ertp/guide/test-readme.js b/snippets/ertp/guide/test-readme.js index ae68e04b1..979dcaffa 100644 --- a/snippets/ertp/guide/test-readme.js +++ b/snippets/ertp/guide/test-readme.js @@ -9,6 +9,7 @@ import { E } from '@endo/eventual-send'; import { makeFakeBoard } from '@agoric/vats/tools/board-utils.js'; import { AmountMath, makeIssuerKit, AssetKind } from '@agoric/ertp'; +import { makeCopySet } from '@endo/patterns'; test('ertp guide readme', async t => { // #region makeIssuerKit @@ -78,12 +79,12 @@ test('ertp guide readme', async t => { // #region makeTicketIssuer const { mint: agoricTheatreTicketMint, brand: agoricTheatreTicketBrand } = - makeIssuerKit('Agoric Theater tickets', AssetKind.SET); + makeIssuerKit('Agoric Theater tickets', AssetKind.COPY_SET); // #endregion makeTicketIssuer // #region ticketPayments const ticketAmounts = ticketValues.map(ticketValue => - AmountMath.make(agoricTheatreTicketBrand, harden([ticketValue])), + AmountMath.make(agoricTheatreTicketBrand, makeCopySet([ticketValue])), ); const agoricTheatreTicketPayments = ticketAmounts.map(ticketAmount => agoricTheatreTicketMint.mintPayment(ticketAmount), From 0550d3c73290a827a7dbe5a9d3981180627fd70c Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Thu, 24 Sep 2026 20:25:50 +0000 Subject: [PATCH 06/21] docs: refresh cosmos-sdk version, CometBFT naming, and vstorage/e2e content - chain-integration.md: cosmos-sdk v0.45 -> v0.53, refresh docs.cosmos.network links to the current sdk/v0.53 structure and a live API endpoint - platform/index.md: rename Tendermint section to CometBFT, drop single-testnet framing, note vat upgrade and Orchestration/dIBC as shipped today - name-services.md: add the uiConfig agoricNames key - what-is-agoric.md: name the shipped Orchestration API and Fast USDC - index.md: X (Twitter) card text/link - e2e-testing.md: add a synthetic-chain/a3p-integration on-chain e2e section alongside the existing synpress coverage - vstorage-ref.md: fully regenerate the published.* dumps against a live chain snapshot (adds fastUsdc, ymax0/ymax1, dATOM/stOSMO/stTIA/stkATOM, drops the 2023 agoric-upgrade-13 pin), mark it illustrative-not-authoritative - reference/repl/{scratch,timerServices,networking}.md: apply the same deprecation framing as repl/index.md, re-sync networking.md with the current packages/network README (PortAllocator, encodeIbcEndpoint) --- main/e2e-testing.md | 117 ++++-- main/guides/integration/chain-integration.md | 22 +- main/guides/integration/name-services.md | 1 + main/guides/platform/index.md | 43 +- main/index.md | 4 +- main/reference/repl/networking.md | 40 +- main/reference/repl/scratch.md | 11 + main/reference/repl/timerServices.md | 9 + main/reference/vstorage-ref.md | 417 +++++++++++++------ main/what-is-agoric.md | 7 + 10 files changed, 480 insertions(+), 191 deletions(-) diff --git a/main/e2e-testing.md b/main/e2e-testing.md index a42a094d8..9e7faed05 100644 --- a/main/e2e-testing.md +++ b/main/e2e-testing.md @@ -4,13 +4,24 @@ sidebar: auto # Testing +This page covers two different kinds of end-to-end testing on Agoric: +browser-driven DApp testing with Keplr, and on-chain testing of the chain +software itself (upgrades and core-eval proposals). If you're testing a +frontend that talks to a wallet, start with +[Testing DApps with `@agoric/synpress`](#testing-dapps-with-agoric-synpress) +below. If you're testing chain software, a governance proposal, or a +contract's on-chain behavior across a chain upgrade, see +[Testing chain software with `@agoric/synthetic-chain`](#testing-chain-software-with-agoric-synthetic-chain). + +## Testing DApps with `@agoric/synpress` + Developing Decentralized Applications (DApps) on the Cosmos network often involves integrating with the Keplr wallet. Testing is key for ensuring users can flawlessly interact with your DApp through the Keplr wallet. -[`@agoric/synpress`](https://github.com/agoric-labs/synpress) is an end-to-end (e2e) testing framework that simplifies the testing process for Keplr-based DApps. This framework automates testing how your DApp interacts with the Keplr wallet, simulating real user experiences. `@agoric/synpress` is built upon [`synthetixio/synpress`](https://github.com/Synthetixio/synpress), a framework designed for Metamask-based DApps. +[`@agoric/synpress`](https://github.com/agoric-labs/synpress) is an end-to-end (e2e) testing framework that simplifies the testing process for Keplr-based DApps. This framework automates testing how your DApp interacts with the Keplr wallet, simulating real user experiences. `@agoric/synpress` is a long-lived fork of [`synthetixio/synpress`](https://github.com/Synthetixio/synpress) predating that project's move to a Playwright-only architecture; `@agoric/synpress` still uses the original Cypress-based API described below. Since `@agoric/synpress` is based on [Cypress](https://www.cypress.io/), the official [Cypress documentation](https://docs.cypress.io/guides/overview/why-cypress) has a lot of information that you can use with `@agoric/synpress`. -## Installation +### Installation Before you start testing your DApp with Keplr, you'll need to install the `@agoric/synpress` in your project using the following command: @@ -18,7 +29,7 @@ Before you start testing your DApp with Keplr, you'll need to install the `@agor yarn add -D @agoric/synpress ``` -## Project structure +### Project structure We recommend the following project structure for keeping your e2e tests clean and manageable: @@ -33,7 +44,7 @@ project_dir └── test.spec.js ``` -## Configure `synpress.config.js` +### Configure `synpress.config.js` Before you start writing your E2E tests, you'll need to create a configuration file named `synpress.config.js` in the `tests/e2e` directory of your project. @@ -62,7 +73,7 @@ Since you have a separate `synpress.config.js` in the `tests/e2e` folder, you ne EXTENSION=keplr synpress run --configFile=tests/e2e/synpress.config.js ``` -## Creating a Support File +### Creating a Support File Navigate to your project's `tests/e2e` directory and create a new file named `support.js`. This file can be used to create reusable commands that encapsulate common testing actions. For example, you can create a custom command to navigate to a specific page within your application. You can read more about it [over here](https://docs.cypress.io/api/cypress-api/custom-commands). @@ -74,11 +85,11 @@ import '@agoric/synpress/support/index'; This import is essential because it brings in the necessary functionalities from `@agoric/synpress` to interact with the Keplr wallet within your e2e tests. Without it, your tests won't be able to leverage the features provided by `@agoric/synpress` for Keplr integration. -## Example Tests +### Example Tests With the environment set up, let's write end-to-end (e2e) tests to test your DApp's functionality. In the `tests/e2e/specs` folder, create a new file with a descriptive name that reflects what it tests (e.g., `user_login.spec.js` or `token_transfer.spec.js`). -### Test Structure +#### Test Structure You use `describe` blocks to group related tests together, and `it` blocks to define individual test cases within those groups. @@ -90,7 +101,7 @@ describe('User Login', () => { }); ``` -### Test 1: Setting Up Keplr Wallet +#### Test 1: Setting Up Keplr Wallet ```js it('should setup a Keplr wallet', () => { @@ -105,7 +116,7 @@ This test case simulates setting up a Keplr wallet for your tests, using the `cy After setting up the wallet, we visit the root path (`/`) of the DApp using `cy.visit('/')`. -### Test 2: Connecting Keplr Wallet +#### Test 2: Connecting Keplr Wallet ```js it('should accept connection with wallet', () => { @@ -116,7 +127,7 @@ it('should accept connection with wallet', () => { This test simulates a user connecting their Keplr wallet to your DApp. `cy.contains('Connect Wallet')` searches for an element containing the text `Connect Wallet` on the webpage and triggers a click event. `cy.acceptAccess` simulates accepting Keplr wallet access for your DApp. -### Test 3: Signing a Transaction +#### Test 3: Signing a Transaction ```js it('should confirm make an offer transaction', () => { @@ -127,7 +138,7 @@ it('should confirm make an offer transaction', () => { This test simulates transaction Signing on your DApp. `cy.contains('Make an Offer')` searches for an element containing the text `Make an Offer` and triggers a click event. `cy.confirmTransaction` simulates confirming a transaction. -### Running the Tests +#### Running the Tests You can now trigger the tests by running this command: @@ -135,18 +146,18 @@ You can now trigger the tests by running this command: EXTENSION=keplr synpress run --configFile=tests/e2e/synpress.config.js ``` -## Projects Using `@agoric/synpress` +### Projects Using `@agoric/synpress` Some examples projects utilizing `@agoric/synpress` for e2e tests: - [PSM dApp E2E Tests](https://github.com/Agoric/dapp-psm/tree/main/tests/e2e) - [Wallet dApp E2E Tests](https://github.com/frazarshad/wallet-app/tree/main/test/e2e) -## @agoric/synpress Commands +### @agoric/synpress Commands The `@agoric/synpress` commands are custom Cypress commands designed for use with Keplr. They provide ready-made functions to interact with Keplr-specific elements and workflows. -### `setupWallet` +#### `setupWallet` Initializes a Keplr wallet for testing. You can either create a new one or import an existing one using the provided options. @@ -167,7 +178,7 @@ The command takes a single object as an argument with the following keys: - _(**boolean**)_: `true` if the wallet was set up successfully, `false` otherwise. -### `acceptAccess` +#### `acceptAccess` Handles the authorization process for connecting the Keplr wallet to a DApp. DApps provide a `Connect Wallet` option to initiate this process. @@ -175,7 +186,7 @@ Handles the authorization process for connecting the Keplr wallet to a DApp. DAp - _(**boolean**)_: `true` if access was accepted successfully, `false` otherwise. -### `confirmTransaction` +#### `confirmTransaction` Handles signing transactions within a DApp using the Keplr wallet. This occurs when a user initiates a transaction, such as sending tokens or interacting with a smart contract. @@ -183,7 +194,7 @@ Handles signing transactions within a DApp using the Keplr wallet. This occurs w - _(**boolean**)_: `true` if transaction was approved successfully, `false` otherwise. -### `disconnectWalletFromDapp` +#### `disconnectWalletFromDapp` Disconnects the Keplr wallet from all previously connected DApps. @@ -191,7 +202,7 @@ Disconnects the Keplr wallet from all previously connected DApps. - _(**boolean**)_:`true` if the disconnection was successful, `false` otherwise. -### `getWalletAddress` +#### `getWalletAddress` Retrieves the wallet address of the currently active wallet associated with a specified blockchain. @@ -203,7 +214,7 @@ Retrieves the wallet address of the currently active wallet associated with a sp - _(**string**)_: The wallet address for the specified blockchain. -### `switchWallet` +#### `switchWallet` Switches the active wallet to the specified wallet by name. @@ -215,7 +226,7 @@ Switches the active wallet to the specified wallet by name. - _(**boolean**)_: `true` if the wallet switch was successful, `false` otherwise. -### `addNewTokensFound` +#### `addNewTokensFound` Adds all the new tokens discovered by the Keplr extension to the user's token portfolio when it connects to a new blockchain network. @@ -223,7 +234,7 @@ Adds all the new tokens discovered by the Keplr extension to the user's token po - _(**boolean**)_: `true` if the tokens were successfully added to the user's token portfolio `false` otherwise. -### `getTokenAmount` +#### `getTokenAmount` Retrieves the balance of a specified token in the wallet. @@ -235,7 +246,7 @@ Retrieves the balance of a specified token in the wallet. - _(**number**)_: The amount of the specified token currently held in the wallet. -### `isExtensionWindowActive` +#### `isExtensionWindowActive` Determines whether the Keplr extension window is the currently active tab. @@ -243,7 +254,7 @@ Determines whether the Keplr extension window is the currently active tab. - _(**boolean**)_:`true` if the Keplr extension window is active, `false` otherwise. -### `switchToExtensionWindow` +#### `switchToExtensionWindow` Switches the focus to the Keplr extension window tab. Keplr window is used for managing wallet related operations. @@ -251,7 +262,7 @@ Switches the focus to the Keplr extension window tab. Keplr window is used for m - _(**boolean**)_:`true` if the focus change was successful, `false` otherwise. -### `isCypressWindowActive` +#### `isCypressWindowActive` Determines whether the Cypress window, where the DApp is running, is the currently active tab. @@ -259,7 +270,7 @@ Determines whether the Cypress window, where the DApp is running, is the current - _(**boolean**)_:`true` if the Cypress window is active, `false` otherwise. -### `switchToCypressWindow` +#### `switchToCypressWindow` Switches the focus to the Cypress window tab. @@ -270,3 +281,59 @@ Switches the focus to the Cypress window tab.
For a full list of commands, you can refer to the [Keplr plugin file](https://github.com/agoric-labs/synpress/blob/dev/plugins/keplr-plugin.js). + +## Testing chain software with `@agoric/synthetic-chain` + +The tests above exercise a DApp frontend against a wallet. A different kind of +e2e test exercises the chain software itself: does a governance proposal or a +chain software upgrade actually produce the on-chain state it's supposed to, +against an environment that behaves like the real `agoric-3` mainnet chain? +That's what +[`a3p-integration`](https://github.com/Agoric/agoric-sdk/tree/master/a3p-integration) +in `agoric-sdk` is for, built on the +[`@agoric/synthetic-chain`](https://www.npmjs.com/package/@agoric/synthetic-chain) +test tool (published from the +[`agoric-3-proposals`](https://github.com/Agoric/agoric-3-proposals) repository). + +`a3p-integration` spins up a synthetic `agoric-3`-like chain in Docker, +applies one or more **proposals** (a chain software upgrade, a core-eval +proposal, or both in sequence), and then runs functional tests against the +result. This is the harness the SDK itself uses to verify that a chain +upgrade or a core-eval (like deploying Fast USDC) behaves as intended before +it goes to a real network. + +### Proposal packages + +Each proposal lives in its own package under `a3p-integration/proposals`, +isolated from the rest of the SDK and from each other; they run inside the +Docker image and can't reach SDK source directly. A proposal's `package.json` +`agoricProposal` field configures its type (`Software Upgrade Proposal` or +`/agoric.swingset.CoreEvalProposal`), its ordering relative to other +proposals, and, for a core-eval, the submission it evaluates. + +### Running it + +`a3p-integration` is a self-contained Yarn 4 project, not part of the +`agoric-sdk` root workspace (so it doesn't run under the root CI for +`packages/`). From `agoric-sdk/a3p-integration`, with Docker and Buildx +available: + +```bash +corepack enable +yarn install + +# build the synthetic chain image, including this checkout's chain software +yarn build + +# run every proposal's tests +yarn test + +# run a single proposal's tests, or drop into it interactively +yarn test -m fast-usdc --debug +``` + +`-m ` matches proposal package names, so `yarn test -m fast-usdc` +runs (or `--debug`-attaches to) just the Fast USDC core-eval proposal. See the +[`a3p-integration` README](https://github.com/Agoric/agoric-sdk/blob/master/a3p-integration/README.md) +and the [`agoric-3-proposals` README](https://github.com/Agoric/agoric-3-proposals/blob/main/README.md) +for the full proposal-package layout and how to add a new one. diff --git a/main/guides/integration/chain-integration.md b/main/guides/integration/chain-integration.md index 801406148..700440aa0 100644 --- a/main/guides/integration/chain-integration.md +++ b/main/guides/integration/chain-integration.md @@ -1,14 +1,14 @@ # Integrating with Agoric Network -The Agoric network builds a blockchain for smart contracts in JavaScript using the `cosmos-sdk`. Cosmos-sdk is software that provides the widely-used Tendermint/CometBFT consensus and best-in-class support for chain operations like staking and governance. For simplicity of chain integration, the Agoric Network works identically to the Cosmos Hub, except using different parameters (e.g., `ubld` instead of `uatom`). +The Agoric network builds a blockchain for smart contracts in JavaScript using the `cosmos-sdk`. Cosmos-sdk is software that provides the widely-used CometBFT consensus (formerly Tendermint Core) and best-in-class support for chain operations like staking and governance. For simplicity of chain integration, the Agoric Network works identically to the Cosmos Hub, except using different parameters (e.g., `ubld` instead of `uatom`). ## TL;DR for Cosmos-experienced -This section points at relevant reference documentation for the underlying `cosmos-sdk` and CometBFT/Tendermint consensus engine, and summarizes the differences. +This section points at relevant reference documentation for the underlying `cosmos-sdk` and CometBFT consensus engine, and summarizes the differences. -The Agoric Network currently uses `cosmos-sdk` v0.45. The general Cosmos documentation for this version can be [found here](https://docs.cosmos.network/v0.45/), including structure and`golang` documentation, and REST API documentation. +The Agoric Network currently uses `cosmos-sdk` v0.53. The general Cosmos documentation for this version can be [found here](https://docs.cosmos.network/sdk/v0.53/), including structure and `golang` documentation, and REST API documentation. -Use the [v0.45.1 version of the REST API](https://v1.cosmos.network/rpc/v0.45.1) for accessing the chain. To use the "Try it out" functionality, change the Base URL to `agoric-api.polkachu.com`: +To browse and try the REST/gRPC-gateway API interactively, use a chain's LCD Swagger UI (served at `/swagger/` on an API node that has Swagger enabled) or a public explorer's API console. To use the "Try it out" functionality, change the Base URL to a live Agoric API endpoint such as `main.api.agoric.net` (see [Chain resources](#chain-resources) below for how to discover current endpoints): | ![Alt name of image](./assets/cosmos-api.png) | | --------------------------------------------- | @@ -21,7 +21,7 @@ The chain can also be accessed via JavaScript using the [`cosmjs` library](https - Additional chain information, including tokens and their logos, gas fee information for wallets, additional entry points, and explorers is maintained in the Cosmos [Chain Registry](https://github.com/cosmos/chain-registry/tree/master/agoric). - The source code for the Agoric Network runtime and contracts is in [the Agoric open source repository](https://github.com/Agoric/agoric-sdk) on GitHub. - The base unit for staking is `ubld` (corresponding to `uatom` for Cosmos Hub) -- The command utility of the agoric chain is `agd` (corresponding to [`simd` for the Cosmos Hub](https://docs.cosmos.network/v0.45/run-node/interact-node.html)). +- The command utility of the agoric chain is `agd` (corresponding to [`simd` for the Cosmos Hub](https://docs.cosmos.network/sdk/v0.53/user/run-node/interact-node)). --- @@ -51,15 +51,15 @@ a working installation. For more detail, see [#7825](https://github.com/Agoric/a # FAQ - How are transactions encoded? - [Cosmos SDK v0.45 Docs - Encoding](https://docs.cosmos.network/v0.45/core/encoding.html) + [Cosmos SDK v0.53 Docs - Encoding](https://docs.cosmos.network/sdk/v0.53/learn/advanced/encoding) - What data is needed to create a transaction (last block hash, nonce, sender public key, etc.)? - [Cosmos SDK v0.45 Docs - Transaction Generation](https://docs.cosmos.network/v0.45/core/transactions.html#transaction-generation) + [Cosmos SDK v0.53 Docs - Transaction Lifecycle](https://docs.cosmos.network/sdk/v0.53/learn/beginner/tx-lifecycle) - What data is signed and how is that data obtained (for example truncated SHA256 of transaction data)? - [Cosmos SDK v0.45 Docs - Transaction Generation](https://docs.cosmos.network/v0.45/core/transactions.html#transaction-generation) + [Cosmos SDK v0.53 Docs - Transactions](https://docs.cosmos.network/sdk/v0.53/learn/advanced/transactions) - Do transactions expire? - Transaction do not expire unless you specify --timeout-height: [Cosmos SDK v0.45 Docs - Transaction Generation](https://docs.cosmos.network/v0.45/core/transactions.html#transaction-generation) + Transaction do not expire unless you specify --timeout-height: [Cosmos SDK v0.53 Docs - Transactions](https://docs.cosmos.network/sdk/v0.53/learn/advanced/transactions) However they do have a sequence number and may be invalidated if another transaction with the same sequence number is processed by the chain - How are addresses generated? - [Cosmos SDK v0.45 Docs - Accounts](https://docs.cosmos.network/v0.45/basics/accounts.html) + [Cosmos SDK v0.53 Docs - Accounts](https://docs.cosmos.network/sdk/v0.53/learn/beginner/accounts) - How is the blockchain queried? - JSON-RPC, gRPC, REST [Cosmos SDK v0.45 Docs - Interact with Node](https://docs.cosmos.network/v0.45/run-node/interact-node.html) + JSON-RPC, gRPC, REST [Cosmos SDK v0.53 Docs - Interact with a Node](https://docs.cosmos.network/sdk/v0.53/user/run-node/interact-node) diff --git a/main/guides/integration/name-services.md b/main/guides/integration/name-services.md index c55ada090..0c6eb4949 100644 --- a/main/guides/integration/name-services.md +++ b/main/guides/integration/name-services.md @@ -35,6 +35,7 @@ The keys of `agoricNames` include: - `oracleBrand` - USD, ATOM - `installation` - psm, reserve, priceAuthority, ... (see [deployed contracts](../zoe/actual-contracts/)) - `instance` - reserve, one for each psm, one for each priceAuthority, ... (see [deployed contracts](../zoe/actual-contracts/)) +- `uiConfig` - per-contract UI configuration (for example the VaultFactory dApp config), keyed the same way as `installation` and `instance` Adding or updating an entry requires access to the corresponding _NameAdmin_ facet: `agoricNamesAdmin` or one of its descendants - most likely as part of [permissioned contract deployment](../coreeval/). For example: diff --git a/main/guides/platform/index.md b/main/guides/platform/index.md index bac48b870..78db13d1e 100644 --- a/main/guides/platform/index.md +++ b/main/guides/platform/index.md @@ -34,14 +34,20 @@ machine. SwingSet provides [orthogonal persistence](). +SwingSet also supports **vat upgrade**: a running vat can be pointed at a new +code bundle without losing its durable state, so contracts and platform +services can be fixed or extended in place instead of being redeployed from +scratch. See the [Orchestration guide](../orchestration/) for how the +platform builds on this to let a contract hold and move assets across +chains from a single durable, upgradable vat. + ## Cosmos SDK -Our testnet has a single SwingSet instance with multiple vats running -on top of Cosmos SDK. SwingSet and most of our code is written in -JavaScript, so we currently have a complicated process that starts up -the JavaScript environment, starts a SwingSet instance, and then -connects through Go to the Cosmos SDK modules, the consensus algorithm -in Tendermint, and back again. +The Agoric chain runs a single SwingSet instance with multiple vats on top +of Cosmos SDK. SwingSet and most of our code is written in JavaScript, so we +have a process that starts up the JavaScript environment, starts a SwingSet +instance, and then connects through Go to the Cosmos SDK modules, the +consensus engine (CometBFT), and back again. ## Dynamic IBC @@ -50,18 +56,21 @@ Communication](https://cosmos.network/ibc/). IBC enables messages to be sent from one blockchain to another with the use of intermediary relayers. -Dynamic IBC (dIBC) is a solution to the problem of rolling out a new -protocol without needing a platform upgrade or chain governance vote. - -In essence, dIBC is the idea of using a smart contract or VM platform -to deploy new contracts that support new protocols, all on an existing -chain without having to wait for chain upgrades. +Dynamic IBC (dIBC) solves the problem of rolling out a new protocol on top of +IBC without needing a platform upgrade or chain governance vote: a smart +contract or VM platform can deploy new contracts that support new protocols, +all on an existing chain. This is no longer just a proposal; it's the +mechanism the [Orchestration API](../orchestration/) uses today to let a +contract open and manage ICA (Interchain Accounts) and IBC connections to +other chains, and it's what the [Fast USDC](https://github.com/Agoric/agoric-sdk/tree/master/packages/fast-usdc#readme) +contract uses to move funds between Noble and Agoric. -For more information, check out [a recent article on +For background, see [a recent article on dIBC](https://medium.com/agoric/the-road-to-dynamic-ibc-4a43bc964bca). -## Tendermint +## CometBFT -Tendermint is a consensus engine, defining how blocks are agreed upon -and created. Effectively, Tendermint is the lowest level layer that -defines the blockchain itself. +CometBFT is the consensus engine, defining how blocks are agreed upon +and created. Effectively, CometBFT is the lowest level layer that +defines the blockchain itself. (CometBFT is the actively maintained +continuation of the project formerly known as Tendermint Core.) diff --git a/main/index.md b/main/index.md index 255e712dc..93635580c 100644 --- a/main/index.md +++ b/main/index.md @@ -68,7 +68,7 @@ features: link: https://github.com/Agoric/agoric-sdk/wiki/Office-Hours - icon: 🐦 - title: Twitter + title: X (Twitter) details: Catch up on all things Agoric product, events, and more. - link: https://twitter.com/agoric + link: https://x.com/agoric --- diff --git a/main/reference/repl/networking.md b/main/reference/repl/networking.md index 07fad12fd..b92e8b1e3 100644 --- a/main/reference/repl/networking.md +++ b/main/reference/repl/networking.md @@ -2,9 +2,22 @@ +::: warning +This page lives under `reference/repl/` alongside documentation for the +retired `ag-solo` REPL, but the Network API itself (`Port`, `Connection`, +`ConnectionHandler`) is current and actively used, including by the +[Orchestration API](/guides/orchestration/) to open ICA and IBC connections +to other chains. The `home.ibcport`/`home.network` objects below are +`ag-solo`-era illustrative names for "whatever Port/NetworkInterface object +your vat holds"; a modern vat gets these from its own bootstrap wiring or +from Orchestration, not from an `ag-solo`'s `home` object. This content is +kept in sync with [`packages/network`](https://github.com/Agoric/agoric-sdk/tree/master/packages/network#readme) +in `agoric-sdk`. +::: + Suitably-empowered code inside a vat can access a "network API" that works vaguely like the BSD socket API. This code can: @@ -50,7 +63,14 @@ You must also prepare a `ConnectionHandler` object to manage the connection you' Then you will call the `connect()` method on your local `Port`. This will return a `Promise` that will fire with a new `Connection` object, on which you can send data. Your `ConnectionHandler` will be notified about the new channel, and will receive inbound data from the other side. ```js -const remoteEndpoint = `/ibc-hop/${hopName}/ibc-port/${portName}/ordered/${version}`; +import { encodeIbcEndpoint } from '@agoric/network/ibc/utils.js'; + +const remoteEndpoint = encodeIbcEndpoint({ + hops: [connectionID], + portID, + order: 'ordered', + version, +}); E(home.ibcport[0]) .connect(remoteEndpoint, connectionHandler) .then(conn => doSomethingWithConnection(conn)); @@ -60,17 +80,13 @@ E(home.ibcport[0]) The other side of `connect()` is a "listening port". These ports are waiting for inbound connections to be established. -To get a listening port, you need a `NetworkInterface` object (such as the one on your `ag-solo` under `home.network`) and ask it to `bind()` to an endpoint. You can either provide a specific port name, or allow the API to allocate a random one for you. The endpoint specifies the type of connection that this port will be able to accept (IBC, TCP, etc), and some properties of that connection. `bind()` uses a "multiaddress" to encode this information. +To get a listening port, you need a `NetworkInterface` object (such as the one on your `ag-solo` under `home.network`) and ask it for a port, via the `PortAllocator`. ```js -// Ask for a random allocation - ends with a slash +// ask for a random allocation - ends with a slash E(home.network) - .bind('/ibc-port/') - .then(port => usePort(port)); - -// or ask for a specific port name -E(home.network) - .bind('/ibc-port/my-cool-port-name') + .getPortAllocator() + .then(portAllocator => E(portAllocator).allocateCustomIBCPort()) .then(port => usePort(port)); ``` @@ -153,12 +169,10 @@ Note that if you want to listen on this port again, you can just call `port.addL ### Closing the Port Entirely -Removing a listener doesn't release the port address to make it available for other `bind()` requests. You can call: +Removing a listener doesn't release the port address to make it available for other `PortAllocator` requests. You can call: ```js port.revoke(); ``` to completely deallocate the port, remove all listeners, close all pending connections, and release its address. - -**CAUTION:** Be aware that if you call `E(home.ibcport[0]).revoke()`, it will be useless for new `connect()` or `addListener()` attempts. You will need to provision a new Agoric client to obtain a new setup with a functioning `home.ibcport[0]`. diff --git a/main/reference/repl/scratch.md b/main/reference/repl/scratch.md index a7595099d..f1fc8ce4e 100644 --- a/main/reference/repl/scratch.md +++ b/main/reference/repl/scratch.md @@ -1,5 +1,16 @@ # Scratch +::: warning DEPRECATED +This page documents the retired `ag-solo` REPL and its `home.*` object, which +are no longer part of the Agoric stack. See [Testing a Contract](/guides/zoe/contract-hello#testing-a-contract) +for the current way to test contracts with [AVA](https://github.com/avajs/ava). +`scratch` had no on-chain equivalent; it was local, ephemeral storage for an +`ag-solo`'s deploy scripts. A current client application that needs to persist +data across runs should keep its own state (for example in the browser, or in +whatever process is driving [`@agoric/client-utils`](https://github.com/Agoric/agoric-sdk/tree/master/packages/client-utils#readme)) +rather than relying on anything the chain or wallet provides. +::: + You use `scratch` to save key-value pairs for later. It is only on the ag-solo and is not accessible from the chain, making it private to the ag-solo user. Since deploy scripts are ephemeral, use `scratch` to save objects from a deploy script for later scripts to use. Note that when calling from the REPL's home object, you must use the [E() syntax](/guides/js-programming/eventual-send) as shown below. diff --git a/main/reference/repl/timerServices.md b/main/reference/repl/timerServices.md index 3846220b5..eff3a0048 100644 --- a/main/reference/repl/timerServices.md +++ b/main/reference/repl/timerServices.md @@ -1,5 +1,14 @@ # Timer Services +::: warning +This page lives under `reference/repl/` alongside documentation for the +retired `ag-solo` REPL, but `chainTimerService` and `@agoric/time` are not +deprecated; they are the current timer API and remain in active use +(including by the [Orchestration API](/guides/orchestration/)). Only the +REPL-specific pages in this section (`scratch`, `networking`, and the REPL +itself) document retired workflows. +::: + ## chainTimerService The `chainTimerService` is based on block times with units of 1 second. diff --git a/main/reference/vstorage-ref.md b/main/reference/vstorage-ref.md index 6325b9d2c..76f5e6b73 100644 --- a/main/reference/vstorage-ref.md +++ b/main/reference/vstorage-ref.md @@ -1,10 +1,25 @@ # VStorage Reference +::: warning +The examples on this page were captured from a live chain snapshot and are +**illustrative, not authoritative**: exact board IDs, wallet addresses, and +`published.*` values change with every governance vote, chain upgrade, and +block. Treat the shapes and key names as stable; treat the specific IDs and +numbers as a point-in-time example, not something to hard-code. +::: + 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) +- [x/vstorage module](https://github.com/Agoric/agoric-sdk/tree/master/golang/cosmos/x/vstorage#readme) + +To read these paths off-chain, the current tools are the `vstorage-kit`/`smart-wallet-kit` +helpers in [`@agoric/client-utils`](https://github.com/Agoric/agoric-sdk/tree/master/packages/client-utils#readme), +the [`@agoric/casting`](https://github.com/Agoric/agoric-sdk/tree/master/packages/casting#readme) +library (`makeFollower`/`makeLeader`), or the `agoric follow` CLI command, which +unmarshal the CapData shown below into the `Object @Alleged: ...#boardNNN {}` +form used in these examples. ## vstorage: top level keys @@ -16,31 +31,35 @@ The `published` and `bundles` keys are the most relevant to dapp development. beansOwing: 'swingset execution fee accounting', bundles: 'MsgInstallBundle outcome', egress: 'reserved for future use', + highPriorityQueue: 'a priority mechanism', 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). +The following keys appear under `published` on a current chain. This list +changes over time as contracts are installed or retired by governance; the +one below is a snapshot, not an exhaustive or permanent list. ```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', + auction: 'the collateral auctioneer used by VaultFactory liquidations', + boardAux: 'auxiliary data for brands etc. keyed by boardId', + committees: 'economic committee / charter electorates', + crabble: 'a long-running demo game contract, reserved by governance proposal #64', + fastUsdc: 'the Fast USDC contract: fee config, feed policy, pool metrics, and transactions', + kread: 'a long-running demo game contract, reserved by governance proposal #53', + priceFeed: 'oracle price feeds (one child per feed, e.g. ATOM-USD_price_feed)', + provisionPool: 'provides initial BLD during smart wallet provisioning', + psm: 'the Parity Stability Module instances (one child per PSM, e.g. IST.USDC)', + reserve: 'the collateral reserve contract', + vaultFactory: 'the VaultFactory contract: governance, managers, metrics', wallet: 'smart wallet status', + ymax0: 'a yield-portfolio orchestration contract instance', + ymax1: 'a yield-portfolio orchestration contract instance', } ``` @@ -50,9 +69,26 @@ agoricNames contains several other NameHubs. See also [agoricNames](/guides/integration/name-services.html#agoricnames-agoricnamesadmin-well-known-names). ```js -['brand', 'installation', 'instance', 'issuer', 'oracleBrand', 'vbankAsset']; +[ + 'brand', + 'chain', + 'chainConnection', + 'installation', + 'instance', + 'issuer', + 'oracleBrand', + 'vbankAsset', +]; ``` +`chain` and `chainConnection` are Orchestration additions: `chain` holds +per-chain configuration (chain-registry-style info keyed by chain name), and +`chainConnection` holds established interchain connection info, both used by +contracts that hold or move assets on other chains. `agoricNamesReserved` in +`packages/vats/src/core/utils.js` also declares a `uiConfig` hub (for +per-contract UI configuration), but it has not been populated with entries on +this chain as of this writing, so it isn't shown below. + ## 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 @@ -62,23 +98,28 @@ regarding un-marshalling the data using board IDs. ```js { - VaultFactory: Object @Alleged: BundleIDInstallation#board05815 {}, - auctioneer: Object @Alleged: BundleIDInstallation#board04016 {}, + QstnContract: Object @Alleged: BundleIDInstallation#board026542 {}, + VaultFactory: Object @Alleged: BundleIDInstallation#board013354 {}, + auctioneer: Object @Alleged: BundleIDInstallation#board047351 {}, binaryVoteCounter: Object @Alleged: BundleIDInstallation#board02314 {}, centralSupply: Object @Alleged: BundleIDInstallation#board0188 {}, committee: Object @Alleged: BundleIDInstallation#board00613 {}, - contractGovernor: Object @Alleged: BundleIDInstallation#board02810 {}, + contractGovernor: Object @Alleged: BundleIDInstallation#board049352 {}, 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 {}, + fastUsdc: Object @Alleged: BundleIDInstallation#board060381 {}, + feeDistributor: Object @Alleged: BundleIDInstallation#board008387 {}, + kreadCommitteeCharter: Object @Alleged: BundleIDInstallation#board01998 {}, + kreadKit: Object @Alleged: BundleIDInstallation#board02897 {}, + mintHolder: Object @Alleged: BundleIDInstallation#board041386 {}, + postalService: Object @Alleged: BundleIDInstallation#board028519 {}, + priceAggregator: Object @Alleged: BundleIDInstallation#board048372 {}, + provisionPool: Object @Alleged: BundleIDInstallation#board013508 {}, + psm: Object @Alleged: BundleIDInstallation#board030392 {}, + reserve: Object @Alleged: BundleIDInstallation#board002511 {}, + scaledPriceAuthority: Object @Alleged: BundleIDInstallation#board031370 {}, + walletFactory: Object @Alleged: BundleIDInstallation#board011545 {}, + ymax0: Object @Alleged: BundleIDInstallation#board038544 {}, + ymax1: Object @Alleged: BundleIDInstallation#board020535 {}, } ``` @@ -87,34 +128,54 @@ The data at this key are the entries of the NameHub. Here we show the object com ```js { - 'ATOM-USD price feed': Object @Alleged: InstanceHandle#board02963 {}, - Crabble: Object @Alleged: InstanceHandle#board04395 {}, - CrabbleCommittee: Object @Alleged: InstanceHandle#board02393 {}, - CrabbleGovernor: Object @Alleged: InstanceHandle#board05396 {}, + 'ATOM-USD price feed': Object @Alleged: InstanceHandle#board058340 {}, + Crabble: Object @Alleged: InstanceHandle#board014143 {}, + CrabbleCommittee: Object @Alleged: InstanceHandle#board061141 {}, + CrabbleGovernor: Object @Alleged: InstanceHandle#board031144 {}, + QstnContract: Object @Alleged: InstanceHandle#board055543 {}, 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 {}, + auctioneer: Object @Alleged: InstanceHandle#board032353 {}, + 'dATOM-USD price feed': Object @Alleged: InstanceHandle#board061375 {}, + econCommitteeCharter: Object @Alleged: InstanceHandle#board059338 {}, + economicCommittee: Object @Alleged: InstanceHandle#board012327 {}, + fastUsdc: Object @Alleged: InstanceHandle#board026384 {}, + feeDistributor: Object @Alleged: InstanceHandle#board015388 {}, + kread: Object @Alleged: InstanceHandle#board003101 {}, + kreadCommittee: Object @Alleged: InstanceHandle#board052103 {}, + kreadCommitteeCharter: Object @Alleged: InstanceHandle#board029102 {}, + postalService: Object @Alleged: InstanceHandle#board053518 {}, 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 {}, + 'psm-IST-DAI_axl': Object @Alleged: InstanceHandle#board02271 {}, + 'psm-IST-DAI_grv': Object @Alleged: InstanceHandle#board01272 {}, + 'psm-IST-USDC': Object @Alleged: InstanceHandle#board051120 {}, + 'psm-IST-USDC_axl': Object @Alleged: InstanceHandle#board01867 {}, + 'psm-IST-USDC_grv': Object @Alleged: InstanceHandle#board02568 {}, + 'psm-IST-USDT': Object @Alleged: InstanceHandle#board064124 {}, + 'psm-IST-USDT_axl': Object @Alleged: InstanceHandle#board05669 {}, + 'psm-IST-USDT_grv': Object @Alleged: InstanceHandle#board05970 {}, reserve: Object @Alleged: InstanceHandle#board06458 {}, reserveGovernor: Object @Alleged: InstanceHandle#board03365 {}, - 'scaledPriceAuthority-stATOM': Object @Alleged: InstanceHandle#board05892 {}, - 'stATOM-USD price feed': Object @Alleged: InstanceHandle#board04091 {}, + 'scaledPriceAuthority-ATOM': Object @Alleged: InstanceHandle#board006346 {}, + 'scaledPriceAuthority-dATOM': Object @Alleged: InstanceHandle#board035376 {}, + 'scaledPriceAuthority-stATOM': Object @Alleged: InstanceHandle#board043347 {}, + 'scaledPriceAuthority-stOSMO': Object @Alleged: InstanceHandle#board036348 {}, + 'scaledPriceAuthority-stTIA': Object @Alleged: InstanceHandle#board013349 {}, + 'scaledPriceAuthority-stkATOM': Object @Alleged: InstanceHandle#board002350 {}, + 'stATOM-USD price feed': Object @Alleged: InstanceHandle#board023341 {}, + 'stOSMO-USD price feed': Object @Alleged: InstanceHandle#board009342 {}, + 'stTIA-USD price feed': Object @Alleged: InstanceHandle#board040343 {}, + 'stkATOM-USD price feed': Object @Alleged: InstanceHandle#board053344 {}, walletFactory: Object @Alleged: InstanceHandle#board06366 {}, + ymax0: Object @Alleged: InstanceHandle#board041540 {}, + ymax1: Object @Alleged: InstanceHandle#board014536 {}, } ``` +Notice `fastUsdc`, `ymax0`, and `ymax1` (Orchestration-based yield/portfolio +contracts) alongside the long-running `VaultFactory`/PSM/auction stack; this +list grows and shrinks as governance installs and retires contracts. + ## vstorage: well-known assets `published.agoricNames.issuer` has Issuers of well-known assets. @@ -125,35 +186,55 @@ The data at this key are the entries of the NameHub. Here we show the object com BLD: Object @Alleged: BLD issuer#board0592 {}, DAI_axl: Object @Alleged: DAI_axl issuer#board02437 {}, DAI_grv: Object @Alleged: DAI_grv issuer#board05039 {}, + FastLP: Object @Alleged: PoolShares issuer#board011383 {}, 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 {}, + KREAdCHARACTER: Object @Alleged: KREAdCHARACTER issuer#board033104 {}, + KREAdITEM: Object @Alleged: KREAdITEM issuer#board016105 {}, + PoC26: Object @Alleged: PoC26 issuer#board049513 {}, + USDC: Object @Alleged: USDC issuer#board007117 {}, + USDC_axl: Object @Alleged: USDC_axl issuer#board02437 {}, + USDC_grv: Object @Alleged: USDC_grv issuer#board05039 {}, + USDT: Object @Alleged: USDT issuer#board030121 {}, + USDT_axl: Object @Alleged: USDT_axl issuer#board05141 {}, + USDT_grv: Object @Alleged: USDT_grv issuer#board00443 {}, + dATOM: Object @Alleged: dATOM issuer#board001373 {}, + stATOM: Object @Alleged: stATOM issuer#board059111 {}, + stOSMO: Object @Alleged: stOSMO issuer#board062162 {}, + stTIA: Object @Alleged: stTIA issuer#board028171 {}, + stkATOM: Object @Alleged: stkATOM issuer#board016182 {}, } ``` +`FastLP` (Fast USDC pool shares) and `PoC26` are recent additions alongside +the original PSM/staking-derivative assets; `USDC` (native, distinct from the +IBC-relayed `USDC_axl`/`USDC_grv`) backs Fast USDC's Noble-to-Agoric transfers. + `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 {}, + DAI_axl: Object @Alleged: DAI_axl brand#board01744 {}, + DAI_grv: Object @Alleged: DAI_grv brand#board03446 {}, + FastLP: Object @Alleged: PoolShares brand#board038382 {}, 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 {}, + KREAdCHARACTER: Object @Alleged: KREAdCHARACTER brand#board06299 {}, + KREAdITEM: Object @Alleged: KREAdITEM brand#board046100 {}, + PoC26: Object @Alleged: PoC26 brand#board036514 {}, + USDC: Object @Alleged: USDC brand#board016118 {}, + USDC_axl: Object @Alleged: USDC_axl brand#board05736 {}, + USDC_grv: Object @Alleged: USDC_grv brand#board03138 {}, + USDT: Object @Alleged: USDT brand#board004122 {}, + USDT_axl: Object @Alleged: USDT_axl brand#board03040 {}, + USDT_grv: Object @Alleged: USDT_grv brand#board04542 {}, + dATOM: Object @Alleged: dATOM brand#board020374 {}, + stATOM: Object @Alleged: stATOM brand#board037112 {}, + stOSMO: Object @Alleged: stOSMO brand#board019163 {}, + stTIA: Object @Alleged: stTIA brand#board006172 {}, + stkATOM: Object @Alleged: stkATOM brand#board033183 {}, timer: Object @Alleged: timerBrand#board0425 {}, } ``` @@ -164,7 +245,11 @@ The data at this key are the entries of the NameHub. Here we show the object com { ATOM: Object @Alleged: Brand#board03935 {}, USD: Object @Alleged: Brand#board01034 {}, - stATOM: Object @Alleged: Brand#board04388 {}, + dATOM: Object @Alleged: Brand#board050371 {}, + stATOM: Object @Alleged: Brand#board022110 {}, + stOSMO: Object @Alleged: Brand#board036161 {}, + stTIA: Object @Alleged: Brand#board053170 {}, + stkATOM: Object @Alleged: Brand#board018181 {}, } ``` @@ -172,18 +257,6 @@ The data at this key are the entries of the NameHub. Here we show the object com ```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 {}, @@ -196,6 +269,18 @@ The data at this key are the entries of the NameHub. Here we show the object com issuerName: 'ATOM', proposedName: 'ATOM', }, +// ... + 'ibc/B1E6288B5A0224565D915D1F66716486F16D8A44BF33A9EC323DD6BA30764C35': { + brand: Object @Alleged: stATOM brand#board037112 {}, + denom: 'ibc/B1E6288B5A0224565D915D1F66716486F16D8A44BF33A9EC323DD6BA30764C35', + displayInfo: { + assetKind: 'nat', + decimalPlaces: 6, + }, + issuer: Object @Alleged: stATOM issuer#board059111 {}, + issuerName: 'stATOM', + proposedName: 'stATOM', + }, // ... ubld: { brand: Object @Alleged: BLD brand#board0566 {}, @@ -208,6 +293,17 @@ The data at this key are the entries of the NameHub. Here we show the object com issuerName: 'BLD', proposedName: 'Agoric staking token', }, + ufastlp: { + brand: Object @Alleged: PoolShares brand#board038382 {}, + denom: 'ufastlp', + displayInfo: { + assetKind: 'nat', + decimalPlaces: 6, + }, + issuer: Object @Alleged: PoolShares issuer#board011383 {}, + issuerName: 'FastLP', + proposedName: 'FastLP', + }, uist: { brand: Object @Alleged: IST brand#board0257 {}, denom: 'uist', @@ -222,13 +318,18 @@ The data at this key are the entries of the NameHub. Here we show the object com } ``` +Note that `USDC` here (and `FastLP`/`ufastlp`) is a **vbank-registered denom +managed by Fast USDC's own IBC path**, distinct from the IBC-relayed +`USDC_axl`/`USDC_grv` variants that arrive over Axelar/Gravity Bridge; check +`denom` and `issuerName` rather than assuming a single canonical "USDC". + ## boardAux The keys under `published.boardAux` are board IDs. Here we show a handful. ```js -['board00282', 'board0074', 'board01744']; +['board0074', 'board004122', 'board01744']; ``` The data are auxiliary info about objects in the board; @@ -242,20 +343,26 @@ for example, displayInfo of brands, including assetKind. assetKind: 'set', }, }, - board01744: { - allegedName: 'USDT_axl', + board004122: { + allegedName: 'USDT', displayInfo: { assetKind: 'nat', decimalPlaces: 6, }, }, + board01744: { + allegedName: 'DAI_axl', + displayInfo: { + assetKind: 'nat', + decimalPlaces: 18, + }, + }, } ``` ## 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 { @@ -267,9 +374,9 @@ See similar data in [Inter Protocol data](https://github.com/Agoric/agoric-sdk/t value: [ { description: 'questionPoser', - handle: Object @Alleged: InvitationHandle#board00848 {}, + handle: Object @Alleged: InvitationHandle#board036509 {}, installation: Object @Alleged: BundleIDInstallation#board00613 {}, - instance: Object @Alleged: InstanceHandle#board04149 {}, + instance: Object @Alleged: InstanceHandle#board012327 {}, }, ], }, @@ -277,27 +384,30 @@ See similar data in [Inter Protocol data](https://github.com/Agoric/agoric-sdk/t PerAccountInitialAmount: { type: 'amount', value: { - brand: Object @Alleged: IST brand#board0257 {}, - value: 250000n, + brand: Object @Alleged: BLD brand#board0566 {}, + value: 10000000n, }, }, }, } ``` +Note `PerAccountInitialAmount` is now denominated in `BLD`, not `IST` as in +earlier chain history. + `published.provisionPool.metrics` ```js { totalMintedConverted: { - brand: Object @Alleged: IST brand#board0257 {}, - value: 20000000n, + brand: Object @Alleged: BLD brand#board0566 {}, + value: 0n, }, totalMintedProvided: { - brand: Object @Alleged: IST brand#board0257 {}, - value: 2750000n, + brand: Object @Alleged: BLD brand#board0566 {}, + value: 3800000000n, }, - walletsProvisioned: 11n, + walletsProvisioned: 1462n, } ``` @@ -309,9 +419,9 @@ See also: [Smart Wallet VStorage Topics](/guides/getting-started/contract-rpc#sm ```js [ - 'agoric1890064p6j3xhzzdf8daknd6kpvhw766ds8flgw', - 'agoric1ee9hr0jyrxhy999y755mp862ljgycmwyp4pl7q', - 'agoric1enwuyn2hzyyvt39x87tk9rhlkpqtyv9haj7mgs' + 'agoric1003uxlkc77u6szrg603m273r00usecc0xvrhph', + 'agoric1009qfjzn5enucuwzmfv3kwy690y5vne4m7kyxr', + 'agoric10229lxdgw6urj90h8xvkg7y6lw6s06u7zgwyy6' ]; ``` @@ -326,20 +436,7 @@ The `.current` child has current wallet status. For example: { 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 {}, - }, - ], + value: [], }, brand: Object @Alleged: Zoe Invitation brand#board0074 {}, }, @@ -347,27 +444,101 @@ The `.current` child has current wallet status. For example: } ``` -The `published.wallet.${address}` key has wallet's last update. For example: +The `published.wallet.${address}` key has the wallet's last update. This +shape has grown beyond simple balance changes; for example, an Orchestration +`invokeEntry` invocation result looks like: ```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 {}, + id: 'setTargetAllocation.2026-07-10T03:07:19.504Z', + result: { + passStyle: 'string', + }, + updated: 'invocation', + } +``` + +## vstorage: fastUsdc + +`published.fastUsdc` has `feeConfig`, `feedPolicy`, `poolMetrics`, and `txns` +children for the [Fast USDC](https://github.com/Agoric/agoric-sdk/tree/master/packages/fast-usdc#readme) +contract. + +`published.fastUsdc.poolMetrics` reports the liquidity pool's running totals: + +```js + { + encumberedBalance: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 299739207n, + }, + shareWorth: { + denominator: { + brand: Object @Alleged: PoolShares brand#board038382 {}, + value: 60439964842n, + }, + numerator: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 62829671966n, + }, + }, + totalBorrows: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 3415666304045n, + }, + totalContractFees: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 698308370n, + }, + totalPoolFees: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 2760193415n, + }, + totalRepays: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 3415366564838n, + }, + } +``` + +`published.fastUsdc.feeConfig` shows the current fee schedule, including +per-destination-chain overrides (keyed by [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) +chain ID, for example `eip155:1` for Ethereum mainnet): + +```js + { + contractRate: { + denominator: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 10n, + }, + numerator: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 2n, + }, + }, + destinationOverrides: { + 'eip155:1': { + relay: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 500000n, }, - ], + }, + // ...one entry per overridden destination chain + }, + flat: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 10000n, + }, + variableRate: { + denominator: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 1000n, + }, + numerator: { + brand: Object @Alleged: USDC brand#board016118 {}, + value: 1n, + }, }, - updated: 'balance', } ``` diff --git a/main/what-is-agoric.md b/main/what-is-agoric.md index 094db735b..c37b8f269 100644 --- a/main/what-is-agoric.md +++ b/main/what-is-agoric.md @@ -8,6 +8,13 @@ Agoric ideal for building software with seamless user experiences. The native token BLD is used for staking and governance. The over-collateralized IST stable token is used to pay network fees. +This orchestration story ships as real code today: the +[Orchestration API](/guides/orchestration/) lets a contract hold and move +assets on other chains from a single JavaScript flow, and +[Fast USDC](https://github.com/Agoric/agoric-sdk/tree/master/packages/fast-usdc#readme) +is a production contract built on it that moves USDC from Noble to Agoric in +seconds instead of the usual IBC transfer delay. + The Agoric blockchain is built on the CometBFT consensus system with native Inter-Blockchain Communication Protocol (IBC) support. Smart contracts can seamlessly integrate 3rd party libraries, so a contract From 52ab750a3d20a93de4a2a01429c2e26c55068a83 Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Thu, 24 Sep 2026 20:31:12 +0000 Subject: [PATCH 07/21] docs: sync UI component library, chainlink stub, and subquery links - UIComponentLibrary/index.md: the react-components package dropped its ChainSelector/NodeSelector/LeapElements/WalletProvisioning components in favor of useAgoric()+AgoricContext state and a ConnectWalletButton/ AmountInput/NoticeBanner set; rewrite to match current ui-kit main, replace the throwaway Cloudflare preview URL with the canonical ui-kit README - remove the 0-byte UIComponentLibrary/assets/asset.md placeholder - chainlink-integration.md: replace the bare 3-link stub with a sentence explaining there's no Chainlink-specific integration, pointing at PriceAuthority instead - subquery-indexing.md: academy.subquery.network now 301s to subquery.network/doc/; repoint links at the canonical domain and drop a 403'd Medium link --- .../guides/UIComponentLibrary/assets/asset.md | 0 main/guides/UIComponentLibrary/index.md | 149 +++++++++--------- main/guides/chainlink-integration.md | 12 +- main/guides/subquery-indexing.md | 13 +- 4 files changed, 88 insertions(+), 86 deletions(-) delete mode 100644 main/guides/UIComponentLibrary/assets/asset.md diff --git a/main/guides/UIComponentLibrary/assets/asset.md b/main/guides/UIComponentLibrary/assets/asset.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/main/guides/UIComponentLibrary/index.md b/main/guides/UIComponentLibrary/index.md index bedb02f00..959595a20 100644 --- a/main/guides/UIComponentLibrary/index.md +++ b/main/guides/UIComponentLibrary/index.md @@ -1,123 +1,118 @@ # Welcome To Agoric's UI Component Library -You'll find a collection of ready-to-use or pre-coded user interface elements that help accelerate your Agoric Dapp-building. These pre-designed elements include wallet connect buttons, chain selector, node selector, amount input, smart wallet provisioning and leap elements. -Utilization of these building blocks ensures best practices in design and accessibility. +[`@agoric/react-components`](https://github.com/Agoric/ui-kit/tree/main/packages/react-components), +part of the [`Agoric/ui-kit`](https://github.com/Agoric/ui-kit) monorepo, provides React hooks and a +small set of pre-built components (a wallet-connect button, an amount input, +and a network-notice banner) that handle the repetitive parts of an Agoric +dapp frontend: watching vstorage, connecting to Keplr, and reading/writing +smart-wallet state. Utilization of these building blocks ensures best +practices in design and accessibility. + +::: tip +The component set here has changed over time; some previously documented +components (a dedicated chain selector, node selector, and "Leap Elements") +are no longer part of the package. What's below reflects the current +`react-components` source. +::: ## Installation and Setup -See [Introduction to Agoric UI Kit](https://a0a31cba.documentation-7tp.pages.dev/guides/getting-started/how-to-use-ui-kit#introduction-to-agoric-ui-kit) for installation and setup how-to. - -Once complete you'll need to run this yarn command: +See [`Agoric/ui-kit` README - Setup](https://github.com/Agoric/ui-kit#setup) +for setup instructions (these packages require [SES](https://github.com/endojs/endo/tree/master/packages/ses), +so lockdown must run before your app's other code), and +[`packages/react-components`](https://github.com/Agoric/ui-kit/tree/main/packages/react-components) +for the package overview. ```sh yarn add @agoric/react-components ``` +Most dapps also want [`@agoric/rpc`](https://github.com/Agoric/ui-kit/tree/main/packages/rpc) +(for `makeAgoricChainStorageWatcher`, to read vstorage) and +[`@agoric/web-components`](https://github.com/Agoric/ui-kit/tree/main/packages/web-components) +(for `makeAgoricWalletConnection`, to connect to Keplr and make/exit offers); +`react-components` wires both of these together behind the `useAgoric` hook +described below. + ## UI Components List -These React UI components can be immediately used to streamline your Agoric Dapp UI +These React UI components can be immediately used to streamline your Agoric Dapp UI: - Connect Wallet -- Wallet Provisioning - Amount Input -- Chain Selector -- Node Selector -- Leap Elements - -## Connect Wallet - -Screenshot: Connect Wallet +- Notice Banner -Screenshot: Wallet Address - -Screenshot: Select Wallet +## The `useAgoric` hook and `AgoricContext` -- [Connecting with Wallet Connect Button](https://github.com/Agoric/ui-kit/tree/main/packages/react-components#integrating) -- [Connecting without Wallet Connect Button](https://github.com/Agoric/ui-kit/tree/main/packages/react-components#connecting-without-connectwalletbutton) -- [Using a Custom Chain Provider](https://github.com/Agoric/ui-kit/tree/main/packages/react-components#using-a-custom-chainprovider) +Most Agoric-related state (wallet address, connected chain, purses, +whether the smart wallet is provisioned, and helpers to make and exit offers) +is accessible through the `useAgoric()` hook, backed by `AgoricContext`. See +[`AgoricContext`](https://github.com/Agoric/ui-kit/blob/main/packages/react-components/src/lib/context/AgoricContext.ts) +for the full interface, which includes: -Customizable Parameters -| Parameter | Type | Description | +| Field | Type | Description | |----------|----------|----------| -| ClassName | string | CSS class name for the underlying `