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 1ad5665825..a2b9492565 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 @@ -434,6 +434,6 @@ This approach gives you the freedom to build complex application logic that comp [transaction]: https://cadence-lang.org/docs/language/transactions [account commands]: ../../../build/tools/flow-cli/commands#account-management [Send the transaction]: ../../../build/tools/flow-cli/commands#send-transaction -[emulator]: ../../../build/tools/flow-cli/deployment/start-emulator +[emulator]: ../../../build/tools/emulator/index.md [MintExampleNFT transaction]: https://github.com/mfbz/flow-nft-tester/blob/main/cadence/transactions/MintExampleNFT.cdc [testnet Flowscan]: https://testnet.flowscan.io/ diff --git a/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md b/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md index bdab2e5180..836c29ab26 100644 --- a/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md +++ b/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md @@ -12,6 +12,9 @@ keywords: - resource-oriented programming - transaction composition - script queries + - contract upgrades + - contract updatability + - incremental upgrades --- # Cadence Advantages @@ -28,9 +31,14 @@ Learn how to compose with someone else's on-chain contracts by writing a Cadence 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. +### [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: first adding an event to notify users when the counter reaches an even number, then extending the contract with additional functionality like incrementing by 2 and checking if numbers are even. You'll understand what can and cannot be changed during upgrades, perform multiple contract updates using Flow CLI, and test upgraded functionality with comprehensive transactions and scripts. + ## Conclusion -Cadence's unique featuresโ€”from resource-oriented programming to native data availability and seamless transaction compositionโ€”represent a fundamental advancement in smart contract development. These tutorials demonstrate how Cadence enables 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โ€”from 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 enables 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. [Compose with Cadence Transactions]: ./compose-with-cadence-transactions.md [Native Data Availability with Cadence Scripts]: ./native-data-availibility-with-cadence-scripts.md +[Upgrading Cadence Contracts]: ./upgrading-cadence-contracts.md 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 new file mode 100644 index 0000000000..708689468e --- /dev/null +++ b/docs/blockchain-development-tutorials/cadence/cadence-advantages/upgrading-cadence-contracts.md @@ -0,0 +1,821 @@ +--- +title: Upgrading Cadence Contracts +description: Learn how to upgrade already deployed Cadence contracts by adding new functionality while preserving existing state. Deploy a Counter contract, modify it to add even/odd counting functionality, and update it on testnet using Flow CLI. +sidebar_position: 2 +keywords: + - Cadence contract upgrades + - contract updates + - Flow CLI + - contract deployment + - testnet deployment + - contract modification + - state preservation + - contract versioning + - Flow CLI commands + - account update contract + - contract evolution +--- + +# 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. + +This tutorial demonstrates how to upgrade a deployed contract through two scenarios: first adding an event to notify users when the counter reaches an even number, then extending the contract with additional functionality like incrementing by 2 and checking if numbers are even. + +## Objectives + +After completing this guide, you will be able to: + +- **Deploy a contract** to Flow testnet using Flow CLI +- **Perform incremental contract upgrades** by adding new events and functions +- **Update deployed contracts multiple times** using the `flow accounts update-contract` command +- **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 + +## Prerequisites + +- [Flow CLI installed] and configured +- Basic familiarity with [Cadence] and [Flow accounts] +- A **funded testnet account** to deploy and update contracts + - See [Create accounts] and [Fund accounts] in the Flow CLI commands + +## Contract Upgrade Overview + +Cadence provides a sophisticated contract upgrade system that allows you to modify deployed contracts while ensuring data consistency and preventing runtime crashes. Understanding what you can and cannot change is crucial for successful upgrades. + +### What You CAN Upgrade + +- **Add new functions** - Extend contract functionality with new methods +- **Add new events** - Emit additional events for monitoring and indexing +- **Modify function implementations** - Change how existing functions work +- **Change function signatures** - Update parameters and return types +- **Remove functions** - Delete functions that are no longer needed +- **Change access modifiers** - Update visibility of functions and fields +- **Reorder existing fields** - Field order doesn't affect storage + +### What You CANNOT Upgrade + +- **Add new fields** - Would cause runtime crashes when loading existing data +- **Change field types** - Would cause deserialization errors +- **Remove existing fields** - Fields become inaccessible but data remains +- **Change enum structures** - Raw values must remain consistent +- **Change contract name** - Contract address must remain the same + +### Why These Restrictions Exist + +The [Cadence Contract Updatability documentation](https://cadence-lang.org/docs/language/contract-updatability) explains that these restrictions prevent: + +- **Runtime crashes** from missing or garbage field values +- **Data corruption** from type mismatches +- **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. + +## Getting Started + +Create a new Flow project for this tutorial: + +```bash +# Create a new Flow project +flow init upgrading-contracts-tutorial +``` + +Follow the prompts and create a `Basic Cadence project (no dependencies)` then open the new project in your editor. + +### Create and Fund Testnet Account + +You'll need a funded testnet account to deploy and update contracts. In a terminal in the root of your project folder: + +```bash +# Create a testnet account +flow accounts create --network testnet +``` + +When prompted: + +1. **Account name**: Enter `testnet-account` +2. Select `testnet` as the network when prompted + +Fund your account with testnet FLOW tokens: + +```bash +# Fund the account +flow accounts fund testnet-account +``` + +This will open the faucet in your browser where you can request 100,000 testnet FLOW tokens. + +:::info + +The faucet provides free testnet tokens for development and testing purposes. These tokens have no real value and are only used on the testnet network. + +::: + +--- + +## Deploy the Initial Counter Contract + +Let's start by deploying a simple Counter contract to testnet. + +Open and review `cadence/contracts/Counter.cdc`. This is a simple contract created with all projects: + +```cadence +access(all) contract Counter { + + access(all) var count: Int + + // Event to be emitted when the counter is incremented + access(all) event CounterIncremented(newCount: Int) + + // Event to be emitted when the counter is decremented + access(all) event CounterDecremented(newCount: Int) + + init() { + self.count = 0 + } + + // Public function to increment the counter + access(all) fun increment() { + self.count = self.count + 1 + emit CounterIncremented(newCount: self.count) + + // NEW: Also emit event if the result is even + if self.count % 2 == 0 { + emit CounterIncrementedToEven(newCount: self.count) + } + } + + // Public function to decrement the counter + access(all) fun decrement() { + self.count = self.count - 1 + emit CounterDecremented(newCount: self.count) + } + + // Public function to get the current count + view access(all) fun getCount(): Int { + return self.count + } +} +``` + +### Configure Deployment + +Add testnet deployment configuration to your `flow.json`: + +```bash +flow config add deployment +``` + +Follow the prompts: + +1. **Network**: `testnet` +2. **Account**: `testnet-account` +3. **Contract**: `Counter` +4. **Deploy more contracts**: `no` + +Your `flow.json` will now include a testnet deployment section: + +```json +{ + "deployments": { + "testnet": { + "testnet-account": ["Counter"] + } + } +} +``` + +### Deploy to Testnet + +Deploy your Counter contract to testnet: + +```bash +flow project deploy --network testnet +``` + +You should see output similar to: + +```bash +Deploying 1 contracts for accounts: testnet-account + +Counter -> 0x9942a81bc6c3c5b7 (contract deployed successfully) + +๐ŸŽ‰ All contracts deployed successfully +``` + +### Test the Initial Contract + +Use the provided transaction to test initial functionality: + +Review `cadence/transactions/TestCounter.cdc`. This transaction simply increments the counter: + +```cadence +import "Counter" + +transaction { + + prepare(acct: &Account) { + // Authorizes the transaction + } + + execute { + // Increment the counter + Counter.increment() + + // Retrieve the new count and log it + let newCount = Counter.getCount() + log("New count after incrementing: ".concat(newCount.toString())) + } +} +``` + +:::info + +Cadence transactions are written in Cadence and can call one or more functions on one or more contracts, all with a single user signature. Check out our tutorial to learn how to [Compose with Cadence Transactions] to learn more! + +::: + +Run the test transaction: + +```bash +flow transactions send cadence/transactions/IncrementCounter.cdc --signer testnet-account --network testnet +``` + +You should see logs showing the counter incrementing and decrementing as expected. + +```bash +Transaction ID: 251ee40a050b8c7298d33f1b73ed94996a9d99deae8559526d9dddae182f7752 + +Block ID 25cdb14fcbaf47b3fb13e6ec43bdef0ede85a6a580caea758220c53d48493e17 +Block Height 284173579 +Status โœ… SEALED +ID 251ee40a050b8c7298d33f1b73ed94996a9d99deae8559526d9dddae182f7752 +Payer adb1efc5826d3768 +Authorizers [adb1efc5826d3768] + +Proposal Key: + Address adb1efc5826d3768 + Index 0 + Sequence 1 + +No Payload Signatures + +Envelope Signature 0: adb1efc5826d3768 +Signatures (minimized, use --include signatures) + +Events: + Index 0 + Type A.adb1efc5826d3768.Counter.CounterIncremented + Tx ID 251ee40a050b8c7298d33f1b73ed94996a9d99deae8559526d9dddae182f7752 + Values + - newCount (Int): 1 +``` + +--- + +## Upgrade the Contract - Part 1: Adding 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: + +```cadence +access(all) contract Counter { + + access(all) var count: Int + + // Event to be emitted when the counter is incremented + access(all) event CounterIncremented(newCount: Int) + + // Event to be emitted when the counter is decremented + access(all) event CounterDecremented(newCount: Int) + + // NEW: Event to be emitted when the counter is incremented and the result is even + access(all) event CounterIncrementedToEven(newCount: Int) + + init() { + self.count = 0 + } + + // Public function to increment the counter + access(all) fun increment() { + self.count = self.count + 1 + emit CounterIncremented(newCount: self.count) + + // NEW: Also emit event if the result is even + if self.count % 2 == 0 { + emit CounterIncrementedToEven(newCount: self.count) + } + } + + // Public function to decrement the counter + access(all) fun decrement() { + self.count = self.count - 1 + emit CounterDecremented(newCount: self.count) + } + + // Public function to get the current count + view access(all) fun getCount(): Int { + return self.count + } +} +``` + +### Key Changes Made - Part 1 + +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 + +:::info + +This demonstrates how you can enhance existing functionality by adding new events and modifying existing function behavior. The original `CounterIncremented` event still works as before, ensuring backward compatibility. + +::: + +--- + +## 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. + +### Update the Contract + +Use the [Flow CLI update contract command] to upgrade your deployed contract: + +```bash +flow accounts update-contract ./cadence/contracts/Counter.cdc --signer testnet-account --network testnet +``` + +You should see output similar to: + +```bash +Contract 'Counter' updated on account '0x9942a81bc6c3c5b7' + +Address 0x9942a81bc6c3c5b7 +Balance 99999999999.70000000 +Keys 1 + +Key 0 Public Key [your public key] + Weight 1000 + Signature Algorithm ECDSA_P256 + Hash Algorithm SHA3_256 + Revoked false + Sequence Number 2 + Index 0 + +Contracts Deployed: 1 +Contract: 'Counter' +``` + +:::success + +The contract has been successfully updated! Notice that: + +- The contract address remains the same (`0x9942a81bc6c3c5b7`) +- The existing state (`count`) is preserved +- New functionality is now available + +::: + +### Test the First Upgrade + +Let's test the new event functionality. Create a simple transaction to test the enhanced `increment()` function: + +```bash +flow generate transaction TestEvenEvent +``` + +Replace the contents of `cadence/scripts/CheckCounter.cdc` with: + +```cadence +import "Counter" + +access(all) fun main(): {String: AnyStruct} { + return { + "count": Counter.getCount(), + "isEven": Counter.isEven() + } +} +``` + +Run the script to check the current state: + +```bash +flow scripts execute cadence/scripts/CheckCounter.cdc --network testnet +``` + +You should see output showing the counter state: + +```bash +Result: {"count": 1, "isEven": false} +``` + +Notice that: + +- The original `count` value is preserved (showing the increment from our earlier test) +- The new `isEven()` function works correctly (1 is odd, so it returns false) + +--- + +## Upgrade the Contract - Part 2: Adding 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. + +### Modify the Counter Contract - Second Upgrade + +Update `cadence/contracts/Counter.cdc` to add the additional functionality: + +```cadence +access(all) contract Counter { + + access(all) var count: Int + + // Event to be emitted when the counter is incremented + access(all) event CounterIncremented(newCount: Int) + + // Event to be emitted when the counter is decremented + access(all) event CounterDecremented(newCount: Int) + + // Event to be emitted when the counter is incremented and the result is even + access(all) event CounterIncrementedToEven(newCount: Int) + + // NEW: Event to be emitted when the counter is incremented by 2 + access(all) event CounterIncrementedByTwo(newCount: Int) + + // NEW: Event to be emitted when the counter is decremented by 2 + access(all) event CounterDecrementedByTwo(newCount: Int) + + init() { + self.count = 0 + } + + // Public function to increment the counter + access(all) fun increment() { + self.count = self.count + 1 + emit CounterIncremented(newCount: self.count) + + // Also emit event if the result is even + if self.count % 2 == 0 { + emit CounterIncrementedToEven(newCount: self.count) + } + } + + // Public function to decrement the counter + access(all) fun decrement() { + self.count = self.count - 1 + emit CounterDecremented(newCount: self.count) + } + + // Public function to get the current count + view access(all) fun getCount(): Int { + return self.count + } + + // NEW: Public function to increment the counter by 2 + access(all) fun incrementByTwo() { + self.count = self.count + 2 + emit CounterIncrementedByTwo(newCount: self.count) + } + + // NEW: Public function to decrement the counter by 2 + access(all) fun decrementByTwo() { + self.count = self.count - 2 + emit CounterDecrementedByTwo(newCount: self.count) + } + + // NEW: Public function to check if the current count is even + view access(all) fun isEven(): Bool { + return self.count % 2 == 0 + } +} +``` + +### Key Changes Made - Part 2 + +This second upgrade adds: + +1. **New functions**: `incrementByTwo()` and `decrementByTwo()` that modify the existing counter by 2 +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 + +Now let's update the deployed contract with our second upgrade. + +### Update the Contract Again + +Use the [Flow CLI update contract command] to upgrade your deployed contract with the additional functionality: + +```bash +flow accounts update-contract ./cadence/contracts/Counter.cdc --signer testnet-account --network testnet +``` + +You should see output similar to: + +```bash +Contract 'Counter' updated on account '0x9942a81bc6c3c5b7' + +Address 0x9942a81bc6c3c5b7 +Balance 99999999999.70000000 +Keys 1 + +Key 0 Public Key [your public key] + Weight 1000 + Signature Algorithm ECDSA_P256 + Hash Algorithm SHA3_256 + Revoked false + Sequence Number 3 + Index 0 + +Contracts Deployed: 1 +Contract: 'Counter' +``` + +:::success + +The contract has been successfully updated again! Notice that: + +- The contract address remains the same (`0x9942a81bc6c3c5b7`) +- The existing state (`count`) is preserved +- All previous functionality is still available +- New functionality is now available + +::: + +### Verify the Update + +Let's verify that the existing functionality still works and the new functionality is available. + +Create a script to check the current state: + +```bash +flow generate script CheckCounter +``` + +Replace the contents of `cadence/scripts/CheckCounter.cdc` with: + +```cadence +import "Counter" + +access(all) fun main(): {String: AnyStruct} { + return { + "count": Counter.getCount(), + "isEven": Counter.isEven() + } +} +``` + +Run the script to check the current state: + +```bash +flow scripts execute cadence/scripts/CheckCounter.cdc --network testnet +``` + +You should see output showing the counter state: + +```bash +Result: {"count": 2, "isEven": true} +``` + +Notice that: + +- The original `count` value is preserved (showing the increments from our earlier tests) +- The new `isEven()` function works correctly (2 is even, so it returns true) + +--- + +## Test the New Functionality + +Now let's create a transaction to test the new even counter functionality. + +### Create Test Transaction + +Create a new transaction to test the upgraded functionality: + +```bash +flow generate transaction TestNewCounter +``` + +Replace the contents of `cadence/transactions/TestNewCounter.cdc` with: + +```cadence +import "Counter" + +transaction { + prepare(acct: &Account) { + // Authorizes the transaction + } + + execute { + // Test the new functionality + log("Current count: ".concat(Counter.getCount().toString())) + log("Is even: ".concat(Counter.isEven().toString())) + + // Test the new incrementByTwo function + Counter.incrementByTwo() + log("After incrementByTwo: ".concat(Counter.getCount().toString())) + log("Is even now: ".concat(Counter.isEven().toString())) + + Counter.incrementByTwo() + log("After second incrementByTwo: ".concat(Counter.getCount().toString())) + + // Test the new decrementByTwo function + Counter.decrementByTwo() + log("After decrementByTwo: ".concat(Counter.getCount().toString())) + + // Verify original functionality still works and test the new event + Counter.increment() + log("After regular increment: ".concat(Counter.getCount().toString())) + log("Is even now: ".concat(Counter.isEven().toString())) + + // Increment again to trigger the CounterIncrementedToEven event + Counter.increment() + log("After second increment: ".concat(Counter.getCount().toString())) + log("Is even now: ".concat(Counter.isEven().toString())) + } +} +``` + +### Run the Test Transaction + +Execute the transaction to test the new functionality: + +```bash +flow transactions send cadence/transactions/TestNewCounter.cdc --signer testnet-account --network testnet +``` + +You should see logs showing: + +- The counter incrementing by 2 each time with `incrementByTwo()` +- The counter decrementing by 2 with `decrementByTwo()` +- The `isEven()` function working correctly +- The original `increment()` function still working normally +- The new `CounterIncrementedToEven` event being emitted when incrementing results in an even number + +### Verify Final State + +Run the check script again to see the final state: + +```bash +flow scripts execute cadence/scripts/CheckCounter.cdc --network testnet +``` + +You should see output similar to: + +```bash +Result: {"count": 6, "isEven": true} +``` + +This confirms that: + +- The new functions work correctly with the existing counter +- The original state was preserved during the upgrade +- The new functionality is fully operational + +--- + +## Understanding 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. + +### What You Can Upgrade + +When upgrading Cadence contracts, you can: + +- **Add new state variables** (like `countEven`) +- **Add new functions** (like `incrementEven()` and `decrementEven()`) +- **Add new events** (like `EvenCounterIncremented`) +- **Add new interfaces** and resource types +- **Modify function implementations** (with careful consideration) +- **Remove existing functions** (they are not stored as data) +- **Change function signatures** (parameters, return types) +- **Change access modifiers** of fields and functions +- **Reorder existing fields** (order doesn't affect storage) + +### What You Cannot Change + +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 + - The initializer only runs once during deployment, not on updates +- **Cannot change the type** of existing 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 + +The contract update validation ensures that: + +- **Stored data doesn't change its meaning** when a contract is updated +- **Decoding and using stored data** does not lead to runtime crashes +- **Type safety is maintained** across all stored values + +:::warning + +The validation system focuses on preventing runtime inconsistencies with stored data. It does not ensure that programs importing the updated contract remain valid - you may need to update dependent code if you change function signatures or remove functions. + +::: + +### Advanced Upgrade Patterns + +#### The `#removedType` Pragma + +For cases where you need to remove a type declaration (which is normally invalid), Cadence provides the `#removedType` pragma. This allows you to "tombstone" a type, preventing it from being re-added with the same name: + +```cadence +access(all) contract Foo { + // Remove the resource R permanently + #removedType(R) + + // Other contract code... +} +``` + +This pragma: + +- **Prevents security issues** from type confusion +- **Cannot be removed** once added (prevents circumventing restrictions) +- **Only works with composite types**, not interfaces + +#### Enum Upgrade Restrictions + +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 +- **Cannot change the raw type** of an enum +- **Cannot change enum case names** (would change stored values' meaning) + +### Best Practices + +When upgrading contracts: + +1. **Plan upgrades carefully** - Consider future extensibility and avoid breaking changes +2. **Test thoroughly** - Verify both old and new functionality work correctly +3. **Use events** - Emit events for new functionality to enable monitoring and indexing +4. **Document changes** - Keep track of what was added, removed, or modified in each upgrade +5. **Consider dependent code** - Update any programs that import your contract if you change function signatures +6. **Use the `#removedType` pragma** - When you need to permanently remove types +7. **Validate enum changes** - Ensure enum modifications follow the strict rules +8. **Test with existing data** - Verify upgrades work with real stored state, not just empty contracts + +--- + +## Why This Matters + +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 +- **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, adding new features and capabilities while maintaining backward compatibility and preserving user data. + +## Conclusion + +In this tutorial, you learned how to upgrade deployed Cadence contracts through multiple incremental upgrades by: + +- **Deploying an initial contract** to Flow testnet +- **Performing a first upgrade** to add an event for even numbers based on user feedback +- **Testing the first upgrade** to verify the new event functionality works correctly +- **Performing a second upgrade** to add additional functions and events +- **Testing the complete upgraded functionality** with comprehensive transactions +- **Verifying state preservation** and backward compatibility across multiple upgrades + +Now that you have completed the tutorial, you should be able to: + +- Deploy contracts to Flow testnet using Flow CLI +- Perform incremental contract upgrades by adding new functions and events +- Update deployed contracts multiple times while preserving existing 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. + + + +[Flow CLI installed]: ../../../build/tools/flow-cli/install.md +[Cadence]: https://cadence-lang.org/docs/tutorial/first-steps +[Flow accounts]: ../../../build/cadence/basics/accounts.md +[Create accounts]: ../../../build/tools/flow-cli/commands.md#create-accounts +[Fund accounts]: ../../../build/tools/flow-cli/commands.md#fund-accounts +[Flow CLI update contract command]: ../../../build/tools/flow-cli/accounts/account-update-contract.md +[Cadence Contract Updatability documentation]: https://cadence-lang.org/docs/language/contract-updatability +[Compose with Cadence Transactions]: ./compose-with-cadence-transactions.md 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 df3c6ec4ef..8b9e3cf6a4 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 @@ -459,7 +459,7 @@ For additional details and advanced usage, refer to the [@onflow/react-sdk docum [`useFlowQuery`]: ../../../build/tools/react-sdk#useflowquery [`useFlowMutate`]: ../../../build/tools/react-sdk#useflowmutate [Dev Wallet]: ../../../build/tools/flow-dev-wallet -[@onflow/react-sdk documentation]: ../../../build/tools/react-sdk/index.md -[**@onflow/react-sdk**]: ../../../build/tools/react-sdk/index.md +[@onflow/react-sdk documentation]: ../../../build/tools/react-sdk +[**@onflow/react-sdk**]: ../../../build/tools/react-sdk [Flow CLI]: ../../../build/tools/flow-cli/install.md [Cadence VSCode extension]: ../../../build/tools/vscode-extension diff --git a/docs/blockchain-development-tutorials/cross-vm-apps/add-to-wagmi.md b/docs/blockchain-development-tutorials/cross-vm-apps/add-to-wagmi.md index d0ca0f9911..afde67b943 100644 --- a/docs/blockchain-development-tutorials/cross-vm-apps/add-to-wagmi.md +++ b/docs/blockchain-development-tutorials/cross-vm-apps/add-to-wagmi.md @@ -517,4 +517,4 @@ For a complete reference implementation, check out the [FCL + RainbowKit + wagmi [Testnet Cadence Flowscan]: https://testnet.flowscan.io [Cadence Owned Accounts]: ../../build/cadence/basics/accounts.md [Testnet EVM Flowscan]: https://evm-testnet.flowscan.io -[pre-built utility from the `@onflow/react-sdk`]: ../../build/tools/react-sdk/index.md#usecrossvmbatchtransaction +[pre-built utility from the `@onflow/react-sdk`]: ../../build/tools/react-sdk#usecrossvmbatchtransaction diff --git a/docs/build/cadence/advanced-concepts/flix.md b/docs/build/cadence/advanced-concepts/flix.md index 360e587f12..0bf8a853eb 100644 --- a/docs/build/cadence/advanced-concepts/flix.md +++ b/docs/build/cadence/advanced-concepts/flix.md @@ -11,7 +11,7 @@ keywords: - FCL - interaction templates - template service -sidebar_position: 3 +sidebar_position: 10 --- # FLIX (Flow Interaction Templates) diff --git a/docs/build/cadence/smart-contracts/deploying.md b/docs/build/cadence/smart-contracts/deploying.md index 36988d13e4..c62321b18a 100644 --- a/docs/build/cadence/smart-contracts/deploying.md +++ b/docs/build/cadence/smart-contracts/deploying.md @@ -1,7 +1,7 @@ --- title: Deploying Contracts sidebar_label: Deploying Contracts -description: Learn how to deploy and update smart contracts on Flow Mainnet and Testnet. Understand account creation, key management, deployment best practices, and network sporks. +description: Learn how to deploy and update smart contracts on Flow Mainnet and Testnet. Understand account creation, key management, and deployment best practices. sidebar_position: 3 sidebar_custom_props: icon: ๐Ÿฅ‡ @@ -23,98 +23,338 @@ keywords: - Flow deployment --- -In order to deploy your smart contracts to the mainnet, you need a funded account. If you want to get started on Testnet, look below for information on how to get started. +# Deploying Contracts - -Make sure you handle your mainnet account keys appropriately. Using a Key Management Service is the best practice. - +Deploying smart contracts to Flow's networks is the final step in bringing your blockchain application to life. This guide covers everything you need to know to deploy your Cadence contracts to both Flow Testnet and Mainnet, from account creation to contract updates. -### Creating an Account +## What You'll Learn -There are two simple methods of creating an account on testnet. **Interactive** and **Manual**, both use the Flow CLI. On mainnet you will have to fund your newly created account, there is no faucet. -Make sure to install the Flow CLI. [Flow CLI](../../../build/tools/flow-cli/accounts/create-accounts.md) has a interactive mode for generating keys. +After completing this guide, you'll be able to: - -Anyone can deploy and update contracts on mainnet. Audits are encouraged but not mandatory to deploying contracts to mainnet. Take every precauction to reduce issues and protect users. - +- **Create and fund accounts** on Flow Testnet and Mainnet +- **Deploy contracts** using Flow CLI with proper configuration +- **Update existing contracts** while preserving their addresses +- **Understand the differences** between testnet and mainnet deployment +- **Follow security best practices** for production deployments -### Create and deploy a mainnet project +## Prerequisites -The tool of choice is Flow CLI, there are quickstarts and guides that use Flow CLI, [Getting Started](../../../blockchain-development-tutorials/cadence/getting-started/smart-contract-interaction) +Before deploying contracts, make sure you have: -- It is highly encouraged to test your contracts, transactions and scripts on Testnet, have strong smart contract test coverage and follow any additional guidelines set out here: [Smart Contract Testing Guidelines](./testing.md). -- Follow the Flow CLI instructions to [Create a Project](../../../build/tools/flow-cli/index.md). You have the Flow CLI installed and ran `flow init` in your project folder and generating a `flow.json` file -- Mainnet account: You completed the mainnet account setup, (see above) and have your key pair and mainnet address ready. -- [Deploy your project](../../../build/tools/flow-cli/deployment/deploy-project-contracts.md), notice that your account now has contracts deployed on mainnet. -- [Deploy a contract](../../../build/tools/flow-cli/accounts/account-add-contract.md) to mainnet. You can deploy contracts individually using the `account-add-contract` command. +- **Flow CLI installed** and configured +- **A Flow project** with contracts ready for deployment +- **Basic understanding** of Cadence smart contracts +- **Completed testing** of your contracts locally - -All your contract deployment addresses are stored in `flow.json`. Mainnet, Testnet and local (emulator) are stored as well. - +## Deployment Workflow + +The recommended deployment workflow follows this progression: + +1. **Emulator Deployment** - Deploy and test your contracts locally (free, instant) +2. **Testnet Deployment** - Deploy and test your contracts on Flow Testnet (free) +3. **Mainnet Deployment** - Deploy to Flow Mainnet once testing is complete (costs FLOW tokens) +4. **Contract Updates** - Update contracts as needed using the update command + +This approach ensures your contracts work correctly before committing real resources to mainnet deployment. + +## Deploy to Emulator + +The Flow Emulator is your local development environment where you can deploy and test contracts instantly without any network costs or delays. This is the first step in your deployment journey. + +### Start the Emulator + +First, start the [Flow Emulator]. In a second terminal: + +```zsh +flow emulator start +``` + +### Create an Emulator Account + +Create a local account for testing: + +```zsh +flow accounts create --network emulator +``` + +When prompted: + +1. **Account name**: Enter `emulator-account` +2. Select `emulator` as the network when prompted + +This creates a new account on the emulator and adds it to your `flow.json` configuration. + +### Configure Emulator Deployment + +Update your `flow.json` to include emulator deployment configuration: + +```zsh +flow config add deployment +``` + +Follow the prompts: + +1. **Network**: `emulator` +2. **Account**: `emulator-account` +3. **Contract**: `YourContract` +4. **Deploy more contracts**: `no` (or `yes` if you have multiple contracts) + +Your `flow.json` will now include an emulator deployment section: + +```json +{ + "deployments": { + "emulator": { + "emulator-account": ["YourContract"] + } + } +} +``` + +### Deploy Contract to Emulator + +Deploy your contract to the local emulator: + +```zsh +flow project deploy --network emulator +``` + +:::warning + +You cannot deploy the same contract to multiple accounts on the same network with one deployment command. If you attempt to do so, you will see: + +โŒ Command Error: the same contract cannot be deployed to multiple accounts on the same network + +Edit `flow.json` to remove the duplicate. + +::: + +You will see output similar to: + +```zsh +Deploying 1 contracts for accounts: emulator-account + +YourContract -> 0xf8d6e0586b0a20c7 (contract deployed successfully) + +๐ŸŽ‰ All contracts deployed successfully +``` + +### Test Your Emulator Deployment + +Verify your contract works by running scripts and transactions: + +```zsh +# Run a script to read contract state +flow scripts execute cadence/scripts/YourScript.cdc --network emulator + +# Send a transaction to interact with your contract +flow transactions send cadence/transactions/YourTransaction.cdc --network emulator --signer emulator-account +``` + +:::info + +The emulator provides instant feedback and is perfect for rapid development and testing. All transactions are free and execute immediately. -### Deploy updated contracts on mainnet +::: -Contracts can be updated and retain the contract address. You can use the [Flow CLI contract update command](../../../build/tools/flow-cli/accounts/account-update-contract.md) to re-deploy an updated version of your contract: +## Deploy to Testnet - -If you see `Error Code: 1103`, your new account does not have enough funds to complete the transaction. Make sure you have enough FLOW and your account is set up correctly, check [Flowdiver](https://flowdiver.io/) to verify. - +For a more complete quickstart, visit the [Getting Started] guide. -Once all your contracts are deployed, you can visit [flow-view-source](https://flow-view-source.com/) or run the [Flow CLI get account command](../../../build/tools/flow-cli/accounts/get-accounts.md) to confirm the deployment. +- You should test your contracts, transactions and scripts on Testnet, have strong smart contract test coverage and follow the additional guidelines set out here: [Smart Contract Testing Guidelines]. +- Use `flow init` to [Create a Project] if you need one to practice deployment with. -### Sporks +### Create a Testnet Account -Currently, **historical event data is not migrated between sporks,** so you'll need to design your application with this in mind. We recognize the usefulness of historical event data and plan on adding a means of accessing it in the near future. Past spork transactional data is available, [See Previous Spork Access Node Info](../../../protocol/node-ops/node-operation/past-upgrades) +First, you'll need a testnet account to deploy your contracts. Create one with: -More Information on [Sporks](../../../protocol/node-ops/node-operation/network-upgrade) +```zsh +flow accounts create --network testnet +``` -### Testnet +:::info -The Flow test network, known as Flow Testnet, exists to help developers test their software and smart contracts against a live network. It's also used as a means of releasing and testing new protocol and smart contract features before they are integrated into Flow's main network (Mainnet). +For security reasons, Flow Cadence does not allow accounts to have the same address on testnet, mainnet, and/or the emulator. -When the Flow protocol is updated or a new version of Cadence is released, those updates will always be made available on the [Flow Emulator](../../../build/tools/emulator) _before_ they're integrated into Flow Testnet or Flow Mainnet. +:::: -## Getting Started on Testnet +When prompted: -If you need to create a flow.json file to store information about accounts and contracts use the `flow init` command to create a project - -To create accounts and generate keys, make sure to install [Flow CLI](../../../build/tools/flow-cli/install). Flow CLI provides convenient functions to simplifies interacting with the blockchain. - +1. **Account name**: Enter `testnet-account` +2. Select `testnet` as the network when prompted -### Creating an Account +This creates a new account on testnet and adds it to your `flow.json` configuration. It also saves the private key for the new account in `.pkey` and uses this file to import the key because `flow.json` will be visible in the repo. -There is a simple Flow CLI command to run to create an account. `flow accounts create` command will create a new account and generate a key pair then add the account to your flow.json. The command will try and You can also use the [Testnet Faucet](https://faucet.flow.com/fund-account) to create and fund an account. +:::danger -More information about [Flow CLI](../../../build/tools/flow-cli/accounts/create-accounts) and creating accounts. +As with any other blockchain network, **anyone** with access to the private key for an account can access that account at any time without you knowing. -### Creating and deploying a Project +::: -Flow CLI can be used to create a Cadence project and stay organized, [Flow CLI: Create a project](../../../build/tools/flow-cli). This will make deployment much easiler and help with the iterative development process. +### Fund Your Testnet Account -After you have a project created and want to deploy your Cadence; contracts, transactions and scripts. -`flow accounts add-contract --signer --network testnet` will deploy your contract to testnet. -More information on how to use Flow CLI to [deploy](../../../build/tools/flow-cli/deployment/deploy-project-contracts.md). +To deploy contracts and send transactions on testnet, you need FLOW tokens. Flow provides a faucet service to get free testnet tokens. -Make sure Flow project was initialized in the previous step and the `flow.json` is present. +```zsh +flow accounts fund testnet-account +``` -### Making Use of Core Contracts +This will open the faucet in your browser. You can also navigate there manually. -Flow Testnet comes with some useful contracts already deployed, called **core contracts.** More information and import addresses for the [core contracts](../core-contracts/index.md). +1. Visit the [Testnet Faucet] +2. Enter your testnet account address +3. Complete any required verification (captcha, etc.) +4. Request tokens (you'll receive 100000 testnet FLOW tokens) -Once your accounts are set up and you're ready to develop, you can look over [some code examples from the Flow Go SDK](https://github.com/onflow/flow-go-sdk/tree/master/examples). +Check your account balance: -### Breaking Changes +```zsh +flow accounts list +``` -The Flow blockchain is improved continuously and thus version updates to Cadence, Flow node software, and the Flow SDKs will contain important updates as well as breaking changes. +You will see your account details with a balance of FLOW tokens. -You should anticipate future updates and join the community ([Forum](https://forum.flow.com/) or [Discord](https://discord.com/invite/J6fFnh2xx6)) to stay tuned on important announcements. Notices and guidelines for changes will be provided as early as possible. +### Configure Testnet Deployment -### Testnet Sporking +Update your `flow.json` to include testnet deployment configuration: -"Sporking" (soft forking) is the process of upgrading the Flow network node software and migrating the chain state from one version to another. +```zsh +flow config add deployment +``` -Currently, **historical event data is not migrated between sporks.** You'll need to design your application with this in mind. We recognize the usefulness of historical event data and plan on adding a means of accessing it in the near future. Only one previous spork data is available through old Access Node. +Follow the prompts: + +1. **Network**: `testnet` +2. **Account**: `testnet-account` +3. **Contract**: `YourContract` +4. **Deploy more contracts**: `no` (or `yes` if you have multiple contracts) + +Your `flow.json` will now include a testnet deployment section: + +```json +{ + "deployments": { + "testnet": { + "testnet-account": ["YourContract"] + } + } +} +``` + +### Deploy Contract to Testnet + +Deploy your contract to the public testnet: + +```zsh +flow project deploy --network testnet +``` + +You will see output similar to: + +```zsh +Deploying 1 contracts for accounts: testnet-account + +YourContract -> 0x9942a81bc6c3c5b7 (contract deployed successfully) + +๐ŸŽ‰ All contracts deployed successfully +``` + +## Deploy to Mainnet + +Once you've successfully tested your contracts on testnet, you can deploy to mainnet. You'll need a mainnet account with real FLOW tokens. + +### Create a Mainnet Account + +For mainnet, you'll need to acquire FLOW tokens through exchanges or other means, as there's no faucet. + +```zsh +flow accounts create --network mainnet +``` + +When prompted: + +1. **Account name**: Enter `mainnet-account` +2. **Select "Mainnet" Network** + +### Acquire FLOW Tokens + +You can purchase FLOW tokens from major exchanges. Make sure your mainnet account has sufficient FLOW tokens to cover deployment costs. Flow is a very efficient network, so even 1.0 FLOW is sufficient to deploy large numbers of contracts. + +### Configure Mainnet Deployment + +Add mainnet deployment configuration to your `flow.json`: + +```zsh +flow config add deployment --network mainnet +``` + +Follow the prompts: + +1. **Network**: `mainnet` +2. **Account**: `mainnet-account` +3. **Contract**: `YourContract` +4. **Deploy more contracts**: `no` (or `yes` if you have multiple contracts) + +Your `flow.json` should now include mainnet configuration: + +```json +{ + "deployments": { + "mainnet": { + "mainnet-account": ["YourContract"] + } + } +} +``` + +### Deploy to Mainnet + +Deploy your contracts to mainnet: + +```zsh +flow project deploy --network mainnet +``` + +:::warning + +This deployment costs (a relatively small amount of) real FLOW tokens and cannot be undone. You can however redeploy your contracts to update them, or delete them. + +::: + +You should see output similar to: + +```zsh +Deploying 1 contracts for accounts: mainnet-account + +YourContract -> 0xABC123DEF456789 (contract deployed successfully) + +๐ŸŽ‰ All contracts deployed successfully +``` + +:::info + +All your contract deployment addresses are stored in `flow.json`. Mainnet, Testnet and local (emulator) are stored as well. - -Flow Testnet is explicitly for experimentation and testing and should not be used to exchange "real value" (e.g. developing a fiat money on/off-ramp for your testnet application). - +::: + +## Deploy updated contracts on mainnet + +Contracts can be updated and retain the contract address. You can use the [Flow CLI contract update command] to redeploy an updated version of your contract: + +```zsh +flow accounts update-contract ./YourContract.cdc --signer mainnet-account --network mainnet +``` + +[Flow CLI]: ../../../build/tools/flow-cli/install +[Getting Started]: ../../../blockchain-development-tutorials/cadence/getting-started/smart-contract-interaction +[Smart Contract Testing Guidelines]: ./testing.md +[Create a Project]: ../../../build/tools/flow-cli/index.md +[Flow CLI contract update command]: ../../../build/tools/flow-cli/accounts/account-update-contract.md +[Flow CLI get account command]: ../../../build/tools/flow-cli/accounts/get-accounts.md +[Sporks]: ../../../protocol/node-ops/node-operation/network-upgrade +[Flow Emulator]: ../../../build/tools/emulator +[Testnet Faucet]: https://faucet.flow.com/ +[core contracts]: ../core-contracts/index.md +[some code examples from the Flow Go SDK]: https://github.com/onflow/flow-go-sdk/tree/master/examples +[Forum]: https://forum.flow.com/ +[Discord]: https://discord.com/invite/J6fFnh2xx6 diff --git a/docs/build/tools/emulator/index.md b/docs/build/tools/emulator/index.md index 451e772a64..d22893cc34 100644 --- a/docs/build/tools/emulator/index.md +++ b/docs/build/tools/emulator/index.md @@ -24,7 +24,17 @@ Then start the Flow Emulator: flow emulator ``` +You'll see output similar to: + +```bash +INFO[0000] โš™๏ธ Using service account 0xf8d6e0586b0a20c7 serviceAddress=f8d6e0586b0a20c7 ... +INFO[0000] ๐ŸŒฑ Starting Flow Emulator +INFO[0000] ๐Ÿ›  GRPC server started on 127.0.0.1:3569 +INFO[0000] ๐Ÿ“ก HTTP server started on 127.0.0.1:8080 +``` + This starts a local Flow network with: + - gRPC server on port `3569` - REST API on `http://localhost:8888` - Admin API on port `8080` @@ -40,6 +50,12 @@ flow emulator --block-time 1s # Persist state between restarts flow emulator --persist + +# Change the gRPC and REST API ports +flow emulator --port 9000 --rest-port 9001 + +# For a complete list of available flags, run: +flow emulator --help ``` For all available options, see the [CLI commands overview](../flow-cli/index.md). @@ -49,6 +65,36 @@ For all available options, see the [CLI commands overview](../flow-cli/index.md) - **Code Coverage**: Add `--coverage-reporting` flag and visit `http://localhost:8080/emulator/codeCoverage` - **Debugging**: Use `#debugger()` pragma in Cadence code for breakpoints +## Snapshots + +The Flow CLI provides a command to create emulator snapshots, which are points in blockchain history you can later jump to and reset the state to that moment. This can be useful for testing where you establish a beginning state, run tests and after revert back to the initial state. + +### Create a new snapshot + +Create a new emulator snapshot at the current block with a name of `myInitialState`. + +```shell +flow emulator snapshot create myInitialState +``` + +### Load an existing snapshot + +To jump to a previously created snapshot we use the load command in combination with the name. + +```shell +flow emulator snapshot load myInitialState +``` + +### List all existing snapshots + +To list all the existing snapshots we previously created and can load to run: + +```shell +flow emulator list +``` + +To learn more about using the Emulator, have a look at the [README of the repository](https://github.com/onflow/flow-emulator). + ## Additional Resources For advanced configuration options, see the [Flow Emulator repository](https://github.com/onflow/flow-emulator/). diff --git a/docs/build/tools/flow-cli/deployment/emulator-snapshot.md b/docs/build/tools/flow-cli/deployment/emulator-snapshot.md deleted file mode 100644 index a1782c0f72..0000000000 --- a/docs/build/tools/flow-cli/deployment/emulator-snapshot.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Create Emulator Snapshot -description: How to start create emulator snapshot from the command line -sidebar_position: 4 ---- - -The Flow CLI provides a command to create emulator snapshots, which are points in blockchain -history you can later jump to and reset the state to that moment. This can be useful for testing where you -establish a begining state, run tests and after revert back to the initial state. - -The command syntax is: -```shell -flow emulator snapshot create|load|list {name} -``` - -## Example Usage - -### Create a new snapshot -Create a new emulator snapshot at the current block with a name of `myInitialState`. -```shell -> flow emulator snapshot create myInitialState -``` - -### Load an existing snapshot -To jump to a previously created snapshot we use the load command in combination with the name. -```shell -> flow emulator snapshot load myInitialState -``` - -### List all existing snapshots -To list all the existing snapshots we previously created and can load to we run the following command: -```shell -> flow emulator list -``` - - -To learn more about using the Emulator, have a look at the [README of the repository](https://github.com/onflow/flow-emulator). - -## Flags - -### Emulator Flags -You can specify any [emulator flags found here](https://github.com/onflow/flow-emulator#configuration) and they will be applied to the emulator service. - -### Configuration - -- Flag: `--config-path` -- Short Flag: `-f` -- Valid inputs: valid filename - -Specify a filename for the configuration files, you can provide multiple configuration -files by using `-f` flag multiple times. - -### Version Check - -- Flag: `--skip-version-check` -- Default: `false` - -Skip version check during start up to speed up process for slow connections. diff --git a/docs/build/tools/flow-cli/deployment/start-emulator.md b/docs/build/tools/flow-cli/deployment/start-emulator.md deleted file mode 100644 index e5e55ff15b..0000000000 --- a/docs/build/tools/flow-cli/deployment/start-emulator.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Start Emulator -description: How to start the Flow Emulator from the command line -sidebar_position: 1 ---- - -The Flow Emulator is a lightweight development tool that mimics the behavior of the real Flow network. It is bundled with the [Flow CLI](https://docs.onflow.org/flow-cli/), which makes starting and configuring the emulator straightforward. - -## Initial Configuration - -The emulator requires a configuration file (`flow.json`). If you donโ€™t already have one, create it using the `flow init` command: - -```bash -flow init -``` - -This initializes a default configuration file that the emulator will use. - -## Starting the Emulator - -To start the emulator with default settings, use the following command: - -```bash -flow emulator -``` - -This will start the emulator with the configuration defined in `flow.json`. - -### Example Output - -When you run the `flow emulator` command, you will see output similar to the following: - -```bash -INFO[0000] โš™๏ธ Using service account 0xf8d6e0586b0a20c7 serviceAddress=f8d6e0586b0a20c7 ... -INFO[0000] ๐ŸŒฑ Starting Flow Emulator -INFO[0000] ๐Ÿ›  GRPC server started on 127.0.0.1:3569 -INFO[0000] ๐Ÿ“ก HTTP server started on 127.0.0.1:8080 -``` - -## Customizing the Emulator - -You can customize the emulator behavior by using flags. Here are some examples: - -Change the gRPC and REST API ports: - -```bash -flow emulator --port 9000 --rest-port 9001 -``` - -Enable persistence of state across restarts: - -```bash -flow emulator --persist -``` - -Enable detailed logs for debugging: - -```bash -flow emulator --verbose -``` - -For a complete list of available flags, run: - -```bash -flow emulator --help -``` - -## Learn More - -To explore advanced features like snapshots, rollbacks, and debugging, visit the [Flow Emulator README](https://github.com/onflow/flow-emulator). \ No newline at end of file diff --git a/docs/build/tools/react-sdk/components.md b/docs/build/tools/react-sdk/components.md index 8e6930e31d..7ebc3eef97 100644 --- a/docs/build/tools/react-sdk/components.md +++ b/docs/build/tools/react-sdk/components.md @@ -1,5 +1,5 @@ --- -title: 'Flow React SDK Components' +title: 'Components' description: Reusable UI components for Flow interactions. sidebar_position: 3 --- @@ -8,6 +8,7 @@ import { Connect, TransactionDialog, TransactionLink, TransactionButton } from " import { FlowProvider } from "@onflow/react-sdk" import FlowProviderDemo from '@site/src/components/FlowProviderDemo'; import TransactionDialogDemo from '@site/src/components/TransactionDialogDemo'; +import PlaygroundButton from '@site/src/components/PlaygroundButton'; # React SDK Components @@ -94,6 +95,8 @@ function MyComponent() { A drop-in wallet connection component with UI for copy address, logout, and balance display. +
+ **Props:** - `variant?: ButtonProps["variant"]` โ€“ Optional button style variant (default: `"primary"`) @@ -128,6 +131,8 @@ import { Connect } from "@onflow/react-sdk" Button component for executing Flow transactions with built-in loading states and global transaction management. +
+ **Props:** - `transaction: Parameters[0]` โ€“ Flow transaction object to execute when clicked @@ -180,6 +185,8 @@ const myTransaction = { Dialog component for real-time transaction status updates. +
+ **Props:** - `open: boolean` โ€“ Whether the dialog is open @@ -216,6 +223,8 @@ import { TransactionDialog } from "@onflow/react-sdk" Link to the block explorer with the appropriate network scoped to transaction ID. +
+ **Props:** - `txId: string` โ€“ The transaction ID to link to diff --git a/docs/build/tools/react-sdk/hooks.md b/docs/build/tools/react-sdk/hooks.md index 47761b1323..2ce8623497 100644 --- a/docs/build/tools/react-sdk/hooks.md +++ b/docs/build/tools/react-sdk/hooks.md @@ -1,9 +1,11 @@ --- -title: 'Flow React SDK Hooks' +title: 'Hooks' description: React hooks for interacting with the Flow blockchain. sidebar_position: 2 --- +import PlaygroundButton from '@site/src/components/PlaygroundButton'; + # React SDK Hooks :::info @@ -16,6 +18,8 @@ Many of these hooks are built using [`@tanstack/react-query`](https://tanstack.c ### `useFlowCurrentUser` + + ```tsx import { useFlowCurrentUser } from "@onflow/react-sdk" ``` @@ -53,6 +57,8 @@ function AuthComponent() { ### `useFlowAccount` + + ```tsx import { useFlowAccount } from "@onflow/react-sdk" ``` @@ -91,6 +97,8 @@ function AccountDetails() { ### `useFlowBlock` + + ```tsx import { useFlowBlock } from "@onflow/react-sdk" ``` @@ -128,6 +136,8 @@ function LatestBlock() { ### `useFlowChainId` + + ```tsx import { useFlowChainId } from "@onflow/react-sdk" ``` @@ -160,6 +170,8 @@ function ChainIdExample() { ### `useFlowClient` + + This hook returns the `FlowClient` for the current `` context. #### Parameters: @@ -170,6 +182,8 @@ This hook returns the `FlowClient` for the current `` context. ### `useFlowConfig` + + ```tsx import { useFlowConfig } from "@onflow/react-sdk" ``` @@ -193,6 +207,8 @@ function MyComponent() { ### `useFlowEvents` + + ```tsx import { useFlowEvents } from "@onflow/react-sdk" ``` @@ -227,6 +243,8 @@ function EventListener() { ### `useFlowQuery` + + ```tsx import { useFlowQuery } from "@onflow/react-sdk" ``` @@ -269,6 +287,8 @@ function QueryExample() { ### `useFlowQueryRaw` + + ```tsx import { useFlowQueryRaw } from "@onflow/react-sdk" ``` @@ -315,6 +335,8 @@ function QueryRawExample() { ### `useFlowMutate` + + ```tsx import { useFlowMutate } from "@onflow/react-sdk" ``` @@ -366,6 +388,8 @@ function CreatePage() { ### `useFlowRevertibleRandom` + + ```tsx import { useFlowRevertibleRandom } from "@onflow/react-sdk" ``` @@ -427,6 +451,8 @@ function RandomValues() { ### `useFlowTransaction` + + ```tsx import { useFlowTransaction } from "@onflow/react-sdk" ``` @@ -467,6 +493,8 @@ function TransactionDetails({ txId }: { txId: string }) { ### `useFlowTransactionStatus` + + ```tsx import { useFlowTransactionStatus } from "@onflow/react-sdk" ``` @@ -496,6 +524,8 @@ function TransactionStatusComponent() { ### `useDarkMode` + + ```tsx import { useDarkMode } from "@onflow/react-sdk" ``` @@ -525,6 +555,8 @@ function ThemeAwareComponent() { ### `useCrossVmBatchTransaction` + + ```tsx import { useCrossVmBatchTransaction } from "@onflow/react-sdk" ``` @@ -620,6 +652,8 @@ function CrossVmBatchTransactionExample() { ### `useCrossVmTokenBalance` + + ```tsx import { useCrossVmTokenBalance } from "@onflow/react-sdk" ``` @@ -684,6 +718,8 @@ function UseCrossVmTokenBalanceExample() { ### `useCrossVmSpendNft` + + ```tsx import { useCrossVmSpendNft } from "@onflow/react-sdk" ``` @@ -757,6 +793,8 @@ function CrossVmSpendNftExample() { ### `useCrossVmSpendToken` + + ```tsx import { useCrossVmSpendToken } from "@onflow/react-sdk" ``` @@ -830,6 +868,8 @@ function CrossVmSpendTokenExample() { ### `useCrossVmTransactionStatus` + + ```tsx import { useCrossVmTransactionStatus } from "@onflow/react-sdk" ``` diff --git a/docs/build/tools/react-sdk/index.md b/docs/build/tools/react-sdk/index.md deleted file mode 100644 index 8680be31ad..0000000000 --- a/docs/build/tools/react-sdk/index.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: '@onflow/react-sdk' -description: React hooks for interacting with the Flow blockchain. -sidebar_position: 1 ---- - -import { Connect, TransactionDialog, TransactionLink, TransactionButton } from "@onflow/react-sdk" -import { FlowProvider } from "@onflow/react-sdk" -import FlowProviderDemo from '@site/src/components/FlowProviderDemo'; - -# @onflow/react-sdk - -**The easiest way to build React apps on Flow.** A lightweight, TypeScript-first library that makes Flow blockchain interactions feel native to React development. - -๐Ÿš€ **Quick to setup** โ€“ One provider, minimal configuration -โšก **Built for performance** โ€“ Powered by TanStack Query for optimal caching -๐ŸŽจ **Styled beautifully** โ€“ Tailwind-based components that match your design -๐Ÿ”— **Cross-VM ready** โ€“ Seamlessly bridge between Cadence and Flow EVM - -## Quick Start - -### 1. Install - -```bash -npm install @onflow/react-sdk -``` - -### 2. Wrap Your App - -```tsx -import React from "react" -import App from "./App" -import { FlowProvider } from "@onflow/react-sdk" -import flowJSON from "../flow.json" - -function Root() { - return ( - - - - ) -} - -export default Root -``` - -:::tip Next.js Users -Place the `FlowProvider` inside your `layout.tsx`. Since React hooks must run on the client, you may need to wrap the provider in a separate file that begins with `'use client'` to avoid issues with server-side rendering. -::: - -### 3. Start Building - -```tsx -import { useFlowCurrentUser, Connect, useFlowQuery } from "@onflow/react-sdk" - -function MyApp() { - const { user } = useFlowCurrentUser() - - const { data: greeting } = useFlowQuery({ - cadence: `access(all) fun main(): String { return "Hello, Flow!" }`, - args: (arg, t) => [], - }) - - return ( -
- - {user?.loggedIn &&

Welcome, {user.addr}!

} -

{greeting}

-
- ) -} -``` - -### Live Demo - - - console.log("Connected!")} - onDisconnect={() => console.log("Disconnected!")} - /> - - ---- - -## What's Included - -### ๐ŸŽฃ [Hooks](./hooks.md) - -**Cadence Hooks** for native Flow interactions: -- Authentication & user management -- Account details & balances -- Block & transaction queries -- Real-time event subscriptions -- Script execution & mutations - -**Cross-VM Hooks** for bridging Cadence โ†” Flow EVM: -- Atomic batch transactions -- Token & NFT bridging -- Cross-chain balance queries - -[โ†’ View all hooks](./hooks.md) - -### ๐ŸŽจ [Components](./components.md) - -Beautiful, accessible UI components: -- `` โ€“ Wallet authentication with balance display -- `` โ€“ Smart transaction execution -- `` โ€“ Real-time transaction tracking -- `` โ€“ Network-aware block explorer links - -[โ†’ View all components](./components.md) - ---- - -## Why Choose React SDK? - -**Developer Experience First** -- TypeScript-native with full type safety -- Familiar React patterns and conventions -- Comprehensive error handling and loading states - -**Production Ready** -- Built on battle-tested libraries (TanStack Query, Tailwind CSS) -- Automatic retries, caching, and background updates -- Cross-VM support for hybrid Cadence/EVM applications - -**Customizable** -- Theme system for brand consistency -- Composable hooks for custom UI -- Dark mode support out of the box - ---- - -## Need Help? - -- ๐Ÿ“– **[Hooks Documentation](./hooks.md)** โ€“ Detailed API reference for all hooks -- ๐ŸŽจ **[Components Documentation](./components.md)** โ€“ UI components and theming guide -- ๐Ÿ”— **[Configuration Guide](../flow-cli/flow.json/configuration.md)** โ€“ Learn about configuring `flow.json` \ No newline at end of file diff --git a/docs/build/tools/react-sdk/index.mdx b/docs/build/tools/react-sdk/index.mdx new file mode 100644 index 0000000000..8484ab97df --- /dev/null +++ b/docs/build/tools/react-sdk/index.mdx @@ -0,0 +1,185 @@ +--- +title: 'Flow React SDK' +description: React hooks and components for interacting with the Flow blockchain. +sidebar_position: 1 +--- + +import ReactSDKOverview from '@site/src/components/ReactSDKOverview'; +import FlowProviderDemo from '@site/src/components/FlowProviderDemo'; +import { Connect } from '@onflow/react-sdk'; + +# Flow React SDK + +**The easiest way to build React apps on Flow.** A lightweight, TypeScript-first library that makes Flow blockchain interactions feel native to React development. + + + +## Quick Start + +### 1. Install + +```bash +npm install @onflow/react-sdk +``` + +### 2. Wrap Your App + +```tsx +import React from 'react'; +import App from './App'; +import { FlowProvider } from '@onflow/react-sdk'; +import flowJSON from '../flow.json'; + +function Root() { + return ( + + + + ); +} + +export default Root; +``` + +:::tip Next.js Users +Create a client component wrapper for the `FlowProvider`: + +```tsx title="components/FlowProviderWrapper.tsx" +'use client'; + +import { FlowProvider } from '@onflow/react-sdk'; +import flowJSON from '../flow.json'; + +export default function FlowProviderWrapper({ children }) { + return ( + + {children} + + ); +} +``` + +Then use it in your `layout.tsx`: + +```tsx title="app/layout.tsx" +import FlowProviderWrapper from '@/components/FlowProviderWrapper'; + +export default function RootLayout({ children }) { + return ( + + + {children} + + + ); +} +``` + +::: + +### 3. Start Building + +```tsx +import { useFlowCurrentUser, Connect, useFlowQuery } from '@onflow/react-sdk'; + +function MyApp() { + const { user } = useFlowCurrentUser(); + + const { data: greeting } = useFlowQuery({ + cadence: `access(all) fun main(): String { return "Hello, Flow!" }`, + args: (arg, t) => [], + }); + + return ( +
+ + {user?.loggedIn &&

Welcome, {user.addr}!

} +

{greeting}

+
+ ); +} +``` + +--- + +## ๐ŸŽฃ [Hooks](./hooks.md) + +**Cadence Hooks** for native Flow interactions: + +- Authentication & user management +- Account details & balances +- Block & transaction queries +- Real-time event subscriptions +- Script execution & mutations + +**Cross-VM Hooks** for bridging Cadence โ†” Flow EVM: + +- Atomic batch transactions +- Token & NFT bridging +- Cross-chain balance queries + +[โ†’ View all hooks](./hooks.md) + +--- + +## ๐ŸŽจ [Components](./components.md) + +Beautiful, accessible UI components: + +- `` โ€“ Wallet authentication with balance display +- `` โ€“ Smart transaction execution +- `` โ€“ Real-time transaction tracking +- `` โ€“ Network-aware block explorer links + +[โ†’ View all components](./components.md) + +--- + +## Why Choose React SDK? + +**Developer Experience First** + +- TypeScript-native with full type safety +- Familiar React patterns and conventions +- Comprehensive error handling and loading states + +**Production Ready** + +- Built on battle-tested libraries (TanStack Query, Tailwind CSS) +- Automatic retries, caching, and background updates +- Cross-VM support for hybrid Cadence/EVM applications + +**Customizable** + +- Theme system for brand consistency +- Composable hooks for custom UI +- Dark mode support out of the box + +--- + +## Need Help? + +- ๐Ÿ“– **[Hooks Documentation](./hooks.md)** โ€“ Detailed API reference for all hooks +- ๐ŸŽจ **[Components Documentation](./components.md)** โ€“ UI components and theming guide +- ๐Ÿ”— **[Configuration Guide](../flow-cli/flow.json/configuration.md)** โ€“ Learn about configuring `flow.json` diff --git a/docs/protocol/node-ops/access-nodes/access-node-configuration-options.md b/docs/protocol/node-ops/access-nodes/access-node-configuration-options.md index 4c574445b8..b32401402c 100644 --- a/docs/protocol/node-ops/access-nodes/access-node-configuration-options.md +++ b/docs/protocol/node-ops/access-nodes/access-node-configuration-options.md @@ -135,21 +135,22 @@ Store the **`root-protocol-state-snapshot.json`** into the **`/bootstrap/public- Now you have the execution sync setup and the root checkpoint in place, itโ€™s time to configure the node to index all of the data so it can be used for script execution. -There are 2 cli flags that you will need to add: +There are 3 cli flags that you will need to add: - `--execution-data-indexing-enabled=true` This will enable the indexer. +- `--store-tx-result-error-messages=true` This will fetch and index transaction result error messages from execution nodes. - `--execution-state-dir` This defines the path where the registers db will be stored. A good default is on the same drive as the protocol db. e.g. `/data/execution-state` # Start your node -Now that all of the settings to enable indexing are in place, you can start your node. +Now that all the settings to enable indexing are in place, you can start your node. At a minimum, you will need the following flags: ``` --execution-data-indexing-enabled=true +--store-tx-result-error-messages=true --execution-state-dir=/data/execution-state ---execution-data-sync-enabled=true --execution-data-dir=/data/execution-data ``` @@ -249,8 +250,9 @@ As a best practice, specify a path with `--execution-data-dir`. A sensible defau Below is a list of the available CLI flags to control the behavior of Execution Data Indexer. | Flag | Type | Description | -| ------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------- | -| execution-data-indexing-enabled | bool | Whether to enable the execution data indexing. Default is false | +|---------------------------------|--------|-------------------------------------------------------------------------------------------------------------| +| execution-data-indexing-enabled | bool | Whether to enable the execution data indexing. Default is false. | +| store-tx-result-error-messages | bool | Whether to enable storing transaction error messages into the db. Default is false. | | execution-state-dir | string | Directory to use for execution-state database. Default is in the userโ€™s home directory. | | execution-state-checkpoint | string | Location of execution-state checkpoint (root.checkpoint.\*) files. | | event-query-mode | string | Mode to use when querying events. one of [local-only, execution-nodes-only(default), failover] | diff --git a/docusaurus.config.js b/docusaurus.config.js index 3196074506..22412686dc 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -316,164 +316,128 @@ const config = { style: 'dark', links: [ { - title: 'Documentation', + title: 'Flow', items: [ { - label: 'Getting Started', - to: '/blockchain-development-tutorials/cadence/getting-started/smart-contract-interaction', + label: 'Build with AI', + to: '/blockchain-development-tutorials/use-AI-to-build-on-flow', }, { - label: "Tools & SDKs", - to: '/build/tools', - }, - { - to: 'https://cadence-lang.org/docs/', - label: 'Cadence', - }, - { - to: '/blockchain-development-tutorials/cadence/mobile', - label: 'Mobile', - }, - { - to: '/build/tools/clients/fcl-js/', - label: 'FCL', - }, - { - to: '/build/cadence/smart-contracts/testing', - label: 'Testing', - }, - { - to: '/build/tools/flow-cli/', - label: 'CLI', + label: 'Why Flow', + to: '/blockchain-development-tutorials/flow-101', }, { - to: '/build/tools/emulator/', - label: 'Emulator', + label: 'Tools', + to: '/build/tools', }, { - href: 'https://github.com/onflow/fcl-dev-wallet', - label: 'Dev Wallet', + label: 'Faucet', + to: '/ecosystem/faucets', }, { - to: '/build/tools/vscode-extension/', - label: 'VS Code Extension', + label: 'Builder Toolkit', + to: '/ecosystem/developer-support-hub', }, ], }, { - title: 'Community', + title: 'Cadence', items: [ { - to: '/ecosystem', - label: 'Ecosystem', - }, - { - href: 'https://port.flow.com/', - label: 'Flow Port', - }, - { - href: 'https://github.com/onflow/developer-grants', - label: 'Developer Grants', + label: 'Quickstart', + to: '/blockchain-development-tutorials/cadence/getting-started', }, { - href: 'https://flow.com/flow-responsible-disclosure', - label: 'Responsible Disclosure', + label: 'Build with Forte', + to: '/blockchain-development-tutorials/forte', }, { - href: 'https://www.flowverse.co/', - label: 'Flowverse', + label: 'Cadence Advantages', + to: '/blockchain-development-tutorials/cadence/cadence-advantages', }, { - href: 'https://academy.ecdao.org/', - label: 'Emerald Academy', + label: 'React SDK', + to: '/build/tools/react-sdk', }, { - href: 'https://floats.city/', - label: 'FLOATs (Attendance NFTs)', - }, + label: 'Language Reference', + href: 'https://cadence-lang.org/', + } ], }, { - title: 'Start Building', + title: 'Solidity (EVM)', items: [ { - href: 'https://play.flow.com/', - label: 'Flow Playground', - }, - { - to: 'https://cadence-lang.org/docs/tutorial/first-steps', - label: 'Cadence Tutorials', + label: 'Quickstart', + to: '/build/evm/quickstart', }, { - href: 'https://cookbook.flow.com', - label: 'Cadence Cookbook', + label: 'Native VRF', + to: '/blockchain-development-tutorials/native-vrf', }, { - to: '/build/cadence/core-contracts/', - label: 'Core Contracts & Standards', + label: 'Batched Transactions', + to: '/blockchain-development-tutorials/cross-vm-apps', }, { - href: '/build/evm/quickstart', - label: 'EVM', - }, + label: 'Network Information', + href: '/build/evm/networks', + } ], }, { - title: 'Network', + title: 'Community & Support', items: [ { - href: 'https://status.flow.com/', - label: 'Network Status', + label: 'Dev Office Hours', + href: 'https://calendar.google.com/calendar/u/0/embed?src=c_47978f5cd9da636cadc6b8473102b5092c1a865dd010558393ecb7f9fd0c9ad0@group.calendar.google.com', }, { - href: 'https://flowscan.io/', - label: 'Flowscan Mainnet', + label: 'Hackathons and Events', + to: '/ecosystem/hackathons-and-events', }, { - href: 'https://testnet.flowscan.io/', - label: 'Flowscan Testnet', - }, - { - to: '/protocol/node-ops/node-operation/past-upgrades', - label: 'Past Sporks', + href: 'https://discord.gg/flow', + label: 'Discord', }, { - to: '/protocol/node-ops', - label: 'Node Operation', + href: 'https://github.com/onflow', + label: 'GitHub', }, { - to: '/protocol/node-ops/node-operation/network-upgrade', - label: 'Spork Information', + href: 'https://flow.com/careers', + label: 'Careers', }, ], }, { - title: 'More', + title: 'Network & Resources', items: [ { - href: 'https://github.com/onflow', - label: 'GitHub', + href: 'https://status.flow.com/', + label: 'Network Status', }, { - href: 'https://discord.gg/flow', - label: 'Discord', + href: 'https://flowscan.io/', + label: 'Block Explorer', }, { - href: 'https://forum.flow.com/', - label: 'Forum', + href: 'https://port.flow.com/', + label: 'Flow Port', }, { href: 'https://flow.com/', - label: 'Flow', + label: 'Flow Website', }, { href: 'https://flow.com/blog', - label: 'Blog', + label: 'Flow Blog', }, ], }, ], - copyright: `Copyright ยฉ ${new Date().getFullYear()} Flow, Inc. Built with Docusaurus.`, + copyright: `Copyright ยฉ ${new Date().getFullYear()} Flow Foundation. All Rights Reserved.`, }, prism: { theme: lightCodeTheme, diff --git a/src/components/PlaygroundButton.tsx b/src/components/PlaygroundButton.tsx new file mode 100644 index 0000000000..4f95b31927 --- /dev/null +++ b/src/components/PlaygroundButton.tsx @@ -0,0 +1,31 @@ +import React from 'react'; + +interface PlaygroundButtonProps { + href: string; + text?: string; +} + +export default function PlaygroundButton({ + href, + text = 'Open in Playground', +}: PlaygroundButtonProps): React.ReactElement { + return ( + + {text} โ†’ + + ); +} diff --git a/src/components/ReactSDKOverview.tsx b/src/components/ReactSDKOverview.tsx new file mode 100644 index 0000000000..0cbb01b482 --- /dev/null +++ b/src/components/ReactSDKOverview.tsx @@ -0,0 +1,805 @@ +import React, { useState } from 'react'; +import useIsBrowser from '@docusaurus/useIsBrowser'; +import { useColorMode } from '@docusaurus/theme-common'; +import { + FlowProvider, + Connect, + TransactionButton, + TransactionLink, + TransactionDialog, + useFlowBlock, + useFlowAccount, + useFlowCurrentUser, + useFlowChainId, + useFlowRevertibleRandom, +} from '@onflow/react-sdk'; +import { flowClient } from '@site/src/config/fcl'; + +function MasonryGrid({ children }: { children: React.ReactNode }) { + return ( +
+ {children} +
+ ); +} + +// Enhanced Card Wrapper +function EnhancedCard({ + title, + description, + darkMode, + children, + accent = '#00ef8b', +}: { + title: string; + description: string; + darkMode: boolean; + children: React.ReactNode; + accent?: string; +}) { + return ( +
+
+

+ {title} +

+

+ {description} +

+
+ {children} +
+ ); +} + +// Component Cards +function ConnectCardMini({ darkMode }: { darkMode: boolean }) { + return ( + +
+ +
+
+ ); +} + +function TransactionButtonCardMini({ darkMode }: { darkMode: boolean }) { + const GREETING_TRANSACTION = ` + transaction(greeting: String) { + prepare(signer: &Account) { + log(greeting) + } + } + `; + + return ( + +
+ [arg('Hello!', t.String)], + limit: 999, + }} + /> +
+
+ ); +} + +function TransactionLinkCardMini({ darkMode }: { darkMode: boolean }) { + const [txId, setTxId] = useState(undefined); + + const GREETING_TRANSACTION = ` + transaction(greeting: String) { + prepare(signer: &Account) { + log(greeting) + } + } + `; + + return ( + +
+
+ [arg('Hello!', t.String)], + limit: 999, + }} + mutation={{ + onSuccess: (data) => setTxId(data), + }} + /> +
+ {txId && ( +
+ +
+ )} +
+
+ ); +} + +function TransactionDialogCardMini({ darkMode }: { darkMode: boolean }) { + const [open, setOpen] = useState(false); + const [txId, setTxId] = useState(undefined); + + const GREETING_TRANSACTION = ` + transaction(greeting: String) { + prepare(signer: &Account) { + log(greeting) + } + } + `; + + return ( + +
+ [arg('Hello!', t.String)], + limit: 999, + }} + mutation={{ + onSuccess: (data) => { + setTxId(data); + setOpen(true); + }, + }} + /> +
+ +
+ ); +} + +// Hook Cards +function UseFlowCurrentUserCardMini({ darkMode }: { darkMode: boolean }) { + const { user } = useFlowCurrentUser(); + + return ( + +
+
+ + Status + + + {user?.loggedIn ? 'โ— Connected' : 'โ—‹ Not Connected'} + +
+ {user?.loggedIn && ( +
+ {user.addr} +
+ )} +
+
+ ); +} + +function UseFlowChainIdCardMini({ darkMode }: { darkMode: boolean }) { + const { + data: chainId, + refetch, + isLoading, + } = useFlowChainId({ + query: { enabled: false }, + }); + + return ( + +
+ + {chainId && ( +
+
+ Network +
+
+ {chainId} +
+
+ )} +
+
+ ); +} + +function UseFlowBlockCardMini({ darkMode }: { darkMode: boolean }) { + const { + data: block, + isLoading, + refetch, + } = useFlowBlock({ + query: { enabled: true }, + }); + + return ( + +
+ + {block && ( +
+
+ Height +
+
+ {block.height} +
+
+ )} +
+
+ ); +} + +function UseFlowAccountCardMini({ darkMode }: { darkMode: boolean }) { + const [address, setAddress] = useState('0x7e60df042a9c0868'); + const { + data: account, + isLoading, + refetch, + } = useFlowAccount({ + address, + query: { enabled: false }, + }); + + return ( + +
+ setAddress(e.target.value)} + placeholder="Enter address..." + style={{ + width: '100%', + padding: '0.75rem', + background: darkMode ? 'rgba(17, 24, 39, 0.6)' : '#ffffff', + color: darkMode ? '#fff' : '#000', + border: darkMode + ? '1px solid rgba(255, 255, 255, 0.1)' + : '1px solid rgba(0, 0, 0, 0.1)', + borderRadius: '8px', + fontSize: '0.75rem', + fontFamily: 'monospace', + outline: 'none', + }} + /> + + {account && ( +
+
+ Balance +
+
+ {(Number(account.balance) / 1e8).toFixed(4)} FLOW +
+
+ )} +
+
+ ); +} + +function UseFlowRevertibleRandomCardMini({ darkMode }: { darkMode: boolean }) { + const { + data: randomResults, + isLoading, + refetch, + } = useFlowRevertibleRandom({ + max: '1000000000', + count: 1, + }); + + return ( + +
+ + {randomResults && randomResults.length > 0 && ( +
+
+ Random Value +
+
+ {randomResults[0].value} +
+
+ )} +
+
+ ); +} + +// Inner component with all the cards +function ReactSDKOverviewContent({ darkMode }: { darkMode: boolean }) { + return ( +
+
+ + + + + + + + + + + + + +

+ Try components and hooks live +

+

+ Explore all React SDK features in our interactive playground with live + examples and documentation +

+ + Open Playground โ†’ + +
+ + + + + + + + + + + + +
+ ); +} + +// Main Overview Component wrapped with FlowProvider +export default function ReactSDKOverview(): React.ReactElement | null { + const isBrowser = useIsBrowser(); + const { colorMode } = useColorMode(); + const darkMode = colorMode === 'dark'; + + if (!isBrowser) return null; + + return ( + + + + ); +} diff --git a/src/constants/ga-events.ts b/src/constants/ga-events.ts index 385823e464..7e3addef04 100644 --- a/src/constants/ga-events.ts +++ b/src/constants/ga-events.ts @@ -6,6 +6,7 @@ export const GA_EVENTS = { SEARCH_CLICK: 'search_click', FEEDBACK_CLICK: 'feedback_click', AUTH_LOGIN: 'login', + FOOTER_CLICK: 'footer_click', } as const; // Event categories for consistent tracking - Using existing categories @@ -15,6 +16,7 @@ export const GA_CATEGORIES = { SEARCH: 'search', FEEDBACK: 'feedback', AUTH: 'auth', + FOOTER: 'footer', } as const; // Event actions for consistent tracking - Using existing actions diff --git a/src/theme/Footer/LinkItem/index.tsx b/src/theme/Footer/LinkItem/index.tsx new file mode 100644 index 0000000000..e39b93a38c --- /dev/null +++ b/src/theme/Footer/LinkItem/index.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import LinkItem from '@theme-original/Footer/LinkItem'; +import type {WrapperProps} from '@docusaurus/types'; +import { event } from '@site/src/utils/gtags.client'; +import { GA_EVENTS, GA_CATEGORIES } from '@site/src/constants/ga-events'; + +type Props = WrapperProps; + +export default function LinkItemWrapper(props: Props): JSX.Element { + const handleClick = (e: React.MouseEvent) => { + // Extract meaningful label from props + const label = props.label || props.href || 'unknown-footer-item'; + + // Check if we're on the homepage + const isHomepage = typeof window !== 'undefined' && window.location.pathname === '/'; + + // Track the footer link click with appropriate event based on page + event({ + action: isHomepage ? GA_EVENTS.ACTION_CARD_CLICK : GA_EVENTS.FOOTER_CLICK, + category: GA_CATEGORIES.FOOTER, + label: label, + location: true, + }); + + // Call original onClick if it exists + if (props.onClick) { + props.onClick(e); + } + }; + + return ( + <> + + + ); +} diff --git a/vercel.json b/vercel.json index 3e8e94a285..795f19e40d 100644 --- a/vercel.json +++ b/vercel.json @@ -2044,16 +2044,29 @@ "permanent": true }, { - "source": "/ecosystem/Hackathons and Events/may-the-flow-be-with-you", + "source": "/ecosystem/hackathons-and-events/may-the-flow-be-with-you", "destination": "/ecosystem/hackathons-and-events", "permanent": true }, { - "source": "/ecosystem/Hackathons and Events", + "source": "/ecosystem/hackathons-and-events", "destination": "/ecosystem/hackathons-and-events", + "permanent": true + }, + { "source": "/protocol/staking/staking-guide", "destination": "/protocol/staking", "permanent": true + }, + { + "source": "/build/tools/flow-cli/deployment/emulator-snapshot", + "destination": "/build/tools/emulator", + "permanent": true + }, + { + "source": "/build/tools/flow-cli/deployment/start-emulator", + "destination": "/build/tools/emulator", + "permanent": true } ] }