|
2 | 2 |
|
3 | 3 | To get started with developing using the Orchestration API, developers can make use of our [dapp-orchestration-basics](https://github.com/Agoric/dapp-orchestration-basics) template.
|
4 | 4 |
|
5 |
| -Following the dApp pattern of our existing dapp templates, `dapp-orchestration-basics` contains both ui & contract folders within a single yarn workspace. |
| 5 | +Following the dApp pattern of our existing dapp templates, `dapp-orchestration-basics` contains both ui & contract directory within a single yarn workspace. |
| 6 | + |
| 7 | +## Installation and Deployment |
| 8 | + |
| 9 | +The dApp implements a smart contract that can installed and deployed any Agoric testnet. Since, the contract interacts with remote chains, we need to a multichain environment - see [Agoric Multichain-Testing]() for details. Follow in the instructions in [dApp Readme]() to install, deploy and interact with dApp on your local machine. |
| 10 | + |
| 11 | +## Orca Contract Code Walkthrough |
| 12 | + |
| 13 | +This section provides a walkthrough of the Orca contract code, explaining its structure, key components, and functionality. The Orca contract is designed to manage orchestration accounts and fund them. It interacts with multiple chains and provides functionality for creating accounts and funding them. The code for the contract logic is in two files: |
| 14 | + |
| 15 | +1. `orca.contract.js` |
| 16 | +2. `orca.flows.js` |
| 17 | + |
| 18 | +### Walkthrough: `orca.contract.js` |
| 19 | + |
| 20 | +The `orca.contract.js` files brings in necessary dependencies and types from various Agoric packages. The flows import contains specific logic for the Orca contract operations. |
| 21 | + |
| 22 | +```js |
| 23 | +import { AmountShape } from '@agoric/ertp'; |
| 24 | +import { makeTracer } from '@agoric/internal'; |
| 25 | +import { withOrchestration } from '@agoric/orchestration/src/utils/start-helper.js'; |
| 26 | +import { ChainInfoShape } from '@agoric/orchestration/src/typeGuards.js'; |
| 27 | +import { InvitationShape } from '@agoric/zoe/src/typeGuards.js'; |
| 28 | +import { M } from '@endo/patterns'; |
| 29 | +import * as flows from './orca.flows.js'; |
| 30 | +``` |
| 31 | + |
| 32 | +#### Type Definitions and Shapes |
| 33 | + |
| 34 | +These definitions create shapes for validating the structure of amounts and orchestration powers. |
| 35 | + |
| 36 | +```js |
| 37 | +const SingleAmountRecord = M.and( |
| 38 | + M.recordOf(M.string(), AmountShape, { numPropertiesLimit: 1 }), |
| 39 | + M.not(harden({})) |
| 40 | +); |
| 41 | + |
| 42 | +const OrchestrationPowersShape = M.splitRecord({ |
| 43 | + localchain: M.remotable('localchain'), |
| 44 | + orchestrationService: M.remotable('orchestrationService'), |
| 45 | + storageNode: M.remotable('storageNode'), |
| 46 | + timerService: M.remotable('timerService'), |
| 47 | + agoricNames: M.remotable('agoricNames') |
| 48 | +}); |
| 49 | +``` |
| 50 | + |
| 51 | +#### Main Contract Function |
| 52 | + |
| 53 | +This is the main contract function that sets up the contract's functionality. |
| 54 | + |
| 55 | +```js |
| 56 | +const contract = async ( |
| 57 | + zcf, |
| 58 | + privateArgs, |
| 59 | + zone, |
| 60 | + { orchestrateAll, zoeTools, chainHub } |
| 61 | +) => { |
| 62 | + // ... (contract logic) |
| 63 | +}; |
| 64 | +``` |
| 65 | + |
| 66 | +Within the `contract` function, following actions are performed. |
| 67 | + |
| 68 | +- **Chain Registration**: Below section registers chains and their connections with the `chainHub`. |
| 69 | + |
| 70 | +```js |
| 71 | +const { chainDetails } = zcf.getTerms(); |
| 72 | +for (const [name, info] of entries(chainDetails)) { |
| 73 | + const { connections = {} } = info; |
| 74 | + trace('register', name, { |
| 75 | + chainId: info.chainId, |
| 76 | + connections: keys(connections) |
| 77 | + }); |
| 78 | + chainHub.registerChain(name, info); |
| 79 | + for (const [chainId, connInfo] of entries(connections)) { |
| 80 | + chainHub.registerConnection(info.chainId, chainId, connInfo); |
| 81 | + } |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +- **Creating Account and Funding Functions**: These functions are created using the `orchestrateAll` helper, which sets up the necessary flow logic for account creation and funding. |
| 86 | + |
| 87 | +```js |
| 88 | +const { makeAccount, makeCreateAndFund } = orchestrateAll(flows, { |
| 89 | + localTransfer: zoeTools.localTransfer |
| 90 | +}); |
| 91 | +``` |
| 92 | + |
| 93 | +- **Public Facet**: The public facet provides two methods: `makeAccountInvitation` creates an invitation to make an orchestration account, and `makeCreateAndFundInvitation` creates an invitation to make an account and fund it. |
| 94 | + |
| 95 | +```js |
| 96 | +const publicFacet = zone.exo( |
| 97 | + 'Orca Public Facet', |
| 98 | + M.interface('Orca PF', { |
| 99 | + makeAccountInvitation: M.callWhen().returns(InvitationShape), |
| 100 | + makeCreateAndFundInvitation: M.callWhen().returns(InvitationShape) |
| 101 | + }), |
| 102 | + { |
| 103 | + makeAccountInvitation() { |
| 104 | + return zcf.makeInvitation(makeAccount, 'Make an Orchestration Account'); |
| 105 | + }, |
| 106 | + makeCreateAndFundInvitation() { |
| 107 | + return zcf.makeInvitation( |
| 108 | + makeCreateAndFund, |
| 109 | + 'Make an Orchestration Account and Fund it', |
| 110 | + undefined, |
| 111 | + M.splitRecord({ give: SingleAmountRecord }) |
| 112 | + ); |
| 113 | + } |
| 114 | + } |
| 115 | +); |
| 116 | +``` |
| 117 | + |
| 118 | +#### `start` Function |
| 119 | + |
| 120 | +The start function is wrapped with `withOrchestration`, which provides additional orchestration setup and tools for the contract. |
| 121 | + |
| 122 | +```js |
| 123 | +export const start = withOrchestration(contract); |
| 124 | +harden(start); |
| 125 | +``` |
| 126 | + |
| 127 | +### Walkthrough `orca.flows.js` |
| 128 | + |
| 129 | +This section provides a walkthrough of the `orca.flows.js` file, which contains flow functions for the Orca contract. The `orca.flows.js` file defines two main functions: |
| 130 | + |
| 131 | +1. `makeAccount`: Creates an account on a Cosmos chain. |
| 132 | +2. `makeCreateAndFund`: Creates an account on a Cosmos chain and funds it. |
| 133 | + |
| 134 | +These functions are called by the Zoe vat when a user makes an offer using a corresponding orca contract inivitation. |
| 135 | + |
| 136 | +#### `makeAccount` Function |
| 137 | + |
| 138 | +This function creates an account on a specified Cosmos chain. Here are the parameters of this function: |
| 139 | + |
| 140 | +- `orch`: An Orchestrator instance |
| 141 | +- `_ctx`: Unused context object |
| 142 | +- `seat`: A `ZCFSeat` instance |
| 143 | +- `offerArgs`: An object containing `chainName` and `denom` |
| 144 | + |
| 145 | +The function validates the `offerArgs` to ensure it contains a `chainName`, retrieves the specified chain using `orch`, creates an account on the chain using `chain.makeAccount()`, and returns the account as a continuing offer. Below is the code of `makeAccount` after removing some debug information logging code. |
| 146 | + |
| 147 | +```js |
| 148 | +mustMatch(offerArgs, M.splitRecord({ chainName: M.string() })); |
| 149 | +const { chainName } = offerArgs; |
| 150 | +seat.exit(); |
| 151 | +const chain = await orch.getChain(chainName); |
| 152 | +const chainAccount = await chain.makeAccount(); |
| 153 | +return chainAccount.asContinuingOffer(); |
| 154 | +``` |
| 155 | + |
| 156 | +#### `makeCreateAndFund` Function |
| 157 | + |
| 158 | +This function creates an account on a specified Cosmos chain and funds it. It accepts the same set of parameters as `make Account`. The function: |
| 159 | + |
| 160 | +- Extracts the amount to be transferred from the seat's proposal, and retrieves both the Agoric chain and the specified target chain. |
| 161 | +- Fetches chain info and asset information. |
| 162 | +- Creates accounts on both the Agoric chain (local) and the target chain (remote). |
| 163 | +- Transfers funds from the seat to the local account. |
| 164 | +- Transfers half of the received funds from the local account to the remote account. |
| 165 | +- Checks the balance of the remote account, and returns the remote account as a continuing offer. |
| 166 | + |
| 167 | +Below is the code of `makeCreateAndFund` after removing some debug information logging code. |
| 168 | + |
| 169 | +```js |
| 170 | + const { give } = seat.getProposal(); |
| 171 | + const [[_kw, amt]] = Object.entries(give); |
| 172 | + const [agoric, chain] = await Promise.all([ |
| 173 | + orch.getChain('agoric'), |
| 174 | + orch.getChain(chainName), |
| 175 | + ]); |
| 176 | + const localAccount = await agoric.makeAccount(); |
| 177 | + const remoteAccount = await chain.makeAccount(); |
| 178 | + const remoteAddress = await remoteAccount.getAddress(); |
| 179 | + await localTransfer(seat, localAccount, give); |
| 180 | + await localAccount.transfer( |
| 181 | + { |
| 182 | + denom: 'ubld', |
| 183 | + value: amt.value / 2n, |
| 184 | + }, |
| 185 | + remoteAddress, |
| 186 | + ); |
| 187 | + seat.exit(); |
| 188 | + return remoteAccount.asContinuingOffer(); |
| 189 | +}; |
| 190 | +``` |
0 commit comments