From 5e369ed6e8be7544b0fbebab4318e5a7a923a0ff Mon Sep 17 00:00:00 2001 From: cshannon1218 Date: Wed, 19 Nov 2025 11:11:11 -0600 Subject: [PATCH] Reference linking edits and additional style guide and consistency edits. --- .../account-linking-with-dapper.md | 50 ++--- .../account-management/child-accounts.md | 211 ++++++------------ .../cadence/account-management/index.md | 130 +++++------ .../account-management/parent-accounts.md | 177 +++++---------- .../compose-with-cadence-transactions.md | 28 +-- .../cadence/cadence-advantages/index.md | 12 +- ...-data-availibility-with-cadence-scripts.md | 28 +-- .../upgrading-cadence-contracts.md | 58 ++--- .../cadence/fork-testing/index.md | 44 ++-- .../building-a-frontend-app.md | 52 ++--- .../cadence-environment-setup.md | 24 +- .../cadence/getting-started/index.md | 20 +- .../getting-started/production-deployment.md | 25 ++- .../smart-contract-interaction.md | 52 ++--- .../cadence/index.md | 14 +- .../cadence/mobile/index.md | 12 +- .../cadence/mobile/ios-quickstart.md | 41 ++-- .../cadence/mobile/react-native-quickstart.md | 128 +++++++---- .../cadence/mobile/walletless-pwa.md | 70 +++--- 19 files changed, 551 insertions(+), 625 deletions(-) diff --git a/docs/blockchain-development-tutorials/cadence/account-management/account-linking-with-dapper.md b/docs/blockchain-development-tutorials/cadence/account-management/account-linking-with-dapper.md index 0e445e2d59..ae79003590 100644 --- a/docs/blockchain-development-tutorials/cadence/account-management/account-linking-with-dapper.md +++ b/docs/blockchain-development-tutorials/cadence/account-management/account-linking-with-dapper.md @@ -22,19 +22,19 @@ keywords: - asset management --- -# Account Linking With NBA Top Shot +# Account Linking with NBA Top Shot -[Account Linking] is a powerful Flow feature that allows users to connect their wallets, enabling linked wallets to view and manage assets in one wallet with another. This feature helps reduce or even eliminate the challenges posed by other account abstraction solutions, which often lead to multiple isolated wallets and fragmented assets. +[Account Linking] is a powerful Flow feature that allows users to connect their wallets, which allows linked wallets to view and manage assets in one wallet with another. This feature helps reduce or even eliminate the challenges posed by other account abstraction solutions, which often lead to multiple isolated wallets and fragmented assets. ![Top Shot Preview](./imgs/top-shot-preview.png) -In this tutorial, you'll build a [simple onchain app] that allows users to sign in to your app with their Flow wallet and view [NBA Top Shot] Moments that reside in their [Dapper Wallet] without those users needing to sign in with Dapper. +In this tutorial, you'll build a [simple onchain app] that allows users to sign in to your app with their Flow wallet and view [NBA Top Shot] Moments that reside in their [Dapper Wallet] without the need for those users to sign in with Dapper. ## Objectives After you complete this guide, you'll be able to: -- Pull your users' NBA Top Shot Moments into your Flow app without needing to transfer them out of their Dapper wallet. +- Pull your users' NBA Top Shot Moments into your Flow app without the need to transfer them out of their Dapper wallet. - Retrieve and list all NFT collections in any child wallet linked to a given Flow address. - Write a [Cadence] script to iterate through the storage of a Flow wallet to find NFT collections. - Run Cadence Scripts from the frontend. @@ -43,7 +43,7 @@ After you complete this guide, you'll be able to: ### Next.js and Modern Frontend Development -This tutorial uses [Next.js]. You don't need to be an expert, but it's helpful to be comfortable with development using a current React framework. You'll be on your own to select and use a package manager, manage Node versions, and other frontend environment tasks. If you don't have your own preference, you can just follow along with us and use [Yarn]. +This tutorial uses [Next.js]. You don't need to be an expert, but it's helpful to be comfortable with development with a current React framework. You'll be on your own to select and use a package manager, manage Node versions, and other frontend environment tasks. If you don't have your own preference, you can just follow along with us and use [Yarn]. ### Flow Wallet @@ -53,7 +53,7 @@ You'll need a [Flow Wallet], but you don't need to deposit any funds. You'll need a [Dapper Wallet] that contains some Moments NFTs, such as [NBA Top Shot] Moments. -## Getting Started +## Get Started This tutorial will use a [Next.js] project as the foundation of the frontend. Create a new project with: @@ -72,13 +72,13 @@ yarn run dev If everything works properly, you can navigate to `localhost:3000` and see the default [Next.js] page. -## Flow Cadence Setup +## Flow Cadence setup You'll need a few more dependencies to efficiently work with Cadence inside of your app. -### Flow CLI and Types +### Flow CLI and types -The [Flow CLI] contains a number of command-line tools for interacting with the Flow ecosystem. If you don't have it installed, you can add it with Brew (or using [other installation methods]): +The [Flow CLI] contains a number of command-line tools to interact with the Flow ecosystem. If you don't have it installed, you can add it with Brew (or with [other installation methods]): ```zsh brew install flow-cli @@ -90,7 +90,7 @@ After it's installed, initialize Flow in your `Next.js` project. From the root, flow init --config-only ``` -The `--config-only` flag [initializes a project] with the just the config file. This allows the Flow CLI to interact with your project without adding adding the other files you want for most projects. +The `--config-only` flag [initializes a project] with the just the config file. This allows the Flow CLI to interact with your project without the need to add the other files you want for most projects. Next, you'll need to do a little bit of config work so that your project knows how to read Cadence files. Install the Flow Cadence Plugin: @@ -116,7 +116,7 @@ const nextConfig: NextConfig = { export default nextConfig; ``` -## Frontend Setup +## Frontend setup We'll use the Flow Client Library [FCL] to manage blockchain interaction from the frontend. It's similar to `viem`, `ethers`, or `web3.js`, but works with the Flow blockchain and transactions and scripts written in Cadence. @@ -130,7 +130,7 @@ Go ahead and install `dotenv` as well: yarn add dotenv ``` -### Provider Setup +### Provider setup You'll need a fair amount of boilerplate code to set up your provider. We'll provide it, but since it's not the purpose of this tutorial, we'll be brief on explanations. For more details, check out the [App Quickstart Guide]. @@ -227,7 +227,7 @@ Don't forget to replace `` with your own [Wallet Connect] app id! ::: -### Implement the Provider and Flow Config +### Implement the provider and Flow Ccnfig Finally, open `layout.tsx`. TO start, import Flow dependencies and the AuthProvider: @@ -300,7 +300,7 @@ export default function RootLayout({ } ``` -### Add the Connect Button +### Add the connect button Open `page.tsx` and clean up the demo code, leaving only the `
` block: @@ -343,7 +343,7 @@ Then add a button in the `
` to handle logging in or out:
``` -## Testing Pass +## Test pass Run the app: @@ -361,7 +361,7 @@ Click `Log In` in the middle of the window and log in with your Flow wallet. Now that your app is set up, you can make use of [Account Linking] to to pull your NFTs from your Dapper Wallet, through your Flow Wallet, and into the app. -### Setting Up Account Linking +### Set up Account Linking If you haven't yet, you'll need to [link your Dapper Wallet] to your Flow Wallet. @@ -371,17 +371,17 @@ The Dapper Wallet requires that you complete KYC before you can use Account Link ::: -### Discovering the NFTs with a Script +### Discover the NFTs with a script With your accounts linked, your Flow Wallet now has a set of capabilities related to your Dapper Wallet and it can use those to view and even manipulate those NFTs and assets. -Before you can add a script that can handle this, you'll need to import the `HybridCustody` contract using the [Flow Dependency Manager]: +Before you can add a script that can handle this, you'll need to import the `HybridCustody` contract with the [Flow Dependency Manager]: ```zsh flow dependencies install mainnet://d8a7e05a7ac670c0.HybridCustody ``` -Choose `none` to skip deploying on the `emulator` and skip adding testnet aliases. There's no point, these NFTs are on mainnet! +Choose `none` to skip deployment on the `emulator` and skip adding testnet aliases. There's no point, these NFTs are on mainnet! You'll get a complete summary from the Dependency Manager: @@ -518,7 +518,7 @@ The above script is a relatively naive implementation. For production, you'll wa ::: -### Running the Script and Displaying the NFTs +### Run the script and display the NFTs Add a component in `app/components` called `DisplayLinkedNFTs.cdc`. @@ -532,7 +532,7 @@ import * as t from '@onflow/types'; import FetchNFTs from '../cadence/scripts/FetchNFTsFromLinkedAccts.cdc'; ``` -As we're using TypeScript, add some types as well to manage the data from the NFTs nicely. For now, just add them to this file: +As we use TypeScript, add some types as well to manage the data from the NFTs nicely. For now, just add them to this file: ```typescript type Thumbnail = { @@ -612,11 +612,11 @@ Return to `page.tsx`, import your new component, and add an instance of ` { }; ``` -Next, add a rendering function with some basic styling: +Next, add a render function with some basic styling: ```tsx // Function to render moments with validation @@ -705,7 +705,7 @@ return ( ); ``` -### Further Polish +### Further polish Finally, you can polish up your `page.tsx` to look a little nicer, and guide your users to the Account Linking process in the Dapper Wallet: diff --git a/docs/blockchain-development-tutorials/cadence/account-management/child-accounts.md b/docs/blockchain-development-tutorials/cadence/account-management/child-accounts.md index 9adec4fa0d..168c04b966 100644 --- a/docs/blockchain-development-tutorials/cadence/account-management/child-accounts.md +++ b/docs/blockchain-development-tutorials/cadence/account-management/child-accounts.md @@ -20,42 +20,36 @@ keywords: - user onboarding --- -In this tutorial, we'll dive into a progressive onboarding flow, including the Cadence scripts & transactions that go into -its implementation in your app. These components will allow any implementing app to create a custodial account, mediate -the user's onchain actions on their behalf, and later delegate access of that app-created account to the user's wallet. -We'll refer to this custodial pattern as the Hybrid Custody Model and the process of delegating control of the app -account as Account Linking. +# Building Walletless Applications Using Child Accounts + +In this tutorial, we'll dive into a progressive onboarding flow, along with the Cadence scripts and transactions that go into its implementation in your app. These components will allow any implementing app to create a custodial account, mediate the user's onchain actions on their behalf, and later delegate access of that app-created account to the user's wallet. We'll refer to this custodial pattern as the Hybrid Custody Model and the process of app account control delegation as Account Linking. ## Objectives -- Create a [walletless onboarding](https://flow.com/post/flow-blockchain-mainstream-adoption-easy-onboarding-wallets) - transaction -- Link an existing app account as a child to a newly authenticated parent account. +- Create a [walletless onboarding] + transaction. +- Link a current app account as a child to a newly authenticated parent account. - Get your app to recognize "parent" accounts along with any associated "child" accounts. - Put it all together to create a blockchain-native onboarding transaction. -- View fungible and non-fungible Token metadata relating to assets across all of a user's associated accounts - their +- View fungible and non-fungible Token metadata that relates to assets across all of a user's associated accounts - their wallet-mediated "parent" account and any "child" accounts. - Facilitate transactions acting on assets in child accounts. -## Point of Clarity +## Point of clarity -Before we dive in, let's make a distinction between "account linking" and "linking accounts". +Before we dive in, let's make a distinction between "Account Linking" and "linking accounts". ### Account Linking :::info -Since account linking is a sensitive action, transactions where an account may be linked are designated by a -topline pragma `#allowAccountLinking`. This lets wallet providers inform users that their account may be linked in the -signed transaction. +Since Account Linking is a sensitive action, transactions where an account may be linked are designated by a topline pragma `#allowAccountLinking`. This lets wallet providers inform users that their account may be linked in the signed transaction. ::: -Very simply, account linking is a [feature in Cadence](https://github.com/onflow/flips/pull/53) that lets an -[Account](https://cadence-lang.org/docs/language/accounts#authaccount) create a -[Capability](https://cadence-lang.org/docs/language/capabilities) on itself. +Very simply, Account Linking is a [feature in Cadence] that lets an [Account] create a [Capability] on itself. -Below is an example demonstrating how to issue an `&Account` Capability from a signing account transaction: +Below is an example that demonstrates how to issue an `&Account` Capability from a signing account transaction: ```cadence link_account.cdc #allowAccountLinking @@ -70,66 +64,39 @@ transaction(linkPathSuffix: String) { } ``` -From there, the signing account can retrieve the privately linked `&Account` Capability and delegate it to another -account, which revokes the Capability if they wish to revoke delegated access. +From there, the signing account can retrieve the privately linked `&Account` Capability and delegate it to another account, which revokes the Capability if they wish to revoke delegated access. -To link an account, a transaction must state the `#allowAccountLinking` pragma in the top line of the -transaction. This is an interim safety measure so that wallet providers can notify users they're about to sign a -transaction that may create a Capability on their `Account`. +To link an account, a transaction must state the `#allowAccountLinking` pragma in the top line of the transaction. This is an interim safety measure so that wallet providers can notify users they're about to sign a transaction that may create a Capability on their `Account`. -### Linking Accounts +### Linking accounts -Linking accounts leverages this account link, otherwise known as an **`&Account` Capability**, and encapsulates it. The -[components and actions](https://github.com/onflow/flips/pull/72) involved in this process - what the Capability is -encapsulated in, the collection that holds those encapsulations, and so on is what we'll dive into in this doc. +Linking accounts leverages this account link, otherwise known as an **`&Account` Capability**, and encapsulates it. The [components and actions] involved in this process - what the Capability is encapsulated in, the collection that holds those encapsulations, and so on is what we'll dive into in this doc. ## Terminology -**Parent-Child accounts** - For the moment, we'll call the account that the app creates the "child" account and the -account that receives its `&Account` Capability the "parent" account. Current methods of account access & delegation (for example, -keys) still imply ownership over the account, but where linked accounts are concerned, the account to which both -the user and the app share access via `&Account` Capability are considered the "child" account. +**Parent-Child accounts** - For the moment, we'll call the account that the app creates the "child" account and the account that receives its `&Account` Capability the "parent" account. Current methods of account access and delegation (for example, keys) still imply ownership over the account, but where linked accounts are concerned, the account to which both the user and the app share access via `&Account` Capability are considered the "child" account. -**Walletless onboarding** - An onboarding flow whereby an app creates a custodial account for a user and onboards them to -the app, which obviates the need for user wallet authentication. +**Walletless onboarding** - An onboarding flow whereby an app creates a custodial account for a user and onboards them to the app, which obviates the need for user wallet authentication. -**Blockchain-native onboarding** - Similar to the already familiar Web3 onboarding flow where a user authenticates with -their existing wallet, an app onboards a user via wallet authentication while additionally creating a custodial app -account and linking it with the authenticated account, resulting in a "hybrid custody" model. +**Blockchain-native onboarding** - Similar to the already familiar Web3 onboarding flow where a user authenticates with their existing wallet, an app onboards a user via wallet authentication while it also creates a custodial app account and links it with the authenticated account, which creates a "hybrid custody" model. -**Hybrid Custody Model** - A custodial pattern in which an app and a user maintain access to an app-created account and -user access to that account is mediated via account linking. +**Hybrid Custody Model** - A custodial pattern in which an app and a user maintain access to an app-created account and user access to that account is mediated via Account Linking. -**Account Linking** - Account linking in our context means to give some other account an -`&Account` Capability from the granting account. This Capability is maintained in standardized resource called a -`HybridCustody.Manager`, which provides its owning user access to any and all of their linked accounts. +**Account Linking** - Account Linking in our context means to give some other account an `&Account` Capability from the granting account. This Capability is maintained in standardized resource called a `HybridCustody.Manager`, which provides its owning user access to any and all of their linked accounts. -**Progressive Onboarding** - An onboarding flow that walks a user up to self-custodial ownership, starting with -walletless onboarding and later linking the app account with the user's authenticated wallet when the user chooses to do -so. +**Progressive Onboarding** - An onboarding flow that walks a user up to self-custodial ownership, which starts with walletless onboarding and later links the app account with the user's authenticated wallet when the user chooses to do so. -**Restricted Child Account** - An account delegation where the access on the delegating account is restricted according -to rules set by the linking child account. We will expand on the distinctions between this and the subsequent term ("owned" account) later. +**Restricted Child Account** - An account delegation where the access on the delegating account is restricted according to rules set by the linking child account. We will expand on the distinctions between this and the subsequent term ("owned" account) later. -**Owned Account** - An account delegation where the delegatee has unrestricted access on the delegating child account, -which gives the delegatee presiding authority superseding any other "restricted" parent accounts. +**Owned Account** - An account delegation where the delegatee has unrestricted access on the delegating child account, which gives the delegatee presiding authority that supersedes any other "restricted" parent accounts. ## Account Linking -Linking an account delegates account access via `&Account` Capability. Of course, we want to do this -in a way that allows the receiving account to maintain that Capability and allows easy identification of the accounts on -either end of the linkage - the user's main "parent" account and the linked "child" account. This is accomplished in the -`HybridCustody` contract which we'll continue to use in this guidance. +Linking an account delegates account access via `&Account` Capability. Of course, we want to do this in a way that allows the receiving account to maintain that Capability and allows easy identification of the accounts on either end of the linkage - the user's main "parent" account and the linked "child" account. This is accomplished in the `HybridCustody` contract which we'll continue to use in this guidance. ### Prerequisites -Since account delegation is mediated by developer-defined rules, you should make sure to first configure the resources -that contain those rules. Contracts involved in defining and enforcing this ruleset are -[`CapabilityFilter`](https://github.com/onflow/hybrid-custody/blob/main/contracts/CapabilityFilter.cdc) and -[`CapabilityFactory`](https://github.com/onflow/hybrid-custody/blob/main/contracts/CapabilityFactory.cdc). The former -enumerates those types that are and are not accessible from a child account while the latter allows the access of those -allowable Capabilities such that the returned values can be properly typed - for example, retrieving a Capability that can be -cast to `Capability<&NonFungibleToken.Collection>` for example. +Since account delegation is mediated by developer-defined rules, you should make sure to first configure the resources that contain those rules. Contracts that help define and enforce this ruleset are [`CapabilityFilter`] and [`CapabilityFactory`]. The former enumerates those types that are and are not accessible from a child account while the latter allows the access of those allowable Capabilities such that the returned values can be properly typed - for example, to retrieve a Capability that can be cast to `Capability<&NonFungibleToken.Collection>`. Here's how you would configure an `AllowlistFilter` and add allowed types to it: @@ -171,9 +138,7 @@ And the following transaction configures a `CapabilityFactory.Manager`, adding N :::info -The Manager configured here allows retrieval of castable Capabilities. We recommend that you implement -Factory resource definitions to support any NFT Collections related with the use of your application so that users can -retrieve Typed Capabilities from accounts linked from your app. +The Manager configured here allows retrieval of castable Capabilities. We recommend that you implement Factory resource definitions to support any NFT Collections related with the use of your application so that users can retrieve Typed Capabilities from accounts linked from your app. ::: @@ -221,37 +186,30 @@ transaction { ![resources/hybrid_custody_high_level](./imgs/hybrid_custody_high_level.png) -_In this scenario, a user custodies a key for their main account which maintains access to a wrapped `Account` -Capability. This provides the user restricted access on the app account. The app maintains custodial access to the account -and regulates the access restrictions to delegatee "parent" accounts._ +_In this scenario, a user custodies a key for their main account which maintains access to a wrapped `Account` Capability. This provides the user restricted access on the app account. The app maintains custodial access to the account and regulates the access restrictions to delegatee "parent" accounts._ -You can link accounts in one of two ways. Put simply, the child account needs to get the parent an `Account` -Capability, and the parent needs to save that Capability so they can retain access. This delegation must occur in a way that represents each side of the link and safeguard the integrity of any access restrictions an application puts in -place on delegated access. +You can link accounts in one of two ways. Put simply, the child account needs to get the parent an `Account` Capability, and the parent needs to save that Capability so they can retain access. This delegation must occur in a way that represents each side of the link and safeguard the integrity of any access restrictions an application puts in place on delegated access. -We can achieve issuance from the child account and claim from the parent account pattern by either: +To achieve issuance from the child account and claim from the parent account pattern, we can either: -1. Leveraging [Cadence's `Account.Inbox`](https://cadence-lang.org/docs/language/accounts#account-inbox) to publish the Capability from the child account & have the parent claim the Capability in a subsequent transaction. -2. Executing a multi-party signed transaction, signed by both the child and parent accounts. +1. Leverage [Cadence's `Account.Inbox`] to publish the Capability from the child account and have the parent claim the Capability in a subsequent transaction. +2. Execute a multi-party signed transaction, signed by both the child and parent accounts. Let's take a look at both. :::info -You'll want to consider whether you would like the parent account to be configured with some app-specific resources or -Capabilities and compose you multisig or claim transactions to include such configurations. +You'll want to consider whether you would like the parent account to be configured with some app-specific resources or Capabilities and compose you multisig or claim transactions to include such configurations. -For example, if your app deals with specific NFTs, you may want to configure the parent account with Collections for -those NFTs so the user can easily transfer them between their linked accounts. +For example, if your app deals with specific NFTs, you may want to configure the parent account with Collections for those NFTs so the user can easily transfer them between their linked accounts. ::: -### Publish & Claim +### Publish and claim #### Publish -Here, the account delegates access to itself, which links its `&Account` Capability and publishes it to be claimed by the -designated parent account. +Here, the account delegates access to itself, which links its `&Account` Capability and publishes it to be claimed by the designated parent account. ```cadence publish_to_parent.cdc import "HybridCustody" @@ -290,8 +248,7 @@ transaction(parent: Address, factoryAddress: Address, filterAddress: Address) { #### Claim -On the other side, the receiving account claims the published `ChildAccount` Capability, which adds it to the signer's -`HybridCustody.Manager.childAccounts` indexed on the child account's Address. +On the other side, the receiving account claims the published `ChildAccount` Capability, which adds it to the signer's `HybridCustody.Manager.childAccounts` indexed on the child account's Address. ```cadence redeem_account.cdc import "MetadataViews" @@ -351,13 +308,11 @@ transaction(childAddress: Address, filterAddress: Address?, filterPath: PublicPa ### Multi-Signed Transaction -We can combine the two transactions in [Publish](#publish) and [Claim](#claim) into a single multi-signed transaction to -achieve Hybrid Custody in a single step. +We can combine the two transactions in [Publish] and [Claim] into a single multi-signed transaction to achieve Hybrid Custody in a single step. :::info -While the following code links both accounts in a single transaction, in practicality you may find it easier -to execute publish and claim transactions separately depending on your custodial infrastructure. +While this code links both accounts in a single transaction, in practicality you may find it easier to execute publish and claim transactions separately depending on your custodial infrastructure. ::: @@ -456,21 +411,13 @@ transaction(parentFilterAddress: Address?, childAccountFactoryAddress: Address, } ``` -## Onboarding Flows +## Onboarding flows -Given the ability to establish an account and later delegate access to a user, apps are freed from the constraints of -dichotomous custodial & self-custodial paradigms. A developer can choose to onboard a user via traditional Web2 identity -and later delegate access to the user's wallet account. Alternatively, an app can enable wallet authentication at the -outset, creating an app-specific account & linking with the user's wallet account. As specified above, these two flows -are known as "walletless" and "blockchain-native" onboarding respectively. Developers can choose to implement one for -simplicity or both for maximum flexibility. +Given the ability to establish an account and later delegate access to a user, apps are freed from the constraints of dichotomous custodial and self-custodial paradigms. A developer can choose to onboard a user via traditional Web2 identity and later delegate access to the user's wallet account. Alternatively, an app can enable wallet authentication at the outset, which creates an app-specific account & link with the user's wallet account. As specified above, these two flows are known as "walletless" and "blockchain-native" onboarding respectively. Developers can choose to implement one for simplicity or both for maximum flexibility. -### Walletless Onboarding +### Walletless onboarding -The following transaction creates an account, funding creation via the signer and adding the provided public key. You'll -notice this transaction is pretty much your standard account creation. The magic for you will be how you custody the key -for this account (locally, KMS, wallet service, etc.) in a manner that allows your app to mediate onchain interactions -on behalf of your user. +This transaction creates an account, funding creation via the signer and adding the provided public key. You'll notice this transaction is pretty much your standard account creation. The magic for you will be how you custody the key for this account (locally, KMS, wallet service, and so on) in a manner that allows your app to mediate onchain interactions on behalf of your user. ```cadence walletless_onboarding import "FungibleToken" @@ -526,27 +473,25 @@ transaction(pubKey: String, initialFundingAmt: UFix64) { } ``` -### Blockchain-Native Onboarding +### Blockchain-native onboarding This onboarding flow is really a single-transaction composition of the steps covered above. This is a testament to the power of the complex transactions you can compose on Flow with Cadence! :::info -Recall the [prerequisites](#prerequisites) needed to be satisfied before linking an account: +Recall the [prerequisites] needed to be satisfied before linking an account: 1. CapabilityFilter Filter saved and linked. 2. CapabilityFactory Manager saved and linked as well as Factory implementations supporting the Capability Types you'll want accessible from linked child accounts as Typed Capabilities. ::: -#### Account Creation & Linking +#### Account creation & linking -Compared to walletless onboarding where a user does not have a Flow account, blockchain-native onboarding assumes a user already has a wallet configured and immediately links it with a newly created app account. This allows the app to sign transactions on the user's behalf via the new child account while immediately delegating control of that account to the onboarding user's main account. +Compared to walletless onboarding where a user does not have a Flow account, blockchain-native onboarding assumes a user already has a wallet configured and immediately links it with a newly created app account. This allows the app to sign transactions on the user's behalf via the new child account and immediately delegate control of that account to the onboarding user's main account. -After this transaction, both the custodial party (presumably the client/app) and the signing parent account will have -access to the newly created account - the custodial party via key access and the parent account via their -`HybridCustody.Manager` maintaining the new account's `ChildAccount` Capability. +After this transaction, both the custodial party (presumably the client/app) and the signing parent account will have access to the newly created account - the custodial party via key access and the parent account via their `HybridCustody.Manager` that maintains the new account's `ChildAccount` Capability. ```cadence blockchain_native_onboarding.cdc #allowAccountLinking @@ -676,50 +621,42 @@ transaction( ## Funding & Custody Patterns -Aside from implementing onboarding flows and account linking, you'll want to also consider the account funding & custodial -pattern appropriate for the app you're building. The only pattern compatible with walletless onboarding (and therefore -the only one showcased above) is one in which the app custodies the child account's key and funds account creation. +Aside from the implementation of onboarding flows and Account Linking, you'll want to also consider the account funding & custodial pattern appropriate for the app you want to build. The only pattern compatible with walletless onboarding (and therefore the only one showcased above) is one in which the app custodies the child account's key and funds account creation. -In general, the funding pattern for account creation will determine, to some extent, the backend infrastructure needed to -support your app and the onboarding flow your app can support. For example, if you want to to create a service-less -client (a totally local app without backend infrastructure), you could forego walletless onboarding in favor of a -user-funded blockchain-native onboarding to achieve a hybrid custody model. Your app maintains the keys to the app -account locally to sign on behalf of the user, and the user funds the creation of the the account, linking to their main -account on account creation. This would be a **user-funded, app custodied** pattern. +In general, the funding pattern for account creation will determine, to some extent, the backend infrastructure needed to support your app and the onboarding flow your app can support. For example, if you want to to create a service-less client (a totally local app without backend infrastructure), you could forego walletless onboarding in favor of a user-funded blockchain-native onboarding to achieve a hybrid custody model. Your app maintains the keys to the app account locally to sign on behalf of the user, and the user funds the creation of the the account, which links to their main account on account creation. This would be a **user-funded, app custodied** pattern. -Again, custody may deserve some regulatory insight depending on your jurisdiction. If building for production, you'll -likely want to consider these non-technical implications in your technical decision-making. Such is the nature of -building in crypto. +Again, custody may deserve some regulatory insight depending on your jurisdiction. If you build for production, you'll likely want to consider these non-technical implications in your technical decision-making. Such is the nature of building in crypto. Here are the patterns you might consider: -### App-Funded, App-Custodied +### App-funded, app-custodied + +If you want to implement walletless onboarding, you can stop here as this is the only compatible pattern. In this scenario, a backend app account funds the creation of a new account and the app custodies the key for said account either on the user's device or some backend KMS. + +### App-funded, user-custodied -If you want to implement walletless onboarding, you can stop here as this is the only compatible pattern. In this -scenario, a backend app account funds the creation of a new account and the app custodies the key for said account -either on the user's device or some backend KMS. +In this case, the backend app account funds account creation, but adds a key to the account which the user custodies. For the app to act on the user's behalf, it has to be delegated access via `&Account` Capability which the backend app account would maintain in a `HybridCustody.Manager`. This means that the new account would have two parent accounts - the user's and the app. -### App-Funded, User-Custodied +While this pattern provides the user maximum ownership and authority over the child account, it may present unique considerations and edge cases for you as a builder depending on your app's access to the child account. Also note that this and the following patterns are incompatible with walletless onboarding in that the user must have a walletvpre-configured before onboarding. -In this case, the backend app account funds account creation, but adds a key to the account which the user custodies. In -order for the app to act on the user's behalf, it has to be delegated access via `&Account` Capability which the backend -app account would maintain in a `HybridCustody.Manager`. This means that the new account would have two parent accounts -- the user's and the app. +### User-funded, app-custodied -While this pattern provides the user maximum ownership and authority over the child account, it may present unique -considerations and edge cases for you as a builder depending on your app's access to the child account. Also note that -this and the following patterns are incompatible with walletless onboarding in that the user must have a wallet -pre-configured before onboarding. +As mentioned above, this pattern unlocks totally service-less architectures - just a local client and smart contracts. An authenticated user signs a transaction creating an account, adds the key that the client provides, and links the account as a child account. At the end of the transaction, hybrid custody is achieved and the app can sign with the custodied key on the user's behalf with the newly-created account. -### User-Funded, App-Custodied +### User-funded, user-custodied -As mentioned above, this pattern unlocks totally service-less architectures - just a local client & smart contracts. An -authenticated user signs a transaction creating an account, adding the key provided by the client, and linking the -account as a child account. At the end of the transaction, hybrid custody is achieved and the app can sign with the -custodied key on the user's behalf using the newly created account. +While perhaps not useful for most apps, this pattern may be desirable for advanced users who wish to create a shared access account themselves. The user funds account creation, adds keys they custody, and delegates secondary access to some other account. -### User-Funded, User-Custodied + -While perhaps not useful for most apps, this pattern may be desirable for advanced users who wish to create a shared -access account themselves. The user funds account creation, adding keys they custody, and delegates secondary access to -some other account. \ No newline at end of file +[Account]: https://cadence-lang.org/docs/language/accounts#authaccount +[Cadence's `Account.Inbox`]: https://cadence-lang.org/docs/language/accounts#account-inbox +[Capability]: https://cadence-lang.org/docs/language/capabilities +[`CapabilityFilter`]: https://github.com/onflow/hybrid-custody/blob/main/contracts/CapabilityFilter.cdc +[`CapabilityFactory`]: https://github.com/onflow/hybrid-custody/blob/main/contracts/CapabilityFactory.cdc +[Claim]: #claim +[components and actions]: https://github.com/onflow/flips/pull/72 +[feature in Cadence]: https://github.com/onflow/flips/pull/53 +[walletless onboarding]: https://flow.com/post/flow-blockchain-mainstream-adoption-easy-onboarding-wallets +[prerequisites]: #prerequisites +[Publish]: #publish \ No newline at end of file diff --git a/docs/blockchain-development-tutorials/cadence/account-management/index.md b/docs/blockchain-development-tutorials/cadence/account-management/index.md index 2791497077..2d4373b51b 100644 --- a/docs/blockchain-development-tutorials/cadence/account-management/index.md +++ b/docs/blockchain-development-tutorials/cadence/account-management/index.md @@ -22,56 +22,33 @@ keywords: # Account Linking -Account linking is a unique Flow concept that allows sharing ownership over [accounts](../../../build/cadence/basics/accounts.md). To understand how we can achieve that, we must first understand how to access accounts on Flow. +Account Linking is a unique Flow concept that allows sharing ownership over [accounts]. To understand how we can achieve that, we must first understand how to access accounts on Flow. -You can access accounts on flow in Cadence through two types, `PublicAccount` and `Account`. As the name implies, the -`PublicAccount` type gives access to all public account information such as address, balance, storage capacity, etc., -but doesn't allow changes to the account. The `Account` type (or more specifically, an -[entitled](https://cadence-lang.org/docs/language/access-control#entitlements) `&Account`) allows the same access as -`PublicAccount` but also allows changes to the account, which includes adding or revoking account keys, managing the deployed -contracts, as well as linking and publishing Capabilities. +You can access accounts on flow in Cadence through two types, `PublicAccount` and `Account`. As the name implies, the `PublicAccount` type gives access to all public account information such as address, balance, storage capacity, etc., but doesn't allow changes to the account. The `Account` type (or more specifically, an [entitled]`&Account`) allows the same access as `PublicAccount` but also allows changes to the account, which includes adding or revoking account keys, managing the deployed contracts, as well as linking and publishing Capabilities. ![Flow account structure](./imgs/account-structure.png) -## Accessing Account +## Access Account -Accessing `Account` allows for modification to account storage, so it's essential to mandate that the account being accessed signs all transactions, which safeguards this access. -[Account -entitlements](https://cadence-lang.org/docs/language/accounts/#performing-write-operations) allow for more granular -access control over the specific parts of the account that you can access from within the signed transaction. A -transaction can list multiple authorizing account it wants to access as part of the `prepare` section of the -transaction. Read more about transaction signing in the [transaction documentation](../../../build/cadence/basics/transactions.md). +When you access `Account`, you can modify account storage, so it's essential to mandate that the account being accessed signs all transactions, which safeguards this access. [Account entitlements] allow for more granular access control over the specific parts of the account that you can access from within the signed transaction. A transaction can list multiple authorizing account it wants to access as part of the `prepare` section of the transaction. Read more about transaction signing in the [transaction documentation]. -Since access to the `Account` object allows state change, the idea of account ownership actually translates to the -ability to access the underlying account. Traditionally, you might consider this the same as having key access on an -account, but we'll see in just a minute how programmatic, ownership-level access is unlocked with [Capabilities on -Flow](https://cadence-lang.org/docs/language/capabilities). +Since access to the `Account` object allows state change, the idea of account ownership actually translates to the ability to access the underlying account. Traditionally, you might consider this the same as having key access on an account, but we'll see in just a minute how programmatic, ownership-level access is unlocked with [Cadence Capabilities] ## Account Capabilities -Before you continue with this section, you'll need a clear understanding of [Cadence -capabilities](https://cadence-lang.org/docs/language/capabilities). Advanced features such as -Account Capabilities are powerful, but they can put your app or users at risk if used incorrectly. +Before you continue with this section, you'll need a clear understanding of [Cadence Capabilities]. Advanced features such as Account Capabilities are powerful, but they can put your app or users at risk if used incorrectly. -Cadence allows for Capabilities creation to delegate access to account storage, which means any account that obtains a valid -Ccapability to another account object in the storage can access it. This is a powerful feature on its own - accessing -another account programmatically without the need for an active key on the accessible account. You can limit the access to the object when you create a Capability so your users can only access intended functions or fields. +Cadence allows for Capabilities creation to delegate access to account storage, which means any account that obtains a valid Ccapability to another account object in the storage can access it. This is a powerful feature on its own - to access another account programmatically without the need for an active key on the accessible account. You can limit the access to the object when you create a Capability so your users can only access intended functions or fields. -Account linking is made possible by the extension of Capabilities on the `Account` object itself. Similar to how storage -capabilities allow access to a value stored in an account's storage, `&Account` Capabilities allow delegated access to -the issuing `Account`. These Capabilities allow for access to key assignment, contract deployment, and other privileged -actions on the delegating `Account` - effectively sharing ownership of the account without ever adding or sharing a key. -This Capability can of course be revoked at any time by the delegating account. +Account Linking is made possible by the extension of Capabilities on the `Account` object itself. Similar to how storage capabilities allow access to a value stored in an account's storage, `&Account` Capabilities allow delegated access to the issuing `Account`. These Capabilities allow for access to key assignment, contract deployment, and other privileged actions on the delegating `Account` - which effectively shares account ownership without the need to add or share a key. The delegating account can revoke this Capability at any time. -### Creating Account Links +### Create Account Links -When we refer to 'account linking,' we mean that the parent account creates an `&Account` Capability and published -to another account. The account that owns the `&Account` Capability which was made available to another account is the child -account. The account in possession of the Capability given by the child account becomes its parent account. +When we refer to 'Account Linking,' we mean that the parent account creates an `&Account` Capability and published to another account. The account that owns the `&Account` Capability which was made available to another account is the child account. The account in possession of the Capability given by the child account becomes its parent account. ![Account linking on Flow relational diagram](./imgs/account-linking-relational-diagram.png) -You can create a link between two existing accounts on Flow in two steps: +You can create a link between two current accounts on Flow in two steps: 1. A child account creates an `&Account` Capability and publishes it to the parent account. 2. The parent account, claims that Capability and can access the child's account through it. @@ -124,21 +101,13 @@ transaction { } ``` -## What is account linking most useful for? +## What is Account Linking most useful for? -Account linking was specifically designed to allow smooth and seamless custodial onboarding of users to your Flow based -application without them first requiring a wallet to do so. This pattern overcomes both the technical hurdle, as well as -user's reluctance to install a wallet, which opens access to Flow applications to every user. Users can experience an app -without any delay while still offering a path to self-sovreign ownership. +Account Linking was specifically designed to allow smooth and seamless custodial onboarding of users to your Flow-based application without the requirement of a wallet to do so. This pattern overcomes both the technical hurdle, as well as user's reluctance to install a wallet, which opens access to Flow applications to every user. Users can experience an app without any delay and still offer a path to self-sovreign ownership. -Naturally, users may expect to use their account with another application, or otherwise move assets stored in that -account elsewhere - at minimum from their wallet. When an app initially leverages account linking, the app creates the -account instead of the user and stores that user's specific state in the app-created account. At a later point, users -can take ownership of the app account providing they possess a full [Flow account](../../../build/cadence/basics/accounts.md), typically -by installing a wallet app. +Naturally, users may expect to use their account with another application, or otherwise move assets stored in that account elsewhere - at minimum from their wallet. When an app initially leverages Account Linking, the app creates the account instead of the user and stores that user's specific state in the app-created account. At a later point, users can take ownership of the app account if they possess a full [Flow account], which they can get if they install a wallet app. -Account linking allows users to possess multiple linked child accounts from different apps. Complexities associated -with accessing those child accounts are eliminated by abstracting access to them through the user's parent account. +Account Linking allows users to possess multiple linked child accounts from different apps. Access complexities associated with those child accounts are eliminated if you abstract access to them through the user's parent account. :::info @@ -146,40 +115,31 @@ Simply put, child accounts are accessed and can be treated as a seamless part of ::: -All assets in the app account can now jump the walled garden to play in the rest of the Flow ecosystem. The user does -not need to rely on the custodial app to execute transactions moving assets from the child account as the parent account -already has access to the assets in the child account. +All assets in the app account can now jump the walled garden to play in the rest of the Flow ecosystem. The user does not need to rely on the custodial app to execute transactions moving assets from the child account as the parent account already has access to the assets in the child account. ![Multiple parent-child accounts on Flow](./imgs/account-linking-multiple-accounts.png) -This shared control over the digital items in the in-app account allows users to establish real ownership of the items -beyond the context of the app, where they can use their parent account to view inventory, take the items to other apps -in the ecosystem, such as a marketplace or a game. +This shared control over the digital items in the in-app account allows users to establish real ownership of the items beyond the context of the app, where they can use their parent account to view inventory, take the items to other apps in the ecosystem, such as a marketplace or a game. -Most importantly, users can do this without the need to transfer the digital items between accounts, which makes it -seamless to continue using the original app and enjoy their assets in other contexts. +Most importantly, users can do this without the need to transfer the digital items between accounts, which makes it seamless to continue to use the original app and enjoy their assets in other contexts. -## Security Considerations +## Security considerations -Account linking is a _very_ powerful Cadence feature, and thus it must be treated with care. So far in this document, -we've discussed account linking between two accounts we own, even if a third-party -application manages the child account. But, we can't make the same trust assumptions about custodial accounts in the real world. +Account Linking is a _very_ powerful Cadence feature, and thus you must treat it with care. So far in this document, we've discussed Account Linking between two accounts we own, even if a third-party application manages the child account. But, we can't make the same trust assumptions about custodial accounts in the real world. -If we create an `&Account` Capability and publish it to an account we don't own, we give that account full -access to our account. This should be seen as an anti-pattern. +If we create an `&Account` Capability and publish it to an account we don't own, we give that account full access to our account. This should be seen as an anti-pattern. :::warning -If you create an `&Account` Capability and share it with a third-party account, you effectively give that person your -account's private keys. +If you create an `&Account` Capability and share it with a third-party account, you effectively give that person your account's private keys. ::: -Because unfiltered account linking can be dangerous, Flow introduces the [`HybridCustody` -contract](./parent-accounts.md) that helps custodial applications regulate access and allows parent accounts to -manage their many child accounts and assets within them. +Because unfiltered account linking can be dangerous, Flow introduces the `HybridCustody` contract that helps custodial applications regulate access and allows parent accounts to manage their many child accounts and assets within them. -## Hybrid Custody and Account Linking +Learn more about it in the [Working With Parent Accounts] documentation. + +## Hybrid custody and Account Linking Apps need assurances that their own resources are safe from malicious actors, so to permit full access might not be what they want. Hybrid custody contracts will allow the app to maintain control of their managed accounts, but they can: @@ -187,22 +147,34 @@ Apps need assurances that their own resources are safe from malicious actors, so parent accounts via helper contracts (the `CapabilityFactory`, and `CapabilityFilter`). 2. Share additional capabilities (public or private) with a parent account via a `CapabilityDelegator` resource. -Learn more about it in the [Hybrid Custody documentation](./parent-accounts.md). + ### Guides -- [Building Walletless Applications Using Child Accounts](./child-accounts.md) covers how apps can leverage Account - Linking to create a seamless user experience and allow future self-custody. -- [Working With Parent Accounts](./parent-accounts.md) covers features enabled by the core `HybridCustody` contract to - access child account assets from parent accounts. This is useful for apps like marketplaces or wallets that are - working with accounts that have potential child accounts. +- [Building Walletless Applications Using Child Accounts] covers how apps can leverage Account Linking to create a seamless user experience and allow future self-custody. +- [Working With Parent Accounts] covers features activated by the core `HybridCustody` contract to access child account assets from parent accounts. This is useful for apps like marketplaces or wallets that work with accounts that have potential child accounts. ### Resources -- [Forum Post](https://forum.flow.com/t/hybrid-custody/4016) where core concepts were introduced and discussed. -- [GitHub repository](https://github.com/onflow/hybrid-custody) where `HybridCustody` core contracts and scripts are - maintained. Check out the repository for more advanced script or transaction examples. -- [Example](https://github.com/jribbink/magic-link-hc-sample/) Account Linking project with - [Magic](https://magic.link/). -- [Starter template](https://github.com/Niftory/niftory-samples/tree/main/walletless-onboarding) for - [Niftory](https://niftory.com/) Account Linking API. +- [Forum Post] where core concepts were introduced and discussed. +- [GitHub repository] where `HybridCustody` core contracts and scripts are maintained. Check out the repository for more advanced script or transaction examples. +- [Example] - Account Linking project with [Magic]. +- [Starter template] for [Niftory] Account Linking API. + + + + +[accounts]: ../../../build/cadence/basics/accounts.md +[Account entitlements]: https://cadence-lang.org/docs/language/accounts/#performing-write-operations +[Building Walletless Applications Using Child Accounts]: ./child-accounts.md +[Cadence capabilities]: https://cadence-lang.org/docs/language/capabilities +[entitled]: https://cadence-lang.org/docs/language/access-control#entitlements) +[Flow account]: ../../../build/cadence/basics/accounts.md +[Forum Post]: https://forum.flow.com/t/hybrid-custody/4016 +[GitHub repository]: https://github.com/onflow/hybrid-custody +[Example]: https://github.com/jribbink/magic-link-hc-sample/ +[Magic]: https://magic.link/ +[Starter template]: https://github.com/Niftory/niftory-samples/tree/main/walletless-onboarding +[Niftory]: https://niftory.com/ +[transaction documentation]: ../../../build/cadence/basics/transactions.md +[Working With Parent Accounts]: ./parent-accounts.md \ No newline at end of file diff --git a/docs/blockchain-development-tutorials/cadence/account-management/parent-accounts.md b/docs/blockchain-development-tutorials/cadence/account-management/parent-accounts.md index b3f460af9d..0b3c5b8f34 100644 --- a/docs/blockchain-development-tutorials/cadence/account-management/parent-accounts.md +++ b/docs/blockchain-development-tutorials/cadence/account-management/parent-accounts.md @@ -20,9 +20,9 @@ keywords: - account security --- -In this tutorial, we'll continue from the perspective of a wallet or marketplace app seeking to facilitate a unified account -experience, abstracting away the partitioned access between accounts into a single dashboard for user interactions on -all their owned assets. +# Working With Parent Accounts + +In this tutorial, we'll continue from the perspective of a wallet or marketplace app who seeks to facilitate a unified account experience, and abstract away the partitioned access between accounts into a single dashboard for user interactions on all their owned assets. ## Objectives @@ -37,110 +37,65 @@ all their owned assets. :::info -TL;DR: An account's -[`HybridCustody.Manager`](https://github.com/onflow/hybrid-custody/blob/main/contracts/HybridCustody.cdc) is the entry -point for all of a user's associated accounts. +TL;DR: An account's [`HybridCustody.Manager`] is the entry point for all of a user's associated accounts. ::: -The basic idea in the Hybrid Custody model is relatively simple. A parent account is one that has received delegated -(albeit restricted) access on another account. The account which has delegated authority over itself to the parent -account is the child account. +The basic idea in the Hybrid Custody model is relatively simple. A parent account is one that has received delegated (albeit restricted) access on another account. The account which has delegated authority over itself to the parent account is the child account. -In the [Hybrid Custody Model](https://forum.flow.com/t/hybrid-custody/4016), this child account would have shared -access between the app - the entity which created and likely custodies the account - and the linked parent account. +In the [Hybrid Custody Model], this child account would have shared access between the app - the entity which created and likely custodies the account - and the linked parent account. -How does this delegation occur? Typically when we think of shared account access in crypto, we think keys. However, -Cadence enables [accounts to link Capabilities on -themselves](https://cadence-lang.org/docs/language/accounts/capabilities#accountcapabilities) and issue those -Capabilities to other parties (more on [capability-based access -here](https://cadence-lang.org/docs/language/capabilities)). +How does this delegation occur? Typically when we think of shared account access in crypto, we think keys. However, Cadence allows [accounts to link Capabilities on themselves] and issue those Capabilities to other parties (more on [capability-based access here]). -This feature has been leveraged in an ecosystem standard so that apps can implement a hybrid custody model whereby the app -creates an account it controls, then later delegates access on that account to the user once they've authenticated with -their wallet. +This feature was leveraged in an ecosystem standard so that apps can implement a hybrid custody model whereby the app creates an account it controls, then later delegates access on that account to the user once they've authenticated with their wallet. -All related constructs are used together in the [`HybridCustody` -contract](https://github.com/onflow/hybrid-custody/tree/main) to define the standard. +All related constructs are used together in the [`HybridCustody` contract] to define the standard. -Parent accounts own a `Manager` resource which stores Capabilities to `ChildAccount` (restricted access) and -`OwnedAccount` (unrestricted access) resources, both of which are stored in any given child account. +Parent accounts own a `Manager` resource which stores Capabilities to `ChildAccount` (restricted access) and `OwnedAccount` (unrestricted access) resources, both of which are stored in any given child account. -Therefore, the presence of a `Manager` in an account implies there are potentially associated accounts for which the -owning account has delegated access. This resource is intended to be configured with a public Capability that enables -querying of an account's child account addresses via `getAccountAddresses()` and `getOwnedAccountAddresses()`. As you can -deduce from these two methods, there is a notion of "owned" accounts which we'll expand on later. +Therefore, the presence of a `Manager` in an account implies there are potentially associated accounts for which the owning account has delegated access. This resource is intended to be configured with a public Capability that allows you to query an account's child account addresses via `getAccountAddresses()` and `getOwnedAccountAddresses()`. As you can deduce from these two methods, there is a notion of "owned" accounts which we'll expand on later. -A wallet or marketplace wishing to discover all of a user's accounts and assets within them can do so by first looking -to the user's `Manager`. +If a wallet or marketplace wants to discover all of a user's accounts and assets within them, they can first look to the user's `Manager`. -### Identifying Account Hierarchy +### Identify account hierarchy -To clarify, insofar as the standard is concerned, an account is a parent account if it contains a `Manager` resource, -and an account is a child account if it contains at minimum an `OwnedAccount` or additionally a `ChildAccount` resource. +To clarify, insofar as the standard is concerned, an account is a parent account if it contains a `Manager` resource, and an account is a child account if it contains at minimum an `OwnedAccount` or additionally a `ChildAccount` resource. -Within a user's `Manager`, its mapping of `childAccounts` points to the addresses of its child accounts in each key, -with corresponding values that give the `Manager` access to those accounts via corresponding `ChildAccount` Capability. +Within a user's `Manager`, its mapping of `childAccounts` points to the addresses of its child accounts in each key, with corresponding values that give the `Manager` access to those accounts via corresponding `ChildAccount` Capability. ![HybridCustody Conceptual Overview](./imgs/hybrid_custody_conceptual_overview.png) -Likewise, the child account's `ChildAccount.parentAddress` (which owns a `Manager`) points to the user's account as its -parent address. This makes it easy to both identify whether an account is a parent, child, or both, and its associated -parent or child account(s). +Likewise, the child account's `ChildAccount.parentAddress` (which owns a `Manager`) points to the user's account as its parent address. This makes it easy to both identify whether an account is a parent, child, or both, and its associated parent or child account(s). -`OwnedAccount` resources underly all account delegations, so can have multiple parents whereas `ChildAccount`s are 1:1. -This provides more granular revocation as each parent account has its own Capability path on which its access relies. +`OwnedAccount` resources underly all account delegations, so can have multiple parents whereas `ChildAccount`s are 1:1. This provides more granular revocation as each parent account has its own Capability path on which its access relies. #### Restricted vs. Owned Accounts - `ChildAccount` Capabilities allow access to the underlying account according to rules -configured by the child account delegating access. The `ChildAccount` maintains these rules along with an `OwnedAccount` -Capability within which the `&Account` Capability is stored. Anyone with access to the surface level `ChildAccount` -can then access the underlying `Account`, but only according the pre-defined rule set. These rules are fundamentally -a list of Types that can/cannot be retrieved from an account. + `ChildAccount` Capabilities allow access to the underlying account according to rules configured when the child account delegates access. The `ChildAccount` maintains these rules along with an `OwnedAccount` Capability within which the `&Account` Capability is stored. Anyone with access to the surface level `ChildAccount` can then access the underlying `Account`, but only within the pre-defined rule set. These rules are fundamentally a list of Types that can or can't be retrieved from an account. -The app developer can codify these rule sets on allowable Capability types in a -[`CapabilityFilter`](https://github.com/onflow/hybrid-custody/blob/main/contracts/CapabilityFilter.cdc) along with a -[`CapabilityFactory`](https://github.com/onflow/hybrid-custody/blob/main/contracts/CapabilityFactory.cdc) defining retrieval -patterns for those Capabilities. When delegation occurs, the developer would provide the `CapabilityFilter` and -`CapabilityFactory` Capabilities to an `OwnedAccount` resource which stores them in a `ChildAccount` resource. Then, -capabilities are created for the `OwnedAccount` and `ChildAccount` resource and are given to the specified parent -account. +The app developer can codify these rule sets on allowable Capability types in a [`CapabilityFilter`] along with a [`CapabilityFactory`] defining retrieval patterns for those Capabilities. When delegation occurs, the developer would provide the `CapabilityFilter` and `CapabilityFactory` Capabilities to an `OwnedAccount` resource which stores them in a `ChildAccount` resource. Then, capabilities are created for the `OwnedAccount` and `ChildAccount` resource and are given to the specified parent account. -So, if an app developer wants to enable Hybrid Custody but doesn't want to allow parent accounts to access FungibleToken -Vaults, for example, the app developer can codify rule sets enumerating allowable Capability types in a -`CapabilityFilter` along with a `CapabilityFactory` defining retrieval patterns for those Capabilities. +So, if an app developer wants to turn on Hybrid Custody but doesn't want to allow parent accounts to access FungibleToken Vaults, for example, the app developer can codify rule sets enumerating allowable Capability types in a `CapabilityFilter` along with a `CapabilityFactory` defining retrieval patterns for those Capabilities. -When delegation occurs, they would provide the `CapabilityFilter` and `CapabilityFactory` Capabilities to an -`OwnedAccount`. This `OwnedAccount` then wraps the given filter & factory Capabilities in a `ChildAccount` along with a -Capability to itself before publishing the new `ChildAccount` Capability for the specified parent account to claim. +When delegation occurs, they would provide the `CapabilityFilter` and `CapabilityFactory` Capabilities to an `OwnedAccount`. This `OwnedAccount` then wraps the given filter & factory Capabilities in a `ChildAccount` along with a Capability to itself before it publishes the new `ChildAccount` Capability for the specified parent account to claim. :::info -If you enumerate allowable Types in your `CapabilityFilter.Filter` implementation, you by default exclude -access to anything other than the Types you declare as allowable. +If you enumerate allowable Types in your `CapabilityFilter.Filter` implementation, you by default exclude access to anything other than the Types you declare as allowable. ::: -As mentioned earlier, `Manager`s also maintain access to "owned" accounts - accounts which define unrestricted access as -they allow direct retrieval of encapsulated `&Account` Capabilities. These owned accounts, found in `Manager.ownedAccounts`, -are simply `OwnedAccount` Capabilities instead of `ChildAccount` Capabilities. +As mentioned earlier, `Manager`s also maintain access to "owned" accounts - accounts which define unrestricted access as they allow direct retrieval of encapsulated `&Account` Capabilities. These owned accounts, found in `Manager.ownedAccounts`, are simply `OwnedAccount` Capabilities instead of `ChildAccount` Capabilities. ![HybridCustody Total Overview](./imgs/hybrid_custody_low_level.png) ### Considerations -Do note that this construction does not prevent an account from having multiple parent accounts or a child account from -being the parent to other accounts. While initial intuition might lead one to believe that account associations are a -tree with the user at the root, the graph of associated accounts among child accounts may lead to cycles of association. +This construction does not prevent an account from having multiple parent accounts or a child account from being the parent to other accounts. While initial intuition might lead one to believe that account associations are a tree with the user at the root, the graph of associated accounts among child accounts may lead to cycles of association. -We believe it's unlikely for a use case to demand a user delegates authority over their main account (in fact -we'd discourage such constructions), but it might be useful to delegate access between child accounts. As an example, -consider a set of local game clients across mobile and web platforms, each with self-custodied app accounts that have -delegated authority to each other while both are child accounts of the user's main account. +We believe it's unlikely for a use case to demand a user delegates authority over their main account (in fact we'd discourage such constructions), but it might be useful to delegate access between child accounts. As an example, consider a set of local game clients across mobile and web platforms, each with self-custodied app accounts that have delegated authority to each other while both are child accounts of the user's main account. -Ultimately, it's' up to the implementing wallet or marketplace how far down the graph of account associations they'd -want to traverse and display to the user. +Ultimately, it's' up to the wallet or marketplace who implements this how far down the graph of account associations they'd want to traverse and display to the user. ## Implementation @@ -151,14 +106,14 @@ From the perspective of a wallet or marketplace app, some relevant things to kno - What NFTs are owned by this user across all associated accounts? - What are the balances of all FungibleTokens across all associated accounts? -And with respect to acting on the assets of child accounts and managing child accounts themselves: +And with respect to actions on the assets of child accounts and management of the child accounts themselves: -- Accessing an NFT from a linked account's Collection -- Removing a linked account +- Access an NFT from a linked account's Collection +- Remove a linked account ## Examples -### Query Whether an Address Has Associated Accounts +### Query whether an address has associated accounts This script will return `true` if a `HybridCustody.Manager` is stored and `false` otherwise @@ -174,10 +129,9 @@ access(all) fun main(parent: Address): Bool { } ``` -### Query All Accounts Associated with Address +### Query all accounts associated with address -The following script will return an array of addresses associated with a given account's address, inclusive of the -provided address. If a `HybridCustody.Manager` is not found, the script will revert. +The following script will return an array of addresses associated with a given account's address, inclusive of the provided address. If a `HybridCustody.Manager` is not found, the script will revert. ```cadence get_child_addresses.cdc import "HybridCustody" @@ -190,20 +144,16 @@ access(all) fun main(parent: Address): [Address] { } ``` -### Query All Owned NFT Metadata +### Query all owned NFT metadata -While it is possible to iterate over the storage of all associated accounts in a single script, memory limits prevent -this approach from scaling well. +While it is possible to iterate over the storage of all associated accounts in a single script, memory limits prevent this approach from scaling well. -Since some accounts hold thousands of NFTs, we recommend breaking up iteration, utilizing several queries to iterate -over accounts and the storage of each account. Batching queries on individual accounts may even be required based on the -number of NFTs held. +Since some accounts hold thousands of NFTs, we recommend that you break up iteration and use several queries to iterate over accounts and the storage of each account. Based on the number of NFTs held, you might be required to batch the queries on individual accounts. 1. Get all associated account addresses (see above). -2. Looping over each associated account address client-side, get each address's owned NFT metadata. +2. Loop over each associated account address client-side and get each address's owned NFT metadata. -For simplicity, we'll show a condensed query, returning NFT display views from all accounts associated with a given -address for a specified NFT Collection path. +For simplicity, we'll show a condensed query that returns NFT display views from all accounts associated with a given address for a specified NFT Collection path. ```cadence get_nft_display_view_from_public.cdc import "NonFungibleToken" @@ -267,16 +217,14 @@ fun main(address: Address, resolverCollectionPath: PublicPath): {Address: {UInt6 } ``` -At the end of this query, the caller will have a mapping of `Display` views indexed on the NFT ID and grouped by account -Address. This script does not take batching into consideration and assumes that each NFT resolves the -`MetadataViews.Display` view type. +At the end of this query, the caller will have a mapping of `Display` views indexed on the NFT ID and grouped by account Address. This script does not take batching into consideration and assumes that each NFT resolves the `MetadataViews.Display` view type. -### Query All Account FungibleToken Balances +### Query all acount FungibleToken balances Similar to the previous example, we recommend that you break up this task due to memory limits. 1. Get all linked account addresses (see above). -2. Looping over each associated account address client-side, get each address's owned FungibleToken Vault metadata. +2. Loop over each associated account address client-side and get each address's owned FungibleToken Vault metadata. However, we'll condense both of these steps down into one script for simplicity: @@ -351,18 +299,13 @@ fun main(address: Address): {Address: {Type: UFix64}} { The above script returns a dictionary of balances indexed on the type and further grouped by account Address. -The returned data at the end of address iteration should be sufficient to achieve a unified balance of all Vaults of -similar types across all of a user's associated account as well as a more granular per account view. +The returned data at the end of address iteration should be sufficient to achieve a unified balance of all Vaults of similar types across all of a user's associated account as well as a more granular per account view. -You might consider resolving -[`FungibleTokenMetadataViews`](https://github.com/onflow/flow-ft/blob/master/contracts/FungibleTokenMetadataViews.cdc) -to aggregate more information about the underlying Vaults. +You might resolve [`FungibleTokenMetadataViews`] to aggregate more information about the underlying Vaults. -### Access NFT in Child Account from Parent Account +### Access NFT in child account from parent account -A user with NFTs in their child accounts will likely want to utilize said NFTs. In this example, the user signs a -transaction with their authenticated account that retrieves a reference to a child account's -`NonFungibleToken.Provider`, which allows withdrawal from the child account that signs as the parent account. +A user with NFTs in their child accounts will likely want to utilize said NFTs. In this example, the user signs a transaction with their authenticated account that retrieves a reference to a child account's `NonFungibleToken.Provider`, which allows withdrawal from the child account that signs as the parent account. ```cadence withdraw_nft_from_child.cdc import "NonFungibleToken" @@ -422,26 +365,19 @@ transaction( ``` -At the end of this transaction, you withdrew an NFT from the specified account using an NFT `Provider` Capability. A -similar approach could get you any allowable Capabilities from a signer's child account. +At the end of this transaction, you withdrew an NFT from the specified account with an NFT `Provider` Capability. A similar approach could get you any allowable Capabilities from a signer's child account. -### Revoking Secondary Access on a Linked Account +### Revoke secondary access on a linked account -The expected uses of child accounts for progressive onboarding implies that they will be accounts with shared access. A -user may decide that they no longer want secondary parties to have access to the child account. +The expected uses of child accounts for progressive onboarding implies that they will be accounts with shared access. A user may decide that they no longer want secondary parties to have access to the child account. -There are two ways a party can have delegated access to an account - keys and `&Account` Capability. With -`ChildAccount` mediated access, a user wouldn't be able to revoke anyone's access except for their own. With -unrestricted access via `OwnedAccount`, one could remove parents (`OwnedAccount.removeParent(parent: Address)`) thereby -unlinking relevant Capabilities and further destroying their `ChildAccount` and `CapabilityDelegator` resources. +There are two ways a party can have delegated access to an account - keys and `&Account` Capability. With `ChildAccount` mediated access, a user wouldn't be able to revoke anyone's access except for their own. With unrestricted access via `OwnedAccount`, one could remove parents (`OwnedAccount.removeParent(parent: Address)`) thereby unlinking relevant Capabilities and further destroying their `ChildAccount` and `CapabilityDelegator` resources. -For now, we recommend that if users want to revoke secondary access, they transfer any assets from the relevant child -account and remove it from their `Manager` altogether. +For now, we recommend that if users want to revoke secondary access, they transfer any assets from the relevant child account and remove it from their `Manager` altogether. ### Remove a Child Account -As mentioned above, if a user no longer wishes to share access with another party, we recommended that they transfer desired assets from that account to either their main account or other linked accounts and the linked account be removed -from their `HybridCustody.Manager`. Let's see how to complete that removal. +As mentioned above, if a user no longer wishes to share access with another party, we recommended that they transfer desired assets from that account to either their main account or other linked accounts and the linked account be removed from their `HybridCustody.Manager`. Let's see how to complete that removal. ```cadence remove_child_account.cdc import "HybridCustody" @@ -460,4 +396,15 @@ After removal, the signer no longer has delegated access to the removed account removed as a parent of the removed child. It's also possible for a child account to remove a parent. This is necessary to give application developers -and ultimately the owners of these child accounts the ability to revoke secondary access on owned accounts. \ No newline at end of file +and ultimately the owners of these child accounts the ability to revoke secondary access on owned accounts. + + + +[`HybridCustody.Manager`]: https://github.com/onflow/hybrid-custody/blob/main/contracts/HybridCustody.cdc +[Hybrid Custody Model]: https://forum.flow.com/t/hybrid-custody/4016 +[accounts to link Capabilities on themselves]: https://cadence-lang.org/docs/language/accounts/capabilities#accountcapabilities +[capability-based access here]: https://cadence-lang.org/docs/language/capabilities. +[`HybridCustody` contract]: https://github.com/onflow/hybrid-custody/tree/main +[`CapabilityFilter`]: https://github.com/onflow/hybrid-custody/blob/main/contracts/CapabilityFilter.cdc +[`CapabilityFactory`]: https://github.com/onflow/hybrid-custody/blob/main/contracts/CapabilityFactory.cdc +[`FungibleTokenMetadataViews`]: https://github.com/onflow/flow-ft/blob/master/contracts/FungibleTokenMetadataViews.cdc \ No newline at end of file diff --git a/docs/blockchain-development-tutorials/cadence/cadence-advantages/compose-with-cadence-transactions.md b/docs/blockchain-development-tutorials/cadence/cadence-advantages/compose-with-cadence-transactions.md index 4c57c0d208..84cfb285a6 100644 --- a/docs/blockchain-development-tutorials/cadence/cadence-advantages/compose-with-cadence-transactions.md +++ b/docs/blockchain-development-tutorials/cadence/cadence-advantages/compose-with-cadence-transactions.md @@ -19,7 +19,7 @@ keywords: - Flowscan --- -# Compose wth Cadence transactions +# Compose wth Cadence Transactions In this tutorial, you'll **compose with someone else's contracts** on Flow testnet. You'll write a Cadence transaction that reads public state from a contract named `Counter` and only increments the counter when it is odd. Then you'll extend the transaction to mint NFTs when the counter is odd, demonstrating how to compose multiple contracts in a single transaction. Everything runs against testnet using the Flow CLI and the dependency manager. @@ -123,7 +123,7 @@ access(all) contract Counter { } ``` -Unlike in Solidity, apps aren't limited to the functionality deployed in a smart contract. One of the ways you can expand your app is to write new transactions that call multiple functions in multiple contracts, with branching based on conditions and state, using a single call and a single signature. You don't need to deploy a new contract, use a proxy, or switch to V2. +Unlike in Solidity, apps aren't limited to the functionality deployed in a smart contract. One of the ways you can expand your app is to write new transactions that call multiple functions in multiple contracts, with branching based on conditions and state, with a single call and a single signature. You don't need to deploy a new contract, use a proxy, or switch to V2. In this simple example, imagine that you've already deployed a product that has thousands of users and is dependent on the `Counter` smart contract. After a time, you realize that a significant portion of your users only wish to use the `increment` feature if the current `count` is odd, to try and make the number be even. @@ -187,7 +187,7 @@ transaction() { :::info -As with most blockchains, `log`s are not exposed or returned when transactions are run on testnet or mainnet, but they are visible in the console when you use the [emulator]. +As with most blockchains, `logs` are not exposed or returned when transactions are run on testnet or mainnet, but they are visible in the console when you use the [emulator]. ::: @@ -211,7 +211,7 @@ As with other blockchain accounts, after an account's private key is compromised ::: -Creating an account using the CLI automatically puts the private key in a `.pkey` file, which is already in `.gitignore`. +When you create an account with the CLI, it automatically puts the private key in a `.pkey` file, which is already in `.gitignore`. [Send the transaction] to testnet, signed with `testnet-account`: @@ -223,7 +223,7 @@ You will see logs that show the prior value and whether the increment occurred. :::tip -You could trigger this same transaction **from an app** and **signed by a wallet** with a single user click. Your dApp would assemble and submit this exact Cadence transaction using your preferred client library, and the user's wallet would authorize it. +You could trigger this same transaction **from an app** and **signed by a wallet** with a single user click. Your dApp would assemble and submit this exact Cadence transaction with your preferred client library, and the user's wallet would authorize it. ::: @@ -231,7 +231,7 @@ You could trigger this same transaction **from an app** and **signed by a wallet ## Extend with NFT minting -Now let's take our composition to the next level by adding NFT minting functionality when the counter is odd. We'll use an example NFT contract that's already deployed on testnet. +Now lets take our composition to the next level and add NFT minting functionality when the counter is odd. We'll use an example NFT contract that's already deployed on testnet. This is a silly use case, but it demonstrates the complex use cases you can add to your apps, after contract deployment, and even if you aren't the author of any of the contracts! @@ -245,7 +245,7 @@ flow dependencies install testnet://012e4d204a60ac6f.ExampleNFT :::warning -This repository uses different deployments for core contracts than those that the Flow CLI installs. If you previously installed core contract dependencies (like `NonFungibleToken`, `MetadataViews`, etc.) using the CLI, manually delete all `dependencies` except `Counter` from your `flow.json` file to avoid conflicts. +This repository uses different deployments for core contracts than those that the Flow CLI installs. If you previously installed core contract dependencies (like `NonFungibleToken`, `MetadataViews`, etc.) with the CLI, manually delete all `dependencies` except `Counter` from your `flow.json` file to avoid conflicts. ::: @@ -291,7 +291,7 @@ You can copy this functionality and adapt it for our use case. ### Update the IncrementIfOdd transaction -Now let's update our `IncrementIfOdd` transaction to mint an NFT when the counter is odd. You can either modify the existing transaction or create a new one: +Now let's update our `IncrementIfOdd` transaction to mint an NFT when the counter is odd. You can either modify the current transaction or create a new one: ```cadence import "Counter" @@ -376,7 +376,7 @@ Run the setup transaction: flow transactions send cadence/transactions/SetupCollection.cdc --signer testnet-account --network testnet ``` -### Test the Enhanced Transaction +### Test the enhanced transaction Now run the enhanced transaction: @@ -412,18 +412,18 @@ The broken image is expected. We didn't use a real URL in the example nft metada ## Conclusion -In this tutorial, you learned how to compose with multiple on-chain contracts using Cadence transactions. You built a transaction that conditionally interacts with a Counter contract based on its current state, and then extended it to mint NFTs when the counter is odd, demonstrating the power and flexibility of Cadence's composition model. +In this tutorial, you learned how to compose with multiple on-chain contracts using Cadence transactions. You built a transaction that conditionally interacts with a Counter contract based on its current state, and then extended it to mint NFTs when the counter is odd, which demonstrates the power and flexibility of Cadence's composition model. Now that you have completed the tutorial, you should be able to: - Configure the Flow CLI _dependency manager_ to import named contracts from **testnet**. - Write a Cadence **transaction** that reads and writes to a public contract you did not deploy. -- Run the transaction on **testnet** with a funded account using the Flow CLI. -- Extend the transaction to compose multiple public contracts (`Counter` + `ExampleNFT` + `NonFungibleToken`) without redeploying anything. +- Run the transaction on **testnet** with a funded account with the Flow CLI. +- Extend the transaction to compose multiple public contracts (`Counter` + `ExampleNFT` + `NonFungibleToken`) without the need to redeploy anything. - Set up NFT collections and mint NFTs conditionally based on on-chain state. -- View transaction results and NFT transfers using Flowscan. +- View transaction results and NFT transfers with Flowscan. -This approach gives you the freedom to build complex application logic that composes with any public contracts on Flow, making Cadence's composition model a powerful tool for developers building on Flow. +This approach gives you the freedom to build complex application logic that composes with any public contracts on Flow, which makes Cadence's composition model a powerful tool for developers building on Flow. diff --git a/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md b/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md index a3fdc05cff..83a313b6ca 100644 --- a/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md +++ b/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md @@ -29,20 +29,20 @@ Learn how to compose with someone else's on-chain contracts by writing a Cadence ### [Native Data Availability with Cadence Scripts] -Discover how Cadence scripts provide native data availability, allowing you to query any on-chain data directly from Flow's state without relying on external indexers or APIs. This comprehensive tutorial shows you how to build scripts that can discover and query NFT collections across multiple child accounts using Hybrid Custody, then extend it to include both NBA Top Shot and NFL All Day NFTs. You'll learn to filter and process NFT collections, extract specific metadata, and compare Cadence's native data availability with Solidity's limitations. +Discover how Cadence scripts provide native data availability, which allows you to query any on-chain data directly from Flow's state without the need to rely on external indexers or APIs. This comprehensive tutorial shows you how to build scripts that can discover and query NFT collections across multiple child accounts with Hybrid Custody, then extend it to include both NBA Top Shot and NFL All Day NFTs. You'll learn to filter and process NFT collections, extract specific metadata, and compare Cadence's native data availability with Solidity's limitations. ### [Upgrading Cadence Contracts] -Learn how to upgrade deployed Cadence contracts through multiple incremental upgrades while preserving existing state and maintaining the same contract address. This tutorial demonstrates Cadence's sophisticated contract upgrade system through two realistic scenarios: +Learn how to upgrade deployed Cadence contracts through multiple incremental upgrades, preserve the current state, and maintain the same contract address. This tutorial demonstrates Cadence's sophisticated contract upgrade system through two realistic scenarios: -- Adding an event to notify users when the counter reaches an even number. -- Extending the contract with additional functionality like incrementing by two and checking if numbers are even. +- Add an event to notify users when the counter reaches an even number. +- Extend the contract with additional functionality like increment by two and check if numbers are even. -You'll understand what you can and can't change during upgrades, perform multiple contract updates using Flow CLI, and test upgraded functionality with comprehensive transactions and scripts. +You'll understand what you can and can't change when you upgrade, perform multiple contract updates with Flow CLI, and test upgraded functionality with comprehensive transactions and scripts. ## Conclusion -Cadence's unique features, such as resource-oriented programming to native data availability, seamless transaction composition, and sophisticated contract upgrade capabilities, represent a fundamental advancement in smart contract development. These tutorials demonstrate how Cadence allows developers to build sophisticated applications with capabilities that simply aren't possible on other blockchain platforms, while maintaining security and developer experience as core principles. +Cadence's unique features, such as resource-oriented programming to native data availability, seamless transaction composition, and sophisticated contract upgrade capabilities, represent a fundamental advancement in smart contract development. These tutorials demonstrate how Cadence allows developers to build sophisticated applications with capabilities that simply aren't possible on other blockchain platforms and maintain security and developer experience as core principles. [Compose with Cadence Transactions]: ./compose-with-cadence-transactions.md [Native Data Availability with Cadence Scripts]: ./native-data-availibility-with-cadence-scripts.md diff --git a/docs/blockchain-development-tutorials/cadence/cadence-advantages/native-data-availibility-with-cadence-scripts.md b/docs/blockchain-development-tutorials/cadence/cadence-advantages/native-data-availibility-with-cadence-scripts.md index e0a1877199..a54be0251c 100644 --- a/docs/blockchain-development-tutorials/cadence/cadence-advantages/native-data-availibility-with-cadence-scripts.md +++ b/docs/blockchain-development-tutorials/cadence/cadence-advantages/native-data-availibility-with-cadence-scripts.md @@ -23,9 +23,9 @@ keywords: # Native Data Availability With Cadence Scripts -In Solidity, you can only retrieve data from **view** functions that the contract author anticipated and included in the original contract. If the exact query you want is not exposed, teams typically rely on a _data availability service_ such as The Graph, Covalent, Alchemy Enhanced APIs, Reservoir, or NFTScan to compute and serve that view. +In Solidity, you can only retrieve data from **view** functions that the contract author anticipated and included in the original contract. If the exact query you want isn't exposed, teams typically rely on a _data availability service_ such as The Graph, Covalent, Alchemy Enhanced APIs, Reservoir, or NFTScan to compute and serve that view. -In Cadence, **scripts** are general-purpose read programs. They can traverse public account storage, read public capabilities, and compose types from multiple contracts to answer new questions without modifying those contracts. You are not limited to the pre-written surface area of a single contract's views. +In Cadence, **scripts** are general-purpose read programs. They can traverse public account storage, read public capabilities, and compose types from multiple contracts to answer new questions without the need to modify those contracts. You are not limited to the pre-written surface area of a single contract's views. :::info @@ -103,7 +103,7 @@ This will install the contract and its own dependencies. You don't need to deplo :::warning -The language server treats installing dependencies in this way similar to installing packages in other platforms. You'll need to close and reopen the file or type something to trigger a refresh. +The language server treats dependency installations in this way similar to package installations in other platforms. You'll need to close and reopen the file or type something to trigger a refresh. ::: @@ -131,7 +131,7 @@ Run it: flow scripts execute cadence/scripts/TopShotQuery.cdc --network mainnet 0xfeb88a0fcc175a3d ``` -You should see a list of child addresses. If you do not, confirm the parent actually stores a manager at `HybridCustody.ManagerStoragePath`. +You will see a list of child addresses. If you do not, confirm the parent actually stores a manager at `HybridCustody.ManagerStoragePath`. ```bash Result: [0xa16b948ba2c9a858] @@ -258,7 +258,7 @@ Run it: flow scripts execute cadence/scripts/TopShotQuery.cdc --network mainnet 0xfeb88a0fcc175a3d ``` -You should now see type identifiers such as `A.
..` for collections the parent can control. We will use these identifiers to filter for Top Shot. +You will now see type identifiers such as `A.
..` for collections the parent can control. We will use these identifiers to filter for Top Shot. ```bash Result: {0xa16b948ba2c9a858: ["A.807c3d470888cc48.Backpack.Collection", "A.e4cf4bdc1751c65d.AllDay.Collection", "A.0b2a3299cc857e29.TopShot.Collection"]} @@ -266,13 +266,13 @@ Result: {0xa16b948ba2c9a858: ["A.807c3d470888cc48.Backpack.Collection", "A.e4cf4 --- -## Filtering NFT collection to find and return Top Shots +## Filter NFT collection to find and return Top Shots Finally, for each detected collection, [borrow] the collection `{NonFungibleToken.CollectionPublic}`, iterate IDs, resolve `MetadataViews.Display`, and return only Top Shot items. We add a small `isTopShot` predicate that you can customize to your deployment. :::info -The [borrow] function is how you use a published [_capability_] in your code. In this case, you're borrowing the **public** functionality of Cadence NFTs, which includes [`MetadataViews`] that return a view of the **fully-onchain metadata** for the NFT. +The [borrow] function is how you use a published [_capability_] in your code. In this case, you borrow the **public** functionality of Cadence NFTs, which includes [`MetadataViews`] that return a view of the **fully-onchain metadata** for the NFT. ::: @@ -388,9 +388,9 @@ Result: {0xa16b948ba2c9a858: {44311697: A.1d7e57aa55817448.MetadataViews.Display --- -## Extending the script to include AllDay NFTs +## Extend the script to include AllDay NFTs -Now that you have a working script for Top Shot NFTs, let's extend it to also return NFL All Day NFTs. This demonstrates the flexibility of Cadence scripts - you can easily modify them to answer new questions without changing any contracts. +Now that you have a working script for Top Shot NFTs, let's extend it to also return NFL All Day NFTs. This demonstrates the flexibility of Cadence scripts - you can easily modify them to answer new questions without the need to change any contracts. Update the `isTopShot` function to also include AllDay NFTs: @@ -418,14 +418,14 @@ This demonstrates how you can easily modify Cadence scripts to answer different --- -## Troubleshooting +## Troubleshoot - If you see `manager does not exist`, confirm the parent address actually stores a `HybridCustody.Manager` at `HybridCustody.ManagerStoragePath`. - If you see empty arrays in Step 3, the parent may not have _provider_ access to any collections in those child accounts. - If you see empty results in Step 4, confirm `isTopShot` matches the identifiers you observed in Step 3. - If you are not using _Hybrid Custody_, you can adapt Steps 2-4 to use `getAccount(child)` and scan **publicly exposed** `{NonFungibleToken.CollectionPublic}` capabilities, but you will not be able to assert provider access. -## How This compares to Solidity +## How this compares to Solidity - **Solidity views are fixed**: You can only retrieve what the contract author exposed via `view` or `pure` functions. If you need a different aggregation or cross-contract traversal, you typically rely on a _data availability service_ or write a new contract to expose that view. - **Cadence scripts are flexible**: You compose types across modules, traverse account storage, and read public capabilities at query time. You do not need to redeploy contracts to answer new questions. @@ -440,18 +440,18 @@ Common _data availability service_ examples used in EVM ecosystems: ## Conclusion -In this tutorial, you learned how to use Cadence scripts to query onchain data directly from Flow's state, without relying on external indexers or APIs. You built a script that can discover and query NFT collections across multiple child accounts using Hybrid Custody, and then extended it to include both NBA Top Shot and NFL All Day NFTs, demonstrating the power and flexibility of Cadence's native data availability. +In this tutorial, you learned how to use Cadence scripts to query onchain data directly from Flow's state, without the need to rely on external indexers or APIs. You built a script that can discover and query NFT collections across multiple child accounts with Hybrid Custody, and then extended it to include both NBA Top Shot and NFL All Day NFTs, which demonstrates the power and flexibility of Cadence's native data availability. Now that you have completed the tutorial, you should be able to: -- Query onchain data directly using Cadence scripts without external dependencies +- Query onchain data directly with Cadence scripts without external dependencies - Use Hybrid Custody to access child account data from parent accounts - Filter and process NFT collections to extract specific metadata - Modify scripts to answer different questions about the same onchain data - Compare Cadence's native data availability with Solidity's limitations - Build applications that can access any onchain data in real-time -This approach gives you the freedom to build applications that can access any onchain data in real-time, making Flow's native data availability a powerful tool for developers building on Flow. +This approach gives you the freedom to build applications that can access any onchain data in real-time, which makes Flow's native data availability a powerful tool for developers who build on Flow. diff --git a/docs/blockchain-development-tutorials/cadence/cadence-advantages/upgrading-cadence-contracts.md b/docs/blockchain-development-tutorials/cadence/cadence-advantages/upgrading-cadence-contracts.md index 279b7a8c33..932c484fb6 100644 --- a/docs/blockchain-development-tutorials/cadence/cadence-advantages/upgrading-cadence-contracts.md +++ b/docs/blockchain-development-tutorials/cadence/cadence-advantages/upgrading-cadence-contracts.md @@ -18,7 +18,7 @@ keywords: # Upgrading Cadence Contracts -In Cadence, you can upgrade deployed contracts by adding new functionality while preserving existing state and maintaining the same contract address. Unlike other blockchain platforms that require complex proxy patterns or complete redeployment, Cadence allows you to seamlessly extend your contracts with new functions and events through multiple incremental upgrades. +In Cadence, to upgrade deployed contracts, you can add new functionality while preserving the current state and maintain the same contract address. Unlike other blockchain platforms that require complex proxy patterns or complete redeployment, Cadence allows you to seamlessly extend your contracts with new functions and events through multiple incremental upgrades. This tutorial demonstrates how to upgrade a deployed contract through two scenarios: @@ -74,7 +74,7 @@ The [Cadence Contract Updatability documentation](https://cadence-lang.org/docs/ - **Storage inconsistencies** from structural changes. - **Type confusion** from enum value changes. -The validation system ensures that existing stored data remains valid and accessible after upgrades. +The validation system ensures that current stored data remains valid and accessible after upgrades. ## Get started @@ -278,13 +278,13 @@ Events: --- -## Upgrade the contract - Part 1: Add event for even numbers +## Upgrade the contract - Part 1: add event for even numbers Let's start with a realistic scenario: What if we've realized it's very important to our users that they know when the counter reaches an even number, but we forgot to add an event for that case? Let's add that functionality first. ### Modify the Counter contract - first upgrade -Update `cadence/contracts/Counter.cdc` to add the new event and enhance the existing `increment()` function: +Update `cadence/contracts/Counter.cdc` to add the new event and enhance the current `increment()` function: ```cadence access(all) contract Counter { @@ -334,19 +334,19 @@ This first upgrade adds: 1. **New event**: `CounterIncrementedToEven` to notify when incrementing results in an even number. 2. **Enhanced existing function**: The `increment()` function now also emits the new event when appropriate. -3. **No new fields**: We only use the existing `count` field to avoid validation errors. +3. **No new fields**: We only use the current `count` field to avoid validation errors. :::info -This demonstrates how you can add new behavior and modify existing function behavior, which enhances existing functionality. The original `CounterIncremented` event still works as before, ensuring backward compatibility. +This demonstrates how you can add new behavior and modify current function behavior, which enhances current functionality. The original `CounterIncremented` event still works as before, which ensures backward compatibility. ::: --- -## Update the deployed contract - Part 1 +## Update the deployed contract - part 1 -Now let's update the deployed contract on testnet using the Flow CLI update command with our first upgrade. +Now let's update the deployed contract on testnet with the Flow CLI update command with our first upgrade. ### Update the contract @@ -356,7 +356,7 @@ Use the [Flow CLI update contract command] to upgrade your deployed contract: flow accounts update-contract ./cadence/contracts/Counter.cdc --signer testnet-account --network testnet ``` -You should see output similar to: +You will see output similar to: ```bash Contract 'Counter' updated on account '0x9942a81bc6c3c5b7' @@ -382,7 +382,7 @@ Contract: 'Counter' The contract successfully updated! Notice that: - The contract address remains the same (`0x9942a81bc6c3c5b7`). -- The existing state (`count`) is preserved. +- The current state (`count`) is preserved. - New functionality is available. ::: @@ -414,7 +414,7 @@ Run the script to check the current state: flow scripts execute cadence/scripts/CheckCounter.cdc --network testnet ``` -You will see output showing the counter state: +You will see output that shows the counter state: ```bash Result: {"count": 1, "isEven": false} @@ -427,7 +427,7 @@ Notice that: --- -## Upgrade the contract - Part 2: add more functionality +## Upgrade the contract - part 2: add more functionality Now that we've successfully added the even number event, let's add more functionality to our contract. This demonstrates how you can make multiple incremental upgrades to extend your contract's capabilities. @@ -504,14 +504,14 @@ access(all) contract Counter { This second upgrade adds: -1. **New functions**: `incrementByTwo()` and `decrementByTwo()` that modify the existing counter by two. -2. **New events**: `CounterIncrementedByTwo` and `CounterDecrementedByTwo` for the new functionality +1. **New functions**: `incrementByTwo()` and `decrementByTwo()` that modify the current counter by two. +2. **New events**: `CounterIncrementedByTwo` and `CounterDecrementedByTwo` for the new functionality. 3. **New view function**: `isEven()` to check if the current count is even. 4. **Preserved existing functionality**: All previous functionality remains intact. --- -## Update the deployed contract - Part 2 +## Update the deployed contract - part 2 Now let's update the deployed contract with our second upgrade. @@ -549,7 +549,7 @@ Contract: 'Counter' The contract successfully updated again! Notice that: - The contract address remains the same (`0x9942a81bc6c3c5b7`). -- The existing state (`count`) is preserved. +- The current state (`count`) is preserved. - All previous functionality is still available. - New functionality is now available. @@ -689,7 +689,7 @@ This confirms that: ## Understand contract upgrades in Cadence -Cadence provides a sophisticated contract upgrade system that ensures data consistency while allowing controlled modifications. The [Cadence Contract Updatability documentation] provides comprehensive details about the validation rules and restrictions. +Cadence provides a sophisticated contract upgrade system that ensures data consistency and allows controlled modifications. The [Cadence Contract Updatability documentation] provides comprehensive details about the validation rules and restrictions. ### What you can upgrade @@ -709,16 +709,16 @@ When you upgrade Cadence contracts, you can: There are important limitations to contract upgrades: -- **Cannot add new fields** to existing structs, resources, or contracts. - - This would cause runtime crashes when loading existing data. +- **Cannot add new fields** to current structs, resources, or contracts. + - This would cause runtime crashes when you load current data. - The initializer only runs once during deployment, not on updates. -- **Cannot change the type** of existing state variables. +- **Cannot change the type** of current state variables. - Would cause deserialization errors with stored data. - **Cannot remove existing state variables** (though they become inaccessible). - **Cannot change enum structures** (raw values must remain consistent). - **Cannot change the contract name** or address. -### Validation Goals +### Validation goals The contract update validation ensures that: @@ -728,7 +728,7 @@ The contract update validation ensures that: :::warning -The validation system focuses on preventing runtime inconsistencies with stored data. It does not ensure that programs which import the updated contract remain valid - you may need to update dependent code if you change function signatures or remove functions. +The validation system focuses on how to prevent runtime inconsistencies with stored data. It does not ensure that programs which import the updated contract remain valid - you may need to update dependent code if you change function signatures or remove functions. ::: @@ -757,8 +757,8 @@ This pragma: Enums have special restrictions due to their raw value representation: -- **Can only add enum cases at the end** of existing cases. -- **Cannot reorder, rename, or remove** existing enum cases. +- **Can only add enum cases at the end** of current cases. +- **Cannot reorder, rename, or remove** current enum cases. - **Cannot change the raw type** of an enum. - **Cannot change enum case names** (would change stored values' meaning). @@ -782,12 +782,12 @@ When you upgrade contracts: Cadence's contract upgrade model provides several advantages: - **No proxy patterns needed** - Unlike Ethereum, you don't need complex proxy contracts. -- **State preservation** - Existing data and functionality remain intact. +- **State preservation** - Current data and functionality remain intact. - **Address stability** - Contract addresses don't change during upgrades. - **Gas efficiency** - Upgrades are more efficient than redeployment. - **User experience** - Applications continue working without interruption. -This approach allows you to evolve your contracts over time, You can add new features and capabilities and maintain backward compatibility and preserving user data. +This approach allows you to evolve your contracts over time, You can add new features and capabilities and maintain backward compatibility and preserve user data. ## Conclusion @@ -802,15 +802,15 @@ In this tutorial, you learned how to upgrade deployed Cadence contracts through Now that you have completed the tutorial, you should be able to: -- Deploy contracts to Flow testnet using Flow CLI. +- Deploy contracts to Flow testnet with Flow CLI. - Perform incremental contract upgrades by adding new functions and events. -- Update deployed contracts multiple times while preserving existing state. +- Update deployed contracts multiple times and preserve the current state. - Test upgraded functionality with Cadence transactions and scripts. - Understand what can and cannot be changed during contract upgrades. - Apply realistic upgrade scenarios based on user feedback and requirements. - Plan and execute multiple contract upgrades over time. -This incremental upgrade model makes Cadence contracts more flexible and maintainable than traditional smart contract platforms, allowing you to evolve your applications over time based on real user needs without complex migration patterns or breaking changes. The ability to make multiple upgrades while preserving state and maintaining the same contract address provides a powerful foundation for long-term application development. +This incremental upgrade model makes Cadence contracts more flexible and maintainable than traditional smart contract platforms, which allows you to evolve your applications over time based on real user needs without complex migration patterns or breaking changes. The ability to make multiple upgrades while you maintain state and the same contract address provides a powerful foundation for long-term application development. diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md index d84123336c..1d30d87729 100644 --- a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -29,13 +29,13 @@ keywords: - forked runtime --- -# Fork testing with Cadence +# Fork Testing with Cadence -This tutorial teaches you how to run your Cadence tests against a snapshot of Flow mainnet using `flow test --fork`. You'll learn how to test your contracts against real deployed contracts and production data without needing to deploy anything to a live network or bootstrap test accounts. +This tutorial teaches you how to run your Cadence tests against a snapshot of Flow mainnet with `flow test --fork`. You'll learn how to test your contracts against real deployed contracts and production data without the need to deploy anything to a live network or bootstrap test accounts. Fork testing bridges the gap between isolated local unit tests and testnet deployments. It allows you to validate your contracts work correctly with real on-chain state, test integrations with deployed contracts, and debug issues with historical blockchain data—all in a safe, local environment. -## What You'll Learn +## What you'll learn After you complete this tutorial, you'll be able to: @@ -46,15 +46,15 @@ After you complete this tutorial, you'll be able to: - **Pin tests to specific block heights** for historical debugging. - **Integrate fork testing** into your development workflow. -## What You'll Build +## What you'll build You'll create a complete fork testing setup that demonstrates: -- Reading from the live FlowToken contract on mainnet. -- Deploying your own contract that interacts with mainnet contracts. -- Testing custom logic against real account balances and state. -- Executing transactions using impersonated mainnet accounts. -- A reusable pattern for integration testing your Flow applications. +- How to read from the live FlowToken contract on mainnet. +- How to deploy your own contract that interacts with mainnet contracts. +- How to test custom logic against real account balances and state. +- How to execute transactions with impersonated mainnet accounts. +- A reusable pattern for integration tests your Flow applications. ### Reproducibility first @@ -64,7 +64,7 @@ Pin a specific block height when you need reproducible results: flow test --fork mainnet --fork-height ``` -Document the pin heights you rely on (for example, in CI variables or a simple file in the repo) and update them via a dedicated freshness PR. For best results, keep a per‑spork stable pin and also run a "latest" freshness job. +Document the pin heights you rely on (for example, in CI variables or a simple file in the repo) and update them via a dedicated freshness pull request (PR). For best results, keep a per‑spork stable pin and also run a "latest" freshness job. ## Prerequisites @@ -80,7 +80,7 @@ For other operating systems, refer to the [installation guide]. ### Basic Cadence testing knowledge -You should be familiar with writing basic Cadence tests. If you're new to Cadence testing, start with [Testing Smart Contracts] first. +You should be familiar with how to write basic Cadence tests. If you're new to Cadence testing, start with [Testing Smart Contracts] first. ### Network access @@ -91,7 +91,7 @@ You'll need network access to Flow's public access nodes. The tutorial uses thes :::info -This tutorial covers `flow test --fork` (running tests against forked network state), which is different from `flow emulator --fork` (starting the emulator in fork mode for manual interaction). +This tutorial covers `flow test --fork` (which runs tests against forked network state), which is different from `flow emulator --fork` (which runs the emulator in fork mode for manual interaction). ::: @@ -143,7 +143,7 @@ Your `flow.json` now includes an entry like: Your `flow.json` now has the mainnet and testnet networks configured from `flow init`. In fork mode, contract imports automatically resolve to the correct network addresses. -## Test Reading Live State +## Test reading live state Generate a script to read `FlowToken` supply: @@ -211,13 +211,13 @@ flow test cadence/tests/FlowToken_test.cdc --fork testnet You will see the test PASS. If not, verify your network host in `flow.json` and that dependencies are installed. -## Deploy and Test Your Contract +## Deploy and test Your contract -Now you'll create a contract that depends on FlowToken and test it against the forked mainnet state—no need to bootstrap tokens or set up test accounts. +Now you'll create a contract that depends on FlowToken and test it against the forked mainnet state. There's no need to bootstrap tokens or set up test accounts. -### Create a Test Account +### Create a test account -Create a new account for deploying your contract: +Create a new account to deploy your contract: ```zsh flow accounts create @@ -234,7 +234,7 @@ This will output the new account address. Use this address as the mainnet alias This creates a local account with a mainnet-format address for fork testing. When you're ready to deploy to actual mainnet, you'll use this same account—see the [Deploying Contracts guide](pathname:///build/cadence/smart-contracts/deploying) for details. ::: -### Create a Contract that Uses `FlowToken` +### Create a contract that uses `FlowToken` Generate a new contract: @@ -384,9 +384,9 @@ access(all) fun testHasMinimumBalance() { ## Execute transactions with account impersonation -Fork testing includes built-in account impersonation—you can execute transactions as **any mainnet account** without needing private keys. This lets you test interactions with real accounts and their existing state. +Fork testing includes built-in account impersonation—you can execute transactions as **any mainnet account** without the need for private keys. This lets you test interactions with real accounts and their current state. -### Create Transactions +### Create transactions Generate the transactions: @@ -587,7 +587,7 @@ For strategy, limitations, and best practices, see the guide: [Testing Smart Con ## Conclusion -In this tutorial, you learned how to use fork testing to validate your Cadence contracts against live Flow network state. You created tests that read from real mainnet contracts, deployed custom contracts that interact with production data, and executed transactions using account impersonation—all without deploying to a live network or bootstrapping test accounts. +In this tutorial, you learned how to use fork testing to validate your Cadence contracts against live Flow network state. You created tests that read from real mainnet contracts, deployed custom contracts that interact with production data, and executed transactions using account impersonation—all without the need deploy to a live network or bootstrap test accounts. Now that you have completed this tutorial, you will be able to: @@ -598,7 +598,7 @@ Now that you have completed this tutorial, you will be able to: - **Pin tests to specific block heights** for historical debugging. - **Integrate fork testing** into your development workflow. -Fork testing bridges the gap between local unit tests and testnet deployments, allowing you to catch integration issues early and test against real-world conditions. Use it as part of your pre-deployment validation process, alongside emulator unit tests for determinism and isolation, and testnet deployments for final verification. +Fork testing bridges the gap between local unit tests and testnet deployments, which allows you to catch integration issues early and test against real-world conditions. Use it as part of your pre-deployment validation process, alongside emulator unit tests for determinism and isolation, and testnet deployments for final verification. ### Next Steps diff --git a/docs/blockchain-development-tutorials/cadence/getting-started/building-a-frontend-app.md b/docs/blockchain-development-tutorials/cadence/getting-started/building-a-frontend-app.md index d8c619be60..18443d4613 100644 --- a/docs/blockchain-development-tutorials/cadence/getting-started/building-a-frontend-app.md +++ b/docs/blockchain-development-tutorials/cadence/getting-started/building-a-frontend-app.md @@ -20,19 +20,19 @@ keywords: - web3 frontend --- -# Building a frontend app +# Building a Frontend App -This tutorial builds on the `Counter` contract you deployed in [Cadence Environment Setup] and [Smart Contract Interaction]. It shows you how to create a simple `Next.js` frontend that interacts with the `Counter` smart contract deployed on your local Flow emulator. Instead of using FCL directly, you'll leverage [**@onflow/react-sdk**] to simplify authentication, querying, transactions, and to display real-time transaction status updates using convenient React hooks. +This tutorial builds on the `Counter` contract you deployed in [Cadence Environment Setup] and [Smart Contract Interaction]. It shows you how to create a simple `Next.js` frontend that interacts with the `Counter` smart contract deployed on your local Flow emulator. Rather than use FCL directly, you'll leverage [**@onflow/react-sdk**] to simplify authentication, querys, transactions, and to display real-time transaction status updates with convenient React hooks. ## Objectives After you complete this tutorial, you will be able to: - Wrap your `Next.js` app with a Flow provider using [**@onflow/react-sdk**]. -- Read data from a Cadence smart contract (`Counter`) using kit's query hook. -- Send a transaction to update the smart contract's state using kit's mutation hook. -- Monitor a transaction's status in real time using kit's transaction hook. -- Authenticate with the Flow blockchain using kit's built-in hooks and the local [Dev Wallet]. +- Read data from a Cadence smart contract (`Counter`) with kit's query hook. +- Send a transaction to update the smart contract's state with kit's mutation hook. +- Monitor a transaction's status in real time with kit's transaction hook. +- Authenticate with the Flow blockchain with kit's built-in hooks and the local [Dev Wallet]. ## Prerequisites @@ -64,15 +64,15 @@ During setup, choose the following options: - **Use src directory**: **Yes** - **Use App Router**: **Yes** -This command creates a new Next.js project named `kit-app-quickstart` inside your current directory. We're generating the frontend in a subdirectory so we can next move it into our existing project structure from the previous steps (you can't create an app in a non-empty directory). +This command creates a new Next.js project named `kit-app-quickstart` inside your current directory. We will generate the frontend in a subdirectory so we can next move it into our current project structure from the previous steps (you can't create an app in a non-empty directory). -### Step 2: Move the Next.js app Up a directory +### Step 2: Move the Next.js app up a directory Move the contents of the `kit-app-quickstart` directory into your project root. You can use the gui in your editor, or the console. :::warning -You'll want to consolidate both `.gitignore` files, keeping the contents of both in the file that ends up in the root. +You'll want to consolidate both `.gitignore` files, which keeps the contents of both in the file that ends up in the root. ::: @@ -94,7 +94,7 @@ Remove-Item -Recurse -Force .\kit-app-quickstart :::tip -When moving hidden files (those beginning with a dot) like `.gitignore`, be cautious not to overwrite any important files. +When you move hidden files (those that start with a dot) like `.gitignore`, be cautious not to overwrite any important files. ::: @@ -106,9 +106,9 @@ Install the kit library in your project: npm install @onflow/react-sdk ``` -This library wraps FCL internally and exposes a set of hooks for authentication, querying, sending transactions, and tracking transaction status. +This library wraps FCL internally and exposes a set of hooks for authentication, querys, to send transactions, and track transaction status. -## Configure the local Flow Emulator and Dev Wallet +## Configure the local Flow emulator and Dev Wallet :::warning @@ -116,7 +116,7 @@ You should already have the Flow emulator running from the local development ste ::: -### Start the Flow Emulator (if not already running) +### Start the Flow emulator (if not already running) Open a new terminal window in your project directory and run: @@ -138,7 +138,7 @@ This will start the [Dev Wallet] on `http://localhost:8701`, which you'll use fo ## Wrap Your app with FlowProvider -[**@onflow/react-sdk**] provides a `FlowProvider` component that sets up the Flow Client Library configuration. In `Next.js` using the App Router, add or update your `src/app/layout.tsx` as follows: +[**@onflow/react-sdk**] provides a `FlowProvider` component that sets up the Flow Client Library configuration. In `Next.js`, use the App Router to add or update your `src/app/layout.tsx` as follows: ```tsx 'use client'; @@ -176,7 +176,7 @@ For more information on Discovery configurations, refer to the [Wallet Discovery ## Interact With the chain -Now that we've set our provider, lets start interacting with the chain. +Now that we've set our provider, lets start to interact with the chain. ### Query the chain @@ -207,7 +207,7 @@ This script fetches the counter value, formats it via the `NumberFormatter`, and :::info -- **Import Syntax:** The imports (`import "Counter"` and `import "NumberFormatter"`) don't include addresses because those are automatically resolved using the `flow.json` file configured in your `FlowProvider`. This keeps your Cadence scripts portable and environment-independent. +- **Import Syntax:** The imports (`import "Counter"` and `import "NumberFormatter"`) don't include addresses because those are automatically resolved with the `flow.json` file configured in your `FlowProvider`. This keeps your Cadence scripts portable and environment-independent. - **`enabled` Flag:** This controls whether the query should run automatically. Set it to `true` to run on mount, or pass a condition (e.g. `!!user?.addr`) to delay execution until the user is available. This is useful for queries that depend on authentication or other asynchronous data. ::: @@ -248,7 +248,7 @@ const handleIncrement = () => { #### Explanation -This sends a Cadence transaction to the blockchain using the `mutate` function. The transaction imports the `Counter` contract and calls its `increment` function. The connected wallet handles authorization automatically during the `prepare` phase. After it's submitted, you cna use the returned `txId` to track the transaction's status in real time. +This sends a Cadence transaction to the blockchain with the `mutate` function. The transaction imports the `Counter` contract and calls its `increment` function. The connected wallet handles authorization automatically during the `prepare` phase. After it's submitted, you cna use the returned `txId` to track the transaction's status in real time. ### Subscribe to transaction status @@ -272,7 +272,7 @@ useEffect(() => { #### Explanation: -- `useFlowTransactionStatus(txId)` subscribes to real-time updates about a transaction's lifecycle using the transaction ID. +- `useFlowTransactionStatus(txId)` subscribes to real-time updates about a transaction's lifecycle with the transaction ID. - `transactionStatus.status` is a numeric code representing the state of the transaction: - `0`: **Unknown** – The transaction status is not yet known. - `1`: **Pending** – The transaction has been submitted and is waiting to be included in a block. @@ -284,16 +284,16 @@ useEffect(() => { #### Why we recommend `Executed` for UI Updates: -Waiting for `Sealed` provides full onchain confirmation but can introduce a delay — especially in local or test environments. Since most transactions (like incrementing a counter) don't require strong finality guarantees, you can typically refetch data once the transaction reaches `Executed` for a faster, more responsive user experience. +Waiting for `Sealed` provides full onchain confirmation but can introduce a delay — especially in local or test environments. Since most transactions (like incrementing a counter) don't require strong finality guarantees, you can typically refetch data after the transaction reaches `Executed` for a faster, more responsive user experience. However: -- If you're dealing with critical state changes (for example, token transfers or contract deployments), prefer waiting for `Sealed`. +- If you experience critical state changes (for example, token transfers or contract deployments), wait for `Sealed`. - For non-critical UI updates, `Executed` is usually safe and significantly improves perceived performance. ### Integrate authentication and build the complete UI -Finally, integrate the query, mutation, and transaction status hooks with authentication using `useFlowCurrentUser`. Combine all parts to build the complete page. +Finally, integrate the query, mutation, and transaction status hooks with authentication via `useFlowCurrentUser`. Combine all parts to build the complete page. ```tsx 'use client'; @@ -408,12 +408,12 @@ In this complete page: - **Step 1** queries the counter value. - **Step 2** sends a transaction to increment the counter and stores the transaction ID. -- **Step 3** subscribes to transaction status updates using the stored transaction ID and uses a `useEffect` hook to automatically refetch the updated count when the transaction is sealed (status code 4). +- **Step 3** subscribes to transaction status updates with the stored transaction ID and uses a `useEffect` hook to automatically refetch the updated count when the transaction is sealed (status code 4). - **Step 4** integrates authentication via `useFlowCurrentUser` and combines all the pieces into a single user interface. :::tip -In this tutorial, we inlined Cadence code for simplicity. For real projects, we recommend storing Cadence in separate `.cdc` files, using the [Cadence VSCode extension], and importing them with the [`flow-cadence-plugin`](https://github.com/chasefleming/flow-cadence-plugin) for Next.js or Webpack projects. +In this tutorial, we inlined Cadence code for simplicity. For real projects, we recommend that you store Cadence in separate `.cdc` files, with the [Cadence VSCode extension], and import them with the [`flow-cadence-plugin`](https://github.com/chasefleming/flow-cadence-plugin) for Next.js or Webpack projects. ::: @@ -429,7 +429,7 @@ npm run dev If you have the Flow wallet browser extension installed, you might automatically log into the app. Normally this is desirable for your users, but you don't want to use it here. -Log out, and log back in selecting the Dev Wallet instead of the Flow Wallet. +Log out, and log back in. Select the Dev Wallet instead of the Flow Wallet. ::: @@ -444,11 +444,11 @@ Then visit [http://localhost:3000](http://localhost:3000) in your browser. You s - The current counter value displayed (formatted with commas using `NumberFormatter`). - A **Log In** button that launches the kit Discovery UI with your local [Dev Wallet]. - Once logged in, your account address appears with options to **Log Out** and **Increment Count**. -- When you click **Increment Count**, the transaction is sent; its status updates are displayed in real time below the action buttons, and once the transaction is sealed, the updated count is automatically fetched. +- When you click **Increment Count**, the transaction is sent; its status updates are displayed in real time below the action buttons, and after the transaction is sealed, the updated count is automatically fetched. ## Conclusion -By following these steps, you've built a simple `Next.js` dApp that interacts with a Flow smart contract using [**@onflow/react-sdk**]. In this guide you learned how to: +When you follow these steps, you've built a simple `Next.js` dApp that interacts with a Flow smart contract with [**@onflow/react-sdk**]. In this guide you learned how to: - Wrap your application in a `FlowProvider` to configure blockchain connectivity. - Use kit hooks such as `useFlowQuery`, `useFlowMutate`, `useFlowTransactionStatus`, and `useFlowCurrentUser` to manage authentication, query onchain data, submit transactions, and monitor their status. diff --git a/docs/blockchain-development-tutorials/cadence/getting-started/cadence-environment-setup.md b/docs/blockchain-development-tutorials/cadence/getting-started/cadence-environment-setup.md index 37c1099309..63cfac4f58 100644 --- a/docs/blockchain-development-tutorials/cadence/getting-started/cadence-environment-setup.md +++ b/docs/blockchain-development-tutorials/cadence/getting-started/cadence-environment-setup.md @@ -17,7 +17,7 @@ keywords: - VSCode extension --- -# Cadence environment setup +# Cadence Environment Setup This comprehensive tutorial will guide you through how to set up your complete development environment, deploy your first smart contract, and learn the fundamentals of Flow development. You'll work hands-on with the Flow CLI, local emulator, and a real smart contract to build practical skills from day one. @@ -28,7 +28,7 @@ Flow is a blockchain built for the next generation of apps, games, and digital a After you complete this tutorial, you'll be able to: - **Set up a complete Flow development environment** with CLI tools and VSCode integration. -- **Create and manage Flow projects** using the Flow CLI and understand project structure. +- **Create and manage Flow projects** with the Flow CLI and understand project structure. - **Deploy and interact with smart contracts** on the local Flow emulator. - **Execute scripts and transactions** to read from and modify blockchain state. - **Understand Flow's account model** and how contracts are deployed to account storage. @@ -39,10 +39,10 @@ After you complete this tutorial, you'll be able to: You'll work with a `Counter` contract, a simple but comprehensive example that demonstrates core Flow development patterns. This contract maintains a count value and provides functions to increment, decrement, and read the current count. By the end of this tutorial, you'll have: - A fully functional local Flow development environment. -- A deployed Counter contract running on your local emulator. +- A deployed Counter contract that runs on your local emulator. - Scripts to query the contract's state. - Transactions to modify the contract's state. -- Understanding of how to extend this foundation for more complex applications. +- Knowledge of how to extend this foundation for more complex applications. **Time Commitment:** Approximately 30-45 minutes @@ -56,7 +56,7 @@ You'll work with a `Counter` contract, a simple but comprehensive example that d ### Install Flow CLI -The [Flow Command Line Interface] (CLI) is a set of tools that developers can use to interact with the Flow blockchain by managing accounts, sending transactions, deploying smart contracts, running the emulator, and more. This quickstart will get you familiar with its main concepts and functionality. +The [Flow Command Line Interface] (CLI) is a set of tools that developers can use to interact with the Flow blockchain. Developers can manage accounts, send transactions, deploy smart contracts, run the emulator, and more. This quickstart will get you familiar with its main concepts and functionality. The first thing you'll need to do is install the Flow CLI. If you have [homebrew] installed, run: @@ -98,7 +98,7 @@ When prompted: The `flow init` command creates: -- **`flow.json`**: Central configuration file containing accounts, contracts, deployments, and network settings. +- **`flow.json`**: Central configuration file that contains accounts, contracts, deployments, and network settings. - **`emulator-account.pkey`**: Private key for the default emulator account. - **`cadence/`**: Directory structure for your Cadence code: - `contracts/`: Smart contract files @@ -190,7 +190,7 @@ access(all) contract Counter { ### Create and configure deployment account -When you create a project, you'll see that a `Counter` contract was added to your [`flow.json` configuration file](../../../build/tools/flow-cli/flow.json/configuration.md), but it's not set up for deployment yet. We could deploy it to the automatically created `emulator-account`, but for this example, lets also create a new account on the emulator to deploy it to. +When you create a project, you'll see that a `Counter` contract was added to your [`flow.json`] configuration file, but it's not set up for deployment yet. We could deploy it to the automatically created `emulator-account`, but for this example, lets also create a new account on the emulator to deploy it to. :::info @@ -209,7 +209,7 @@ When prompted: 1. **Account name:** Enter `test-account` 2. **Network:** Select `Emulator` -This adds the new account to your `flow.json` configuration file.You'll now see this account in your [`flow.json`](../../../build/tools/flow-cli/flow.json/configuration.md). +This adds the new account to your `flow.json` configuration file. After you've created you accounts, then you can view all your accounts on the with the Flow CLI with: @@ -240,7 +240,7 @@ This shows which networks your configured accounts are accessible on: 💡 Tip: To fund testnet accounts, run: flow accounts fund ``` -This is a great tool to visualize your different accounts and balances when you are developing. +This is a great tool to visualize your different accounts and balances while you develop.. ### Configure contract deployment @@ -404,8 +404,8 @@ You've successfully established a solid foundation for building on Flow. Let's r ✅ **Blockchain interactions** -- Scripts to query contract state (reading blockchain data). -- Transactions to modify contract state (writing to blockchain). +- Scripts to query contract state (read blockchain data). +- Transactions to modify contract state (write to blockchain). - Real-time interaction with blockchain data through CLI commands. ### Resources for continued learning @@ -425,7 +425,7 @@ Welcome to the Flow developer community—you're ready to build the future of di [Flow Command Line Interface]: ../../../build/tools/flow-cli/index.md [installation guide]: ../../../build/tools/flow-cli/install [Flow Cadence VSCode Extension]: https://marketplace.visualstudio.com/items?itemName=onflow.cadence -[`flow.json`]: https://developers.flow.com/build/tools/flow-cli/flow.json/configuration +[`flow.json`]: ../../../build/tools/flow-cli/flow.json/configuration.md [Generating Cadence Boilerplate]: https://developers.flow.com/build/tools/flow-cli/generate [basic scripts]: https://developers.flow.com/build/cadence/basics/scripts [basic transactions]: https://developers.flow.com/build/cadence/basics/transactions diff --git a/docs/blockchain-development-tutorials/cadence/getting-started/index.md b/docs/blockchain-development-tutorials/cadence/getting-started/index.md index 26c17d7146..cea8654cf9 100644 --- a/docs/blockchain-development-tutorials/cadence/getting-started/index.md +++ b/docs/blockchain-development-tutorials/cadence/getting-started/index.md @@ -17,9 +17,9 @@ keywords: - Production deployment --- -# Getting started with cadence +# Getting Started With Cadence -The Cadence is designed for the next generation of apps, games, and digital assets. This comprehensive tutorial series will guide you from setting up your development environment to deploying production-ready applications on Flow's mainnet while a complete Counter application that demonstrates all essential Flow development patterns. +The Cadence is designed for the next generation of apps, games, and digital assets. This comprehensive tutorial series will guide you from development environment setup to production-ready application deployment on Flow's mainnet as a complete Counter application that demonstrates all essential Flow development patterns.