From 5ba1bf2af86cbb5b7e9f083487e56cad535cb9a4 Mon Sep 17 00:00:00 2001 From: Mudassir Shabbir Date: Mon, 30 Sep 2024 16:20:43 +0500 Subject: [PATCH 1/8] sendanywhere walkthrough --- .../contract-walkthrough/send-anywhere.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md diff --git a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md new file mode 100644 index 000000000..292ed00c0 --- /dev/null +++ b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md @@ -0,0 +1,58 @@ +# SendAnywhere Contract Walkthrough + +The "Send Anywhere" contract is designed to facilitate the transfer of assets from one chain to another using +Agoric's Orchestration library. The contract allows a user to send a specific amount of a brand (token or asset) +to a destination address on any supported blockchain. + +The high-level flow of the contract is: + +- Validate the asset brand on the source chain. +- Create or ensure the existence of a local account (held by the contract) to handle temporary holding. +- Transfer the asset from the source address to the local account. +- Initiate a transfer to the destination address, which could reside on a remote blockchain. +- Gracefully handle failures. + +The contract is implemented in two separate files: + +1. `send-anywhere.contract.js` implements the `start` function of the contract to initialize the contract and + expose `publicFacet` and `creatorFacet`. +2. `send-anywhere.flows.js` implements the `sendIt` function which performs that actual transfer of assets when a + user makes an offer. + +Let us walkthroug these files one by one. + +## `send-anywhere.contract.js` + +The contract begins by importing various modules and utilities necessary for its functionality. These include: + +- **State management**: `makeSharedStateRecord` is imported to create and manage the state across contract executions. +- **Type validation**: `AmountShape` and `InvitationShape` ensure that the contract works with correct data types, such as amounts and invitations. +- **Orchestration utilities**: `withOrchestration` is imported to facilitate interactions with Zoe and other orchestration functions. +- **Flows**: The orchestration flows for handling transfers are imported from `send-anywhere.flows.js`. + +These imports set up the contract for the validation, orchestration, and execution of transfers. + +### Contract State Setup + +The contract defines a shared state record as below: + +```js +export const SingleNatAmountRecord = M.and( + M.recordOf(M.string(), AnyNatAmountShape, { + numPropertiesLimit: 1, + }), + M.not(harden({})), +); +harden(SingleNatAmountRecord); +``` + +This state keeps track of the local account that will hold the transferred assets temporarily before they are sent to the destination address. + +- **State initialization**: The state starts with an undefined `localAccount`. This account will be created later during the orchestration process if needed. + This shared state ensures that the contract retains context between different transactions and orchestrations. + +### Single Amount Record Validation + +In order to ensure that only a single asset (or `brand`) is transferred per transaction, a `SingleNatAmountRecord` is defined (lines 14-19 in send-anywhere.contract.js). This validation ensures that the proposal shape submitted by users contains exactly one asset and no other extraneous properties. + +This check prevents errors or misuse by enforcing strict transaction shapes. From 82abf6860bd28037bbdcd371ddae5f4c31f94131 Mon Sep 17 00:00:00 2001 From: Mudassir Shabbir Date: Mon, 30 Sep 2024 16:25:31 +0500 Subject: [PATCH 2/8] docs: Single Amount Record Validation --- .../contract-walkthrough/send-anywhere.md | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md index 292ed00c0..83d0f05a5 100644 --- a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md +++ b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md @@ -37,13 +37,11 @@ These imports set up the contract for the validation, orchestration, and executi The contract defines a shared state record as below: ```js -export const SingleNatAmountRecord = M.and( - M.recordOf(M.string(), AnyNatAmountShape, { - numPropertiesLimit: 1, - }), - M.not(harden({})), -); -harden(SingleNatAmountRecord); +const contractState = makeSharedStateRecord( + /** @type {{ account: OrchestrationAccount | undefined }} */ { + localAccount: undefined, + }, + ); ``` This state keeps track of the local account that will hold the transferred assets temporarily before they are sent to the destination address. @@ -53,6 +51,17 @@ This state keeps track of the local account that will hold the transferred asset ### Single Amount Record Validation -In order to ensure that only a single asset (or `brand`) is transferred per transaction, a `SingleNatAmountRecord` is defined (lines 14-19 in send-anywhere.contract.js). This validation ensures that the proposal shape submitted by users contains exactly one asset and no other extraneous properties. +In order to ensure that only a single asset (or `brand`) is transferred per transaction, a `SingleNatAmountRecord` is defined: + +```js +export const SingleNatAmountRecord = M.and( + M.recordOf(M.string(), AnyNatAmountShape, { + numPropertiesLimit: 1, + }), + M.not(harden({})), +); +harden(SingleNatAmountRecord); +``` + +This validation ensures that the proposal shape submitted by users contains exactly one asset and no other extraneous properties. -This check prevents errors or misuse by enforcing strict transaction shapes. From b0785a09bc71645d211701227d257a0daed15802 Mon Sep 17 00:00:00 2001 From: Mudassir Shabbir Date: Mon, 30 Sep 2024 16:38:32 +0500 Subject: [PATCH 3/8] logging and orchFns --- .../contract-walkthrough/send-anywhere.md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md index 83d0f05a5..c21c7ca81 100644 --- a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md +++ b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md @@ -65,3 +65,24 @@ harden(SingleNatAmountRecord); This validation ensures that the proposal shape submitted by users contains exactly one asset and no other extraneous properties. +### Logging setup + +The contract initializes a logging mechanism (`logNode`) to capture the contract's internal actions and state changes. Logs are written to a newly created `log` child in VStorage, making debugging and auditing easier. +```js +const logNode = E(privateArgs.storageNode).makeChildNode('log'); + +const log = msg => vowTools.watch(E(logNode).setValue(msg)); +``` + +### Orchestration functions (`orchFns`): + +These functions, imported from `send-anywhere.flows.js`, define the main behaviors for handling asset transfers. The contract wraps these functions with the necessary context (such as the contract state, logging, and Zoe tools). +```js +const orchFns = orchestrateAll(flows, { + contractState, + log, + zoeTools, + }); +``` + +### \ No newline at end of file From 5a3fbc46dfa48d1057afc6a54c5ea4b7cecee0b7 Mon Sep 17 00:00:00 2001 From: Mudassir Shabbir Date: Mon, 30 Sep 2024 17:00:42 +0500 Subject: [PATCH 4/8] docs: sendIt function walkthrough --- .../contract-walkthrough/send-anywhere.md | 126 ++++++++++++++++-- 1 file changed, 117 insertions(+), 9 deletions(-) diff --git a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md index c21c7ca81..8188b511e 100644 --- a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md +++ b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md @@ -38,10 +38,10 @@ The contract defines a shared state record as below: ```js const contractState = makeSharedStateRecord( - /** @type {{ account: OrchestrationAccount | undefined }} */ { - localAccount: undefined, - }, - ); + /** @type {{ account: OrchestrationAccount | undefined }} */ { + localAccount: undefined, + }, +); ``` This state keeps track of the local account that will hold the transferred assets temporarily before they are sent to the destination address. @@ -68,6 +68,7 @@ This validation ensures that the proposal shape submitted by users contains exac ### Logging setup The contract initializes a logging mechanism (`logNode`) to capture the contract's internal actions and state changes. Logs are written to a newly created `log` child in VStorage, making debugging and auditing easier. + ```js const logNode = E(privateArgs.storageNode).makeChildNode('log'); @@ -77,12 +78,119 @@ const log = msg => vowTools.watch(E(logNode).setValue(msg)); ### Orchestration functions (`orchFns`): These functions, imported from `send-anywhere.flows.js`, define the main behaviors for handling asset transfers. The contract wraps these functions with the necessary context (such as the contract state, logging, and Zoe tools). + ```js const orchFns = orchestrateAll(flows, { - contractState, - log, - zoeTools, - }); + contractState, + log, + zoeTools, +}); +``` + +### Public Facet and Invitation Creation + +The contract provides a public-facing API (`publicFacet`) that allows external users to interact with it: + +```js +const publicFacet = zone.exo( + 'Send PF', + M.interface('Send PF', { + makeSendInvitation: M.callWhen().returns(InvitationShape), + }), + { + makeSendInvitation() { + return zcf.makeInvitation( + orchFns.sendIt, + 'send', + undefined, + M.splitRecord({ give: SingleNatAmountRecord }), + ); + }, + }, +); +``` + +The exposed `makeSendInvitation` method creates an invitation for users, allowing them to initiate a transfer by submitting a proposal. The proposal must match the structure defined by the `SingleNatAmountRecord`, ensuring that only one asset is transferred per transaction. The invitation is connected to the `sendIt` function (explained later), which performs the asset transfer. +The public facet makes the contract accessible to external users, enabling them to initiate asset transfers in a controlled and secure way. + +## `send-anywhere.flows.js` + +This flows file defines a single function `sendIt` that handles offers made to the contract. The `sendIt` +function is the core of the transfer process. It handles the actual movement of assets between the local and +remote chains. The parameters passed to this function include: + +- `orch`: The orchestrator object for managing chain/account interactions. +- `ctx`: The contract state and utility functions, including: + - `contractState`: Holds the local account for intermediate storage. + - `localTransfer`: The transfer function for moving assets between local accounts. +- `seat`: The Zoe seat representing the assets to be transferred. +- `offerArgs`: Includes details about the destination chain and address. + +The `sendIt` function performs several important steps: + +### Offer Validation and Setup + +Upon receiving an offer, the `sendIt` function: +TODO: link here + +- Validates the offer arguments using [endo]() pattern-matching to ensure the correct structure is submitted (lines 17-18 in send-anywhere.flows.js). + TODO: link here +- Retrieves the `proposal` from the seat, extracting the asset (`brand` and `amount`) being transferred. +- The contract ensures that the asset brand is registered on the local chain by querying the chain’s asset registry (`vbank`). If not, the contract throws an error and exits the transaction. +- If a local account for the contract doesn’t already exist, the function creates one. + +```js +mustMatch(offerArgs, harden({ chainName: M.scalar(), destAddr: M.string() })); +const { chainName, destAddr } = offerArgs; +// NOTE the proposal shape ensures that the `give` is a single asset +const { give } = seat.getProposal(); +const [[_kw, amt]] = entries(give); +void log(`sending {${amt.value}} from ${chainName} to ${destAddr}`); +const agoric = await orch.getChain('agoric'); +const assets = await agoric.getVBankAssetInfo(); +void log(`got info for denoms: ${assets.map(a => a.denom).join(', ')}`); +const { denom } = NonNullish( + assets.find(a => a.brand === amt.brand), + `${amt.brand} not registered in vbank`, +); + +if (!contractState.localAccount) { + contractState.localAccount = await agoric.makeAccount(); +} +``` + +This setup phase ensures the transaction is valid and the contract is prepared to handle it. + +### Asset Transfer + +Once everything is validated, the contract performs the following steps: + +- **Local transfer**: The assets are first transferred from the Zoe seat to the contract’s local account using `localTransfer` API. + +```js +await localTransfer(seat, contractState.localAccount, give); +``` + +- **Remote transfer**: The contract initiates the transfer to the destination address on remote chain. This transfer includes details such as the destination chain ID and address. + +```js +await contractState.localAccount.transfer( + { + value: destAddr, + encoding: 'bech32', + chainId, + }, + { denom, value: amt.value }, +); ``` -### \ No newline at end of file +- **Error handling**: If the transfer fails, the contract reverses the transaction by withdrawing the assets from the local account back to the Zoe seat. A detailed error message is logged and the seat is exited with the error. + This process ensures that assets are transferred securely, with clear rollback mechanisms in case of failure. + +```js +await withdrawToSeat(contractState.localAccount, seat, give); +const errorMsg = `IBC Transfer failed ${q(e)}`; +void log(`ERROR: ${errorMsg}`); +seat.exit(errorMsg); +throw makeError(errorMsg); +``` From 1cfdd2296145eb13831d71371189bb715561ab0b Mon Sep 17 00:00:00 2001 From: Mudassir Shabbir Date: Mon, 30 Sep 2024 17:22:17 +0500 Subject: [PATCH 5/8] docs: send-anywhere conclusion --- .../contract-walkthrough/send-anywhere.md | 71 ++++++++++--------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md index 8188b511e..15b4ace68 100644 --- a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md +++ b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md @@ -1,7 +1,7 @@ # SendAnywhere Contract Walkthrough The "Send Anywhere" contract is designed to facilitate the transfer of assets from one chain to another using -Agoric's Orchestration library. The contract allows a user to send a specific amount of a brand (token or asset) +Agoric's [Orchestration](/glossary/#orchestration) library. The contract allows a user to send assets of a specific brand to a destination address on any supported blockchain. The high-level flow of the contract is: @@ -21,33 +21,16 @@ The contract is implemented in two separate files: Let us walkthroug these files one by one. -## `send-anywhere.contract.js` +## 1. `send-anywhere.contract.js` The contract begins by importing various modules and utilities necessary for its functionality. These include: -- **State management**: `makeSharedStateRecord` is imported to create and manage the state across contract executions. +- **State management**: `makeSharedStateRecord` is imported to create and manage the state across contract incarnations. - **Type validation**: `AmountShape` and `InvitationShape` ensure that the contract works with correct data types, such as amounts and invitations. -- **Orchestration utilities**: `withOrchestration` is imported to facilitate interactions with Zoe and other orchestration functions. -- **Flows**: The orchestration flows for handling transfers are imported from `send-anywhere.flows.js`. +- **Orchestration utilities**: `withOrchestration` is imported to facilitate interactions with orchestration functions. +- **Flows**: The orchestration flows for handling transfers are imported from `send-anywhere.flows.js` to be made available to Zoe. -These imports set up the contract for the validation, orchestration, and execution of transfers. - -### Contract State Setup - -The contract defines a shared state record as below: - -```js -const contractState = makeSharedStateRecord( - /** @type {{ account: OrchestrationAccount | undefined }} */ { - localAccount: undefined, - }, -); -``` - -This state keeps track of the local account that will hold the transferred assets temporarily before they are sent to the destination address. - -- **State initialization**: The state starts with an undefined `localAccount`. This account will be created later during the orchestration process if needed. - This shared state ensures that the contract retains context between different transactions and orchestrations. +These imports set up the contract for the validation, orchestration, and execution of transfers through Zoe API. ### Single Amount Record Validation @@ -65,7 +48,21 @@ harden(SingleNatAmountRecord); This validation ensures that the proposal shape submitted by users contains exactly one asset and no other extraneous properties. -### Logging setup +### Contract State Setup (in `contract` Function) + +The contract defines a shared state record as below: + +```js +const contractState = makeSharedStateRecord( + /** @type {{ account: OrchestrationAccount | undefined }} */ { + localAccount: undefined, + }, +); +``` + +This state keeps track of the local account that will hold the transferred assets temporarily before they are sent to the destination address. The state starts with an undefined `localAccount`. This account will be created later during the offer handling process if needed. + +### Logging setup (in `contract` Function) The contract initializes a logging mechanism (`logNode`) to capture the contract's internal actions and state changes. Logs are written to a newly created `log` child in VStorage, making debugging and auditing easier. @@ -75,7 +72,7 @@ const logNode = E(privateArgs.storageNode).makeChildNode('log'); const log = msg => vowTools.watch(E(logNode).setValue(msg)); ``` -### Orchestration functions (`orchFns`): +### Orchestration functions (in `contract` Function) These functions, imported from `send-anywhere.flows.js`, define the main behaviors for handling asset transfers. The contract wraps these functions with the necessary context (such as the contract state, logging, and Zoe tools). @@ -87,7 +84,7 @@ const orchFns = orchestrateAll(flows, { }); ``` -### Public Facet and Invitation Creation +### Public Facet and Invitation Creation (in `contract` Function) The contract provides a public-facing API (`publicFacet`) that allows external users to interact with it: @@ -110,10 +107,9 @@ const publicFacet = zone.exo( ); ``` -The exposed `makeSendInvitation` method creates an invitation for users, allowing them to initiate a transfer by submitting a proposal. The proposal must match the structure defined by the `SingleNatAmountRecord`, ensuring that only one asset is transferred per transaction. The invitation is connected to the `sendIt` function (explained later), which performs the asset transfer. -The public facet makes the contract accessible to external users, enabling them to initiate asset transfers in a controlled and secure way. +The `makeSendInvitation` method creates an invitation for users, allowing them to initiate a transfer by submitting a proposal. The proposal must match the structure defined by the `SingleNatAmountRecord`, ensuring that only one asset is transferred per transaction. The invitation is connected to the `sendIt` function (explained later), which performs the asset transfer. -## `send-anywhere.flows.js` +## 2. `send-anywhere.flows.js` This flows file defines a single function `sendIt` that handles offers made to the contract. The `sendIt` function is the core of the transfer process. It handles the actual movement of assets between the local and @@ -126,15 +122,13 @@ remote chains. The parameters passed to this function include: - `seat`: The Zoe seat representing the assets to be transferred. - `offerArgs`: Includes details about the destination chain and address. -The `sendIt` function performs several important steps: +The `sendIt` function performs following important steps: ### Offer Validation and Setup Upon receiving an offer, the `sendIt` function: -TODO: link here -- Validates the offer arguments using [endo]() pattern-matching to ensure the correct structure is submitted (lines 17-18 in send-anywhere.flows.js). - TODO: link here +- Validates the offer arguments using [endo's pattern-matching library](https://github.com/endojs/endo/tree/master/packages/patterns) to ensure the correct structure is submitted. - Retrieves the `proposal` from the seat, extracting the asset (`brand` and `amount`) being transferred. - The contract ensures that the asset brand is registered on the local chain by querying the chain’s asset registry (`vbank`). If not, the contract throws an error and exits the transaction. - If a local account for the contract doesn’t already exist, the function creates one. @@ -161,7 +155,7 @@ if (!contractState.localAccount) { This setup phase ensures the transaction is valid and the contract is prepared to handle it. -### Asset Transfer +### Assets Transfer Once everything is validated, the contract performs the following steps: @@ -194,3 +188,12 @@ void log(`ERROR: ${errorMsg}`); seat.exit(errorMsg); throw makeError(errorMsg); ``` + +## Conclusion + +The "Send Anywhere" contract is a robust and flexible solution for transferring assets between blockchains. It ensures that: + +- Assets are securely held in a local account before being transferred. +- Detailed logs are kept for transparency and error tracing. +- The contract is resilient to failure, with built-in rollback mechanisms. +- By using Agoric’s orchestration tools, this contract provides a secure way to facilitate cross-chain asset transfers. From 454b777af0ebcb5b6d1c7390934d7fb2cf7941d4 Mon Sep 17 00:00:00 2001 From: Mudassir Shabbir Date: Mon, 30 Sep 2024 17:30:45 +0500 Subject: [PATCH 6/8] docs: entry walkthroughs page --- .../contract-walkthrough/send-anywhere.md | 66 +++++++++++-------- .../getting-started/contract-walkthroughs.md | 26 ++++++-- 2 files changed, 56 insertions(+), 36 deletions(-) diff --git a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md index 15b4ace68..879d3edfb 100644 --- a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md +++ b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md @@ -6,20 +6,19 @@ to a destination address on any supported blockchain. The high-level flow of the contract is: -- Validate the asset brand on the source chain. -- Create or ensure the existence of a local account (held by the contract) to handle temporary holding. -- Transfer the asset from the source address to the local account. -- Initiate a transfer to the destination address, which could reside on a remote blockchain. -- Gracefully handle failures. +- Validates the asset brand on the source chain. +- Creates or ensures the existence of a local account (held by the contract) to handle temporary holding. +- Transfers the asset from the source address to the local account. +- Initiates a transfer to the destination address, which could reside on the remote blockchain. +- Gracefully handles the failures. The contract is implemented in two separate files: 1. `send-anywhere.contract.js` implements the `start` function of the contract to initialize the contract and expose `publicFacet` and `creatorFacet`. -2. `send-anywhere.flows.js` implements the `sendIt` function which performs that actual transfer of assets when a - user makes an offer. +2. `send-anywhere.flows.js` implements the `sendIt` function which performs the actual transfer of assets when a user makes an offer. -Let us walkthroug these files one by one. +Let us walkthrough these files one by one. ## 1. `send-anywhere.contract.js` @@ -39,9 +38,9 @@ In order to ensure that only a single asset (or `brand`) is transferred per tran ```js export const SingleNatAmountRecord = M.and( M.recordOf(M.string(), AnyNatAmountShape, { - numPropertiesLimit: 1, + numPropertiesLimit: 1 }), - M.not(harden({})), + M.not(harden({})) ); harden(SingleNatAmountRecord); ``` @@ -55,16 +54,19 @@ The contract defines a shared state record as below: ```js const contractState = makeSharedStateRecord( /** @type {{ account: OrchestrationAccount | undefined }} */ { - localAccount: undefined, - }, + localAccount: undefined + } ); ``` -This state keeps track of the local account that will hold the transferred assets temporarily before they are sent to the destination address. The state starts with an undefined `localAccount`. This account will be created later during the offer handling process if needed. +This state keeps track of the local account that will hold the transferred assets temporarily before they are sent to the destination +address. The state starts with an undefined `localAccount`. This account will be created later during the offer handling process if +needed. ### Logging setup (in `contract` Function) -The contract initializes a logging mechanism (`logNode`) to capture the contract's internal actions and state changes. Logs are written to a newly created `log` child in VStorage, making debugging and auditing easier. +The contract initializes a logging mechanism (`logNode`) to capture the contract's internal actions and state changes. Logs are written +to a newly created `log` child in vStorage, making debugging and auditing easier. ```js const logNode = E(privateArgs.storageNode).makeChildNode('log'); @@ -74,13 +76,14 @@ const log = msg => vowTools.watch(E(logNode).setValue(msg)); ### Orchestration functions (in `contract` Function) -These functions, imported from `send-anywhere.flows.js`, define the main behaviors for handling asset transfers. The contract wraps these functions with the necessary context (such as the contract state, logging, and Zoe tools). +These functions, imported from `send-anywhere.flows.js`, define the main behaviors for handling asset transfers. The contract wraps +these functions with the necessary context (such as the contract state, logging, and Zoe tools). ```js const orchFns = orchestrateAll(flows, { contractState, log, - zoeTools, + zoeTools }); ``` @@ -92,7 +95,7 @@ The contract provides a public-facing API (`publicFacet`) that allows external u const publicFacet = zone.exo( 'Send PF', M.interface('Send PF', { - makeSendInvitation: M.callWhen().returns(InvitationShape), + makeSendInvitation: M.callWhen().returns(InvitationShape) }), { makeSendInvitation() { @@ -100,14 +103,16 @@ const publicFacet = zone.exo( orchFns.sendIt, 'send', undefined, - M.splitRecord({ give: SingleNatAmountRecord }), + M.splitRecord({ give: SingleNatAmountRecord }) ); - }, - }, + } + } ); ``` -The `makeSendInvitation` method creates an invitation for users, allowing them to initiate a transfer by submitting a proposal. The proposal must match the structure defined by the `SingleNatAmountRecord`, ensuring that only one asset is transferred per transaction. The invitation is connected to the `sendIt` function (explained later), which performs the asset transfer. +The `makeSendInvitation` method creates an invitation for users, allowing them to initiate a transfer by submitting a proposal. The +proposal must match the structure defined by the `SingleNatAmountRecord`, ensuring that only one asset is transferred per transaction. +The invitation is connected to the `sendIt` function (explained later), which performs the asset transfer. ## 2. `send-anywhere.flows.js` @@ -130,13 +135,14 @@ Upon receiving an offer, the `sendIt` function: - Validates the offer arguments using [endo's pattern-matching library](https://github.com/endojs/endo/tree/master/packages/patterns) to ensure the correct structure is submitted. - Retrieves the `proposal` from the seat, extracting the asset (`brand` and `amount`) being transferred. -- The contract ensures that the asset brand is registered on the local chain by querying the chain’s asset registry (`vbank`). If not, the contract throws an error and exits the transaction. +- The contract ensures that the asset brand is registered on the local chain by querying the chain’s asset registry (`vbank`). If not + the contract throws an error and exits the transaction. - If a local account for the contract doesn’t already exist, the function creates one. ```js mustMatch(offerArgs, harden({ chainName: M.scalar(), destAddr: M.string() })); const { chainName, destAddr } = offerArgs; -// NOTE the proposal shape ensures that the `give` is a single asset + const { give } = seat.getProposal(); const [[_kw, amt]] = entries(give); void log(`sending {${amt.value}} from ${chainName} to ${destAddr}`); @@ -145,7 +151,7 @@ const assets = await agoric.getVBankAssetInfo(); void log(`got info for denoms: ${assets.map(a => a.denom).join(', ')}`); const { denom } = NonNullish( assets.find(a => a.brand === amt.brand), - `${amt.brand} not registered in vbank`, + `${amt.brand} not registered in vbank` ); if (!contractState.localAccount) { @@ -165,21 +171,23 @@ Once everything is validated, the contract performs the following steps: await localTransfer(seat, contractState.localAccount, give); ``` -- **Remote transfer**: The contract initiates the transfer to the destination address on remote chain. This transfer includes details such as the destination chain ID and address. +- **Remote transfer**: The contract initiates the transfer to the destination address on the remote chain. This transfer includes + details such as the destination chain ID and address. ```js await contractState.localAccount.transfer( { value: destAddr, encoding: 'bech32', - chainId, + chainId }, - { denom, value: amt.value }, + { denom, value: amt.value } ); ``` -- **Error handling**: If the transfer fails, the contract reverses the transaction by withdrawing the assets from the local account back to the Zoe seat. A detailed error message is logged and the seat is exited with the error. - This process ensures that assets are transferred securely, with clear rollback mechanisms in case of failure. +- **Error handling**: If the transfer fails, the contract reverses the transaction by withdrawing the assets from the local account + back to the Zoe seat. A detailed error message is logged and the seat is exited with the error. This process ensures that assets + are transferred securely, with clear rollback mechanisms in case of failure. ```js await withdrawToSeat(contractState.localAccount, seat, give); diff --git a/main/guides/orchestration/getting-started/contract-walkthroughs.md b/main/guides/orchestration/getting-started/contract-walkthroughs.md index c7d8da8da..bebb50c9f 100644 --- a/main/guides/orchestration/getting-started/contract-walkthroughs.md +++ b/main/guides/orchestration/getting-started/contract-walkthroughs.md @@ -4,17 +4,29 @@ This section is designed to provide detailed explanations and insights into exam In this section, we will cover three primary contracts: -1. `swapExample.contract.js`: A comprehensive guide to the process of swapping assets between different chains using the Agoric orchestration library. -2. `unbondExample.contract.js`: A detailed walkthrough of the unbonding and liquid staking process, highlighting the steps involved in managing cross-chain operations. -3. `orca.contract.js`: A dapp template serving as an introduction to the foundational concepts and implementation of basic orchestration within an Agoric dApp (currently under active development). +1. `Assets Transfer Contract`: A guide to `send-anywhere` contract that demonstrates a simple yet robust and secure way for cross-chain assets transfer. +2. `Swap Contract`: A comprehensive guide to the process of swapping assets between different chains using the Agoric orchestration library. +3. `Unbond Contract`: A detailed walkthrough of the unbonding and liquid staking process, highlighting the steps involved in managing cross-chain operations. +4. `Orchestration Basics Contract`: A dApp template serving as an introduction to the foundational concepts and implementation details of orchestration basics within an Agoric dApp. -Each walkthrough will include line-by-line explanations of the contract code, providng insights into the mechanics and best practices of smart contract development on the Agoric platform. By the end of these walkthroughs, you should have a solid understanding of how to utilize Agoric’s tools and libraries to create robust and efficient cross-chain smart contracts. +Each walkthrough will include detailed explanations of the contract code, providing insights into the mechanics and best practices of smart contract development on the Agoric platform. By the end of these walkthroughs, you should have a solid understanding of how to utilize Agoric’s tools and libraries to create robust and efficient cross-chain smart contracts. + +## Assets Transfer Contract + +The "Send Anywhere" contract is a robust and secure solution for transferring assets between blockchains. It ensures that: + +- Assets are securely held in a local account before being transferred. +- Detailed logs are kept for transparency and error tracing. +- The contract is resilient to failure, with built-in rollback mechanisms. +- By using Agoric’s orchestration tools, this contract provides a secure way to facilitate cross-chain asset transfers. + +[See Contract Overview](/guides/orchestration/getting-started/contract-walkthrough/send-anywhere) ## Swap Contract The Swap Contract demonstrates how to swap assets between the Agoric chain and another blockchain. This example covers: -- Initializing and seting up the contract. +- Initializing and setting up the contract. - Creating and managing accounts on different chains. - Executing cross-chain asset transfers. - Handling errors and ensuring secure transactions. @@ -31,9 +43,9 @@ The Unbond Contract focuses on the process of unbonding staked assets and perfor [See Contract Overview](/guides/orchestration/getting-started/contract-walkthrough/cross-chain-unbond) -## Dapp Orchestration Basics +## DApp Orchestration Basics -The Agoric Dapp Orchestration Basics walkthrough (currently under development) will provide an introduction to the core concepts and basic implementation of orchestrtion within an Agoric dApp. This guide aims to: +DApp Orchestration Basics walkthrough will provide an introduction to the implementation level details of orchestration within an Agoric dApp. This guide aims to: - Explain the fundamental principles of orchestration. - Show an end-to-end dApp using the Orchestration API From 281713b9a2ba95b71e2305a82bac4585267b0b1f Mon Sep 17 00:00:00 2001 From: Mudassir Shabbir Date: Thu, 3 Oct 2024 16:45:55 +0500 Subject: [PATCH 7/8] chore: adding to navbar --- main/.vitepress/config.mjs | 4 ++++ main/.vitepress/themeConfig/nav.js | 4 ++++ .../contract-walkthrough/send-anywhere.md | 12 ++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/main/.vitepress/config.mjs b/main/.vitepress/config.mjs index e770704ab..4fd63c5b3 100644 --- a/main/.vitepress/config.mjs +++ b/main/.vitepress/config.mjs @@ -133,6 +133,10 @@ export default defineConfig({ text: 'Contract Walkthroughs', link: '/guides/orchestration/getting-started/contract-walkthroughs', items: [ + { + text: 'Send Anywhere Example', + link: '/guides/orchestration/getting-started/contract-walkthrough/send-anywhere', + }, { text: 'Cross-Chain Swap Example', link: '/guides/orchestration/getting-started/contract-walkthrough/cross-chain-swap', diff --git a/main/.vitepress/themeConfig/nav.js b/main/.vitepress/themeConfig/nav.js index 55651bd91..996dcea46 100644 --- a/main/.vitepress/themeConfig/nav.js +++ b/main/.vitepress/themeConfig/nav.js @@ -20,6 +20,10 @@ export const nav = [ { text: 'Contract Walkthroughs', items: [ + { + text: 'Send Anywhere Example', + link: '/guides/orchestration/getting-started/contract-walkthrough/send-anywhere', + }, { text: 'Cross-Chain Swap Example', link: '/guides/orchestration/getting-started/contract-walkthrough/cross-chain-swap', diff --git a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md index 879d3edfb..76ea8b8d9 100644 --- a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md +++ b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md @@ -18,7 +18,7 @@ The contract is implemented in two separate files: expose `publicFacet` and `creatorFacet`. 2. `send-anywhere.flows.js` implements the `sendIt` function which performs the actual transfer of assets when a user makes an offer. -Let us walkthrough these files one by one. +Let us walk through these files one by one. ## 1. `send-anywhere.contract.js` @@ -47,7 +47,7 @@ harden(SingleNatAmountRecord); This validation ensures that the proposal shape submitted by users contains exactly one asset and no other extraneous properties. -### Contract State Setup (in `contract` Function) +### Contract State Setup The contract defines a shared state record as below: @@ -63,10 +63,10 @@ This state keeps track of the local account that will hold the transferred asset address. The state starts with an undefined `localAccount`. This account will be created later during the offer handling process if needed. -### Logging setup (in `contract` Function) +### Logging setup The contract initializes a logging mechanism (`logNode`) to capture the contract's internal actions and state changes. Logs are written -to a newly created `log` child in vStorage, making debugging and auditing easier. +to a newly created `log` child in VStorage, making debugging and auditing easier. ```js const logNode = E(privateArgs.storageNode).makeChildNode('log'); @@ -74,7 +74,7 @@ const logNode = E(privateArgs.storageNode).makeChildNode('log'); const log = msg => vowTools.watch(E(logNode).setValue(msg)); ``` -### Orchestration functions (in `contract` Function) +### Orchestration functions These functions, imported from `send-anywhere.flows.js`, define the main behaviors for handling asset transfers. The contract wraps these functions with the necessary context (such as the contract state, logging, and Zoe tools). @@ -87,7 +87,7 @@ const orchFns = orchestrateAll(flows, { }); ``` -### Public Facet and Invitation Creation (in `contract` Function) +### Public Facet and Invitation Creation The contract provides a public-facing API (`publicFacet`) that allows external users to interact with it: From 146b47b1015e6eec25d106ffd16f2258649ff22c Mon Sep 17 00:00:00 2001 From: Mudassir Shabbir Date: Fri, 4 Oct 2024 18:44:18 +0500 Subject: [PATCH 8/8] chore: remove orca-dapp from example contracts --- main/.vitepress/config.mjs | 4 ---- main/.vitepress/themeConfig/nav.js | 4 ---- .../contract-walkthrough/send-anywhere.md | 4 ++-- .../getting-started/contract-walkthroughs.md | 16 +++------------- 4 files changed, 5 insertions(+), 23 deletions(-) diff --git a/main/.vitepress/config.mjs b/main/.vitepress/config.mjs index 4fd63c5b3..0878e2f00 100644 --- a/main/.vitepress/config.mjs +++ b/main/.vitepress/config.mjs @@ -144,10 +144,6 @@ export default defineConfig({ { text: 'Cross-Chain Unbond Example', link: '/guides/orchestration/getting-started/contract-walkthrough/cross-chain-unbond', - }, - { - text: 'Orchestration Basics', - link: '/guides/orchestration/getting-started/contract-walkthrough/orchestration-basics', } ] }, diff --git a/main/.vitepress/themeConfig/nav.js b/main/.vitepress/themeConfig/nav.js index 996dcea46..ebabdd189 100644 --- a/main/.vitepress/themeConfig/nav.js +++ b/main/.vitepress/themeConfig/nav.js @@ -31,10 +31,6 @@ export const nav = [ { text: 'Cross-Chain Unbond Example', link: '/guides/orchestration/getting-started/contract-walkthrough/cross-chain-unbond', - }, - { - text: 'Orchestration Basics', - link: '/guides/orchestration/getting-started/contract-walkthrough/orchestration-basics', } ] }, diff --git a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md index 76ea8b8d9..860fc103a 100644 --- a/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md +++ b/main/guides/orchestration/getting-started/contract-walkthrough/send-anywhere.md @@ -1,4 +1,4 @@ -# SendAnywhere Contract Walkthrough +# "Send Anywhere" Contract Walkthrough The "Send Anywhere" contract is designed to facilitate the transfer of assets from one chain to another using Agoric's [Orchestration](/glossary/#orchestration) library. The contract allows a user to send assets of a specific brand @@ -15,7 +15,7 @@ The high-level flow of the contract is: The contract is implemented in two separate files: 1. `send-anywhere.contract.js` implements the `start` function of the contract to initialize the contract and - expose `publicFacet` and `creatorFacet`. + expose `publicFacet`. 2. `send-anywhere.flows.js` implements the `sendIt` function which performs the actual transfer of assets when a user makes an offer. Let us walk through these files one by one. diff --git a/main/guides/orchestration/getting-started/contract-walkthroughs.md b/main/guides/orchestration/getting-started/contract-walkthroughs.md index bebb50c9f..adacfab49 100644 --- a/main/guides/orchestration/getting-started/contract-walkthroughs.md +++ b/main/guides/orchestration/getting-started/contract-walkthroughs.md @@ -4,10 +4,9 @@ This section is designed to provide detailed explanations and insights into exam In this section, we will cover three primary contracts: -1. `Assets Transfer Contract`: A guide to `send-anywhere` contract that demonstrates a simple yet robust and secure way for cross-chain assets transfer. -2. `Swap Contract`: A comprehensive guide to the process of swapping assets between different chains using the Agoric orchestration library. -3. `Unbond Contract`: A detailed walkthrough of the unbonding and liquid staking process, highlighting the steps involved in managing cross-chain operations. -4. `Orchestration Basics Contract`: A dApp template serving as an introduction to the foundational concepts and implementation details of orchestration basics within an Agoric dApp. +1. **Assets Transfer Contract**: A guide to `send-anywhere` contract that demonstrates a simple yet robust and secure way for cross-chain assets transfer. +2. **Swap Contract**: A comprehensive guide to the process of swapping assets between different chains using the Agoric orchestration library. +3. **Unbond Contract**: A detailed walkthrough of the unbonding and liquid staking process, highlighting the steps involved in managing cross-chain operations. Each walkthrough will include detailed explanations of the contract code, providing insights into the mechanics and best practices of smart contract development on the Agoric platform. By the end of these walkthroughs, you should have a solid understanding of how to utilize Agoric’s tools and libraries to create robust and efficient cross-chain smart contracts. @@ -42,12 +41,3 @@ The Unbond Contract focuses on the process of unbonding staked assets and perfor - Managing asynchronous operations and ensuring the completion of long-running processes. [See Contract Overview](/guides/orchestration/getting-started/contract-walkthrough/cross-chain-unbond) - -## DApp Orchestration Basics - -DApp Orchestration Basics walkthrough will provide an introduction to the implementation level details of orchestration within an Agoric dApp. This guide aims to: - -- Explain the fundamental principles of orchestration. -- Show an end-to-end dApp using the Orchestration API - -[See Contract Overview](/guides/orchestration/getting-started/contract-walkthrough/orchestration-basics)