diff --git a/.env.example b/.env.example index 546b735a..34f32956 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,2 @@ -TYPESENSE_COLLECTION_NAME= -TYPESENSE_SERVER_HOST= -TYPESENSE_SEARCH_ONLY_APIKEY= \ No newline at end of file +FEEDBACK_CONTENT_SET_ID= +HOTJAR_ID=abc \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..15451b66 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,91 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# GitHub recommends pinning actions to a commit SHA. +# To get a newer version, you will need to update the SHA. +# You can also reference a tag or branch, but the action may change without warning. + +name: Publish Docker image + +on: + push: + branches: [main] + +jobs: + build: + name: Build and Push Docker image to Docker Hub + runs-on: ubuntu-latest + environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'development' }} + permissions: + contents: read + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'npm' + + - run: npm install + - name: create env file + run: | + touch .env + echo TYPESENSE_COLLECTION_NAME=${{ vars.TYPESENSE_COLLECTION_NAME }} >> .env + echo TYPESENSE_SERVER_HOST=${{ vars.TYPESENSE_SERVER_HOST }} >> .env + echo TYPESENSE_SEARCH_ONLY_APIKEY=${{ vars.TYPESENSE_SEARCH_ONLY_APIKEY }} >> .env + echo HOTJAR_ID=${{ vars.HOTJAR_ID }} >> .env + + - run: npm run build + + - name: Log in to Docker Hub + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }} + tags: | + type=sha + # set latest tag for default branch + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: Set short git commit SHA + id: vars + run: | + calculatedSha=$(git rev-parse --short ${{ github.sha }}) + echo "short_sha=$calculatedSha" >> "$GITHUB_OUTPUT" + + - name: Deploy + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.WORKFLOW_DISPATCH }} + script: | + await github.rest.actions.createWorkflowDispatch({ + owner: 'poc-aaa', + repo: 'devops', + workflow_id: 'deploy.yaml', + ref: 'main', + inputs: { + env: '${{ github.ref == 'refs/heads/main' && 'production' || 'development' }}', + appName: 'docs', + appProject: 'aelf-docs', + commit_sha: 'sha-${{ steps.vars.outputs.short_sha }}', + } + }) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7cb6b686..3b91792e 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -32,7 +32,5 @@ jobs: - name: create env file run: | touch .env - echo TYPESENSE_COLLECTION_NAME="test-collection" >> .env - echo TYPESENSE_SERVER_HOST="test-host" >> .env - echo TYPESENSE_SEARCH_ONLY_APIKEY="test-api-key" >> .env + echo FEEDBACK_CONTENT_SET_ID=${{ vars.FEEDBACK_CONTENT_SET_ID }} >> .env - run: npm run build \ No newline at end of file diff --git a/.github/workflows/s3.yml b/.github/workflows/s3.yml index 0caaa199..6487146b 100644 --- a/.github/workflows/s3.yml +++ b/.github/workflows/s3.yml @@ -1,12 +1,9 @@ name: Deploy to S3 - on: push: branches: [ "main", "develop" ] workflow_dispatch: - jobs: - build: environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'development' }} permissions: @@ -22,17 +19,14 @@ jobs: - name: create env file run: | touch .env - echo TYPESENSE_COLLECTION_NAME=${{ vars.TYPESENSE_COLLECTION_NAME }} >> .env - echo TYPESENSE_SERVER_HOST=${{ vars.TYPESENSE_SERVER_HOST }} >> .env - echo TYPESENSE_SEARCH_ONLY_APIKEY=${{ vars.TYPESENSE_SEARCH_ONLY_APIKEY }} >> .env + echo FEEDBACK_CONTENT_SET_ID=${{ vars.FEEDBACK_CONTENT_SET_ID }} >> .env + echo HOTJAR_ID=${{ vars.HOTJAR_ID }} >> .env - run: npm run build - - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v2 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - - name: Sync to S3 - run: aws s3 sync ./build s3://${{ secrets.AWS_S3_BUCKET }} + run: aws s3 sync ./build s3://${{ secrets.AWS_S3_BUCKET }} \ No newline at end of file diff --git a/docs/_get-testnet-token.md b/docs/_get-testnet-token.md index b62464dc..a1acceb2 100644 --- a/docs/_get-testnet-token.md +++ b/docs/_get-testnet-token.md @@ -2,36 +2,6 @@ To deploy smart contracts or execute on-chain transactions on aelf, you'll requi **Get ELF Tokens** -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - - -Run the following command to get testnet ELF tokens from faucet. Remember to either export your wallet address or replace $WALLET_ADDRESS with your wallet address. - -```bash title="Terminal" -curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` -To check your wallet's current ELF balance: -```bash title="Terminal" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` -You will be prompted for the following: - -```sh -Enter the required param : **ELF** -Enter the required param : **$WALLET_ADDRESS** -``` - -You should see the Result displaying your wallet's ELF balance. - - - - Go to this url [https://faucet-ui.aelf.dev](https://faucet-ui.aelf.dev). Enter your address and click `Get Tokens`. ![result](/img/get-token-ui.png) - - - \ No newline at end of file diff --git a/docs/about-aelf/elf-token/index.md b/docs/about-aelf/elf-token/index.md index 8417cefc..985958f4 100644 --- a/docs/about-aelf/elf-token/index.md +++ b/docs/about-aelf/elf-token/index.md @@ -14,7 +14,7 @@ description: What is ELF? ELF is the native token of the aelf blockchain, serving multiple critical functions within the ecosystem. ELF is used for paying transaction fees on the aelf blockchain. -ELF is used by developers to pay block index fees, as cross-chain transfers and verifications require the MainChain to index the SideChain's block information. +ELF is used by developers to pay block index fees, as cross-chain transfers and verifications require the MainChain to index the aelf dAppChain's block information. ELF is used by individuals or teams who are interested in becoming block producer nodes. To be one of aelf's block producers, they are required to purchase and deposit ELF tokens to participate in the block producer node election. Upon a successful election, the deposited ELF tokens are locked and will be unlocked and returned once the node steps down, provided no violations have occurred. ELF is used by voters to participate in aelf node elections, with each ELF token equating to one vote. @@ -38,9 +38,9 @@ Ethereum: `0xbf2179859fc6d5bee9bf9158632dc51678a4100e` BSC: `0xa3f020a5c92e15be13caf0ee5c95cf79585eecc9` -MainChain AELF: `ELF_JRmBduh4nXWi1aXgdUsj5gJrzeZb2LxmrAbf7W99faZSvoAaE_AELF` +aelf MainChain: `ELF_JRmBduh4nXWi1aXgdUsj5gJrzeZb2LxmrAbf7W99faZSvoAaE_AELF` -SideChain tDVV: `ELF_7RzVGiuVWkvL4VfVHdZfQF2Tri3sgLe9U991bohHFfSRZXuGX_tDVV` +aelf dAppChain: `ELF_7RzVGiuVWkvL4VfVHdZfQF2Tri3sgLe9U991bohHFfSRZXuGX_tDVV` ::: @@ -105,7 +105,7 @@ As of the latest information, here are the exchanges that support the aelf mainn Exchanges supporting aelf Mainnet include Binance, Bithumb, Upbit, HTX, OKX, Gate.io, MEXC, and these exchanges support deposits and withdrawals of Mainnet ELF tokens. -Please note that the exchanges supporting aelf Mainnet only support token deposits and withdrawals using MainChain AELF. You should never deposit or withdraw using SideChain tDVV as this may result in your tokens being lost forever. +Please note that the exchanges supporting aelf Mainnet only support token deposits and withdrawals using aelf MainChain. You should never deposit or withdraw using aelf dAppChain as this may result in your tokens being lost forever. We recommend verifying the latest information on the exchange platforms or aelf official channels. diff --git a/docs/about-aelf/introduction/index.md b/docs/about-aelf/introduction/index.md index 66e0dc18..8c1399d1 100644 --- a/docs/about-aelf/introduction/index.md +++ b/docs/about-aelf/introduction/index.md @@ -12,7 +12,7 @@ description: What is aelf? :::faq[What is aelf?] -aelf, an AI-enhanced Layer 1 blockchain network, leverages the robust C# programming language for efficiency and scalability across its sophisticated multi-layered architecture. Founded in 2017 with its global hub in Singapore, aelf is a pioneer in the industry, leading Asia in evolving blockchain with state-of-the-art AI integration and modular Layer 2 ZK Rollup technology, ensuring an efficient, low-cost, and highly secure platform that is both developer and end-user friendly. Aligned with its progressive vision, aelf is committed to fostering innovation within its ecosystem and advancing Web3 and AI technology adoption. For more information about aelf, please refer to our [Whitepaper V2.0](https://docs.aelf.com/resources/whitepaper-2/). +aelf, an AI-enhanced Layer 1 blockchain network, leverages the robust C# programming language for efficiency and scalability across its sophisticated multi-layered architecture. Founded in 2017 with its global hub in Singapore, aelf is a pioneer in the industry, leading Asia in evolving blockchain with state-of-the-art AI integration to ensure an efficient, low-cost, and highly secure platform that is both developer and end-user friendly. Aligned with its progressive vision, aelf is committed to fostering innovation within its ecosystem and advancing Web3 and AI technology adoption. For more information about aelf, please refer to our [Whitepaper V2.0](https://docs.aelf.com/resources/whitepaper-2/). ::: @@ -52,7 +52,7 @@ aelf is primarily a multi-chain parallel computing blockchain network which was :::faq[What makes aelf different from other blockchains? Why is aelf unique?] -aelf's unique strength lies in its underlying architecture, which utilises a multi-layered structure comprising a MainChain and multiple SideChains. This differs from a traditional Single Chain system in that aelf is a "Branched Ecosystem", where the MainChain works as the backbone of the system and connects to multiple SideChains. Compared with the traditional "one Chain to any type of Contract", aelf's "One Chain to one type of Contract" design allows aelf to distribute tasks efficiently and process transactions in parallel, significantly enhancing scalability and reducing congestion. At the same time, the SideChains are easier to manage and can be tailored for specific applications, enabling aelf to support a wide range of use cases without compromising performance. +aelf's unique strength lies in its underlying architecture, which utilises a multi-layered structure comprising a MainChain and multiple dAppChains. This differs from a traditional Single Chain system in that aelf is a "Branched Ecosystem", where the MainChain works as the backbone of the system and connects to multiple dAppChains. Compared with the traditional "one Chain to any type of Contract", aelf's "One Chain to one type of Contract" design allows aelf to distribute tasks efficiently and process transactions in parallel, significantly enhancing scalability and reducing congestion. At the same time, the aelf dAppChains are easier to manage and can be tailored for specific applications, enabling aelf to support a wide range of use cases without compromising performance. The [C# programming language](https://learn.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/) forms the foundation of the entire aelf blockchain, which underpins aelf's ability to handle high transaction volumes and complex operations with ease. C# also offers a powerful foundation for AI integration in blockchain development, primarily due to its alignment with the [.NET ecosystem](https://dotnetfoundation.org/), which provides a wide range of libraries and tools that facilitate the development of sophisticated AI models, including the integration of machine learning algorithms, natural language processing (NLP), and data analytics. The integration of AI into the aelf ecosystem marks a significant advancement in the blockchain’s operational capabilities which not only optimises performance and security, but also plays a crucial role in transitioning mass Web2 users to Web3 by significantly improving the overall user and developer experience. @@ -126,7 +126,7 @@ Nevertheless, do continue to stay updated via our [website](https://aelf.com/), The primary cryptocurrency supported on the aelf blockchain is the ELF token. This token has several functions within the aelf ecosystem, including governance, resource allocation, and staking. -As aelf is a multi-chain network with various sidechains, users can unlock utility with other tokens specific to dApps built on the aelf ecosystem, such as [AwakenSwap](https://awaken.finance/), [Portkey](https://portkey.finance/), and [Project Schrodinger](https://schrodingernft.ai/). Here are some of the supported tokens and stablecoins: +As aelf is a multi-chain network with various dAppChains, users can unlock utility with other tokens specific to dApps built on the aelf ecosystem, such as [AwakenSwap](https://awaken.finance/), [Portkey](https://portkey.finance/), and [Project Schrodinger](https://schrodingernft.ai/). Here are some of the supported tokens and stablecoins: - ELF - USDT - BNB diff --git a/docs/about-aelf/partnerships-and-ecosystem/index.md b/docs/about-aelf/partnerships-and-ecosystem/index.md index 3b4b8010..d6e57a37 100644 --- a/docs/about-aelf/partnerships-and-ecosystem/index.md +++ b/docs/about-aelf/partnerships-and-ecosystem/index.md @@ -141,14 +141,14 @@ aelf provides a range of educational resources and developer programmes for thos ::: -### 15. Do aelf ecosystem DApps use tokens on the MainChain or SideChain? When staking and earning rewards on aelf ecosystem DApps, are these staked tokens and reward tokens on the MainChain or SideChain? If I do not have any tokens on the SideChain, do I need to transfer them from the MainChain first? +### 15. Do aelf ecosystem DApps use tokens on the MainChain or dAppChain? When staking and earning rewards on aelf ecosystem DApps, are these staked tokens and reward tokens on the MainChain or dAppChain? If I do not have any tokens on the aelf dAppChain, do I need to transfer them from the MainChain first? -:::faq[Do aelf ecosystem DApps use tokens on the MainChain or SideChain? When staking and earning rewards on aelf ecosystem DApps, are these staked tokens and reward tokens on the MainChain or SideChain? If I do not have any tokens on the SideChain, do I need to transfer them from the MainChain first?] +:::faq[Do aelf ecosystem DApps use tokens on the MainChain or dAppChain? When staking and earning rewards on aelf ecosystem DApps, are these staked tokens and reward tokens on the MainChain or dAppChain? If I do not have any tokens on the dAppChain, do I need to transfer them from the MainChain first?] -Some aelf ecosystem DApps, like Portkey Wallet, ETransfer, and eBridge, can use tokens on either the MainChain or SideChain, while other DApps, like Awaken and Forest, only support the SideChain, depending on the specific application and its design. Generally, more complex operations, such as DApp interactions, are often handled on SideChains to enhance scalability and reduce congestion on the MainChain. +Some aelf ecosystem DApps, like Portkey Wallet, ETransfer, and eBridge, can use tokens on either the MainChain or dAppChain, while other DApps, like Awaken and Forest, only support the aelf dAppChain, depending on the specific application and its design. Generally, more complex operations, such as DApp interactions, are often handled on aelf dAppChains to enhance scalability and reduce congestion on the MainChain. -Typically, when you stake tokens or earn rewards through staking and voting on aelf governance, these activities are carried out on the MainChain. However, if you stake tokens or earn rewards through ecosystem DApps, it depends on the specific rules of those DApps; most of them are carried out on the SideChain. +Typically, when you stake tokens or earn rewards through staking and voting on aelf governance, these activities are carried out on the MainChain. However, if you stake tokens or earn rewards through ecosystem DApps, it depends on the specific rules of those DApps; most of them are carried out on the aelf dAppChain. -If the DApp you are interacting with requires tokens on the SideChain, and you currently only have tokens on the MainChain, you will need to transfer those tokens from the MainChain to the SideChain first. This transfer can usually be done within your Portkey Wallet. +If the DApp you are interacting with requires tokens on the aelf dAppChain, and you currently only have tokens on the MainChain, you will need to transfer those tokens from the MainChain to the aelf dAppChain first. This transfer can usually be done within your Portkey Wallet. ::: \ No newline at end of file diff --git a/docs/about-aelf/technical-and-security/index.md b/docs/about-aelf/technical-and-security/index.md index 69b20a44..93a00c5b 100644 --- a/docs/about-aelf/technical-and-security/index.md +++ b/docs/about-aelf/technical-and-security/index.md @@ -90,12 +90,12 @@ ELF token holders would vote to elect a set of 'Core Data Centers', which are al :::faq[How are transactions processed on the aelf network?] -Transactions on the aelf blockchain are processed through a combination of its AEDPoS (aelf Delegated Proof of Stake) consensus mechanism and sidechain architecture that enables parallel processing. Here's what happens when a user initiates a transaction: -- The transaction is broadcast to the relevant network and sidechain -- The Core Data Center (also known as the miner) of that particular sidechain will validate the transaction and package it into blocks +Transactions on the aelf blockchain are processed through a combination of its AEDPoS (aelf Delegated Proof of Stake) consensus mechanism and dAppChain architecture that enables parallel processing. Here's what happens when a user initiates a transaction: +- The transaction is broadcast to the relevant network and dAppChain +- The Core Data Center (also known as the miner) of that particular dAppChain will validate the transaction and package it into blocks - Through the AEDPoS, the elected Core Data Centers take turns to produce blocks. The produced blocks are validated by other Core Data Centers to ensure accuracy and integrity. -- Once a block is validated and added to the sidechain's blockchain, the transactions are final and irreversible -- In the event a transaction requires interaction between different sidechains, aelf's interoperability ensures the transfer and synchronisation of data across chains. +- Once a block is validated and added to the dAppChain's blockchain, the transactions are final and irreversible +- In the event a transaction requires interaction between different dAppChains, aelf's interoperability ensures the transfer and synchronisation of data across chains. ::: @@ -109,7 +109,7 @@ Some common issues that users may face include network congestion, technical dif Users might experience delays during peak times. -**Solution**: aelf's multi-sidechain architecture distributes workload efficiently to minimise congestion. +**Solution**: aelf's multi-dAppChain architecture distributes workload efficiently to minimise congestion. #### Technical Difficulties Issues with wallet integration or transaction processing. @@ -126,7 +126,7 @@ Navigating the platform might be difficult for new users. **Solution**: User-friendly interfaces and tutorials are provided to ease the onboarding process. -::: + -### 10. How does aelf compare to other blockchain platforms in terms of transaction speed and scalability? +### 9. How does aelf compare to other blockchain platforms in terms of transaction speed and scalability? :::faq[How does aelf compare to other blockchain platforms in terms of transaction speed and scalability?] -aelf stands out in the blockchain landscape with its exceptional transaction speed and scalability. Its multi-sidechain architecture enables parallel processing of transactions, significantly enhancing both speed and scalability compared to traditional single-chain systems. Furthermore, aelf leverages advanced Layer 2 solutions such as ZK Rollups to further improve performance and efficiency. In terms of benchmarking, aelf consistently performs favourably against other leading blockchain platforms in transaction throughput and network efficiency. Additionally, aelf integrates artificial intelligence (AI) to optimise various aspects of its operations, including smart contract execution and network management, which further boosts its performance and scalability. This combination of multi-sidechain architecture, advanced Layer 2 solutions, and AI integration positions aelf as a superior choice in the blockchain arena. +aelf stands out in the blockchain landscape with its exceptional transaction speed and scalability. Its multi-dAppChain architecture enables parallel processing of transactions, significantly enhancing both speed and scalability compared to traditional single-chain systems. In terms of benchmarking, aelf consistently performs favourably against other leading blockchain platforms in transaction throughput and network efficiency. Additionally, aelf integrates artificial intelligence (AI) to optimise various aspects of its operations, including smart contract execution and network management, which further boosts its performance and scalability. This combination of multi-dAppChain architecture, advanced Layer 2 solutions, and AI integration positions aelf as a superior choice in the blockchain arena. ::: -### 11. What is the difference between aelf's MainChain and SideChains? +### 10. What is the difference between aelf's MainChain and dAppChains? -:::faq[What is the difference between aelf's MainChain and SideChains?] +:::faq[What is the difference between aelf's MainChain and dAppChains?] -aelf's MainChain and SideChains serve distinct but complementary roles within its blockchain architecture. The MainChain acts as the backbone of the network, responsible for overall governance, security, and coordination. It manages cross-chain interactions and ensures the integrity of the entire ecosystem. SideChains, on the other hand, are specialised chains that handle specific types of transactions or applications. They operate independently but are connected to the MainChain, allowing for parallel processing of transactions. This design significantly enhances scalability by distributing the workload across multiple SideChains, reducing congestion and improving performance. Each SideChain can be customised for different use cases, providing flexibility and efficiency in handling diverse applications. +aelf's MainChain and aelf dAppChains serve distinct but complementary roles within its blockchain architecture. The MainChain acts as the backbone of the network, responsible for overall governance, security, and coordination. It manages cross-chain interactions and ensures the integrity of the entire ecosystem. aelf dAppChains, on the other hand, are specialised chains that handle specific types of transactions or applications. They operate independently but are connected to the MainChain, allowing for parallel processing of transactions. This design significantly enhances scalability by distributing the workload across multiple aelf dAppChains, reducing congestion and improving performance. Each aelf dAppChain can be customised for different use cases, providing flexibility and efficiency in handling diverse applications. ::: -### 12. What is the transaction gas fee on the aelf blockchain? Are there any addresses that are exempt from fees? +### 11. What is the transaction gas fee on the aelf blockchain? Are there any addresses that are exempt from fees? :::faq[What is the transaction gas fee on the aelf blockchain? Are there any addresses that are exempt from fees?] @@ -183,7 +183,7 @@ If address A has a balance of 10 ELF at 1:00 UTC today but transfers out 7 ELF a ::: -### 13. At what block confirmation number on the aelf blockchain can we consider it unlikely that a chain becomes reversible? +### 12. At what block confirmation number on the aelf blockchain can we consider it unlikely that a chain becomes reversible? :::faq[At what block confirmation number on the aelf blockchain can we consider it unlikely that a chain becomes reversible?] @@ -193,27 +193,27 @@ The most accurate method is to follow the calculation based on the LIB (Last Irr ::: -### 14. What is the RPC service address for the SideChain tDVV? +### 13. What is the RPC service address for the aelf dAppChain? -:::faq[What is the RPC service address for the SideChain tDVV?] +:::faq[What is the RPC service address for the aelf dAppChain?] You can access it via the following link: https://tdvv-public-node.aelf.io/ ::: -### 15. Is a cross-chain transaction on the aelf blockchain considered a single transaction or two? Are there any examples? +### 14. Is a cross-chain transaction on the aelf blockchain considered a single transaction or two? Are there any examples? :::faq[Is a cross-chain transaction on the aelf blockchain considered a single transaction or two? Are there any examples?] -Cross-chain transactions between the MainChain and SideChain are considered two separate transactions. For example, transferring 1.5 ELF from the SideChain address ELF_75sSRT8rJqrKNF8h169qwwhiFLgXjaoLjthtA6ihnf7TnRDqB_tDVV to the MainChain address ELF_75sSRT8rJqrKNF8h169qwwhiFLgXjaoLjthtA6ihnf7TnRDqB_AELF: +Cross-chain transactions between the MainChain and dAppChain are considered two separate transactions. For example, transferring 1.5 ELF from the aelf dAppChain address ELF_75sSRT8rJqrKNF8h169qwwhiFLgXjaoLjthtA6ihnf7TnRDqB_tDVV to the MainChain address ELF_75sSRT8rJqrKNF8h169qwwhiFLgXjaoLjthtA6ihnf7TnRDqB_AELF: -First, a transaction called CrossChainTransfer is initiated on the SideChain: https://tdvv-explorer.aelf.io/tx/2b01a4cac416ae77c6f98c8a7cace66d2fb1edd565a5c0bedb9f44b395103895 +First, a transaction called CrossChainTransfer is initiated on the aelf dAppChain: https://tdvv-explorer.aelf.io/tx/2b01a4cac416ae77c6f98c8a7cace66d2fb1edd565a5c0bedb9f44b395103895 Then, a transaction called CrossChainReceiveToken is generated on the MainChain: https://explorer.aelf.io/tx/db29e36851549e3c5650ba853078ab02c6bb31c252ddfd7e0f8a7c33191ca3dd ::: -### 16. How to become a Block Producer (BP)? How to run a full node? +### 15. How to become a Block Producer (BP)? How to run a full node? :::faq[How to become a Block Producer (BP)? How to run a full node?] @@ -223,4 +223,4 @@ Here is a guide on how to apply to be a BP: https://docs.aelf.com/quick-start/no Here is a guide on how to set up a node on Mainnet: https://docs.aelf.com/quick-start/node-operators/set-up-a-node-on-mainnet/ -::: \ No newline at end of file +::: diff --git a/docs/about-aelf/wallet/index.md b/docs/about-aelf/wallet/index.md index 441b6d97..7c888cd0 100644 --- a/docs/about-aelf/wallet/index.md +++ b/docs/about-aelf/wallet/index.md @@ -37,9 +37,9 @@ We highly recommend using a supported Web3 wallet like Portkey as it provides a ::: -### 3. If I want to send ELF from a crypto exchange like Binance and OKEX to my Portkey wallet, should I select MainChain or SideChain on my Portkey wallet? +### 3. If I want to send ELF from a crypto exchange like Binance and OKEX to my Portkey wallet, should I select MainChain or dAppChain on my Portkey wallet? -:::faq[If I want to send ELF from a crypto exchange like Binance and OKEX to my Portkey wallet, should I select MainChain or SideChain on my Portkey wallet?] +:::faq[If I want to send ELF from a crypto exchange like Binance and OKEX to my Portkey wallet, should I select MainChain or dAppChain on my Portkey wallet?] When sending ELF tokens from a crypto exchange like Binance or OKEX to your Portkey wallet, you should select the MainChain address in your Portkey wallet. @@ -47,43 +47,43 @@ The MainChain is generally where the ELF tokens are held when they are on major ::: -### 4. What if I erraneously send ELF from a crypto exchange like Binance and OKEX to the SideChain in my Portkey wallet? +### 4. What if I erraneously send ELF from a crypto exchange like Binance and OKEX to the dAppChain in my Portkey wallet? -:::faq[What if I erraneously send ELF from a crypto exchange like Binance and OKEX to the SideChain in my Portkey wallet?] +:::faq[What if I erraneously send ELF from a crypto exchange like Binance and OKEX to the dAppChain in my Portkey wallet?] -This is unlikely to happen because exchanges that allow aelf chain mainnet withdrawal of ELF requires the prefix (ie. ELF) and suffix (i.e. AELF for mainchain / tDVV for sidechain) to be first excluded from your aelf chain wallet recipient address before the exchange executes the transfer. If you enter your aelf chain wallet recipient address which includes the prefix (i.e. ELF) and suffix (i.e. AELF for mainchain / tDVV for sidechain), the exchange will indicate an error in the address format and you will have to input the correct address again before the transfer can be made. +This is unlikely to happen because exchanges that allow aelf chain mainnet withdrawal of ELF requires the prefix (ie. ELF) and suffix (i.e. AELF for mainchain / tDVV for dappChain) to be first excluded from your aelf chain wallet recipient address before the exchange executes the transfer. If you enter your aelf chain wallet recipient address which includes the prefix (i.e. ELF) and suffix (i.e. AELF for mainchain / tDVV for dAppChain), the exchange will indicate an error in the address format and you will have to input the correct address again before the transfer can be made. ::: -### 5. Do MainChain and SideChain in my Portkey wallet have different addresses? +### 5. Do MainChain and dAppChain in my Portkey wallet have different addresses? -:::faq[Do MainChain and SideChain in my Portkey wallet have different addresses?] +:::faq[Do MainChain and dAppChain in my Portkey wallet have different addresses?] -In your Portkey wallet, the MainChain and SideChain typically share the same base address, but they differ by the suffix (i.e. AELF for mainchain / tDVV for sidechain). +In your Portkey wallet, the MainChain and dAppChain typically share the same base address, but they differ by the suffix (i.e. AELF for mainchain / tDVV for dAppChain). -However, if you are still using the deprecated version of Portkey Wallet, the MainChain and SideChain addresses might be different for the same account. +However, if you are still using the deprecated version of Portkey Wallet, the MainChain and dAppChain addresses might be different for the same account. ::: -### 6. Can I send ELF from the SideChain in my Portkey wallet to a crypto exchange like Binance and OKEX? +### 6. Can I send ELF from the dAppChain in my Portkey wallet to a crypto exchange like Binance and OKEX? -:::faq[Can I send ELF from the SideChain in my Portkey wallet to a crypto exchange like Binance and OKEX?] +:::faq[Can I send ELF from the dAppChain in my Portkey wallet to a crypto exchange like Binance and OKEX?] -No, you cannot directly send ELF from the SideChain in your Portkey wallet to a crypto exchange like Binance or OKEX. Most exchanges, including Binance and OKEX, only support ELF tokens on the MainChain. +No, you cannot directly send ELF from the dAppChain in your Portkey wallet to a crypto exchange like Binance or OKEX. Most exchanges, including Binance and OKEX, only support ELF tokens on the MainChain. -If you have ELF tokens on the SideChain in your Portkey wallet and wish to transfer them to an exchange, you should first transfer the tokens from the SideChain to the MainChain within your wallet. Once the tokens are on the MainChain, you can then send them to your exchange account. This ensures that the tokens are correctly received by the exchange. +If you have ELF tokens on the dAppChain in your Portkey wallet and wish to transfer them to an exchange, you should first transfer the tokens from the dAppChain to the MainChain within your wallet. Once the tokens are on the MainChain, you can then send them to your exchange account. This ensures that the tokens are correctly received by the exchange. ::: -### 7. What if I erraneously send ELF from the SideChain in my Portkey wallet to a crypto exchange like Binance and OKEX? What should I do? +### 7. What if I erraneously send ELF from the dAppChain in my Portkey wallet to a crypto exchange like Binance and OKEX? What should I do? -:::faq[What if I erraneously send ELF from the SideChain in my Portkey wallet to a crypto exchange like Binance and OKEX? What should I do?] +:::faq[What if I erraneously send ELF from the dAppChain in my Portkey wallet to a crypto exchange like Binance and OKEX? What should I do?] -If you mistakenly send ELF from the SideChain in your Portkey wallet to a crypto exchange like Binance or OKEX, the tokens will likely not be credited to your exchange account because these exchanges typically only support ELF on the MainChain. Here's what you should do: +If you mistakenly send ELF from the dAppChain in your Portkey wallet to a crypto exchange like Binance or OKEX, the tokens will likely not be credited to your exchange account because these exchanges typically only support ELF on the MainChain. Here's what you should do: #### Check the Transaction Details: -Verify the transaction on the blockchain explorer to confirm that the tokens were sent to the correct address on the exchange but from the SideChain. +Verify the transaction on the blockchain explorer to confirm that the tokens were sent to the correct address on the exchange but from the dAppChain. #### Contact the Exchange's Customer Support: @@ -101,10 +101,10 @@ By following these steps, you may be able to recover the tokens or at least unde ::: -### 8. What does tDVV or tDVW in Sidechain mean and do I need to care? +### 8. What does tDVV or tDVW in dAppChain mean and do I need to care? -:::faq[What does tDVV or tDVW in Sidechain mean and do I need to care?] +:::faq[What does tDVV or tDVW in dAppChain mean and do I need to care?] -In simpler terms, "tDVV" is just a special code that uniquely identifies the first SideChain in the aelf network. "tDVW" uniquely identifies the second SideChain. You do not need to care. +In simpler terms, "tDVV" is just a special code that uniquely identifies the first dAppChain in the aelf network. "tDVW" uniquely identifies the second dAppChain. You do not need to care. ::: \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index f6311bed..20fc2393 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,7 +11,7 @@ hide_table_of_contents: true # aelf Documentation -aelf is a high-performance, cloud-native, layer-1 blockchain with Mainnet nodes in cloud data centers. It supports parallel smart contract execution, microservices, and scalable MainChain and multi-SideChains architecture. The cross-chain design enables fast data interaction, and its hybrid SideChain model reduces costs and boosts network performance. +aelf is a high-performance, cloud-native, layer-1 blockchain with Mainnet nodes in cloud data centers. It supports parallel smart contract execution, microservices, and scalable MainChain and multi-dAppChains architecture. The cross-chain design enables fast data interaction, and its hybrid aelf dAppChain model reduces costs and boosts network performance.
diff --git a/docs/learn/smart-contract/requirements-and-restrictions/namespace-and-type-restrictions/index.md b/docs/learn/smart-contract/requirements-and-restrictions/namespace-and-type-restrictions/index.md index 2022f903..d8de9831 100644 --- a/docs/learn/smart-contract/requirements-and-restrictions/namespace-and-type-restrictions/index.md +++ b/docs/learn/smart-contract/requirements-and-restrictions/namespace-and-type-restrictions/index.md @@ -64,6 +64,15 @@ When deploying new contract code, Nodes perform checks against a whitelist. If a | string | ALL | Allowed | | string | Constructor | Denied | | Byte[] | ALL | Allowed | +| Func 4 | ALL | Allowed | +| ValueTuple 1 | ALL | Allowed | +| ValueTuple 2 | ALL | Allowed | +| ValueTuple 3 | ALL | Allowed | +| ValueTuple 4 | ALL | Allowed | +| ValueTuple 5 | ALL | Allowed | +| ValueTuple 6 | ALL | Allowed | +| ValueTuple 7 | ALL | Allowed | +| ValueTuple 8 | ALL | Allowed | ## Types and Members Whitelist in System.Reflection Namespace diff --git a/docs/learn/smart-contract/requirements-and-restrictions/structure-restrictions-and-requirements/index.md b/docs/learn/smart-contract/requirements-and-restrictions/structure-restrictions-and-requirements/index.md index d497686b..ec918518 100644 --- a/docs/learn/smart-contract/requirements-and-restrictions/structure-restrictions-and-requirements/index.md +++ b/docs/learn/smart-contract/requirements-and-restrictions/structure-restrictions-and-requirements/index.md @@ -183,4 +183,5 @@ In contract state, only the following types are allowed: - `MappedState` - `MethodReference` - `ProtobufState` -- `ContractReferenceState` \ No newline at end of file +- `ContractReferenceState` +- `StructuredState` \ No newline at end of file diff --git a/docs/legal/privacy-policy/index.md b/docs/legal/privacy-policy/index.md index 03c303b8..4d04a6bf 100644 --- a/docs/legal/privacy-policy/index.md +++ b/docs/legal/privacy-policy/index.md @@ -2,7 +2,7 @@ sidebar_position: 2 title: Privacy Policy --- -**Last updated: 25 June 2024** +**Last updated: 3 September 2024** This privacy policy ("Privacy Policy") elucidates the procedures by which Aelf Pte Ltd("Aelf", "our", "Company", "we", or "us") gathers, employs, and divulges information about you. @@ -140,9 +140,9 @@ We only share and disclose your information with the following categories of thi \- Website Hosting Service Providers -**7. Use Cookies And Other Tracking Technologies?** +**7. Use of Cookies And Other Tracking Technologies** -We do not use cookies or tracking technologies. Rather, we utilise anonymous page view tracking information provided by third-party analytics providers which do not collect or store any personal data. As such, we make no use of cookies. +While we do not directly utilize cookies or other tracking technologies on our Website, we may engage with third-party service providers who deploy such technologies as part of their service offerings. For instance, we use Hotjar in order to better understand our users' needs and to optimize this service and experience. Hotjar is a technology service that helps us better understand our users' experience (eg how much time they spend on which pages, which links they choose to click, what users do and don't like, etc.) and this enables us to build and maintain our service with user feedback. Hotjar uses cookies and other technologies to collect data on our users' behavior and their devices device's IP address (processed during your session and stored in a de-identified form), device screen size, device type (unique device identifiers), browser information, geographic location (country only), and the preferred language used to display our website. Hotjar stores this information on our behalf in a pseudonymized user profile. Hotjar is contractually forbidden to sell any of the data collected on our behalf. By interacting with our Website, you may be subject to these third-party technologies, which are governed by the respective provider's privacy policies. We recommend reviewing these policies to understand how your information may be collected and used. For further details, please see the 'about Hotjar' section of [Hotjar's support site](https://help.hotjar.com/hc/en-us/categories/115001323967-About-Hotjar). **8. Transfer of Information to Other Jurisdictions** diff --git a/docs/quick-start/advance-tutorials/_category_.json b/docs/quick-start/advance-tutorials/_category_.json new file mode 100644 index 00000000..bf55be6d --- /dev/null +++ b/docs/quick-start/advance-tutorials/_category_.json @@ -0,0 +1,15 @@ +{ + "position": 3, + "label": "Advance Tutorials", + "collapsible": true, + "collapsed": true, + "link": { + "type": "generated-index", + "title": "Advance Tutorials", + "slug": "quick-start/advance-tutorials", + "description": "Welcome to the advanced technical documentation for developing smart contracts on the aelf blockchain. This guide is tailored to help you master advanced concepts and techniques for creating robust and scalable smart contracts. Each tutorial delves deeper into intricate functionalities, building on your foundational knowledge to enhance your expertise step by step." + }, + "customProps": { + "description": "Master advanced dApp development on aelf" + } +} diff --git a/docs/quick-start/advance-tutorials/_setup.md b/docs/quick-start/advance-tutorials/_setup.md new file mode 100644 index 00000000..1d9221f8 --- /dev/null +++ b/docs/quick-start/advance-tutorials/_setup.md @@ -0,0 +1,89 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +- Basic knowledge of terminal commands +- **IDE** - Install [VS Code](https://code.visualstudio.com/) + +**Note for Apple Silicon users:** + +Ensure that Rosetta is installed, if it is not, use the following command: + +```bash title="Terminal" +softwareupdate --install-rosetta +``` + +**Install Required Packages** + +- [Install dotnet 8.0.x SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) +- Install aelf contract templates + + + +```bash title="Terminal" +dotnet new --install AElf.ContractTemplates +``` + + + +```bash title="Command Prompt" +dotnet new install AElf.ContractTemplates +``` + + + +AELF.ContractTemplates contains various predefined templates for the ease of developing smart contracts on the aelf blockchain. + +- Install aelf deploy tool + +```bash title="Terminal" +dotnet tool install --global aelf.deploy +``` + +aelf.deploy is a utility tool for deploying smart contracts on the aelf blockchain. +Please remember to export PATH after installing aelf.deploy. + +:::info +ℹ️ Note: If you have installed aelf.deploy and your terminal says that there is no such command available, please uninstall and reinstall aelf.deploy. +::: + +**Install Node.js and Yarn** + +- [Install Node.js](https://nodejs.org/en) +- [Install Yarn](https://classic.yarnpkg.com/lang/en/docs/install) + +**Install aelf-command** + + + +```bash title="Terminal" +sudo npm i -g aelf-command +``` + + + +```bash title="Command Prompt" +npm i -g aelf-command +``` + + + +aelf-command is a CLI tool for interacting with the aelf blockchain, enabling tasks like creating wallets and managing transactions. +Provide required permissions while installing aelf-command globally. + + + + +1. Visit [aelf-devcontainer-template](https://github.com/AElfProject/aelf-devcontainer-template). +2. Click the `Use this template` button. Choose `Create a new repository`. +3. Enter a suitable repository name. Click `Create repository`. +4. Within the GitHub interface of your new repository, click on `Code`. + Select `Codespaces`. +5. Click on the `+` sign to create a new Codespace. +6. After some time, your workspace will load with the contents of the repository. + You may now continue your development using GitHub Codespaces. + + + diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_create_aeindexer.md b/docs/quick-start/advance-tutorials/nft-indexer/_create_aeindexer.md new file mode 100644 index 00000000..93a0c7c6 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_create_aeindexer.md @@ -0,0 +1,8 @@ +## Step 2 - Create AeIndexer in AeFinder +- Log in to the AeFinder website. + TestNet: [https://test.aefinder.io/login](https://test.aefinder.io/login) + +- Enter the AeIndexer Name and other information to create a NFT AeIndexer. + +![run-app-success](/img/create-nft-indexer.png) +![create-app](/img/name-nft-indexer.png) diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_deploy_aeindexer.md b/docs/quick-start/advance-tutorials/nft-indexer/_deploy_aeindexer.md new file mode 100644 index 00000000..94359410 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_deploy_aeindexer.md @@ -0,0 +1,30 @@ +## Step 4 - Deploy AeIndexer +- Open the AeIndexer details page and click Deploy. +![deploy](/img/deploy-nft-indexer-template.png) +- Fill out the subscription manifest and upload the DLL file. +1. Subscription manifest: +```json +{ + "subscriptionItems": [ + { + "chainId": "tDVW", + "startBlockNumber": 151018963, + "onlyConfirmed": false, + "transactions": [], + "logEvents": [ + { + "contractAddress": "ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx", + "eventNames": [ + "Issued", + "Issue" + ] + } + ] + } + ] +} +``` + 2. DLL file location: src/NFTAeIndexer/bin/Release/net8.0/NFTAeIndexer.dll +![deploy-2](/img/subscription-nft-indexer.png) +- Click the deploy button to submit deployment information. When the normal processing block information appears on the Logs page at the bottom of the details page, it means that the deployment has been successful and data indexing has started. +![log](/img/logs-nft-indexer.png) diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_develop_aeindexer.md b/docs/quick-start/advance-tutorials/nft-indexer/_develop_aeindexer.md new file mode 100644 index 00000000..d6db81d5 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_develop_aeindexer.md @@ -0,0 +1,488 @@ +## Step 3 - Develop NFT AeIndexer + +### Download the Development Template + +1. Go to the AeIndexer details page for your created project. +2. Download the development template by entering your project name. + ![download-template](/img/download-nft-indexer-template.png) +3. Unzip the downloaded file to extract the project files. +4. After unzipping the files, you are ready to start development + +### Project Structure + +import FileTree from '@theme/FileTree'; + +The initial version of the NFT AeIndexer project has the following structure: + +export const initialProjectTree = { +"type": "directory", +"uri": "NFTAeIndexer", +"expanded": true, +"children": [ +{ +"type": "directory", +"uri": "Contracts", +"expanded": true, +"children": [ +{ +"type": "file", +"uri" : "MyContract.c.cs" +}, +{ +"type": "file", +"uri" : "MyContract.g.cs" +}, +] +}, +{ +"type": "directory", +"uri": "Entities", +"expanded": true, +"children": [ +{ +"type": "file", +"uri" : "MyEntity.cs" +}, +] +}, +{ +"type": "directory", +"uri": "Processors", +"expanded": true, +"children": [ +{ +"type": "file", +"uri" : "MyLogEventProcessor.cs" +}, +] +}, +{ +"type": "directory", +"uri": "GraphQL", +"expanded": true, +}, +] +} + +
+ +To ensure the project is set up correctly, follow these steps: + +### Setting Up the Files for NFT AeIndexer + +1. **Rename Files in the `Contracts/` Folder:** + + - Navigate to the `Contracts/` folder inside your project. + - Rename `MyContract.c.cs` to `TokenContract.c.cs`. + - Rename `MyContract.g.cs` to `TokenContract.g.cs`. + +2. **Download Token Contract Files:** + + - Go to the [AeFinder GitHub NFT Indexer sample](https://github.com/AElfProject/aelf-samples/tree/master/nft/nft-indexer/src/nftIndexer/Contracts). + - Locate and download the token contract files. + +3. **Copy and Replace Code:** + + - Open the downloaded token contract files. + - Copy the content from `TokenContract.c.cs` and `TokenContract.g.cs`. + - Paste the copied code into the corresponding files in the `src/NFTAeIndexer/Contracts` directory of your project: + - Paste into `TokenContract.c.cs`. + - Paste into `TokenContract.g.cs`. + +4. **Rename and add new files in the `Entities/` Folder:** + + - Navigate to the `Entities/` folder inside your project. + - Rename `MyEntity.cs` to `Account.cs`. + - Add new `TransferRecord.cs` file inside `Entities` folder. + +5. **Rename and add new files in the `Processors/` Folder:** + - Navigate to the `Processors/` folder inside your project. + - Rename `MyLogEventProcessor.cs` to `NFTTransferredProcessor.cs`. + +### Updated Project Structure + +After the setup, your NFT AeIndexer project will have the following structure: + +export const finalProjectTree = { +"type": "directory", +"uri": "NFTAeIndexer", +"expanded": true, +"children": [ +{ +"type": "directory", +"uri": "Contracts", +"expanded": true, +"children": [ +{ +"type": "file", +"uri" : "TokenContract.c.cs" +}, +{ +"type": "file", +"uri" : "TokenContract.g.cs" +}, +] +}, +{ +"type": "directory", +"uri": "Entities", +"expanded": true, +"children": [ +{ +"type": "file", +"uri" : "Account.cs" +}, +{ +"type": "file", +"uri" : "TransferRecord.cs" +}, +] +}, +{ +"type": "directory", +"uri": "Processors", +"expanded": true, +"children": [ +{ +"type": "file", +"uri" : "NFTTransferredProcessor.cs", +}, +] +}, +{ +"type": "directory", +"uri": "GraphQL", +"expanded": true, +}, +] +} + +
+ +:::tip +ℹ️ Note: If other contract files are needed, they need to be generated by compiling the corresponding contract project! +::: + +#### 1. Entity Models + +- Navigate to the `Entities/` folder inside your project. + +- `Account.cs` file is as follows: + +```csharp title="Account.cs" +using AeFinder.Sdk.Entities; +using Nest; + +namespace NFTAeIndexer.Entities; + +public class Account: AeFinderEntity, IAeFinderEntity +{ + [Keyword] public string Address { get; set; } + [Keyword] public string Symbol { get; set; } + public long Amount { get; set; } + public string TokenName { get; set; } + public string NftImageUri { get; set; } + public string NftAttributes { get; set; } +} +``` + +- **`TransferRecord.cs`** file is as follows: + +```csharp title="TransferRecord.cs" +using AeFinder.Sdk.Entities; +using Nest; + +namespace NFTAeIndexer.Entities; + +public class TransferRecord: AeFinderEntity, IAeFinderEntity +{ + [Keyword] public string Symbol { get; set; } + [Keyword] public string ToAddress { get; set; } + public long Amount { get; set; } + [Text] public string Memo { get; set; } +} +``` + +#### 2. NFT Transfer Processor + +The NFTTransferredProcessor handles NFT transfer events and updates account balances: + +- Navigate to the `Processors/` folder inside your project. + +- `NFTTransferredProcessor.cs` file is as follows: + +```csharp title="NFTTransferredProcessor.cs" +using Microsoft.Extensions.Logging; +using AElf.Contracts.MultiToken; +using AeFinder.Sdk.Logging; +using AeFinder.Sdk.Processor; +using AeFinder.Sdk; +using NFTAeIndexer.Entities; +using Volo.Abp.DependencyInjection; + +namespace NFTAeIndexer.Processors; + +public class NFTTransferredProcessor : LogEventProcessorBase, ITransientDependency +{ + private readonly IBlockChainService _blockChainService; + + public NFTTransferredProcessor(IBlockChainService blockChainService) + { + _blockChainService = blockChainService; + } + + public override string GetContractAddress(string chainId) + { + return chainId switch + { + "AELF" => "JRmBduh4nXWi1aXgdUsj5gJrzeZb2LxmrAbf7W99faZSvoAaE", + "tDVW" => "ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx", + _ => string.Empty + }; + } + + public override async Task ProcessAsync(Issued logEvent, LogEventContext context) + { + if (!IsNftTransfer(logEvent)) + { + return; + } + + var tokenInfoParam = new GetTokenInfoInput + { + Symbol = logEvent.Symbol + }; + + var nftTransfer = new TransferRecord + { + Id = $"{context.ChainId}-{context.Transaction.TransactionId}-{context.LogEvent.Index}", + ToAddress = logEvent.To.ToBase58(), + Symbol = logEvent.Symbol, + Amount = logEvent.Amount, + Memo = logEvent.Memo + }; + await SaveEntityAsync(nftTransfer); + + await ChangeNFTBalanceAsync(context.ChainId, logEvent.To.ToBase58(), logEvent.Symbol, logEvent.Amount); + } + + private async Task ChangeNFTBalanceAsync(string chainId, string address, string symbol, long amount) + { + var accountId = $"{chainId}-{address}-{symbol}"; + var account = await GetEntityAsync(accountId); + var tokenInfoParam = new GetTokenInfoInput { Symbol = symbol }; + var contractAddress = GetContractAddress(chainId); + var tokenInfo = await _blockChainService.ViewContractAsync( + chainId, contractAddress, + "GetTokenInfo", tokenInfoParam); + + Logger.LogDebug("TokenInfo response: {@TokenInfo}", tokenInfo); + + if (account == null) + { + account = new Account + { + Id = accountId, + Symbol = symbol, + Amount = amount, + Address = address, + TokenName = tokenInfo.TokenName, + NftImageUri = tokenInfo.ExternalInfo?.Value["__nft_image_uri"] ?? tokenInfo.ExternalInfo?.Value["__nft_image_url"], + NftAttributes = tokenInfo.ExternalInfo?.Value["__nft_attributes"] + }; + } + else + { + account.Amount += amount; + } + + Logger.LogDebug("NFT Balance changed: {0} {1} {2} {3}", account.Address, account.Symbol, account.Amount, account.TokenName); + + await SaveEntityAsync(account); + } + + private bool IsNftTransfer(Issued logEvent) + { + return !string.IsNullOrEmpty(logEvent.Symbol) && logEvent.Symbol.Contains("-") && + logEvent.Amount > 0 && + logEvent.To != null && !string.IsNullOrEmpty(logEvent.To.ToBase58()); + } +} +``` + +- Add files `AccountDto.cs`, `TransferRecordDto.cs`, `GetAccountInput.cs`, `GetTransferRecordInput.cs` to the directory `src/NFTAeIndexer/GraphQL`. + +```csharp title="AccountDto.cs" +using AeFinder.Sdk.Dtos; + +namespace NFTAeIndexer.GraphQL; + +public class AccountDto : AeFinderEntityDto +{ + public string Address { get; set; } + public string Symbol { get; set; } + public long Amount { get; set; } + public string TokenName { get; set; } + public string NftImageUri { get; set; } + public string NftAttributes { get; set; } +} +``` + +```csharp title="TransferRecordDto.cs" +using AeFinder.Sdk.Dtos; + +namespace NFTAeIndexer.GraphQL; + +public class TransferRecordDto : AeFinderEntityDto +{ + public string Symbol { get; set; } + public string FromAddress { get; set; } + public string ToAddress { get; set; } + public long Amount { get; set; } +} +``` + +```csharp title="GetAccountInput.cs" +namespace NFTAeIndexer.GraphQL; + +public class GetAccountInput +{ + public string ChainId { get; set; } + public string Address { get; set; } + public string Symbol { get; set; } +} +``` + +```csharp title="GetTransferRecordInput.cs" +namespace NFTAeIndexer.GraphQL; + +public class GetTransferRecordInput +{ + public string ChainId { get; set; } + public string Address { get; set; } + public string Symbol { get; set; } +} +``` + +- Modify `src/NFTAeIndexer/GraphQL/Query.cs` to add query logic. + +```csharp title="Query.cs" +using AeFinder.Sdk; +using GraphQL; +using NFTAeIndexer.Entities; +using Volo.Abp.ObjectMapping; + +namespace NFTAeIndexer.GraphQL; + +public class Query +{ + public static async Task> Account( + [FromServices] IReadOnlyRepository repository, + [FromServices] IObjectMapper objectMapper, + GetAccountInput input) + { + var queryable = await repository.GetQueryableAsync(); + + queryable = queryable.Where(a => a.Metadata.ChainId == input.ChainId); + + if (!input.Address.IsNullOrWhiteSpace()) + { + queryable = queryable.Where(a => a.Address == input.Address); + } + + if (!input.Symbol.IsNullOrWhiteSpace()) + { + queryable = queryable.Where(a => a.Symbol == input.Symbol && a.Symbol.Contains("-")); + } + + var accounts = queryable.OrderBy(o => o.Metadata.Block.BlockHeight).ToList(); + + return objectMapper.Map, List>(accounts); + } + + public static async Task> TransferRecord( + [FromServices] IReadOnlyRepository repository, + [FromServices] IObjectMapper objectMapper, + GetTransferRecordInput input) + { + var queryable = await repository.GetQueryableAsync(); + + queryable = queryable.Where(a => a.Metadata.ChainId == input.ChainId); + + if (!input.Address.IsNullOrWhiteSpace()) + { + queryable = queryable.Where(a => a.ToAddress == input.Address); + } + + // Filter by Symbol, ensuring it matches the NFT pattern + if (!input.Symbol.IsNullOrWhiteSpace()) + { + queryable = queryable.Where(a => a.Symbol == input.Symbol && a.Symbol.Contains("-")); + } + + // Ensure NFT-specific conditions + queryable = queryable.Where(a => a.Symbol.Contains("-") && a.Amount > 0); + + var transferRecords = queryable.OrderBy(o => o.Metadata.Block.BlockHeight).ToList(); + + return objectMapper.Map, List>(transferRecords); + } +} +``` + +- Register log event processor + + Modify `src/NFTAeIndexer/NFTAeIndexerModule.cs` to register NFTTransferredProcessor. + +```csharp title="NFTAeIndexerModule.cs" +using AeFinder.Sdk.Processor; +using NFTAeIndexer.GraphQL; +using NFTAeIndexer.Processors; +using GraphQL.Types; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; + +namespace NFTAeIndexer; + +public class NFTAeIndexerModule: AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => { options.AddMaps(); }); + context.Services.AddSingleton(); + + // Add your LogEventProcessor implementation. + context.Services.AddSingleton(); + } +} +``` + +- Add entity mapping + + Modify `src/NFTAeIndexer/NFTAeIndexerAutoMapperProfile.cs` and add entity mapping code. + +```csharp title="NFTAeIndexerAutoMapperProfile.cs" +using NFTAeIndexer.Entities; +using NFTAeIndexer.GraphQL; +using AutoMapper; + +namespace NFTAeIndexer; + +public class NFTAeIndexerAutoMapperProfile : Profile +{ + public NFTAeIndexerAutoMapperProfile() + { + CreateMap(); + CreateMap(); + } +} +``` + +### Building code + +Use the following command in the code directory to compile the code. + +```bash +dotnet build -c Release +``` diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_frontend_configure_wallet_provider.md b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_configure_wallet_provider.md new file mode 100644 index 00000000..e60449e9 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_configure_wallet_provider.md @@ -0,0 +1,85 @@ +### Configure Portkey Provider & Write Connect Wallet Function + +We'll set up our Portkey provider to allow users to connect their Portkey wallets to our app and interact with the aelf smart contracts. We'll be interacting with the already deployed multi-token contract for this tutorial. + +**Step 1. Locate the File:** + +- Go to the `src/hooks/useNFTSmartContract.ts` file. + +**Step 2. Fetch the Smart Contract:** + +- Find the comment `//Step A - Function to fetch a smart contract based on the chain symbol and the contract address.` + +- Replace the existing **`fetchContract`** function with this updated code: + +```ts title="useNFTSmartContract.ts" +//Step A - Function to fetch a smart contract based on the chain symbol and the contract address +const fetchContract = async ( + symbol: "AELF" | "tDVW", + contractAddress: string +) => { + try { + // If no provider is available, return null + if (!provider) return null; + + // Fetch the chain information using the provider + const chain = await provider.getChain(symbol); + if (!chain) throw new Error("Chain not found"); + + // Get the smart contract instance from the chain + const contract = chain.getContract(contractAddress); + + // Return the smart contract instance + return contract; + } catch (error) { + console.error("Error in fetchContract", { symbol, contractAddress, error }); + } +}; +``` + +**Explanation:** + +- **`fetchContract`** **Function**: This function fetches a smart contract based on the given chain symbol (e.g., "AELF" or "tDVW") and the contract address. + + - **Check Provider** : If no provider is available, the function returns null. + - **Fetch Chain** : The function fetches chain information using the provider. + - **Get Contract** : It retrieves the smart contract instance from the chain. + - **Error Handling** : If an error occurs, it logs the error to the console. + +**Step 3. Initialize and Fetch the Smart Contracts:** + +- Find the comment `// Step B - Effect hook to initialize and fetch the smart contracts when the provider changes.` + +- Replace the existing **`useEffect`** hook with this updated code: + +```ts title="useNFTSmartContract.ts" +// Step B - Effect hook to initialize and fetch the smart contracts when the provider changes + useEffect(() => { + (async () => { + // Fetch the MainChain Testnet Contract + const mainChainContract = await fetchContract( + "AELF", + "JRmBduh4nXWi1aXgdUsj5gJrzeZb2LxmrAbf7W99faZSvoAaE" + ); + setMainChainSmartContract(mainChainContract as IContract); + + // Fetch the dAppChain Testnet Contract + const sideChainContract = await fetchContract( + "tDVW", + "ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx" + ); + setSideChainSmartContract(sideChainContract as IContract); + })(); + }, [provider]); // Dependency array ensures this runs when the provider changes +``` + +**Explanation:** + +- **`useEffect`** **Hook** : This hook initializes and fetches the smart contracts when the provider changes. + + - **Check Provider** : If no provider is available, the function returns null. + - **Fetch Contracts** : It fetches and sets the smart contracts for the main chain, side chain, and cross chain. + - **MainChain Contract** : Fetches the MainChain Testnet Contract and sets it in the state. + - **dAppChain Contract** : Fetches the dAppChain Testnet Contract and sets it in the state. + +By following these steps, we'll configure the Portkey provider to connect users' wallets to your app and interact with the multi-token smart contract including NFT related functionalities. This setup will enable our frontend components to perform actions like `create NFTs`, `validate NFTs`, and `transfer NFTs`. diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_frontend_connect_wallet.md b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_connect_wallet.md new file mode 100644 index 00000000..068a9346 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_connect_wallet.md @@ -0,0 +1,39 @@ +### Configure Connect Wallet Function + +**Step 1: Locate the File** + +- Go to the `src/components/layout/header/index.tsx` file. + +**Step 2: Write the Connect Wallet Function** + +- The `header/index.tsx` file is the header of our NFT dApp. It allows users to connect their Portkey wallet with the NFT dApp. + +- Before users can interact with the smart contract, we need to write the `Connect Wallet` function. + +- Find the comment `// Step C - Connect Portkey Wallet`. + +- Replace the existing connect function with this code snippet: + +```tsx title="header/index.tsx" +const connect = async (walletProvider?: IPortkeyProvider) => { + // Step C - Connect Portkey Wallet + const accounts = await (walletProvider ? walletProvider : provider)?.request({ + method: MethodsBase.REQUEST_ACCOUNTS, + }); + const account = accounts?.AELF && accounts?.AELF[0]; + if (account) { + setCurrentWalletAddress(account.replace(/^ELF_/, "").replace(/_AELF$/, "")); + setIsConnected(true); + } + !walletProvider && toast.success("Successfully connected"); +}; +``` +**Explanation:** +- **`connect`** **Function** : This function connects the user's Portkey wallet with the dApp. + - **Fetch Accounts** : It fetches the wallet accounts using the provider. + - **Log Accounts** : Logs the accounts to the console for debugging. + - **Set Wallet Address** : Sets the current wallet address state variable with the fetched account. + - **Update Connection Status** : Updates the state to indicate that the wallet is connected. + - **User Notification** : Displays an alert to notify the user that their wallet is successfully connected. +In this code, we fetch the Portkey wallet account using the provider and update the wallet address state variable. An alert notifies the user that their wallet is successfully connected. +With the Connect Wallet function defined, we're ready to write the remaining functions in the next steps. diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_frontend_fetch_nft_data.md b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_fetch_nft_data.md new file mode 100644 index 00000000..54b503c1 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_fetch_nft_data.md @@ -0,0 +1,118 @@ +### Fetch NFT Data + +Let's write the Function for the fetch NFT data from user's Wallet using API. + +**Step 1: Locate the File** + +- go to the `src/lib/commonFunctions.ts` file. + +**Step 2: Write the Helper Functions for fetch the NFT data** + +- The `commonFunctions.ts` file is contains the helpers function for fetch NFT and etc. +- Find the comment `// fetch NFT Data from Indexer API`. + +- Replace the existing **`fetchUserNftData`** function with this code snippet: + +```ts title="commonFunctions.ts" +// fetch NFT Data from Indexer API +export const fetchUserNftData = async (address:string) => { + + const url = 'add_your_aeindexer_api'; + const headers = { 'Content-Type': 'application/json'}; + + const body = JSON.stringify({ + query: ` + query { + account(input: { chainId: "tDVW", address: "${address}" }) { + symbol + amount + address + tokenName + metadata { + chainId + block { + blockHeight + } + } + } + } + `, + variables: {}, + }); + + try { + const response = await fetch(url, { + method: 'POST', + headers: headers, + body: body, + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + return result.data.account; + } catch (error) { + console.error('Error fetching data:', error); + return "error"; + } +}; +``` +:::info +ℹ️ Note: Ensure that you are updating your aeindexer api with **"add_your_aeindexer_api"** value in **url** variable. +::: +#### Here's what the function does: +1. **Retrieves NFT Data:** The function `fetchUserNftData` fetches the NFT data for a given owner using AeIndexer API. +We have Prepared all necessary function for fetch NFT Data from User's Wallet. +Now, Let's call **`fetchUserNftData`** on necessary page. + +**Step 3: Call fetchUserNftData Functions on Home Page** + +- go to the `src/pages/home/index.tsx` file. +- The `home/index.tsx` file contains the Home Page of NFT dApp +- Find the comment `// get NFT Data from User's wallet`. + +- Replace the existing **`getNFTData`** function with this code snippet: + +```tsx title="home/index.tsx" +// get NFT Data from User's wallet +const getNFTData = async () => { + const result = await fetchUserNftData(currentWalletAddress as string); + if (result !== "error") { + setUserNfts(result); + } + setLoading(false); +}; +``` +#### Here's what the function does: +1. **Fetches NFT Data:** The function `getNFTData` retrieves NFT data from the user's wallet. +2. **Calls Fetch Function:** It calls the `fetchUserNftData` function with the `currentWalletAddress` parameters. +3. **Handles Result:** It checks the result: + - If the result is not "error", it updates the state with the fetched NFT data by calling `setUserNfts(result)`. +4. **Updates Loading State:** Regardless of the result, it sets the loading state to false by calling `setLoading(false)`. + +**Step 4: Call fetchUserNftData Functions on Profile Page** + +- go to the `src/pages/profile/index.tsx` file. +- The `profile/index.tsx` file contains the Home Page of NFT dApp +- Find the comment `// get NFT Data from User's wallet`. + +- Replace the existing **`getNFTData`** function with this code snippet: + +```tsx title="profile/index.tsx" +// get NFT Data from User's wallet +const getNFTData = async () => { + const result = await fetchUserNftData(currentWalletAddress as string); + if (result !== "error") { + setUserNfts(result); + } + setLoading(false); +}; +``` +#### Here's what the function does: +1. **Fetches NFT Data:** The function `getNFTData` retrieves NFT data from the user's wallet. +2. **Calls Fetch Function:** It calls the `fetchUserNftData` function with the `currentWalletAddress` parameters. +3. **Handles Result:** It checks the result: + - If the result is not "error", it updates the state with the fetched NFT data by calling `setUserNfts(result)`. +4. **Updates Loading State:** Regardless of the result, it sets the loading state to false by calling `setLoading(false)`. diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_collection.md b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_collection.md new file mode 100644 index 00000000..79f925aa --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_collection.md @@ -0,0 +1,308 @@ +### Create NFT Collection +Let's write the functions to `Create New NFT Collection` on the aelf mainchain and the dAppChain. + +**Step 1: Write the function to `Create New NFT Collection` on the MainChain** + +- The `create-nft/index.tsx` file includes the code to create NFTs. It allows users to create new NFTs. + +- Find the comment `// step 1 - Create New NFT Collection on the mainchain`. + +- Replace the existing **`createNftCollectionOnMainChain`** function with this code snippet: + +```tsx title="create-nft/index.tsx" +// step - 1 Create New NFT Collection on the mainchain +const createNftCollectionOnMainChain = async ( + values: z.infer +): Promise => { + let createLoadingId; + try { + createLoadingId = toast.loading("Creating NFT Collection.."); + + // Create an object with the necessary information for the new NFT collection. + const createNftInput: INftInput = { + tokenName: values.tokenName, // Name of the nft Collection + symbol: values.symbol, // Symbol of the token (You have to get it from your PortKey wallet on NFT seed from NFT section) + totalSupply: values.totalSupply, // Total supply of the token + decimals: values.decimals, // Decimals of the token + issuer: currentWalletAddress, // Address of the token issuer + isBurnable: true, // Indicates if the token can be burned + issueChainId: sidechain_from_chain_id, // ID of the issuing chain + owner: currentWalletAddress, // Owner's wallet address + }; + + // Call the smart contract method to create the new NFT collection on the main chain. + const result = await mainChainSmartContract?.callSendMethod( + "Create", + currentWalletAddress, + createNftInput + ); + + // Log the result of the creation for debugging purposes. + console.log("========= result of createNewNft =========", result); + + toast.update(createLoadingId, { + render: "NFT Collection Created Successfully On MainChain", + type: "success", + isLoading: false, + }); + removeNotification(createLoadingId); + + // Return the input data for further use. + return createNftInput; + } catch (error) { + handleError(createLoadingId as number, error); + return "error"; + } +}; +``` +:::tip +ℹ️ Note: You need to get **symbol** from the Portkey wallet. +::: +- **Follow Steps to get NFT symbol from Portkey Wallet:** + - Open Portkey Wallet. + - Go to the NFTs tab. + - You will find the SEED that you already got from the above **seed generation** step. + - Click on the SEED to see details. + - You will find the **Token Symbol** inside the **Token Creation via This Seed** section. + - Copy and use that value of the token symbol. +#### What This Function Does: +1. **Creates an Object with NFT Details** : It prepares the data needed to create a new NFT collection. +2. **Calls Smart Contract Method** : It interacts with the blockchain smart contract to create the new NFT collection using the prepared data. +3. **Logs Information** : It logs the result for debugging purposes. +4. **Return Values of Object** : It returns necessary values as a object. +Next, we'll write the **Validate Collection Info Exist** function. +**Step 2: Write the validates collection info exist function** +- Scroll up to find the comment `// step 2 - Validate Collection information exist`. + +- Replace the existing **`validateNftCollectionInfo`** function with this code snippet: + +```tsx title="create-nft/index.tsx" +// step 2 - Validate Collection information exist +// This function validates if the token collection information already exists on the main blockchain. +const validateNftCollectionInfo = async ( + values: INftInput +): Promise => { + let validateLoadingId; + try { + // Start loading before initiating the transaction + validateLoadingId = toast.loading( + + ); + + // Create an object with the necessary information for token validation. + const validateInput: INftInput = { + symbol: values.symbol, // Symbol of the token + tokenName: values.tokenName, // Name of the token + totalSupply: values.totalSupply, // Total supply of the token + decimals: values.decimals, // Decimals of the token + issuer: currentWalletAddress, // Address of the token issuer + isBurnable: true, // Indicates if the token can be burned + issueChainId: sidechain_from_chain_id, // ID of the issuing chain + owner: currentWalletAddress, // Owner's wallet address + }; + + // Get mainnet contract + const aelfTokenContract = await getTokenContract(aelf, wallet); + + // Prepare to sign the transaction using the contract method + const signedTx = + aelfTokenContract.ValidateTokenInfoExists.getSignedTx(validateInput); + + // Send the transaction using the signed transaction + const { TransactionId: VALIDATE_TXID } = await aelf.chain.sendTransaction( + signedTx + ); + + // Get the validation result + let VALIDATE_TXRESULT = await aelf.chain.getTxResult(VALIDATE_TXID); + + // Wait until the latest index height is greater than or equal to the transaction block number + let heightDone = false; + + while (!heightDone) { + await delay(5000); // Wait 5 seconds before checking again + // Get the latest index height + const sideIndexMainHeight = await GetParentChainHeight(); + if (Number(sideIndexMainHeight) >= VALIDATE_TXRESULT.Transaction.RefBlockNumber) { + VALIDATE_TXRESULT = await aelf.chain.getTxResult(VALIDATE_TXID); + heightDone = true; + } + } + + console.log("VALIDATE_TXRESULT", VALIDATE_TXRESULT); + + // Update the loading message + toast.update(validateLoadingId, { + render: "Validating Token Successfully Executed", + type: "success", + isLoading: false, + }); + + // Remove the loading message + removeNotification(validateLoadingId); + + // Return necessary details + return { + transactionId: VALIDATE_TXID, + signedTx: signedTx, + BlockNumber: VALIDATE_TXRESULT.BlockNumber, + }; + } catch (error) { + handleError(validateLoadingId as number, error); + return "error"; + } +}; +``` +#### What This Function Does: +1. **Creates an Object with Validate Collection Details** : It prepares the data needed to validate the token information. +2. **Calls Smart Contract Method** : It interacts with the multi-token smart contract method to check if the token information already exists using the prepared data. +3. **Return Values** : It returns necessary values as an object. +Next, we'll write the **Get the parent chain height** function. +**Step 3: Write the get the parent chain height function** +- Scroll up to find the comment `// Step 3: Get the parent chain height`. + +- Replace the existing **`GetParentChainHeight`** function with the following code snippet: + +```tsx title="create-nft/index.tsx" +// Step 3: Get the parent chain height +// This function fetches the current height of the parent blockchain. +const GetParentChainHeight = async () => { + try { + const tdvwCrossChainContract = await getCrossChainContract(tdvw, wallet); + // Call the smart contract method to get the parent chain height. + const result = await tdvwCrossChainContract.GetParentChainHeight.call() + // Return the parent chain height if it exists, otherwise return an empty string. + return result ? (result.value as string) : ""; + } catch (error) { + // If there's an error, log it and return an error status. + console.error(error, "=====error in GetParentChainHeight"); + return "error"; + } +}; +``` +#### What This Function Does: +1. **Calls Smart Contract Method** : It interacts with the side chain smart contract method to fetch the current height of the parent blockchain. +2. **Returns Parent Chain's Height** : It returns the parent chain's height if it exists. +Next, we'll write the **Fetch the Merkle path** function. +**Step 4: Write the fetch the merkle path function** +- Scroll up to find the comment `// step 4 - Fetch the merkle path by transaction Id`. + +- Replace the existing **`getMerklePathByTxId`** function with this code snippet: + +```tsx title="create-nft/index.tsx" +// step 4 - Fetch the merkle path by transaction Id +const getMerklePathByTxId = async (aelf: AElf, txId: string) => { + try { + const { MerklePathNodes } = await aelf.chain.getMerklePathByTxId(txId); + + const formattedMerklePathNodes = MerklePathNodes.map( + ({ + Hash, + IsLeftChildNode, + }: { + Hash: string, + IsLeftChildNode: boolean, + }) => ({ + hash: Hash, + isLeftChildNode: IsLeftChildNode, + }) + ); + + return { merklePathNodes: formattedMerklePathNodes }; + } catch (error) { + console.error("Error fetching Merkle path:", error); + throw new Error("Failed to get Merkle path by transaction ID."); + } +}; +``` +#### What This Function Does: +1. **Fetches Merkle Path** : It sends a request to fetch the merkle path using the transaction ID. +2. **Parses Response** : It parses the response from the server as JSON. +3. **Returns Merkle Path Nodes** : It extracts and returns the merkle path of the nodes from the JSON response. +4. **Handles Errors** : If an error occurs, it clears the transaction status and logs the error. +Next, we'll write the **Create a Collection on the cross-chain** function. +**Step 5: Write a function to create a collection on the side chain** +- Scroll up to find the comment `// step 5 - Create a collection on the dAppChain`. + +- Replace the existing **`createCollectionOnSideChain`** function with this code snippet: + +```tsx title="create-nft/index.tsx" +// step 5 - Create a collection on the dAppChain +const createCollectionOnSideChain = async ( + transactionId: string, + signedTx: string, + BlockNumber: number +) => { + let crossChainLoadingId; + try { + crossChainLoadingId = toast.loading( + "Creating Collection on dAppChain..." + ); + + const merklePath = await getMerklePathByTxId(aelf, transactionId); + + const tdvwTokenContract = await getTokenContract(tdvw, wallet); + + const CROSS_CHAIN_CREATE_TOKEN_PARAMS = { + fromChainId: mainchain_from_chain_id, + parentChainHeight: "" + BlockNumber, + transactionBytes: Buffer.from(signedTx, "hex").toString("base64"), + merklePath, + }; + const signedTx2 = + await tdvwTokenContract.CrossChainCreateToken.getSignedTx( + CROSS_CHAIN_CREATE_TOKEN_PARAMS + ); + + let done = false; + + while (!done) { + try { + await delay(10000); + const { TransactionId } = await tdvw.chain.sendTransaction(signedTx2); + const txResult = await tdvw.chain.getTxResult(TransactionId); + + if (txResult.Status === "SUCCESS" || txResult.Status === "MINED") { + done = true; + setIsNftCollectionCreated(true); + toast.update(crossChainLoadingId, { + render: "Collection was Created Successfully On dAppChain", + type: "success", + isLoading: false, + }); + removeNotification(crossChainLoadingId); + toast.info("You Can Create NFT now"); + setTransactionStatus(false); + } + } catch (err) { + if ((err as { Error: string }).Error.includes("Cross chain verification failed.")) { + console.log("Exit."); + done = true; + toast.update(crossChainLoadingId, { + render: "Please try again to create NFT using new NFT seed", + type: "error", + isLoading: false, + }); + removeNotification(crossChainLoadingId); + } else { + console.error("An unexpected error occurred:", err); + } + } + } + return "success"; + } catch (error) { + handleError(crossChainLoadingId as number, error); + return "error"; + } +}; +``` +#### What This Function Does: +1. **Displays Loading Toast**: Shows a notification indicating the creation process of the collection on the dAppChain. +2. **Fetches Merkle Path**: Retrieves the merkle path using the provided transactionId. +3. **Prepares and Signs Transaction**: Constructs parameters for the cross-chain transaction and signs it. +4. **Sends Transaction and Checks Status**: Sends the signed transaction and polls for its status every 10 seconds. Updates the notification and state, if successful. +5. **Handles Errors**: Logs errors and returns "error" if something goes wrong. +6. **Final Return**: Returns "success" upon successful completion. diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_form.md b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_form.md new file mode 100644 index 00000000..009a0183 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_form.md @@ -0,0 +1,25 @@ +### Configure Create NFT Form Code +**Step 1: Locate the File** +1. Go to the `src/pages/create-nft/index.tsx` file. This file is the **Create NFTs** page where users can enter details like the `tokenName`, `symbol`, `totalSupply` and `decimals`. +**Step 2: Prepare Form to Create NFTs** +1. Find the comment `// Step D - Configure NFT Form`. + +2. Replace the form variable with this code snippet: + +```tsx title="create-nft/index.tsx" +// Step D - Configure NFT Form +const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + tokenName: "", + symbol: "", + totalSupply: "", + decimals: "", + }, +}); +``` + +#### Here's what the function does: +1. Initializes a new form variable with default values needed to create an NFT. +2. Fields include: `tokenName` , `symbol` , `totalSupply` , and `decimals`. +Now the form is ready for users to fill in the necessary details for their NFT function interaction. diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_submit_form.md b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_submit_form.md new file mode 100644 index 00000000..8c22c132 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_submit_form.md @@ -0,0 +1,48 @@ +### Configure Submit Form +Now, let's write a function to call necessary functions for NFT creation. +1. Scroll down to find the comment `//Step 11 - Handle Submit Form`. + +2. Replace the existing **`onSubmit`** function with this code snippet: + +```tsx title="create-nft/index.tsx" +//Step 11 - Handle Submit Form +const onSubmit = async (values: z.infer) => { + setTransactionStatus(true); + + if (isNftCollectionCreated) { + // Already Collection Created + // create NFT Token + await createNftToken(values); + } else { + // create NFT Collection on MainChain + const createResult = await createNftCollectionOnMainChain(values); + + if (createResult === "error") { + setTransactionStatus(false); + return; + } + // Validate NFT Collection + const validateCollectionResult = await validateNftCollectionInfo( + createResult + ); + + if (validateCollectionResult === "error") { + setTransactionStatus(false); + return; + } + + // create NFT Collection on dAppChain + await createCollectionOnSideChain( + validateCollectionResult.transactionId, + validateCollectionResult.signedTx, + validateCollectionResult.BlockNumber + ); + } +}; +``` +#### Here's what the function does: +1. **Starts Transaction:** Sets the transaction status to true. +2. **Checks NFT Collection Status:** If the NFT collection is already created, calls `createNftToken` to create the NFT token. +3. **Creates and Validates NFT Collection:** If the collection isn’t created, calls `createNftCollectionOnMainChain` to create it. If successful, validates the NFT collection with `validateNftCollectionInfo`. +4. **Creates Collection on dAppChain:** If validation is successful, calls `createCollectionOnSideChain` to create the collection on the dAppChain. +5. **Handles Errors:** Updates the transaction status to false and exits if any step fails. diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_token.md b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_token.md new file mode 100644 index 00000000..c06d24e5 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_nft_token.md @@ -0,0 +1,323 @@ +### Create NFT Token +**Step 1: Write a Function to create NFTs on the mainchain** + +Now, let's write the **create NFTs on MainChain** function. +1. Scroll down to find the comment `// step 6 - Create an NFT on the mainchain`. + +2. Replace the existing **`createNFTOnMainChain`** function with this code snippet: + +```tsx title="create-nft/index.tsx" +// step 6 - Create an NFT on the mainchain +const createNFTOnMainChain = async (values: INftParams) => { + let createMainChainNFTLoadingId; + + try { + createMainChainNFTLoadingId = toast.loading( + "Creating NFT on MainChain..." + ); + + // Preparing Parameter for Create Function + const createNftMainChainInput = { + tokenName: values.tokenName, + symbol: values.symbol, + totalSupply: values.totalSupply, + issuer: currentWalletAddress, + isBurnable: true, + issueChainId: sidechain_from_chain_id, + owner: currentWalletAddress, + externalInfo: {}, + }; + + const resultMainchain = await mainChainSmartContract?.callSendMethod( + "Create", + currentWalletAddress, + createNftMainChainInput + ); + + console.log( + "========= result of createNewNft =========", + resultMainchain + ); + + toast.update(createMainChainNFTLoadingId, { + render: "NFT Created Successfully on MainChain", + type: "success", + isLoading: false, + }); + removeNotification(createMainChainNFTLoadingId); + + return "success"; + } catch (error) { + handleError(createMainChainNFTLoadingId as number, error); + return "error"; + } +}; +``` +#### What this function does: +1. **Displays Loading Toast:** Shows a notification indicating the creation process of the NFT on the mainchain. +2. **Prepares Parameters:** Constructs input parameters for creating the NFT, including token details and the issuer's information. +3. **Calls Smart Contract:** Sends a request to the mainchain smart contract to create the NFT using the prepared parameters. +4. **Handles Success:** Updates the notification to show successful NFT creation. +5. **Handles Errors:** Displays an error message if the operation fails and logs the error. +6. **Final Return:** Returns `"success"` if the NFT is created successfully; otherwise, returns `"error"`. + +**Step 2: Write the Function for Validate NFT Info Exist** + +Now, let's write the Validate NFT Info Exist function. +1. Scroll down to find the comment `// step 7 - Validate an NFT token on the mainchain`. + +2. Replace the existing **`validateNftToken`** function with this code snippet: + +```tsx title="create-nft/index.tsx" +// step 7 - Validate an NFT token on the maincgit stashhain +const validateNftToken = async (values: INftParams) => { + let validateNFTLoadingId; + try { + // Start Loading before initiate the transaction + validateNFTLoadingId = toast.loading( + + ); + + // Create an object with the necessary information for token validation. + const validateInput = { + symbol: values.symbol, + tokenName: values.tokenName, + totalSupply: values.totalSupply, + issuer: currentWalletAddress, + isBurnable: true, + issueChainId: sidechain_from_chain_id, + owner: currentWalletAddress, + externalInfo: {}, + }; + + // get mainnet contract + const aelfTokenContract = await getTokenContract(aelf, wallet); + + // prepare Sign the transaction using contract method (ValidateTokenInfoExists Function) + const signedTx = + aelfTokenContract.ValidateTokenInfoExists.getSignedTx(validateInput); + + // send the transaction using signed Transaction + const { TransactionId: VALIDATE_TXID } = await aelf.chain.sendTransaction( + signedTx + ); + + await delay(3000); + + // get Validate Result + let VALIDATE_TXRESULT = await aelf.chain.getTxResult(VALIDATE_TXID); + + await delay(3000); + + // if dAppChain index has a MainChain height greater than validateTokenInfoExist's + let heightDone = false; + + while (!heightDone) { + await delay(5000); // Wait 5 seconds before checking again + // get latest index Hight + const sideIndexMainHeight = await GetParentChainHeight(); + if ( + // check the latest index Hight is grater than or equal + Number(sideIndexMainHeight) >= VALIDATE_TXRESULT.Transaction.RefBlockNumber + ) { + VALIDATE_TXRESULT = await aelf.chain.getTxResult(VALIDATE_TXID); + heightDone = true; + } + } + + console.log(VALIDATE_TXRESULT, "VALIDATE_TXRESULT=====2"); + + const merklePath = await getMerklePathByTxId(aelf, VALIDATE_TXID); + + toast.update(validateNFTLoadingId, { + render: "Validating NFT Successfully Executed", + type: "success", + isLoading: false, + }); + removeNotification(validateNFTLoadingId); + + // return necessary values + return { + parentChainHeight: VALIDATE_TXRESULT.BlockNumber, + signedTx: signedTx, + merklePath: merklePath, + }; + } catch (error) { + handleError(validateNFTLoadingId as number, error); + return "error"; + } +}; +``` +#### Here's what the function does: +1. **Displays Loading Toast:** Shows a notification indicating that the NFT validation is in progress on the blockchain. +2. **Prepares Validation Input:** Constructs the input parameters needed for validating the NFT token. +3. **Gets Token Contract:** Retrieves the token contract instance from the MainChain. +4. **Signs and Sends Transaction:** Signs the transaction to validate the token info and sends it to the blockchain. +5. **Polls for Transaction Result:** Waits for the transaction result and ensures the transaction has reached the required block height. +6. **Fetches Merkle Path:** Retrieves the Merkle path for the validated transaction. +7. **Handles Success:** Updates the notification to show successful validation and returns necessary values. +8. **Handles Errors:** Logs errors and returns `"error"` if something goes wrong. + +**Step 3: Write a Function for Create NFT on dAppChain** + +Now, let's write the Create NFT on dAppChain function. +1. Scroll down to find the comment `// step 8 - Create a NFT on dAppChain`. + +2. Replace the existing **`createNftTokenOnSideChain`** function with this code snippet: + +```tsx title="create-nft/index.tsx" +// step 8 - Create a NFT on dAppChain. +const createNftTokenOnSideChain = async (values: INftValidateResult) => { + let createSideChainNFTLoadingId; + try { + createSideChainNFTLoadingId = toast.loading("Creating NFT on SideChain..."); + + const CROSS_CHAIN_CREATE_TOKEN_PARAMS = { + fromChainId: mainchain_from_chain_id, + parentChainHeight: values.parentChainHeight, + transactionBytes: Buffer.from(values.signedTx, "hex").toString("base64"), + merklePath: values.merklePath, + }; + + await sideChainSmartContract?.callSendMethod( + "CrossChainCreateToken", + currentWalletAddress, + CROSS_CHAIN_CREATE_TOKEN_PARAMS + ); + + toast.update(createSideChainNFTLoadingId, { + render: "NFT Created Successfully On SideChain", + type: "success", + isLoading: false, + }); + removeNotification(createSideChainNFTLoadingId); + return "success"; + } catch (error) { + handleError(createSideChainNFTLoadingId as number, error); + return "error"; + } +}; +``` +#### Here's what the function does: +1. **Displays Loading Toast:** Shows a notification indicating that the NFT is being created on the dAppChain. +2. **Prepares Cross-Chain Transaction Parameters:** Constructs the parameters needed for creating the NFT on the dAppChain, including chain IDs, block height, transaction data, and Merkle path. +3. **Calls Smart Contract Method:** Sends the transaction to the dAppChain smart contract to create the NFT. +4. **Handles Success:** Updates the notification to show successful NFT creation on the dAppChain. +5. **Handles Errors:** Logs errors and returns `"error"` if something goes wrong. + +**Step 4: Write a Function for Issue NFT Token which has been Created on dAppChain.** + +Now, let's write the Issue NFT Function. + +1. Scroll down to find the comment `// step 9 - Issue a NFT Function which has been Created on dAppChain`. + +2. Replace the existing **`issueNftOnSideChain`** function with this code snippet: + +```tsx title="create-nft/index.tsx" +// step 9 - Issue a NFT Function which has been Created on dAppChain +const issueNftOnSideChain = async (values: { + symbol: string; + amount: string; + memo: string; +}) => { + let issuingNFTLoadingId + try { + issuingNFTLoadingId = toast.loading( + "Issuing NFT on SideChain..." + ); + const issueNftInput = { + symbol: values.symbol, + amount: values.amount, + memo: values.memo, + to: currentWalletAddress, + }; + const result = await sideChainSmartContract?.callSendMethod( + "Issue", + currentWalletAddress, + issueNftInput + ); + console.log("========= result of createNewNft =========", result); + + toast.update(issuingNFTLoadingId, { + render: "NFT Issue Successfully Executed", + type: "success", + isLoading: false, + }); + removeNotification(issuingNFTLoadingId); + toast.success("You will get NFT on your Wallet! It can take sometimes to get into your wallet"); + handleReturnClick(); + return "success"; + } catch (error) { + handleError(issuingNFTLoadingId as number, error); + setTransactionStatus(false); + return "error"; + } +}; +``` +#### Here's what the function does: +1. **Displays Loading Toast:** Shows a notification indicating that the NFT is being issued on the dAppChain. +2. **Prepares Issuance Input:** Constructs the input parameters for issuing the NFT, including symbol, amount, memo, and recipient address. +3. **Calls Smart Contract Method:** Sends the transaction to the dAppChain smart contract to issue the NFT. +4. **Handles Success:** Updates the notification to show successful issuance and notifies the user that the NFT will appear in their wallet. +5. **Handles Errors:** Logs and displays any error messages, updates the transaction status, and returns `"error"`. + +**Step 5: Create a Function to Call Necessary Functions for NFT Creation** + +Now, let's write the createNftToken Function. + +1. Scroll down to find the comment `// step 10 - Call Necessary Function for Create NFT`. + +2. Replace the existing **`createNftToken`** function with this code snippet: + +```tsx title="create-nft/index.tsx" +// step 10 - Call Necessary Function for Create NFT +const createNftToken = async (values: INftParams) => { + try { + const mainChainResult = await createNFTOnMainChain(values); + + if (mainChainResult === "error") { + setTransactionStatus(false); + return; + } + await delay(3000); + + const validateNFTData: INftValidateResult | "error" = await validateNftToken(values); + + if (validateNFTData === "error") { + setTransactionStatus(false); + return; + } + + const sideChainResult = await createNftTokenOnSideChain(validateNFTData); + + if (sideChainResult === "error") { + setTransactionStatus(false); + return; + } + + await issueNftOnSideChain({ + symbol: values.symbol, + amount: values.totalSupply, + memo: "We are issuing nftToken", + }); + setTransactionStatus(false); + } catch (error) { + setTransactionStatus(false); + if (error instanceof Error) { + toast.error( error.message); + } else { + toast.error( "An unexpected error occurred."); + } + return "error"; + } +}; +``` +#### Here's what the function does: +1. **Creates NFT on MainChain:** Calls `createNFTOnMainChain` to create the NFT on the MainChain. If it fails, it updates the transaction status and exits. +2. **Validates NFT Token:** Waits for 3 seconds, then calls `validateNftToken` to validate the NFT. If validation fails, it updates the transaction status and exits. +3. **Creates NFT on dAppChain:** Calls `createNftTokenOnSideChain` to create the NFT on the dAppChain using the validated data. If it fails, it updates the transaction status and exits. +4. **Issues NFT on dAppChain:** Calls `issueNftOnSideChain` to issue the NFT. Updates the transaction status to false after completion. +5. **Handles Errors:** Catches and logs any errors, updates the transaction status, and displays an error notification. diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_frontend_project_setup.md b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_project_setup.md new file mode 100644 index 00000000..a88d02b3 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_project_setup.md @@ -0,0 +1,106 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +### Project Setup + +Let's start by cloning the frontend project repository from GitHub. + +- Run the following command your Terminal: + +```bash title="Terminal" +git clone https://github.com/AElfProject/aelf-samples.git +``` + +- Next, navigate to the frontend project directory with this command: + +```bash title="Terminal" +cd aelf-samples/advance/nft/2-dapp +``` + +- Once you're in the `2-dapp` directory, open the project with your preferred IDE (e.g., VSCode). You should see the project structure as shown below. + +export const tree = { +"type": "directory", +"uri": "2-dapp", +"expanded": true, +"children": [ +{ +"type": "directory", +"uri": "app" +}, +{ +"type": "directory", +"uri": "assets" +}, +{ +"type": "directory", +"uri": "public" +}, +{ +"type": "directory", +"uri": "src" +}, +{ +"type": "file", +"uri": ".gitignore" +}, +{ +"type": "file", +"uri": "components.json" +}, +{ +"type": "file", +"uri": "index.html" +}, +{ +"type": "file", +"uri": "package.json" +}, +{ +"type": "file", +"uri": "postcss.config.js" +}, +{ +"type": "file", +"uri": "README.md" +}, +{ +"type": "file", +"uri": "tailwind.config.js" +}, +{ +"type": "file", +"uri": "tsconfig.json" +}, +{ +"type": "file", +"uri": "tsconfig.node.json" +}, +{ +"type": "file", +"uri": "vite.config.ts" +} +] +} + +
+ +#### Install necessary packages and libraries + +- Run teh following command in the terminal: + + + +```bash title="Terminal" +sudo npm install +``` + + + +```bash title="Command Prompt" +npm install +``` + + + +We are now ready to build the frontend components of our NFT dApp. diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_frontend_run_application.md b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_run_application.md new file mode 100644 index 00000000..ba527470 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_run_application.md @@ -0,0 +1,178 @@ +### Run Application + +In this step, we will run the NFT dApp application. + +- To begin, run the following command on your terminal. + +```bash title="Terminal" +npm run dev +``` + +:::info +ℹ️ Note: Ensure that you are running this command under the **nft/2-dapp** folder. +::: + +- You should observe the following as shown below. + + ![run-app-success](/img/vote-npm-run-console.png) + +- Upon clicking on the **localhost URL**, you should be directed to the NFTs landing page as shown below. + +:::tip +If you are developing and testing this with GitHub codespace, you can use Port Forward to test the web server that is running in codespace, here is the link on how to usePort forward for codespace https://docs.github.com/en/codespaces/developing-in-a-codespace/forwarding-ports-in-your-codespace +::: + +- Usually codespace will automatically forward port, you should see a pop-up message at the bottom right of your codespace browser window as shown in the diagram below: + + ![open-in-browser](/img/codespace-forwarded-port.png) + +- Click the link to open the NFT dApp in the browser. + + ![nft-home-page](/img/nft-home-page.png) + +#### Create Portkey Wallet + +:::info +Portkey is the first AA wallet from aelf's ecosystem, migrating users, developers and projects from Web2 to Web3 with DID solution. +Users can swiftly log into Portkey via their Web2 social info with no private keys or mnemonics required. Underpinned by social recovery and decentralized guardian design, Portkey safeguards users' assets from centralized control and theft. Portkey has a unique payment delegation mechanism which enables interested parties to function as delegatees to pay for user activities on users' behalf. This means that users can create accounts for free and fees for other usages may also be covered in Portkey. +Portkey also provides crypto on/off-ramp services, allowing users to exchange fiat with crypto freely. It supports the storage and management of various digital assets such as tokens, NFTs, etc. The compatibility with multi-chains and seamless connection to all kinds of DApps makes Portkey a great way to enter the world of Web3. +With DID solution as its core, Portkey provides both Portkey Wallet and Portkey SDKs. +For more information, you may visit the official documentation for Portkey at https://doc.portkey.finance/. +::: + +- Download the Chrome extension for Portkey from https://chromewebstore.google.com/detail/portkey-wallet/iglbgmakmggfkoidiagnhknlndljlolb. + + :::info + The Portkey extension supports Chrome browser only (for now). Please ensure that you are using Chrome browser. + You may download Chrome from https://www.google.com/intl/en_sg/chrome/. + ::: + +- Once you have downloaded the extension, you should see the following on your browser as shown below. + + ![welcome-to-portkey](/img/welcome-to-portkey.png) + +- Click on `Get Start` and you should see the following interface as shown below. + + ![portkey-login](/img/portkey-login.png) + +**Sign up** + +- Switch to **aelf Testnet** network by selecting it: + + ![portkey-switch-to-testnet](/img/portkey-switch-to-testnet.png) + +:::danger +Please make sure you are using `aelf Testnet` in order to be able to receive your testnet tokens from the Faucet. +::: + +- Proceed to sign up with a Google Account or your preferred login method and complete the necessary accounts creation prompts and you should observe the following interface once you have signed up. + + ![success-login](/img/success-login.png) + + With that, you have successfully created your very first Portkey wallet within seconds. How easy was that? + +:::info +It is highly recommended to pin the Portkey wallet extension for easier access and navigation to your Portkey wallet! +::: + +- Next, click on ‘Open Portkey’ and you should now observe the following as shown below. + + ![portkey-wallet-preview](/img/portkey-wallet-preview.png) + +**Connect Portkey Wallet** + +- Click on **"Connect Wallet"** to connect your Portkey wallet. + + ![connect-wallet](/img/connect-wallet.png) + +- The button will change to **"Your Wallet Address"** when the connection is successful. + + ![collect-wallet-success](/img/collect-wallet-success.png) + +**Create NFT Collection** + +- Click on **"Create NFT Collection"** button to create new NFT Collection. + + ![collect-wallet-success](/img/create-collection-button.png) + +- You will be redirect this create NFT Collection page + + ![create-collection-form](/img/create-collection-form.png) + +- Now you need **NFT Seed** for create the new collection. + +- If you Don't have **NFT Seed** then please follow this [steps](#step-2---getting-nft-seed) to get it. + +- Open you Portkey Wallet and you will find the **NFT Seed** on **NFT** Tab. + + ![portkey-nft-seed.png](/img/portkey-nft-seed.png) + ![copy-nft-seed](/img/copy-nft-seed.png) + +- Copy the **Token Symbol** and use it on **`Symbol`** field of Form Submission of Create Collection. + +- Fill all other Necessary Fields like **`Token Name`** means `(Collection Name)`, **`Total Supply`**, **`Decimals`**. + + ![collection-form-example](/img/collection-form-example.png) + +- Click on **Create Collection** Button. + +- You will get Transaction Request on your Portkey Wallet so **Sign In** the Transaction. + + ![signin-transaction](/img/signin-transaction.png) + +- After **Sign In** the Transaction, Please wait to complete these steps. It will take approx 3-4 minutes. + - NFT Collection Created Successfully On MainChain. + - Validating Token Successfully Executed. + - Collection was Created Successfully On dAppChain. + +**Create NFT Token** + +- Once you done with create collection process the Now, It's time to Create NFT. + + ![create-nft-form](/img/create-nft-form.png) + +:::info +Please make sure the Symbol will be change to `[your_symbol]-id`. ie `VARBFUXYTY-1`, `VARBFUXYTY-2`, `VARBFUXYTY-3` etc. It means you can only create Collection with id 0 like `VARBFUXYTY-0` and for NFT Token Please use another integer as a id in Symbol. +::: + +- Fill all Necessary Fields in Create NFT Form like **`Token Name`** means `(Collection Name)`, **`Symbol`** means `(NFT Symbol)`, and **`Total Supply`**. + +- Click on **Create NFT** Button. + +- You will get Transaction Request on your Portkey Wallet so **Sign In** the Transaction for Create NFT as above you got for Create NFT Collection + +- After **Sign In** the Transaction, Please wait to complete these steps. It will take approx 3-4 minutes. + - NFT Created Successfully on MainChain. + - Validating NFT Successfully Executed. + - NFT Created Successfully On dAppChain. + - You will get NFT on your Wallet! It can take sometimes to get into your wallet. + +- After Successfully Create NFT, Now you redirected to Home page and as you can see you will get the NFT in your account. (It' take some time to store your NFT in your wallet so please reload the page multiple times till you get the NFT). + + ![home-nft-page](/img/home-nft-page.png) + +- You will also able you access you NFT data on your **Profile Page**. + + ![profile-page](/img/profile-page.png) + +**Transfer NFT Token** + +- Once you get NFT in your account like above image then it's time to transfer NFT to another account. + +- Please Click on **"Transfer NFT"** Button. + + ![transfer-button](/img/transfer-button.png) + +- Now you will be redirected to **Transfer NFT page**. + +- Please Fill all the Necessary Fields for Transfer NFT to another account like below image 👇. + + ![transfer-nft-page](/img/transfer-nft-page.png) + +- Click on **Transfer NFT** button. + +- Your NFT Transfer Successfully to another account. + +:::success +🎉 Congratulations Learners! You have successfully built your NFT dApp and this is no mean feat! +::: diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_frontend_transfer_nft.md b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_transfer_nft.md new file mode 100644 index 00000000..934daf38 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_frontend_transfer_nft.md @@ -0,0 +1,115 @@ +### Transfer NFT Token + +As we have completed `Create` and `Fetch NFT` so now it's time to `Transfer NFT`. +So now let's **Transfer NFT** to other wallet now. + +**Step 1: Locate the File** + +1. go to the `src/pages/transfer-nft/index.tsx` file. This file is the **Transfer NFT** page where users can enter details like the `address`, `amount` and `memo`. + +**Step 2: Prepare Form for Transfer NFT** + +1. Find the comment `// Configure NFT Transfer Form`. + +2. Replace the form variable with this code snippet: + +```tsx title="transfer-nft/index.tsx" +// Configure NFT Transfer Form +const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + address: "", + amount: "0", + memo: "", + }, +}); +``` + +#### Here's what the function does: +1. Initializes a new form variable with default values needed to transfer a nft. +2. Fields include: `address` , `amount` , and `memo`. +Now your form is ready for users to fill in the necessary details for their NFTs Transfer function Interaction. + +**Step 3: Create NFT Transfer Function** + +1. Find the comment `// Transfer NFT to Other Wallet`. +2. Replace the form variable with this code snippet: + +```tsx title="transfer-nft/index.tsx" +// Transfer NFT to Other Wallet +const transferNftToOtherAccount = async (values: { + address: string; + amount: string; + memo: string; +}) => { + if (Number(values.amount) > Number(nftBalance)) { + toast.error("Amount must be Less than or Equal to Supply Balance"); + return; + } + const transferNFTLoadingId = toast.loading("Transfer Transaction Executing"); + try { + const transferNtfInput = { + to: values.address, + symbol: nftSymbol, + amount: +values.amount, + memo: values.memo, + }; + await sideChainSmartContract?.callSendMethod( + "Transfer", + currentWalletAddress, + transferNtfInput + ); + toast.update(transferNFTLoadingId, { + render: "NFT Transferred Successfully!", + type: "success", + isLoading: false, + }); + removeNotification(transferNFTLoadingId); + await delay(3000); + handleReturnClick(); + } catch (error) { + if (error instanceof Error) { + toast.error(error.message); + } else { + toast.error("An unexpected error occurred."); + } + }; +}; +``` +#### Here's what the function does: + +1. **Transfers NFT to Another Wallet:** The function `transferNftToOtherAccount` transfers a specified amount of an NFT to another wallet. +2. **Parameters:** It takes a `values` object containing: + - `address`: The destination wallet address. + - `amount`: The amount of NFT to transfer. + - `memo`: An optional memo for the transfer. +3. **Checks Balance:** It checks if the transfer amount is greater than the available `nftBalance`. If it is, it shows an error message and exits the function. +4. **Displays Loading Toast:** It displays a loading toast notification indicating that the transfer transaction is executing. +5. **Prepares Transfer Data:** It prepares the transfer data in the `transferNtfInput` object, which includes the destination address, NFT symbol, transfer amount, and memo. +6. **Executes Transfer:** It calls the `Transfer` method on the side chain smart contract to execute the transfer. +7. **Success Handling:** If the transfer is successful: + - It updates the toast notification to indicate success. + - It removes the loading notification. + - It waits for 3 seconds using `await delay(3000)`. + - It calls `handleReturnClick` to handle any post-transfer actions. +8. **Error Handling:** If an error occurs during the transfer: + - It logs the error message to the console. + - It displays an error toast notification with the error message. + +**Step 4: Configure on handle Submit Form** + +1. Find the comment `// Handle Transfer Submit Form`. + +2. Replace the form variable with this code snippet: + +```tsx title="" +// Handle Transfer Submit Form +function onSubmit(values: z.infer) { + transferNftToOtherAccount(values); +} +``` +#### Here's what the function does: +1. **Handles Form Submission:** The function `onSubmit` handles the submission of a transfer form. +2. **Parameters:** It takes `values`, which is inferred from the `formSchema` and represents the form's data. +3. **Calls Transfer Function:** It calls the `transferNftToOtherAccount` function with the form values to initiate the NFT transfer. +Now that we've written all the necessary frontend functions and components, we're ready to run the NFT dApp application in the next step. diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_getting_seed.md b/docs/quick-start/advance-tutorials/nft-indexer/_getting_seed.md new file mode 100644 index 00000000..c2c8dd4e --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_getting_seed.md @@ -0,0 +1,20 @@ +## Step 6 - Getting NFT Seed + +In order to create an NFT collection on the aelf blockchain, the deployer wallet must have an **NFT SEED**. + +- Visit [NFT Faucet](https://faucet-ui.aelf.dev/) to get your NFT SEED. + +--- + +![result](/img/Seed.png) + +- After the request is successfully processed, the requestor wallet will receive the **SEED**. + +--- + +![result](/img/symbol.png) + +--- + +- Please note this **SEED** symbol value, as it will be needed later while creating the NFT collection and NFT generation. This will become our **Token Symbol**. + diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_query_index_data.md b/docs/quick-start/advance-tutorials/nft-indexer/_query_index_data.md new file mode 100644 index 00000000..6f266cee --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_query_index_data.md @@ -0,0 +1,27 @@ +## Step 5 - Query indexed data +Through the Playground page below the details page, you can use GraphQL syntax to query the indexed data information. Enter the query statement on the left, and the query results will be displayed on the right. + +``` +query{ + account(input: { chainId: "tDVW", address: "2AaBGTi2cJLWtEXR7w96hzun4qVz2KnsGZ1XfqErhKTgDj9Q8x"}) { + symbol, + amount, + address, + tokenName, + nftImageUri, + nftAttributes, + metadata { + chainId, + block { + blockHeight + } + } + } +} +``` +![query-graphQL](/img/query-nft-indexer.png) + +:::tip +ℹ️ Note: For the complete demo code, please visit AeFinder github to download. https://github.com/AeFinderProject/aefinder/tree/master/samples/TokenAeIndexer +::: + diff --git a/docs/quick-start/advance-tutorials/nft-indexer/_setup.md b/docs/quick-start/advance-tutorials/nft-indexer/_setup.md new file mode 100644 index 00000000..71492fc0 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/_setup.md @@ -0,0 +1,3 @@ +## Step 1 - Setting up your development environment +- Install [dotnet 8.0 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) +- Install IDE: Install your favorite IDE, such as: [VS Code](https://code.visualstudio.com/), [Visual Studio](https://visualstudio.microsoft.com/), [Rider](https://www.jetbrains.com/rider/), etc. diff --git a/docs/quick-start/advance-tutorials/nft-indexer/index.md b/docs/quick-start/advance-tutorials/nft-indexer/index.md new file mode 100644 index 00000000..2ab735e6 --- /dev/null +++ b/docs/quick-start/advance-tutorials/nft-indexer/index.md @@ -0,0 +1,89 @@ +--- +sidebar_position: 1 +title: NFT AeIndexer dApp +description: Advance featured AeIndexer application +--- +# NFT AeIndexer + +**Description**: This application demonstrates how to maintain account balances and transfer records by indexing aelf's NFT issued data. + +**Purpose**: Shows you how to create, develop, and deploy your own AeIndexer on AeFinder. + +**Difficulty Level**: Easy + +
+ +
+ +import Setup from "./\_setup.md" +import CreateAeIndexer from "./\_create_aeindexer.md" +import DevelopAeIndexer from "./\_develop_aeindexer.md" +import DeployAeIndexer from "./\_deploy_aeindexer.md" +import QueryIndexData from "./\_query_index_data.md" +import GettingSeed from "./\_getting_seed.md" + + + + + + + + +## Step 7 - Interact with Smart Contract through frontend dApp + +import ProjectSetup from "./\_frontend_project_setup.md" +import ConfigureWalletProvider from "./\_frontend_configure_wallet_provider.md" +import ConnectWallet from "./\_frontend_connect_wallet.md" +import ConfigureNftForm from "./\_frontend_nft_form.md" +import CreateNftCollection from "./\_frontend_nft_collection.md" +import CreateNftToken from "./\_frontend_nft_token.md" +import ConfigureNftSubmitForm from "./\_frontend_nft_submit_form.md" +import FetchNftData from "./\_frontend_fetch_nft_data.md" +import TransferNft from "./\_frontend_transfer_nft.md" +import RunApplication from "./\_frontend_run_application.md" + + + + + + + + + + + + +## 🎯 Conclusion + +🎉 Congratulations on completing the advanced NFT dApp tutorial with AEIndexer on the aelf blockchain! 🎉 You've successfully mastered not only the fundamentals of NFT development but also the sophisticated techniques of data indexing and multi-layered interactions. 🌟 + +**📚 What You've Learned** + +Through this advanced tutorial, you’ve gained expertise in: + +- **🛠️ Setting Up Your Development Environment**: Prepared a robust foundation for smooth development and deployment processes. +- **📂 Creating and Configuring AEIndexer**:Learned to set up AeIndexer in AeFinder to manage and index NFT data efficiently. +- **🖋️ Developing NFT AeIndexer**: Built a structured, scalable project with customized files for NFT indexing and optimized data organization. +- **🚀 Deploying AeIndexer**: Deployed and integrated the AeIndexer to enhance querying capabilities within your dApp. +- **🔍 Querying Indexed Data**: Enabled fast and accurate retrieval of NFT-related data using indexed results. +- **🌱 Obtaining NFT Seed**: Familiarized yourself with the NFT Faucet for initializing NFT creation. +- **💻 Smart Contract Interaction through Frontend**: Configured your dApp for end-to-end functionality, including wallet connection, form-based NFT creation, and token transfers. + +**🔍 Final Output** + +By the end of this journey, you’ve accomplished: + +- 🌐 Successfully creating and deploying an AEIndexer for seamless NFT data indexing. +- 🎨 Developing and interacting with NFT collections and tokens through a fully configured frontend. +- ⚡ Optimizing dApp performance with efficient querying of indexed blockchain data. + +**➡️ What's Next?** + +With a firm grasp of advanced indexing and NFT development, you're ready to push the boundaries of blockchain technology even further. Consider exploring: + +- **📊 Advanced Data Indexing Strategies**: Scale your AEIndexer to support complex queries and large datasets. +- **🔒 Enhanced Smart Contract Logic**: Strengthen your contracts with innovative features and robust security protocols. +- **🌐 Cross-Chain NFT Interoperability**: Expand your dApp’s functionality by exploring how aelf connects blockchains seamlessly. + +Your journey in blockchain innovation is just beginning. Keep experimenting, building, and shaping the future of decentralized applications with aelf! 🚀 +Happy coding and indexing! 😊 \ No newline at end of file diff --git a/docs/quick-start/developers/_deploy.md b/docs/quick-start/developers/_deploy.md index 61df4887..1674a1c4 100644 --- a/docs/quick-start/developers/_deploy.md +++ b/docs/quick-start/developers/_deploy.md @@ -44,76 +44,10 @@ To deploy smart contracts or execute on-chain transactions on aelf, you'll requi **Get ELF Tokens** -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - - -**1. Get Testnet ELF Tokens:** - -To receive testnet ELF tokens, run this command after replacing `$WALLET_ADDRESS` and `$WALLET_PASSWORD` with your wallet details: - - - -```bash title="Terminal" -export WALLET_ADDRESS="YOUR_WALLET_ADDRESS" -curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` - - - - -```bash title="Command Prompt" -$headers = @{ - "accept" = "application/json" -} - -$env:WALLET_ADDRESS = "YOUR_WALLET_ADDRESS" - -Invoke-WebRequest -Uri "https://faucet.aelf.dev/api/claim?walletAddress=$env:WALLET_ADDRESS" -Method POST -Headers $headers -Body "" -``` - - - - -**2. Check ELF Balance:** - -To check your ELF balance, use: - - - -```bash title="Terminal" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -```bash title="Command Prompt" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -You will be prompted for the following: - -```sh title="Terminal" -Enter the required param : ELF -Enter the required param : **$WALLET_ADDRESS** -``` - -You should see the result displaying your wallet's ELF balance. - - - - Go to https://faucet-ui.aelf.dev Enter your address and click `Get Tokens`. ![result](/img/get-token-ui.png) - - - **Deploy Smart Contract:** The smart contract needs to be deployed on the chain before users can interact with it. diff --git a/docs/quick-start/developers/_deploy_allowance_contract.md b/docs/quick-start/developers/_deploy_allowance_contract.md new file mode 100644 index 00000000..e00c8f4b --- /dev/null +++ b/docs/quick-start/developers/_deploy_allowance_contract.md @@ -0,0 +1,176 @@ +#### Create A Wallet + +To send transactions on the aelf blockchain, you must have a wallet. + +- Run this command to create aelf wallet. + +```bash title="Terminal" +aelf-command create +``` + +![result](/img/create_wallet_output.png) + +- You will be prompted to save your account, please do **save** your account as shown below: + +```bash title="Terminal" +? Save account info into a file? (Y/n) Y +``` + +**Make sure to choose Y to save your account information.** + +:::tip +ℹ️ Note: If you do not save your account information (by selecting n or N), do not export the wallet password. Only **proceed to the next** step if you have saved your account information. +::: + +- Next, enter and confirm your password. Then export your wallet password as shown below: + + + +```bash title="Terminal" +export WALLET_PASSWORD="YOUR_WALLET_PASSWORD" +``` + + + +```bash title="Command Prompt" +$env:WALLET_PASSWORD = "YOUR_WALLET_PASSWORD" +``` + + + +#### Acquire Testnet Tokens (Faucet) for Development + +To deploy smart contracts or execute on-chain transactions on aelf, you'll require testnet ELF tokens. + +**Get ELF Tokens** + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +**1. Get Testnet ELF Tokens:** + +To receive testnet ELF tokens, run this command after replacing `$WALLET_ADDRESS` and `$WALLET_PASSWORD` with your wallet details: + + + +```bash title="Terminal" +export WALLET_ADDRESS="YOUR_WALLET_ADDRESS" +curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" +``` + + + + +```bash title="Command Prompt" +$headers = @{ + "accept" = "application/json" +} + +$env:WALLET_ADDRESS = "YOUR_WALLET_ADDRESS" + +Invoke-WebRequest -Uri "https://faucet.aelf.dev/api/claim?walletAddress=$env:WALLET_ADDRESS" -Method POST -Headers $headers -Body "" +``` + + + + +**2. Check ELF Balance:** + +To check your ELF balance, use: + + + +```bash title="Terminal" +aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance +``` + + + +```bash title="Command Prompt" +aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance +``` + + + +You will be prompted for the following: + +```sh title="Terminal" +Enter the required param : ELF +Enter the required param : **$WALLET_ADDRESS** +``` + +You should see the result displaying your wallet's ELF balance. + + + + +Go to https://faucet-ui.aelf.dev Enter your address and click `Get Tokens`. + +![result](/img/get-token-ui.png) + + + + +**Deploy Smart Contract:** + +The smart contract needs to be deployed on the chain before users can interact with it. + +Run the following command to deploy a contract. Remember to export the path of AllowanceContract.dll.patched to CONTRACT_PATH. + + + +```bash title="Terminal" +export CONTRACT_PATH=$(find ~+ . -path "*patched*" | head -n 1) +``` + +```bash title="Terminal" +aelf-deploy -a $WALLET_ADDRESS -p $WALLET_PASSWORD -c $CONTRACT_PATH -e https://tdvw-test-node.aelf.io/ +``` + + + + +```bash title="Command Prompt" +$CONTRACT_PATH = Get-ChildItem -Recurse -Filter "*patched*" | Select-Object -First 1 -ExpandProperty FullName +$env:CONTRACT_PATH = $CONTRACT_PATH +``` + +```bash title="Command Prompt" +aelf-deploy -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -c $env:CONTRACT_PATH -e https://tdvw-test-node.aelf.io/ +``` + + + + +- Please wait for approximately 1 to 2 minutes. If the deployment is successful, it will provide you with the contract address. + ![result](/img/deploy-result.png) + +- Copy the smart contract address from the `address` field + ![result](/img/Contract_Address.png) + +- Export your smart contract address: + + + + ```bash title="Terminal" + export CONTRACT_ADDRESS="YOUR_SMART_CONTRACT_ADDRESS e.g. 2LUmicHyH4RXrMjG4beDwuDsiWJESyLkgkwPdGTR8kahRzq5XS" + ``` + + + + ```bash title="Command Prompt" + $env:CONTRACT_ADDRESS="YOUR_SMART_CONTRACT_ADDRESS e.g. 2LUmicHyH4RXrMjG4beDwuDsiWJESyLkgkwPdGTR8kahRzq5XS" + ``` + + + +:::tip +ℹ️ Note: You are to copy the smart contract address as we will be referencing it in the next steps! +::: + +:::info +🎉 You have successfully deployed your Allowance smart contract on the aelf testnet! In the next steps, we will be building the frontend components that allow us to interact with our deployed smart contract! +::: diff --git a/docs/quick-start/developers/_deploy_dao.md b/docs/quick-start/developers/_deploy_dao.md index 5466ef8e..2e662cd6 100644 --- a/docs/quick-start/developers/_deploy_dao.md +++ b/docs/quick-start/developers/_deploy_dao.md @@ -44,76 +44,10 @@ To deploy smart contracts or execute on-chain transactions on aelf, you'll requi **Get ELF Tokens** -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - - -**1. Get Testnet ELF Tokens:** - -To receive testnet ELF tokens, run this command after replacing `$WALLET_ADDRESS` and `$WALLET_PASSWORD` with your wallet details: - - - -```bash title="Terminal" -export WALLET_ADDRESS="YOUR_WALLET_ADDRESS" -curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` - - - - -```bash title="Command Prompt" -$headers = @{ - "accept" = "application/json" -} - -$env:WALLET_ADDRESS = "YOUR_WALLET_ADDRESS" - -Invoke-WebRequest -Uri "https://faucet.aelf.dev/api/claim?walletAddress=$env:WALLET_ADDRESS" -Method POST -Headers $headers -Body "" -``` - - - - -**2. Check ELF Balance:** - -To check your ELF balance, use: - - - -```bash title="Terminal" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -```bash title="Command Prompt" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -You will be prompted for the following: - -```sh title="Terminal" -Enter the required param : ELF -Enter the required param : **$WALLET_ADDRESS** -``` - -You should see the result displaying your wallet's ELF balance. - - - - Go to https://faucet-ui.aelf.dev Enter your address and click `Get Tokens`. ![result](/img/get-token-ui.png) - - - **Deploy Smart Contract:** The smart contract needs to be deployed on the chain before users can interact with it. diff --git a/docs/quick-start/developers/_deploy_dice.md b/docs/quick-start/developers/_deploy_dice.md new file mode 100644 index 00000000..f0a48a26 --- /dev/null +++ b/docs/quick-start/developers/_deploy_dice.md @@ -0,0 +1,112 @@ +#### Create A Wallet + +To send transactions on the aelf blockchain, you must have a wallet. + +- Run this command to create aelf wallet. + +```bash title="Terminal" +aelf-command create +``` + +![result](/img/create_wallet_output.png) + +- You will be prompted to save your account, please do **save** your account as shown below: + +```bash title="Terminal" +? Save account info into a file? (Y/n) Y +``` + +**Make sure to choose Y to save your account information.** + +:::tip +ℹ️ Note: If you do not save your account information (by selecting n or N), do not export the wallet password. Only **proceed to the next** step if you have saved your account information. +::: + +- Next, enter and confirm your password. Then export your wallet password as shown below: + + + +```bash title="Terminal" +export WALLET_PASSWORD="YOUR_WALLET_PASSWORD" +``` + + + +```bash title="Command Prompt" +$env:WALLET_PASSWORD = "YOUR_WALLET_PASSWORD" +``` + + + +#### Acquire Testnet Tokens (Faucet) for Development + +To deploy smart contracts or execute on-chain transactions on aelf, you'll require testnet ELF tokens. + +**Get ELF Tokens** + +Go to https://faucet-ui.aelf.dev Enter your address and click `Get Tokens`. + +![result](/img/get-token-ui.png) + +**Deploy Smart Contract:** + +The smart contract needs to be deployed on the chain before users can interact with it. + +Run the following command to deploy a contract. Remember to export the path of DiceMaster.dll.patched to CONTRACT_PATH. + + + +```bash title="Terminal" +export CONTRACT_PATH=$(find ~+ . -path "*patched*" | head -n 1) +``` + +```bash title="Terminal" +aelf-deploy -a $WALLET_ADDRESS -p $WALLET_PASSWORD -c $CONTRACT_PATH -e https://tdvw-test-node.aelf.io/ +``` + + + + +```bash title="Command Prompt" +$CONTRACT_PATH = Get-ChildItem -Recurse -Filter "*patched*" | Select-Object -First 1 -ExpandProperty FullName +$env:CONTRACT_PATH = $CONTRACT_PATH +``` + +```bash title="Command Prompt" +aelf-deploy -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -c $env:CONTRACT_PATH -e https://tdvw-test-node.aelf.io/ +``` + + + + +- Please wait for approximately 1 to 2 minutes. If the deployment is successful, it will provide you with the contract address. + ![result](/img/deploy-result.png) + +- Copy the smart contract address from the `address` field + ![result](/img/Contract_Address.png) + +- Export your smart contract address: + + + + ```bash title="Terminal" + export CONTRACT_ADDRESS="YOUR_SMART_CONTRACT_ADDRESS e.g. 2LUmicHyH4RXrMjG4beDwuDsiWJESyLkgkwPdGTR8kahRzq5XS" + ``` + + + + ```bash title="Command Prompt" + $env:CONTRACT_ADDRESS="YOUR_SMART_CONTRACT_ADDRESS e.g. 2LUmicHyH4RXrMjG4beDwuDsiWJESyLkgkwPdGTR8kahRzq5XS" + ``` + + + +:::tip +ℹ️ Note: You are to copy the smart contract address as we will be referencing it in the next steps! +::: + +:::info +🎉 You have successfully deployed your dApp smart contract on the aelf testnet! In the next steps, we will be building the frontend components that allow us to interact with our deployed smart contract! +::: + + diff --git a/docs/quick-start/developers/_deploy_expense_tracker.md b/docs/quick-start/developers/_deploy_expense_tracker.md index 1b79bd66..59dbd7e0 100644 --- a/docs/quick-start/developers/_deploy_expense_tracker.md +++ b/docs/quick-start/developers/_deploy_expense_tracker.md @@ -44,76 +44,10 @@ To deploy smart contracts or execute on-chain transactions on aelf, you'll requi **Get ELF Tokens** -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - - -**1. Get Testnet ELF Tokens:** - -To receive testnet ELF tokens, run this command after replacing `$WALLET_ADDRESS` and `$WALLET_PASSWORD` with your wallet details: - - - -```bash title="Terminal" -export WALLET_ADDRESS="YOUR_WALLET_ADDRESS" -curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` - - - - -```bash title="Command Prompt" -$headers = @{ - "accept" = "application/json" -} - -$env:WALLET_ADDRESS = "YOUR_WALLET_ADDRESS" - -Invoke-WebRequest -Uri "https://faucet.aelf.dev/api/claim?walletAddress=$env:WALLET_ADDRESS" -Method POST -Headers $headers -Body "" -``` - - - - -**2. Check ELF Balance:** - -To check your ELF balance, use: - - - -```bash title="Terminal" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -```bash title="Command Prompt" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -You will be prompted for the following: - -```sh title="Terminal" -Enter the required param : ELF -Enter the required param : **$WALLET_ADDRESS** -``` - -You should see the result displaying your wallet's ELF balance. - - - - Go to https://faucet-ui.aelf.dev Enter your address and click `Get Tokens`. ![result](/img/get-token-ui.png) - - - **Deploy Smart Contract:** The smart contract needs to be deployed on the chain before users can interact with it. diff --git a/docs/quick-start/developers/_deploy_lottery.md b/docs/quick-start/developers/_deploy_lottery.md index 77249bbc..9148306b 100644 --- a/docs/quick-start/developers/_deploy_lottery.md +++ b/docs/quick-start/developers/_deploy_lottery.md @@ -44,76 +44,10 @@ To deploy smart contracts or execute on-chain transactions on aelf, you'll requi **Get ELF Tokens** -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - - -**1. Get Testnet ELF Tokens:** - -To receive testnet ELF tokens, run this command after replacing `$WALLET_ADDRESS` and `$WALLET_PASSWORD` with your wallet details: - - - -```bash title="Terminal" -export WALLET_ADDRESS="YOUR_WALLET_ADDRESS" -curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` - - - - -```bash title="Command Prompt" -$headers = @{ - "accept" = "application/json" -} - -$env:WALLET_ADDRESS = "YOUR_WALLET_ADDRESS" - -Invoke-WebRequest -Uri "https://faucet.aelf.dev/api/claim?walletAddress=$env:WALLET_ADDRESS" -Method POST -Headers $headers -Body "" -``` - - - - -**2. Check ELF Balance:** - -To check your ELF balance, use: - - - -```bash title="Terminal" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -```bash title="Command Prompt" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -You will be prompted for the following: - -```sh title="Terminal" -Enter the required param : ELF -Enter the required param : **$WALLET_ADDRESS** -``` - -You should see the result displaying your wallet's ELF balance. - - - - Go to https://faucet-ui.aelf.dev Enter your address and click `Get Tokens`. ![result](/img/get-token-ui.png) - - - **Deploy Smart Contract:** The smart contract needs to be deployed on the chain before users can interact with it. diff --git a/docs/quick-start/developers/_deploy_role_contract.md b/docs/quick-start/developers/_deploy_role_contract.md new file mode 100644 index 00000000..6a2fbff8 --- /dev/null +++ b/docs/quick-start/developers/_deploy_role_contract.md @@ -0,0 +1,176 @@ +#### Create A Wallet + +To send transactions on the aelf blockchain, you must have a wallet. + +- Run this command to create aelf wallet. + +```bash title="Terminal" +aelf-command create +``` + +![result](/img/create_wallet_output.png) + +- You will be prompted to save your account, please do **save** your account as shown below: + +```bash title="Terminal" +? Save account info into a file? (Y/n) Y +``` + +**Make sure to choose Y to save your account information.** + +:::tip +ℹ️ Note: If you do not save your account information (by selecting n or N), do not export the wallet password. Only **proceed to the next** step if you have saved your account information. +::: + +- Next, enter and confirm your password. Then export your wallet password as shown below: + + + +```bash title="Terminal" +export WALLET_PASSWORD="YOUR_WALLET_PASSWORD" +``` + + + +```bash title="Command Prompt" +$env:WALLET_PASSWORD = "YOUR_WALLET_PASSWORD" +``` + + + +#### Acquire Testnet Tokens (Faucet) for Development + +To deploy smart contracts or execute on-chain transactions on aelf, you'll require testnet ELF tokens. + +**Get ELF Tokens** + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +**1. Get Testnet ELF Tokens:** + +To receive testnet ELF tokens, run this command after replacing `$WALLET_ADDRESS` and `$WALLET_PASSWORD` with your wallet details: + + + +```bash title="Terminal" +export WALLET_ADDRESS="YOUR_WALLET_ADDRESS" +curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" +``` + + + + +```bash title="Command Prompt" +$headers = @{ + "accept" = "application/json" +} + +$env:WALLET_ADDRESS = "YOUR_WALLET_ADDRESS" + +Invoke-WebRequest -Uri "https://faucet.aelf.dev/api/claim?walletAddress=$env:WALLET_ADDRESS" -Method POST -Headers $headers -Body "" +``` + + + + +**2. Check ELF Balance:** + +To check your ELF balance, use: + + + +```bash title="Terminal" +aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance +``` + + + +```bash title="Command Prompt" +aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance +``` + + + +You will be prompted for the following: + +```sh title="Terminal" +Enter the required param : ELF +Enter the required param : **$WALLET_ADDRESS** +``` + +You should see the result displaying your wallet's ELF balance. + + + + +Go to https://faucet-ui.aelf.dev Enter your address and click `Get Tokens`. + +![result](/img/get-token-ui.png) + + + + +**Deploy Smart Contract:** + +The smart contract needs to be deployed on the chain before users can interact with it. + +Run the following command to deploy a contract. Remember to export the path of RoleContract.dll.patched to CONTRACT_PATH. + + + +```bash title="Terminal" +export CONTRACT_PATH=$(find ~+ . -path "*patched*" | head -n 1) +``` + +```bash title="Terminal" +aelf-deploy -a $WALLET_ADDRESS -p $WALLET_PASSWORD -c $CONTRACT_PATH -e https://tdvw-test-node.aelf.io/ +``` + + + + +```bash title="Command Prompt" +$CONTRACT_PATH = Get-ChildItem -Recurse -Filter "*patched*" | Select-Object -First 1 -ExpandProperty FullName +$env:CONTRACT_PATH = $CONTRACT_PATH +``` + +```bash title="Command Prompt" +aelf-deploy -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -c $env:CONTRACT_PATH -e https://tdvw-test-node.aelf.io/ +``` + + + + +- Please wait for approximately 1 to 2 minutes. If the deployment is successful, it will provide you with the contract address. + ![result](/img/deploy-result.png) + +- Copy the smart contract address from the `address` field + ![result](/img/Contract_Address.png) + +- Export your smart contract address: + + + + ```bash title="Terminal" + export CONTRACT_ADDRESS="YOUR_SMART_CONTRACT_ADDRESS e.g. 2LUmicHyH4RXrMjG4beDwuDsiWJESyLkgkwPdGTR8kahRzq5XS" + ``` + + + + ```bash title="Command Prompt" + $env:CONTRACT_ADDRESS="YOUR_SMART_CONTRACT_ADDRESS e.g. 2LUmicHyH4RXrMjG4beDwuDsiWJESyLkgkwPdGTR8kahRzq5XS" + ``` + + + +:::tip +ℹ️ Note: You are to copy the smart contract address as we will be referencing it in the next steps! +::: + +:::info +🎉 You have successfully deployed your Role smart contract on the aelf testnet! In the next steps, we will be building the frontend components that allow us to interact with our deployed smart contract! +::: diff --git a/docs/quick-start/developers/_deploy_single_pool_staking.md b/docs/quick-start/developers/_deploy_single_pool_staking.md index a334c07c..a8fecff7 100644 --- a/docs/quick-start/developers/_deploy_single_pool_staking.md +++ b/docs/quick-start/developers/_deploy_single_pool_staking.md @@ -44,76 +44,10 @@ To deploy smart contracts or execute on-chain transactions on aelf, you'll requi **Get ELF Tokens** -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - - -**1. Get Testnet ELF Tokens:** - -To receive testnet ELF tokens, run this command after replacing `$WALLET_ADDRESS` and `$WALLET_PASSWORD` with your wallet details: - - - -```bash title="Terminal" -export WALLET_ADDRESS="YOUR_WALLET_ADDRESS" -curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` - - - - -```bash title="Command Prompt" -$headers = @{ - "accept" = "application/json" -} - -$env:WALLET_ADDRESS = "YOUR_WALLET_ADDRESS" - -Invoke-WebRequest -Uri "https://faucet.aelf.dev/api/claim?walletAddress=$env:WALLET_ADDRESS" -Method POST -Headers $headers -Body "" -``` - - - - -**2. Check ELF Balance:** - -To check your ELF balance, use: - - - -```bash title="Terminal" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -```bash title="Command Prompt" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -You will be prompted for the following: - -```sh title="Terminal" -Enter the required param : ELF -Enter the required param : **$WALLET_ADDRESS** -``` - -You should see the result displaying your wallet's ELF balance. - - - - Go to https://faucet-ui.aelf.dev Enter your address and click `Get Tokens`. ![result](/img/get-token-ui.png) - - - **Deploy Smart Contract:** The smart contract needs to be deployed on the chain before users can interact with it. diff --git a/docs/quick-start/developers/_deploy_tic_tac_toe.md b/docs/quick-start/developers/_deploy_tic_tac_toe.md index c560d694..5ae97f10 100644 --- a/docs/quick-start/developers/_deploy_tic_tac_toe.md +++ b/docs/quick-start/developers/_deploy_tic_tac_toe.md @@ -44,76 +44,10 @@ To deploy smart contracts or execute on-chain transactions on aelf, you'll requi **Get ELF Tokens** -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - - -**1. Get Testnet ELF Tokens:** - -To receive testnet ELF tokens, run this command after replacing `$WALLET_ADDRESS` and `$WALLET_PASSWORD` with your wallet details: - - - -```bash title="Terminal" -export WALLET_ADDRESS="YOUR_WALLET_ADDRESS" -curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` - - - - -```bash title="Command Prompt" -$headers = @{ - "accept" = "application/json" -} - -$env:WALLET_ADDRESS = "YOUR_WALLET_ADDRESS" - -Invoke-WebRequest -Uri "https://faucet.aelf.dev/api/claim?walletAddress=$env:WALLET_ADDRESS" -Method POST -Headers $headers -Body "" -``` - - - - -**2. Check ELF Balance:** - -To check your ELF balance, use: - - - -```bash title="Terminal" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -```bash title="Command Prompt" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -You will be prompted for the following: - -```sh title="Terminal" -Enter the required param : ELF -Enter the required param : **$WALLET_ADDRESS** -``` - -You should see the result displaying your wallet's ELF balance. - - - - Go to https://faucet-ui.aelf.dev Enter your address and click `Get Tokens`. ![result](/img/get-token-ui.png) - - - **Deploy Smart Contract:** The smart contract needs to be deployed on the chain before users can interact with it. diff --git a/docs/quick-start/developers/_deploy_todo.md b/docs/quick-start/developers/_deploy_todo.md index a3647a9f..607ab0ca 100644 --- a/docs/quick-start/developers/_deploy_todo.md +++ b/docs/quick-start/developers/_deploy_todo.md @@ -44,76 +44,10 @@ To deploy smart contracts or execute on-chain transactions on aelf, you'll requi **Get ELF Tokens** -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - - -**1. Get Testnet ELF Tokens:** - -To receive testnet ELF tokens, run this command after replacing `$WALLET_ADDRESS` and `$WALLET_PASSWORD` with your wallet details: - - - -```bash title="Terminal" -export WALLET_ADDRESS="YOUR_WALLET_ADDRESS" -curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` - - - - -```bash title="Command Prompt" -$headers = @{ - "accept" = "application/json" -} - -$env:WALLET_ADDRESS = "YOUR_WALLET_ADDRESS" - -Invoke-WebRequest -Uri "https://faucet.aelf.dev/api/claim?walletAddress=$env:WALLET_ADDRESS" -Method POST -Headers $headers -Body "" -``` - - - - -**2. Check ELF Balance:** - -To check your ELF balance, use: - - - -```bash title="Terminal" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -```bash title="Command Prompt" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $env:WALLET_ADDRESS -p $env:WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` - - - -You will be prompted for the following: - -```sh title="Terminal" -Enter the required param : ELF -Enter the required param : **$WALLET_ADDRESS** -``` - -You should see the result displaying your wallet's ELF balance. - - - - Go to https://faucet-ui.aelf.dev Enter your address and click `Get Tokens`. ![result](/img/get-token-ui.png) - - - **Deploy Smart Contract:** The smart contract needs to be deployed on the chain before users can interact with it. diff --git a/docs/quick-start/developers/_setup.md b/docs/quick-start/developers/_setup.md index ed9d4ef1..630131bd 100644 --- a/docs/quick-start/developers/_setup.md +++ b/docs/quick-start/developers/_setup.md @@ -7,6 +7,14 @@ import TabItem from '@theme/TabItem'; - Basic knowledge of terminal commands - **IDE** - Install [VS Code](https://code.visualstudio.com/) +**Note for Apple Silicon users:** + +Ensure that Rosetta is installed, if it is not, use the following command: + +```bash title="Terminal" +softwareupdate --install-rosetta +``` + **Install Required Packages** - [Install dotnet 8.0.x SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) diff --git a/docs/quick-start/developers/allowance-dapp/index.md b/docs/quick-start/developers/allowance-dapp/index.md new file mode 100644 index 00000000..4208abb5 --- /dev/null +++ b/docs/quick-start/developers/allowance-dapp/index.md @@ -0,0 +1,1545 @@ +--- +sidebar_position: 9 +title: Allowance dApp +description: Smart contracts explaining inter-contract calls +--- + +**Description**: This project demonstrates the integration of two smart contracts, RoleContract and AllowanceContract, focusing on role-based access and fund management. It highlights **inter-contract calls**, where the allowance logic depends on roles retrieved dynamically from the role contract. + +**Purpose**: The purpose of this dApp is to teach state management, access control, and inter smart contract calls on the aelf blockchain. This example models how multi-contract systems work together and call each other to securely manage roles and funds in a blockchain environment. +**Difficulty Level**: Moderate + + + +## Step 1 - Setting up your development environment + +import Setup from "../\_setup.md" + + + +## Step 2 - Develop Role Smart Contract + +### Start Your Smart Contract Project + +- Open your `Terminal`. + +- Enter the following command to generate a new RoleContract project: + +```bash title="Terminal" +mkdir role-contract +cd role-contract +dotnet new aelf -n RoleContract +``` + +### Adding Your Smart Contract Code + +Now that we have a RoleContract template, we can customize it to implement role-based permissions for various use cases. Below are the core functionalities of the RoleContract: + +1. Set Admin: Allows the current admin to assign a new admin address. +2. Set Parent/Child: Grants parent or child roles with appropriate permissions. +3. Retrieve Role Addresses: Methods to fetch the current admin, parent, and child addresses. +4. Role-based Access Control: Ensures only admins or parents can assign roles using access validation logic. + +This template provides a foundation for building secure systems where role management and hierarchical permissions are essential. + +- Enter this command in your `Terminal`. + +```bash title="Terminal" +cd src +``` + +#### Defining Methods and Messages + +- Rename the file name from `Protobuf/contract/hello_world_contract.proto` to `role_contract.proto` manually or by using the following command: + +```bash title="Terminal" +mv Protobuf/contract/hello_world_contract.proto Protobuf/contract/role_contract.proto +``` + +- Open the project with your IDE. + +The implementation of file `src/Protobuf/contract/role_contract.proto` is as follows: + +```csharp title="role_contract.proto" +syntax = "proto3"; + +import "aelf/core.proto"; + +import "google/protobuf/empty.proto"; +import "Protobuf/reference/acs12.proto"; +import "aelf/options.proto"; +import "google/protobuf/wrappers.proto"; + +// The namespace of this class +option csharp_namespace = "AElf.Contracts.RoleContract"; + +service RoleContract { + + // The name of the state class the smart contract is going to use to access blockchain state + option (aelf.csharp_state) = "AElf.Contracts.RoleContract.RoleContractState"; + option (aelf.base) = "Protobuf/reference/acs12.proto"; + + rpc Initialize (google.protobuf.Empty) returns (google.protobuf.Empty){ + + } + + rpc SetAdmin (aelf.Address) returns (google.protobuf.Empty) { + } + + rpc GetAdmin (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + + rpc SetParent (aelf.Address) returns (google.protobuf.Empty) { + } + + rpc GetParent (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + + rpc SetChild (aelf.Address) returns (google.protobuf.Empty) { + } + + rpc GetChild (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + +} +``` + +- `rpc` methods define the callable functions within the contract, allowing external systems to interact with the contract's logic. +- `message` represent the structured data exchanged between the contract and external systems. + +#### Define Contract States + +The implementation of the role contract's state inside file `src/RoleContractState.cs` is as follows: + +```csharp title="src/RoleContractState.cs" +using AElf.Sdk.CSharp.State; +using AElf.Types; + +namespace AElf.Contracts.RoleContract +{ + public class RoleContractState : ContractState + { + public BoolState Initialized { get; set; } + + public SingletonState
AdminAddress { get; set; } + + public SingletonState
ParentAddress { get; set; } + + public SingletonState
ChildAddress { get; set; } + + } +} +``` + +- The `State.cs` file on the aelf blockchain smart contract holds the variables that store the contract's data, making sure this data is saved and accessible whenever the contract needs it. + +#### Implement Role Smart Contract + +The implementation of the role contract inside file `src/RoleContract.cs` is as follows: + +```csharp title="src/RoleContract.cs" +using AElf.Sdk.CSharp; +using AElf.Types; +using Google.Protobuf.WellKnownTypes; + +namespace AElf.Contracts.RoleContract +{ + public class RoleContract : RoleContractContainer.RoleContractBase + { + + private const string DefaultAdmin = "ENTER_YOUR_PORTKEY_ADDRESS"; + + public override Empty Initialize(Empty input) + { + if (State.Initialized.Value) + { + return new Empty(); + } + State.Initialized.Value = true; + State.AdminAddress.Value = Context.Sender; //Can set Deployer as admin + State.AdminAddress.Value = Address.FromBase58(DefaultAdmin); // Can set YOUR_PORTKEY_ADDRESS as admin + return new Empty(); + } + + public override Empty SetAdmin(Address input) + { + AssertIsAdmin(); + + // Set the new admin address + State.AdminAddress.Value = input; + + return new Empty(); + } + + public override Empty SetParent(Address input) + { + AssertIsAdminOrParent(); + + // Set the parent address + State.ParentAddress.Value = input; + + return new Empty(); + } + + public override Empty SetChild(Address input) + { + AssertIsAdminOrParent(); + + // Set the chlid address + State.ChildAddress.Value = input; + + return new Empty(); + } + + + // Get the current admin address + public override StringValue GetAdmin(Empty input) + { + return State.AdminAddress.Value == null ? new StringValue() : new StringValue {Value = State.AdminAddress.Value.ToBase58()}; + } + + // Get the current parent address + public override StringValue GetParent(Empty input) + { + return State.ParentAddress.Value == null ? new StringValue() : new StringValue {Value = State.ParentAddress.Value.ToBase58()}; + } + + // Get the current child address + public override StringValue GetChild(Empty input) + { + return State.ChildAddress.Value == null ? new StringValue() : new StringValue {Value = State.ChildAddress.Value.ToBase58()}; + } + + + private void AssertIsAdmin() + { + Assert(Context.Sender == State.AdminAddress.Value, "Unauthorized(Not Admin) to perform the action."); + } + + private void AssertIsAdminOrParent() + { + Assert(Context.Sender == State.AdminAddress.Value || Context.Sender == State.ParentAddress.Value, "Unauthorized (Not Parent or Admin) to perform the action."); + } + + + } +} +``` + +### Building Role Smart Contract + +- Build the smart contract code with the following command inside `src` folder: + +```bash title="Terminal" +dotnet build +``` + +You should see **RoleContract.dll.patched** in the directory `RoleContract/src/bin/Debug/net.6.0` + +## Step 3 - Deploy Role Smart Contract + +import DeployRoleContract from "../\_deploy_role_contract.md" + + + +## Step 4 - Develop Allowance Smart Contract + +### Start Your Smart Contract Project + +- Open your `Terminal`. + +- Enter the following command to generate a new RoleContract project: + +```bash title="Terminal" +cd ../.. +mkdir allowance-contract +cd allowance-contract +dotnet new aelf -n AllowanceContract +``` + +### Adding Your Smart Contract Code + +Now that we have an AllowanceContract template, it can be customized to manage funds with role-based permissions. Below are its core functionalities: + +1. Set Allowance: Increases the current allowance, with permissions verified through parent and child roles fetched from the RoleContract. +2. Use Funds: Allows a child role to spend funds, reducing the current allowance. +3. Get Allowance: Retrieves the remaining allowance. +4. Role-based Permissions: Ensures only authorized roles, like parent of a child can modify or the child use the allowance. + +This contract showcases **inter-contract calls** and role-based fund management, demonstrating how multiple smart contracts work together for secure, controlled financial operations on the aelf blockchain. It helps in understanding *how the AllowanceContract calls the RoleContract* to check which sender (either of Parent, Child & Admin) is calling the methods of the AllowanceContract to put control on the access of the functions. + +- Enter this command in your `Terminal`. + +```bash title="Terminal" +cd src +``` + +#### Defining Methods and Messages + +- Rename the file name from `Protobuf/contract/hello_world_contract.proto` to `allowance_contract.proto`: + +```bash title="Terminal" +mv Protobuf/contract/hello_world_contract.proto Protobuf/contract/allowance_contract.proto +``` + +- Open the project with your IDE. + +The implementation of file `src/Protobuf/contract/allowance_contract.proto` is as follows: + +```csharp title="allowance_contract.proto" +syntax = "proto3"; + +import "aelf/core.proto"; + +import "google/protobuf/empty.proto"; +import "Protobuf/reference/acs12.proto"; +import "aelf/options.proto"; +import "google/protobuf/wrappers.proto"; + +// The namespace of this class +option csharp_namespace = "AElf.Contracts.AllowanceContract"; + +service AllowanceContract { + + // The name of the state class the smart contract is going to use to access blockchain state + option (aelf.csharp_state) = "AElf.Contracts.AllowanceContract.AllowanceContractState"; + option (aelf.base) = "Protobuf/reference/acs12.proto"; + + rpc Initialize (google.protobuf.Empty) returns (google.protobuf.Empty){ + + } + + rpc SetAllowance (google.protobuf.Int64Value) returns (google.protobuf.Empty) { + } + + rpc GetAllowance (aelf.Address) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + rpc useFunds (google.protobuf.Int64Value) returns (google.protobuf.Empty) { + } + + rpc IfInitialized (google.protobuf.Empty) returns (google.protobuf.BoolValue) { + option (aelf.is_view) = true; + } + + +} +``` + +- `rpc` methods define the callable functions within the contract, allowing external systems to interact with the contract's logic. +- `message` represent the structured data exchanged between the contract and external systems. + +#### Define Contract States + +The implementation of the allowance contract state inside file `src/AllowanceContractState.cs` is as follows: + +```csharp title="src/AllowanceContractState.cs" +using AElf.Sdk.CSharp.State; +using AElf.Types; + +namespace AElf.Contracts.AllowanceContract +{ + public partial class AllowanceContractState : ContractState + { + public BoolState Initialized { get; set; } + + public SingletonState
AdminAddress { get; set; } + + public SingletonState
ParentAddress { get; set; } + + public SingletonState
ChildAddress { get; set; } + + public Int32State CurrentAllowance { get; set; } + + } +} +``` + +- The `State.cs` file in an aelf blockchain smart contract holds the variables that store the contract's data, making sure this data is saved and accessible whenever the contract needs it. + +#### Implement Allowance Smart Contract + +The implementation of the AllowanceContract inside file `src/AllowanceContract.cs` is as follows: + +```csharp title="src/AllowanceContract.cs" +using AElf.Sdk.CSharp; +using AElf.Types; +using Google.Protobuf.WellKnownTypes; + +namespace AElf.Contracts.AllowanceContract +{ + // Contract class must inherit the base class generated from the proto file + public class AllowanceContract : AllowanceContractContainer.AllowanceContractBase + { + + private const string RoleContractAddress = "YOUR_ROLE_CONTRACT_ADDRESS"; // tDVW role contract address + + public override Empty Initialize(Empty input) + { + // Check if the contract is already initialized + Assert(State.Initialized.Value == false, "Already initialized."); + // Set the contract state + State.Initialized.Value = true; + // Set the owner address + State.AdminAddress.Value = Context.Sender; + + // Initialize the role contract + State.RoleContract.Value = Address.FromBase58(RoleContractAddress); + + return new Empty(); + } + + public override Empty SetAllowance(Int64Value input) + { + State.ParentAddress.Value = Address.FromBase58(State.RoleContract.GetParent.Call(new Empty()).Value); + + Assert(Context.Sender == State.ParentAddress.Value, "Unauthorized(Not Parent) to perform the action."); + + State.ChildAddress.Value = Address.FromBase58(State.RoleContract.GetChild.Call(new Empty()).Value); + + State.CurrentAllowance.Value = (int)(State.CurrentAllowance.Value + input.Value) ; + + return new Empty(); + } + + public override Int64Value GetAllowance(Address input) + { + + Assert(Context.Sender == State.ChildAddress.Value || Context.Sender == State.ParentAddress.Value, "Unauthorized(Not Parent or Child) to perform the action."); + + var allowance = State.CurrentAllowance.Value; + + return new Int64Value + { + Value = allowance + }; + } + + public override Empty useFunds(Int64Value input) + { + State.ChildAddress.Value = Address.FromBase58(State.RoleContract.GetChild.Call(new Empty()).Value); + + Assert(Context.Sender == State.ChildAddress.Value, "Unauthorized(Not Child) to perform the action."); + + State.CurrentAllowance.Value = (int)(State.CurrentAllowance.Value - input.Value) ; + + return new Empty(); + } + + // Function to check if the allowance contract is already initialized or not + public override BoolValue IfInitialized(Empty input) + { + return new BoolValue { Value = State.Initialized.Value }; + } + + } + +} +``` + +### Add Inter-Contract Calls +- Now, AllowanceContract needs to create a reference with the RoleContract. First, AllowanceContract will use the `role_contract.proto` file inside the **Protobuf/reference** folder. Copy the `role_contract.proto` from the role-contract/src/Protobuf/contract folder. + +```csharp title="role_contract.proto" +syntax = "proto3"; + +import "aelf/core.proto"; + +import "google/protobuf/empty.proto"; +import "Protobuf/reference/acs12.proto"; +import "aelf/options.proto"; +import "google/protobuf/wrappers.proto"; + +// The namespace of this class +option csharp_namespace = "AElf.Contracts.RoleContract"; + +service RoleContract { + + // The name of the state class the smart contract is going to use to access blockchain state + option (aelf.csharp_state) = "AElf.Contracts.RoleContract.RoleContractState"; + option (aelf.base) = "Protobuf/reference/acs12.proto"; + + rpc Initialize (google.protobuf.Empty) returns (google.protobuf.Empty){ + + } + + rpc SetAdmin (aelf.Address) returns (google.protobuf.Empty) { + } + + rpc GetAdmin (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + + rpc SetParent (aelf.Address) returns (google.protobuf.Empty) { + } + + rpc GetParent (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + + rpc SetChild (aelf.Address) returns (google.protobuf.Empty) { + } + + rpc GetChild (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + +} +``` + + - Now, create a file inside `src` folder and name it as `ContractReferences.cs` and add the following code to establish connection between AllowanceContract and the RoleContract. + +```csharp title="ContractReferences.cs" +using AElf.Contracts.RoleContract; + +namespace AElf.Contracts.AllowanceContract +{ + public partial class AllowanceContractState + { + internal RoleContractContainer.RoleContractReferenceState RoleContract { get; set; } + } +} +``` + +### Building Allowance Smart Contract + +- Build the smart contract code with the following command inside `src` folder: + +```bash title="Terminal" +dotnet build +``` + +You should see **AllowanceContract.dll.patched** in the directory `AllowanceContract/src/bin/Debug/net.6.0` + +## Step 5 - Deploy Allowance Smart Contract + +import DeployAllowanceContract from "../\_deploy_allowance_contract.md" + + + +## Step 6 - Interact with Your Deployed Smart Contract through dApp + +### Project Setup + +Let's start by cloning the frontend project repository from github. + +```bash title="Terminal" +git clone https://github.com/AElfProject/aelf-samples.git +``` + +- Next, navigate to the frontend project directory with this command: + +```bash title="Terminal" +cd aelf-samples/allowance/2-dapp +``` + +- Once you're inside the `2-dapp` directory, open the project with your preferred IDE (e.g., VSCode). You should see the project structure as shown below. + +export const tree = { +"type": "directory", +"uri": "2-dapp", +"expanded": true, +"children": [ +{ +"type": "directory", +"uri": "app" +}, +{ +"type": "directory", +"uri": "assets" +}, +{ +"type": "directory", +"uri": "public" +}, +{ +"type": "directory", +"uri": "src" +}, +{ +"type": "file", +"uri": ".gitignore" +}, +{ +"type": "file", +"uri": "components.json" +}, +{ +"type": "file", +"uri": "index.html" +}, +{ +"type": "file", +"uri": "package.json" +}, +{ +"type": "file", +"uri": "postcss.config.js" +}, +{ +"type": "file", +"uri": "README.md" +}, +{ +"type": "file", +"uri": "tailwind.config.js" +}, +{ +"type": "file", +"uri": "tsconfig.json" +}, +{ +"type": "file", +"uri": "tsconfig.node.json" +}, +{ +"type": "file", +"uri": "vite.config.ts" +} +] +} + +
+ +#### Install necessary libraries + +- Run this command in the terminal to install all necessary packages and libraries: + +```bash title="Terminal" +npm install +``` + +We are now ready to build the frontend components of our Allowance dApp. + +### Configure Portkey Provider & Write Connect Wallet Function + +Now, we'll set up our Portkey wallet provider to allow users to connect their Portkey wallets to the dApp and interact with the smart contract. We'll be interacting with the already deployed RoleContract and AllowanceContract for this tutorial. + +**Step 1: Locate the File:** + +- Go to the `src/hooks/useSmartContract.ts` file. + +**Step 2: Fetch the Smart Contract:** + +- Find the comment `//Step A - Function to fetch a smart contract based on deployed wallet address` + +- Replace the existing **`fetchContract`** function with this updated code: + +```javascript title="useSmartContract.ts" +//Step A - Function to fetch a smart contract based on deployed wallet address +const fetchContract = async (address: string) => { + if (!provider) return null; + + try { + // 1. get the dAppChain using provider.getChain + const chain = await provider?.getChain("tDVW"); + if (!chain) throw new Error("No chain"); + + // 2. return contract + return chain?.getContract(address); + } catch (error) { + console.log(error, "====error"); + return; + } +}; +``` + +- Find the comment `// Step B - fetch role-contract` + +- Replace the existing **`getRoleContract`** function with this updated code: + +```javascript title="useSmartContract.ts" +// Step B - fetch role-contract +const getRoleContract = async () => { + //Replace with Address of Deployed Role Smart Contract + const contract = await fetchContract( + "your_deployed_role_smart_contract_address" + ); + contract && setRoleContract(contract); +}; +``` + +- Find the comment `// Step C - fetch allowance-contract` + +- Replace the existing **`getAllowanceContract`** function with this updated code: + +```javascript title="useSmartContract.ts" +// Step C - fetch allowance-contract +const getAllowanceContract = async () => { + //Replace with Address of Deployed Allowance Smart Contract + const contract = await fetchContract( + "your_deployed_allowance_smart_contract_address" + ); + contract && setAllowanceContract(contract); +}; +``` + +:::tip +ℹ️ Note: You are to replace the address placeholder with your deployed Role and Allowance smart contract address from "Deploy Smart Contract" steps (Step 3 and 5)! + +example: +**"your_deployed_role_smart_contract_address"**, +**"your_deployed_allowance_smart_contract_address"** +::: + +**Explanation:** + +- **`fetchContract`** **Function**: This function fetches a smart contract based on the given chain symbol (e.g., "AELF" or "tDVW") and the contract address. + + - **Check Provider** : If no provider is available, the function returns null. + - **Fetch Chain** : The function fetches chain information using the provider. + - **Get Contract** : It retrieves the smart contract instance from the chain. + +- **`getRoleContract`** **Function**: This function fetches the *role smart contract*. +- **`getAllowanceContract`** **Function**: This function fetches the *allowance smart contract*. + +`AELF` represents the mainnet chain and `tDVW` represents the testnet chain respectively on aelf blockchain. + +**Step 3. Initialize and Fetch the Smart Contracts:** + +- Find the comment `// Step D - Effect hook to initialize and fetch the smart contract when the provider changes` + +- Replace the existing **`useEffect`** with this updated code: + +```javascript title="useSmartContract.ts" +// Step D - Effect hook to initialize and fetch the smart contract when the provider changes +useEffect(() => { + getRoleContract(); + getAllowanceContract(); +}, [provider]); // Dependency array ensures this runs when the provider changes +``` + +**Explanation:** + +- **`useEffect` Hook** : This hook initializes and fetches the smart contracts when the provider changes. + - **Check Provider** : If no provider is available, the function returns null. + - **Fetch Contracts** : It fetches and sets the smart contracts. + +By following these steps, we'll configure the Portkey provider to connect users' wallets to our dApp and interact with the Role and Allowance smart contracts including assigning specific roles and allowance related functionalities. This setup will enable our frontend components to perform actions like `Set Roles` , `Get Roles` , `Set Allowance` , `Get Allowance` and `Spend Allowed Funds`. + +### Configure Connect Wallet Function + +**Step 1: Locate the File** + +- Go to the `src/components/layout/header/index.tsx` file. + +**Step 2: Write the Connect Wallet Function** + +- The `header/index.tsx` file is the header of our allowance dApp. It allows users to connect their Portkey wallet with the allowance dApp. + +- Before users can interact with the smart contract, we need to write the `Connect Wallet` function. + +- Find the comment `// Step E - Connect Portkey Wallet`. + +- Replace the existing connect function with this code snippet: + +```javascript title="header/index.tsx" +// Step E - Connect Portkey Wallet +const connect = async (walletProvider?: IPortkeyProvider) => { + const accounts = await (walletProvider ? walletProvider : provider)?.request({ + method: MethodsBase.REQUEST_ACCOUNTS, + }); + const account = accounts?.AELF && accounts?.AELF[0]; + if (account) { + setCurrentWalletAddress(account.replace(/^ELF_/, "").replace(/_AELF$/, "")); + setIsConnected(true); + } + !walletProvider && toast.success("Successfully connected"); +}; +``` + +**Explanation:** + +- **`connect` Function** : This function connects the user's Portkey wallet with the dApp. + - **Fetch Accounts** : It fetches the wallet accounts using the provider. + - **Log Accounts** : Logs the accounts to the console for debugging. + - **Set Wallet Address** : Sets the current wallet address state variable with the fetched account. + - **Update Connection Status** : Updates the state to indicate that the wallet is connected. + - **User Notification** : Displays an alert to notify the user that their wallet is successfully connected. + +In this code, we fetch the Portkey wallet account using the provider and update the wallet address state variable. An alert notifies the user that their wallet is successfully connected. + +With the connect wallet function defined, we're ready to write the remaining functions in the next steps. + +### Configure Set Admin Role + +**Step 1: Locate the File** + +1. Go to the `src/pages/home/index.tsx` file. This file contains all the functionalities like initialize Contract, SetAdmin, GetAdmin etc. + +**Step 2: Prepare Form to set Roles** + +1. Find the comment `// Step F - Configure Role Form`. + +2. Replace the form variable with this code snippet: + +```javascript title="home/index.tsx" +// Step F - Configure Role Form +const form = useForm >{ + resolver: zodResolver(formSchema), + defaultValues: { + address: "", + }, +}; +``` + +#### Here's what the function does: + +1. Initializes a new form variable with default values needed to set roles. + +2. Field include: `address`. + +Now the form is ready for users to fill in the necessary details. + +### Initialize Contract & Set Default Admin + +- Scroll down to find the comment `// Step G - Initialize Role Contract`. + +- Replace the existing **`initializeContract`** function with this code snippet: + +```javascript title="home/index.tsx" +// Step G - Initialize Role Contract +const initializeContract = async () => { + let loadingId; + try { + // Start Loading + loadingId = toast.loading("Contract Initializing InProgress.."); + await roleContract?.callSendMethod( + "Initialize", // Function Name + currentWalletAddress as string, // User Wallet Address + {} // No Arguments + ); + // Update Loading Message with Success + toast.update(loadingId, { + render: `Contract Initialize Successful`, + type: "success", + isLoading: false, + }); + setIsContractInitialize(true); + } catch (error: any) { + // Update Loading Message with Error + toast.update(loadingId as Id, { + render: error.message, + type: "error", + isLoading: false, + }); + return "error"; + } finally { + // Remove Loading Message + removeNotification(loadingId as Id); + return; + } +}; +``` + +### Set Admin Role + +- Write the function to **`Set Users Role`** + +- Find the comment `// Step H - Set Differentt Users Role`. + +- Replace the existing **`setAuthority`** function with this code snippet: + +```javascript title="home/index.tsx" +// Step H - Set Differentt Users Role +const setAuthority = async (values: { address: string }, type: string) => { + let loadingId; + try { + // Start Loading + loadingId = toast.loading("Set Authority InProgress.."); + setFormLoading(true); + + // Prepare Arguments for set Admin + const sendData = values.address; + + // Call the appropriate smart contract method based on the type (Admin, Parent, or Child) + await roleContract?.callSendMethod( + type === ROLE.admin + ? "SetAdmin" + : type === ROLE.parent + ? "SetParent" + : "SetChild", + currentWalletAddress as string, + sendData // Pass the address as the argument + ); + + // Update Loading Message with Success + toast.update(loadingId, { + render: `Set ${type} Successful`, + type: "success", + isLoading: false, + }); + + // Fetch and update the role data from the contract after successful execution + getAuthorityData(); + return "success"; + } catch (error: any) { + // Update Loading Message with Error + toast.update(loadingId as Id, { + render: error.message, + type: "error", + isLoading: false, + }); + return "error"; + } finally { + // Close Form Modal + handleCloseModal(); + + // Remove Loading Message + removeNotification(loadingId as Id); + setFormLoading(false); + } +}; +``` + +#### What This Function Does: + +1. **Calls Smart Contract Method** : It interacts with the blockchain smart contract to set admin, parent and child using their respective wallet address. + +Next, we'll **Handle the submit form to set the roles** function. + +### Submit Set Admin Role + +Write the function to handle the submit form to set the users' role. + +- Scroll down to find the comment `// Step I - Handle Submit Form`. + +- Replace the existing **`onSubmit`** function with this code snippet: + +```javascript title="home/index.tsx" +// Step I - Handle Submit Form +const onSubmit = async (values: { address: string }) => { + // Set form loading state + setFormLoading(true); + // Check if the contract is initialized, if not, initialize it + if (!isContractInitialize) { + await initializeContract(); // Initialize the smart contract if not already done + } + // Call the setAuthority function to set the authority (Admin/Parent/Child) based on the roleType + await setAuthority(values, roleType); // Pass the form values and role type (Admin/Parent/Child) +}; +``` + +Next, we'll write the **Get Role Details** function. + +### Get Role Details + +- Write the function to **`Get Roles Details`** + +- Find the comment `// Step J - Get Role Details`. + +- Replace the existing **`getAuthorityData`** function with this code snippet: + +```javascript title="home/index.tsx" +// Step J - Get Role Details +const getAuthorityData = async () => { + setLoading(true); + try { + // Fetch admin, parent, and child roles simultaneously using Promise.all + const [admin, parent, child] = await Promise.all([ + roleContract?.callViewMethod("GetAdmin", ""), + roleContract?.callViewMethod("GetParent", ""), + roleContract?.callViewMethod("GetChild", ""), + ]); + + // If all roles are successfully fetched + if (admin && parent && child) { + // Set the role state with the retrieved admin, parent, and child values + setRole({ + Admin: admin?.data?.value, + Parent: parent?.data?.value, + Child: child?.data?.value, + }); + } + } catch (error) { + // Log any error that occurs during the process + console.log("error======", error); + } finally { + // Stop the loading indicator, whether or not the request was successful + setLoading(false); + } +}; +``` + +#### What This Function Does: + +1. **Calls Smart Contract Methods** : It interacts with the blockchain smart contract to get the addressess of the admin, parent and child roles respectively. Once the wallet addresses based on the roles are present, FE will display different components for each user role, like Admin, Parent, and Child. Each role has specific actions they can perform: + +- **Admin Role** : The *admin* can assign roles to both parent and child. +- **Parent Role** : The *parent* can assign the child role and set an allowance for the child. +- **Child Role** : The *child* can spend money, but only up to the allowance set by the parent. + +Now that we've finished integrating the functionality of the RoleContract, let's move on to the functions of the AllowanceContract. + +### Configure Set Allowance by Parent + +**Step 1: Locate the File** + +- Go to the `src/components/parent/index.tsx` file. This file contains functionalities like initialize contract, set allowance and get allowance. + +**Step 2: Configure form** + +Write the Function of configure the set allowance form. + +- Find the comment `// Step K - Configure Set Allowance Form`. + +- Replace the existing code snippet: + +```javascript title="parent/index.tsx" +// Step K - Configure Set Allowance Form +const form = useForm >{ + resolver: zodResolver(formSchema), + defaultValues: { + amount: "", + }, +}; +``` + +### Check Contract Initialize Status + +Write the Function to check contract initialization status of the **AllowanceContract**. + +- Scroll down to find the comment `// step L - Check if Allowance Contract is initialized or not`. + +- Replace the existing **`checkIsContractInitialized`** function with this code snippet: + +```javascript title="parent/index.tsx" +// step L - Check if Allowance Contract is initialized or not +const checkIsContractInitialized = async () => { + try { + const result = await allowanceContract?.callViewMethod("IfInitialized", ""); // Call the IfInitialized method which is present on Smart Contract + if (result?.data) { + setIsContractInitialize(true); + } + } catch (error) { + console.log("error", error); + } +}; +``` + +#### What This Function Does: + +1. **Calls Smart Contract Methods** : It interacts with the allowance contract to get the initialization status of the allowance contract. + +### Initialize Allowance Contract + +Write the function to initialize the **AllowanceContract**. + +- Scroll down to find the comment `// Step M - Initialize Allowance Contract`. + +- Replace the existing **`initializeContract`** function with this code snippet: + +```javascript title="parent/index.tsx" +// Step M - Initialize Allowance Contract +const initializeContract = async () => { + let loadingId; + try { + // Start Loading + loadingId = toast.loading("Contract Initializing InProgress.."); + await allowanceContract?.callSendMethod( + "Initialize", // Function Name + currentWalletAddress as string, // User Wallet Address + {} // No Arguments + ); + + // Update Loading Message with Success + toast.update(loadingId, { + render: `Contract Initialize Successful`, + type: "success", + isLoading: false, + }); + setIsContractInitialize(true); + } catch (error: any) { + // Update Loading Message with Error + toast.update(loadingId as Id, { + render: error.message, + type: "error", + isLoading: false, + }); + return "error"; + } finally { + // Remove Loading Message + removeNotification(loadingId as Id); + return; + } +}; +``` + +#### What This Function Does: + +1. **Calls Smart Contract Methods** : It call the Initialize of the allowance contract. + +Now that we've finished the initialize contract functionality. Let's move on to the *set allowance* functionality. + +### Set Allowance + +Write the function for set the allowance value for child by the parent. + +- Scroll down to find the comment `// step N - Set AllowanceValue`. + +- Replace the existing **`initializeContract`** function with this code snippet: + +```javascript title="parent/index.tsx" +// step N - Set AllowanceValue +const setAllowance = async (value: { amount: string }) => { + setFormLoading(true); + let loadingId; + try { + // Start Loading + loadingId = toast.loading("SetAllowance InProgress.."); + await allowanceContract?.callSendMethod( + "SetAllowance", // Function Name + currentWalletAddress as string, // User Wallet Address + { value: value.amount } // Allowance Amount + ); + + // fetch updated allowance value + getAllowance(); + + // Update Loading Message with Success + toast.update(loadingId, { + render: `SetAllowance Successful`, + type: "success", + isLoading: false, + }); + } catch (error: any) { + console.error(error); + // Update Loading Message with Error + toast.update(loadingId as Id, { + render: error.message, + type: "error", + isLoading: false, + }); + return "error"; + } finally { + // Close Form Modal + handleCloseModal(); + // Remove Loading Message + removeNotification(loadingId as Id); + setFormLoading(false); + } +}; +``` + +#### What This Function Does: + +1. **Calls Smart Contract Methods** : It call the initialization method of the allowance contract. + +Let's handle the submit form for set allowance. + +### Submit Set Allowance Form (Parent) + +Write the function to handle the set allowance form. + +- Scroll down to find the comment `// Step O - Handle Set Allowance Submit Form`. + +- Replace the existing **`onSubmit`** function with this code snippet: + +```javascript title="parent/index.tsx" +// Step O - Handle Set Allowance Submit Form +const onSubmit = async (value: { amount: string }) => { + if (!isContractInitialize) { + await initializeContract(); + } + setAllowance(value); +}; +``` + +As we have completed the step of setting allowance value, now it's time to get that allowance value form the contract. + +### Get Allowance Value + +Write the function for get the allowance value. + +- Scroll down to find the comment `// step P - Get AllowanceValue`. + +- Replace the existing **`getAllowance`** function with this code snippet: + +```javascript title="parent/index.tsx" +// step P - Get AllowanceValue +const getAllowance = async () => { + try { + // Call the smart contract method "GetAllowance" for the child role + const result = await allowanceContract?.callViewMethod( + "GetAllowance", + role.Child + ); + + // If the result contains a valid allowance value, set it in the state + if (result?.data?.value) { + setAllowanceValue(result?.data?.value); + } else { + // If no valid allowance is returned, set the allowance value to null + setAllowanceValue(null); + } + } catch (error) { + // Log any errors that occur during the process + console.log("error", error); + } +}; +``` + +At this point, we have completed all the functionalities for the parent role and now it's time to prepare functionalities for the child role. + +### Configure Spend Allowance Form + +**Step 1: Locate the File** + +1. Go to the `src/components/child/index.tsx` file. This file contains functionalities like spend allowance and get allowance value. + +**Step 2: Prepare Form for Spend Allowance** + +1. Find the comment `// Step Q - Configure Spend Allowance Form`. + +2. Replace the form variable with this code snippet: + +```javascript title="child/index.tsx" +// Step Q - Configure Spend Allowance Form +const form =useForm >{ + resolver: zodResolver(formSchema), + defaultValues: { + amount: "0", + }, +}; +``` + +### Ge Allowance Value (Child) + +Write the function for get the allowance value. + +- Scroll down to find the comment `// step R - Get AllowanceValue`. + +- Replace the existing **`getAllowance`** function with this code snippet: + +```javascript title="child/index.tsx" +// step R - Get AllowanceValue +const getAllowance = async () => { + try { + // Call the smart contract method "GetAllowance" for the child role + const result = await allowanceContract?.callViewMethod( + "GetAllowance", + currentWalletAddress + ); + + // If the result contains a valid allowance value, set it in the state + if (result?.data?.value) { + setAllowanceValue(result?.data?.value); + } + } catch (error) { + // Log any errors that occur during the process + console.log("error", error); + } +}; +``` + +### Spend Funds + +Write the function to spend the funds by the child. + +- Scroll down to find the comment `// step S - Spend Allowance`. + +- Replace the existing **`spendFunds`** function with this code snippet: + +```javascript title="child/index.tsx" +// step S - Spend Funds +const spendFunds = async (value: { amount: string }) => { + if(value.amount === "0"){ + return + } + + let loadingId; + try { + if (Number(allowanceValue) < Number(value.amount)) { + toast.info("Amount should be less then or equal to Allowance value"); + return; + } + + setFormLoading(true); + + // Start Loading + loadingId = toast.loading("Spending Funds InProgress.."); + await allowanceContract?.callSendMethod( + "useFunds", // Function Name + currentWalletAddress as string, // User Wallet Address + { value: value.amount } // Allowance Amount + ); + + form.reset(); + getAllowance(); + + // Update Loading Message with Success + toast.update(loadingId, { + render: `Funds Spent Successful`, + type: "success", + isLoading: false, + }); + } catch (error: any) { + console.error(error); + // Update Loading Message with Error + toast.update(loadingId as Id, { + render: error.message, + type: "error", + isLoading: false, + }); + return "error"; + } finally { + // Remove Loading Message + removeNotification(loadingId as Id); + setFormLoading(false); + } +}; +``` + +#### What This Function Does: + +1. **Calls Smart Contract Methods** : It calls the useFunds smart contract method to spend the allowance value. + +Let's handle the submit form to spend allowance. + +### Submit Spend Funds Form (Child) + +Write the function for handle the spend Funds form. + +- Scroll down to find the comment `// Step T - Handle Spend Funds Submit Form`. + +- Replace the existing **`onSubmit`** function with this code snippet: + +```javascript title="child/index.tsx" +// Step T - Handle Spend Funds Submit Form +const onSubmit = (values: { amount: string }) => { + spendFunds(values); +}; +``` + +Now that we've written all the necessary frontend functions and components, we're ready to run the Allowance dApp application in the next step. + +### Run Application + +In this step, we will run the Allowance dApp application. + +- To begin, run the following command on your terminal. + +```bash title="Terminal" +npm run dev +``` + +:::info + +**Note**: Ensure that you are running this command under the **allowance/2-dapp** folder. + +::: + +- You should observe the following as shown below. + + ![run-app-success](/img/vote-npm-run-console.png) + +- Upon clicking on the **localhost URL**, you should be directed to the Allowance dApp landing page as shown below. + +:::tip +If you are developing and testing this with github codespace, you can use port forward to test the web server that is running in codespace, here is the link on how to use port forward for codespace https://docs.github.com/en/codespaces/developing-in-a-codespace/forwarding-ports-in-your-codespace +::: + +- Usually codespace will automatically forward port, you should see a pop-up message at the bottom right of your codespace browser window as shown in the diagram below: + + ![open-in-browser](/img/codespace-forwarded-port.png) + +- Click the link to open the Allowance dApp in the browser. + + ![allowance-home-page](/img/allowance-home-page.png) + +#### Create Portkey Wallet + +:::info +Portkey is the first AA wallet from aelf's ecosystem, migrating users, developers and projects from Web2 to Web3 with DID solution. + +Users can swiftly log into Portkey via their Web2 social info with no private keys or mnemonics required. Underpinned by social recovery and decentralized guardian design, Portkey safeguards users' assets from centralized control and theft. Portkey has a unique payment delegation mechanism which enables interested parties to function as delegatees to pay for user activities on users' behalf. This means that users can create accounts for free and fees for other usages may also be covered in Portkey. + +Portkey also provides crypto on/off-ramp services, allowing users to exchange fiat with crypto freely. It supports the storage and management of various digital assets such as tokens, NFTs, etc. The compatibility with multi-chains and seamless connection to all kinds of DApps makes Portkey a great way to enter the world of Web3. + +With DID solution as its core, Portkey provides both Portkey Wallet and Portkey SDKs. + +For more information, you may visit the official documentation for Portkey at https://doc.portkey.finance/. +::: + +- Download the Chrome extension for Portkey from https://chromewebstore.google.com/detail/portkey-wallet/iglbgmakmggfkoidiagnhknlndljlolb. + +:::info +The Portkey extension supports Chrome browser only (for now). Please ensure that you are using Chrome browser. +You may download Chrome from https://www.google.com/intl/en_sg/chrome/. +::: + +- Once you have downloaded the extension, you should see the following on your browser as shown below. + + ![welcome-to-portkey](/img/welcome-to-portkey.png) + +- Click on `Get Start` and you should see the following interface as shown below. + + ![portkey-login](/img/portkey-login.png) + +**Sign up** + +- Switch to **aelf Testnet** network by selecting it: + + ![portkey-switch-to-testnet](/img/portkey-switch-to-testnet.png) + +:::danger +Please make sure you are using `aelf Testnet` in order to be able to receive your testnet tokens from the Faucet. +::: + +- Proceed to sign up with a Google Account or your preferred login method and complete the necessary accounts creation prompts and you should observe the following interface once you have signed up. + + ![success-login](/img/success-login.png) + +With that, you have successfully created your very first Portkey wallet within seconds. How easy was that? + +:::info +It is highly recommended to pin the Portkey wallet extension for easier access and navigation to your Portkey wallet! +::: + +- Next, click on ‘Open Portkey’ and you should now observe the following as shown below. + + ![portkey-wallet-preview](/img/portkey-wallet-preview.png) + +**Connect Portkey Wallet** + +- Click on **"Connect Wallet"** to connect your Portkey wallet. + + ![connect-wallet](/img/allowance-connect-wallet.png) + +- The button will change to **"Your Wallet Address"** when the connection is successful. + + ![collect-wallet-success](/img/allowance-wallet-connect-success.png) +Now we have successfully connected our portkey wallet with Allowance dApp so let's move into set Roles functionality throgh Admin wallet. +--- + +**Set Roles** + +- Click on **"Set Admin"** button to assign the admin role. + + ![step-1-allowance](/img/step-1-allowance.png) + +- A pop-up form will appear to set the admin role. Please enter the wallet address you want to assign as admin address. You can then use this wallet to perform other admin functions. + + ![step-2-allowance](/img/step-2-allowance.png) + +- Click on the **Set Admin** button. + +- You will now receive two transaction requests in your Portkey wallet to **sign**. The first request is to initialize the role contract, and the second is to set the admin role. + +- Click on **Sign** for both the transaction. + + ![step-3-allowance](/img/step-3-allowance.png) + ![step-4-allowance](/img/step-4-allowance.png) + +- After the transaction is successfully processed, you will be able to see the wallet address of the **Admin role**. + + ![step-5-allowance](/img/step-5-allowance.png) + +- As Admin role has been assigned, Please follow same steps to assign the **Parent** and **Child** roles. + + ![step-6-allowance](/img/step-6-allowance.png) + +- After assigning the Parent and Child roles, you will be able to see the wallet addresses for each of the roles. + + ![step-7-allowance](/img/step-7-allowance.png) + +We have now assigned the role using the role contract, and as an Admin, you can update all the roles. Next, we need to work with the allowance contract. To access the parent front end components, connect the *Parent* address portkey wallet, and you will automatically switch to the Parent role. + +--- + +**Set Allowance (Parent)** + +As a Parent, you can manage child role functions, such as set a child address, edit the child's address, and set an allowance for the child. + + ![step-8-allowance](/img/step-8-allowance.png) + +- Click on **Set Allowance** button to set the allowance for child. + + ![step-9-allowance](/img/step-9-allowance.png) + +- A pop-up form will appear to set the allowance. Please enter the amount you want to set as an allowance and click on the **Set Allowance** button. + + ![step-10-allowance](/img/step-10-allowance.png) + +- You will now receive two transaction requests in your Portkey wallet to **sign** . The first request is to initialize the allowance contract, and the second is to set the allowance. + +- Click on **Sign** for both the transaction. + + ![step-11-allowance](/img/step-11-allowance.png) + ![step-12-allowance](/img/step-12-allowance.png) + +- After the transaction is successfully processed, allowance value will be appear as shown below. + + ![step-13-allowance](/img/step-13-allowance.png) + +As we hav completed **Set Allowance** functionality successfully. Let's move to the other functionalities for the child role. To access the child role's front end components, connect the assigned child's Portkey wallet, and you will automatically switch to the child role. + +--- + +**Spend Funds** + +As a Child, the allowance amount will be visible and the child can spend funds within the assigned allowance limit. + + ![step-14-allowance](/img/step-14-allowance.png) + +- Enter the amount you want to spend and click on the **Spend** button. + + ![step-15-allowance](/img/step-15-allowance.png) + +- Now, You will receive a transaction request on your portkey wallet to **Sign** the transaction. + + ![step-16-allowance](/img/step-16-allowance.png) + +- Click on **Sign** the transaction. + +- After the transaction is successfully processed, your allowance value will be updated. + + ![step-17-allowance](/img/step-17-allowance.png) + +:::success +🎉 Congratulations Learners! You have successfully built your Allowance dApp. +::: + +## 🎯 Conclusion + +🎉 Congratulations on completing the **Allowance dApp** tutorial! 🎉 You’ve taken significant steps in setting up your development environment, building and deploying two smart contracts, and creating a fully functional Allowance dApp on the aelf blockchain. 🌟 + +**📚 What You've Learned** + +Throughout this tutorial, you've mastered: + +- **🛠️ Setting Up Your Development Environment:** You prepared your workspace by installing and configuring all the necessary tools to kickstart your smart contract project. + +- **💻 Developing the Role Smart Contract:** You created a Role contract that defines roles and permissions, including Admin, Parent, and Child roles, which allow users to interact according to assigned roles. + +- **💻 Developing the Allowance Smart Contract:** You built the Allowance contract to enable Parents to set spending limits for Children, creating the foundation of a decentralized allowance management system. + +- **🚀 Deploying Both Smart Contracts:** You deployed both contracts to the aelf blockchain, enabling your dApp to use the features in a live environment. + +- **🔧 Interacting with Your Deployed Smart Contract:** You connected the dApp frontend to the blockchain, integrated Portkey for wallet connectivity, and set up functions for managing roles and allowances directly through the dApp interface. + +**🔍 Final Output** + +By now, you should have: + +- 📜 **Two deployed smart contracts** — one for managing user roles (Admin, Parent, and Child) and another for setting and managing allowances within the dApp. + +- 💻 **A fully functional Allowance dApp** — allowing users to assign roles, set allowances, and spend funds within set limits, all through a secure and intuitive interface. + +**➡️ What's Next?** + +With the foundation in place, consider exploring advanced topics: + +- **📈 Enhancing Smart Contract Logic:** Add new features, such as notifications for spending limits, allowance resets, or reports on spending habits. + +- **🔒 Improving Security:** Ensure your dApp and smart contract are secure by implementing best practices and security measures. + +- **🌍 Exploring Cross-Chain Features:** Expand your dApp’s reach by exploring aelf’s cross-chain interoperability, enabling interactions with other blockchain networks + +You’ve now acquired the tools to take your Allowance dApp to the next level! Keep building, innovating, and exploring with aelf. 🚀 + +Happy coding and growing your **Allowance dApp! 😊** diff --git a/docs/quick-start/developers/dao-dapp/index.md b/docs/quick-start/developers/dao-dapp/index.md index 3d3e3902..3070c2f7 100644 --- a/docs/quick-start/developers/dao-dapp/index.md +++ b/docs/quick-start/developers/dao-dapp/index.md @@ -339,7 +339,7 @@ namespace AElf.Contracts.BuildersDAO ``` :::danger -Aelf sidechain does not allow duplicate identical smart contracts. Hence, we will be using the author variable as the unique identifier for our voting smart contract in order to deploy the smart contract successfully. +Aelf dAppChain does not allow duplicate identical smart contracts. Hence, we will be using the author variable as the unique identifier for our voting smart contract in order to deploy the smart contract successfully. ::: #### Implementing Initialize Function @@ -552,7 +552,7 @@ public override BoolValue GetMemberExist(Address input) With that, we have implemented all the functionalities of our Voting dApp smart contract. -In the next step, we will compile our smart contract and deploy our written smart contract to the aelf sidechain. +In the next step, we will compile our smart contract and deploy our written smart contract to the aelf dAppChain. diff --git a/docs/quick-start/node-operators/apply-to-be-a-bp/index.md b/docs/quick-start/node-operators/apply-to-be-a-bp/index.md index 0060fc08..5ef637cb 100644 --- a/docs/quick-start/node-operators/apply-to-be-a-bp/index.md +++ b/docs/quick-start/node-operators/apply-to-be-a-bp/index.md @@ -28,7 +28,7 @@ description: Participate in BP election aelf doesn't have light nodes, so all nodes are full nodes. [Click here](/quick-start/node-operators/set-up-a-node-on-mainnet/) to learn how to set up a full node. -**Note:** To become a BP, you need to run individual nodes for both MainChain aelf and all the SideChains. +**Note:** To become a BP, you need to run individual nodes for both aelf MainChain and all the dAppChains. ### Participate in BP Election diff --git a/docs/quick-start/node-operators/set-up-a-node-on-mainnet/index.md b/docs/quick-start/node-operators/set-up-a-node-on-mainnet/index.md index ff76d4da..8ab4e616 100644 --- a/docs/quick-start/node-operators/set-up-a-node-on-mainnet/index.md +++ b/docs/quick-start/node-operators/set-up-a-node-on-mainnet/index.md @@ -30,7 +30,7 @@ There are two ways to run an aelf node: using Docker (recommended) or running bi **Note:** * For non-block producing nodes, there is no requirement on the number of nodes. -* To become a BP, run individual nodes for both MainChain aelf and all SideChains. +* To become a BP, run individual nodes for both aelf MainChain and all dAppChains. **Time Syncing:** Ensure your server is time-synced via NTP to avoid syncing issues. diff --git a/docs/quick-start/node-operators/set-up-a-node-on-testnet/index.md b/docs/quick-start/node-operators/set-up-a-node-on-testnet/index.md index 7c722efa..b825304f 100644 --- a/docs/quick-start/node-operators/set-up-a-node-on-testnet/index.md +++ b/docs/quick-start/node-operators/set-up-a-node-on-testnet/index.md @@ -26,7 +26,7 @@ Before starting, install the necessary tools and frameworks. Detailed instructio * c5.xlarge or N2 instance: 4 vCPU, 8GiB RAM, 800GiB storage, 100 Mbps internet bandwidth -**Note:** For testing or dApp deployment, run a SideChain node only. Use the same configuration for multiple nodes on both MainChain and SideChain. +**Note:** For testing or dApp deployment, run a dAppChain node only. Use the same configuration for multiple nodes on both MainChain and dAppChain. **Time Syncing:** Ensure your server is time-synced via NTP to avoid syncing issues. @@ -189,7 +189,7 @@ aelf-command get-blk-height -e http://your-node-ip:port ### Note -Each side chain has its own P2P network, add the mainnet sidechain nodes as peer: +Each side chain has its own P2P network, add the mainnet dAppChain nodes as peer: ```` ```sh diff --git a/docs/resources/whitepaper-2/ai-integration-points-in-the-aelf-ecosystem/operational-excellence/index.md b/docs/resources/whitepaper-2/ai-integration-points-in-the-aelf-ecosystem/operational-excellence/index.md index 8fce96ae..90935f82 100644 --- a/docs/resources/whitepaper-2/ai-integration-points-in-the-aelf-ecosystem/operational-excellence/index.md +++ b/docs/resources/whitepaper-2/ai-integration-points-in-the-aelf-ecosystem/operational-excellence/index.md @@ -106,7 +106,7 @@ Intelligent load balancing, powered by AI and machine learning, offers substanti ## iv) AI-Facilitated Cross-Chain Interoperability for aelf -Incorporating AI into aelf's cross-chain interoperability framework can significantly enhance the efficiency and security of data transfer and validation processes. By leveraging AI-driven optimisations, aelf can ensure seamless communication and robust performance within itself between MainChain and SideChains, and more importantly with various other blockchain networks. +Incorporating AI into aelf's cross-chain interoperability framework can significantly enhance the efficiency and security of data transfer and validation processes. By leveraging AI-driven optimisations, aelf can ensure seamless communication and robust performance within itself between MainChain and dAppChains, and more importantly with various other blockchain networks. ### Optimising Data Transfer diff --git a/docs/resources/whitepaper-2/background-on-aelf/index.md b/docs/resources/whitepaper-2/background-on-aelf/index.md index 9fdab792..7bd7ea0c 100644 --- a/docs/resources/whitepaper-2/background-on-aelf/index.md +++ b/docs/resources/whitepaper-2/background-on-aelf/index.md @@ -11,13 +11,13 @@ The story of aelf began on 10 December 2017, when aelf's vision and plans were i aelf is primarily a multi-chain parallel computing blockchain framework which was created to address several of the limitations of traditional blockchain systems, such as performance bottlenecks and data complexity. aelf's vision is to be a "Linux Ecosystem" equivalent for a blockchain that incorporates state of the art IT design principles, which in particular allows developers to customise Chains to meet their own needs. At its core, aelf contains the following main features: -1. MainChain and multi-layer SideChains to handle various user driven scenarios. One chain is designed for one use case, distributing different tasks on multiple chains, which improves processing efficiency. +1. MainChain and multi-layer dAppChains to handle various user driven scenarios. One chain is designed for one use case, distributing different tasks on multiple chains, which improves processing efficiency. 2. Communication with external blockchain networks, such as Bitcoin and Ethereum, via cross chain messaging protocols. 3. Parallel processing for non-competing transactions in a cloud-based environment. 4. Basic components for a minimum viable Block and Genesis Smart Contract Collection for each Chain, which reduces data complexity and allows for high customisation at the same time. -5. Permission for stakeholders to approve amendments to the protocol, including redefining the Consensus Protocol; Permission for SideChains to join or exit from MainChain dynamically based on the Consensus Protocol. +5. Permission for stakeholders to approve amendments to the protocol, including redefining the Consensus Protocol; Permission for dAppChains to join or exit from MainChain dynamically based on the Consensus Protocol. -aelf's primary strength lies in its architecture, which utilises a multi-layered structure comprising a MainChain and multiple SideChains. This differs from a traditional Single Chain system in that aelf is a "Branched Ecosystem", where the MainChain works as the backbone of the system and connects to multiple SideChains. Compared with the traditional "one Chain to any type of Contract", aelf's "One Chain to one type of Contract" design allows aelf to distribute tasks efficiently and process transactions in parallel, significantly enhancing scalability and reducing congestion. At the same time, the SideChains are easier to manage and can be tailored for specific applications, enabling aelf to support a wide range of use cases without compromising performance. +aelf's primary strength lies in its architecture, which utilises a multi-layered structure comprising a MainChain and multiple dAppChains. This differs from a traditional Single Chain system in that aelf is a "Branched Ecosystem", where the MainChain works as the backbone of the system and connects to multiple dAppChains. Compared with the traditional "one Chain to any type of Contract", aelf's "One Chain to one type of Contract" design allows aelf to distribute tasks efficiently and process transactions in parallel, significantly enhancing scalability and reducing congestion. At the same time, the dAppChains are easier to manage and can be tailored for specific applications, enabling aelf to support a wide range of use cases without compromising performance. For aelf's consensus mechanism, it utilises the Delegated Proof of Stake (DPoS) to manage overall network efficiency. DPoS is known for its speed and energy efficiency compared to other consensus mechanisms like Proof of Work (PoW). By allowing token holders to vote for delegates who validate transactions and maintain the network, aelf ensures a high level of security and decentralisation while keeping transaction times low. Additionally, aelf's dynamic indexing and comprehensive token system offer robust support for various applications, from digital asset management to DeFi platforms, making it a versatile and powerful blockchain solution for all types of developers. diff --git a/docs/resources/whitepaper-2/executive-summary/index.md b/docs/resources/whitepaper-2/executive-summary/index.md index ec68b10c..d508c2a3 100644 --- a/docs/resources/whitepaper-2/executive-summary/index.md +++ b/docs/resources/whitepaper-2/executive-summary/index.md @@ -7,12 +7,12 @@ description: "" Download our latest Whitepaper v2.0 [here](pathname:///pdf/aelf_whitepaper_v2.0.pdf). -[aelf](https://aelf.com/) is a cutting-edge multi-chain blockchain framework launched in December 2017, utilising the powerful C# programming language. Its multi-layered structure, featuring MainChain and SideChains, effectively tackles the challenges of traditional blockchain systems, such as performance bottlenecks and data complexity. This architecture improves scalability and reduces congestion by distributing tasks across multiple chains. With an emphasis on developer customisation and parallel processing, aelf's framework is versatile, supporting a wide range of applications from digital asset management to DeFi. For aelf's original technical architecture, please refer to our original Whitepaper v1.0 [here](/resources/whitepaper/). +[aelf](https://aelf.com/) is a cutting-edge multi-chain blockchain framework launched in December 2017, utilising the powerful C# programming language. Its multi-layered structure, featuring MainChain and dAppChains, effectively tackles the challenges of traditional blockchain systems, such as performance bottlenecks and data complexity. This architecture improves scalability and reduces congestion by distributing tasks across multiple chains. With an emphasis on developer customisation and parallel processing, aelf's framework is versatile, supporting a wide range of applications from digital asset management to DeFi. For aelf's original technical architecture, please refer to our original Whitepaper v1.0 [here](/resources/whitepaper/). In aelf's Whitepaper 2.0, the mission is to leverage artificial intelligence (AI) to enhance its operational efficiency. AI-driven machine learning models optimise smart contract execution and gas usage, predict network congestion, and dynamically adjust resources to ensure high performance. Additionally, AI enables intelligent load balancing and predictive scaling, ensuring efficient traffic distribution and resource utilisation throughout the network. For aelf's AI Oracle, it's aim is to implement a credible Web3 AI framework that enhances on-chain smart contracts with AI features, promoting the creation of AI-centric decentralized applications(AI-dApps). For developers, aelf provides an AI-enhanced environment that simplifies smart contract creation with Natural Language Processing (NLP) and offers real-time support through AI-powered chatbots. These tools make blockchain technology more accessible to non-technical users and streamline the development process for experienced developers. In aelf's AI-based smart contract auditing, smart contract code is input into aelf's pre-trained model to analyse syntax and logical structure, identifying security vulnerabilities and errors, and generating a detailed audit report with remediation suggestions for aelf developers before deploying their smart contracts on the aelf chain. By incorporating AI, aelf not only improves the user experience but also expands its user base, fostering adoption and innovation in the blockchain space. -Beyond AI, aelf will be introducing a new modular Layer 2 chain utilising ZK Rollup technology that would significantly enhance aelf's performance, scalability, and EVM compatibility. This approach will reduce Layer 1 gas storage costs, lower transaction costs for users, and ultimately improves privacy and the user experience. +Beyond AI, aelf will be introducing a new modular blockchain technology that would significantly enhance aelf's performance, scalability, and EVM compatibility. This approach will reduce gas storage costs, lower transaction costs for users, and ultimately improves privacy and the user experience. -Ultimately, aelf is a versatile multi-chain blockchain framework that enhances efficiency and scalability through a multi-layered architecture, AI integration, and modular Layer 2 ZK Rollup technology, making it highly efficient, secure, and developer-friendly. +Ultimately, aelf is a versatile multi-chain blockchain framework that enhances efficiency and scalability through a multi-layered architecture, AI integration, and modular structure, making it highly efficient, secure, and developer-friendly. diff --git a/docs/resources/whitepaper-2/index.md b/docs/resources/whitepaper-2/index.md index 69b6b33a..eb8ec56b 100644 --- a/docs/resources/whitepaper-2/index.md +++ b/docs/resources/whitepaper-2/index.md @@ -21,6 +21,6 @@ description: aelf's updated Whitepaper v2.0 featuring AI + Blockchain - [Enabling Non-Technical Users to Create Smart Contracts with NLP on aelf](./ai-integration-points-in-the-aelf-ecosystem/developer-and-user-experience/#i-enabling-non-technical-users-to-create-smart-contracts-with-nlp-on-aelf) - [AI based Smart Contract Audit for Developers on aelf](./ai-integration-points-in-the-aelf-ecosystem/developer-and-user-experience/#ii-ai-based-smart-contract-audit-for-developers-on-aelf) - [Enhancing User and Developer Experience with AI-Powered Chatbots on aelf](./ai-integration-points-in-the-aelf-ecosystem/developer-and-user-experience/#iii-enhancing-user-and-developer-experience-with-ai-powered-chatbots-on-aelf) -- [Beyond AI - A Modular + ZK Rollup Blockchain](./modular-blockchain/) +- [Beyond AI - A Modular Blockchain](./modular-blockchain/) - [Roadmap](./roadmap/) - [References and further readings](./references-and-further-readings/) \ No newline at end of file diff --git a/docs/resources/whitepaper-2/modular-blockchain/index.md b/docs/resources/whitepaper-2/modular-blockchain/index.md index bf9c91fe..f21777d8 100644 --- a/docs/resources/whitepaper-2/modular-blockchain/index.md +++ b/docs/resources/whitepaper-2/modular-blockchain/index.md @@ -1,6 +1,6 @@ --- sidebar_position: 9 -title: Beyond AI - A Modular + ZK Rollup Blockchain +title: An AI-enhanced Layer 1 blockchain description: "" --- # aelf as a modular blockchain @@ -21,11 +21,11 @@ By separating these tasks, a modular blockchain enables independent optimisation ## The present status of aelf -As elaborated before, aelf operates on a mainchain-sidechain architecture. Its sidechains resemble the consumer chains of Cosmos or the parachains of Polkadot. Similar to these platforms, aelf decouples functionality at the code level — a modular or deconstructed approach rooted in software engineering principles. The primary objectives of this architecture are to facilitate the development of modular plugins within the aelf ecosystem and to enable the loading of various modules in a pluggable manner, thereby enhancing aelf's scalability and flexibility. For instance, the consensus functionality can be treated as a pluggable/replaceable code package, making it convenient for developers to customise. +As elaborated before, aelf operates on a mainchain-dAppChain architecture. Its dAppChains resemble the consumer chains of Cosmos or the parachains of Polkadot. Similar to these platforms, aelf decouples functionality at the code level — a modular or deconstructed approach rooted in software engineering principles. The primary objectives of this architecture are to facilitate the development of modular plugins within the aelf ecosystem and to enable the loading of various modules in a pluggable manner, thereby enhancing aelf's scalability and flexibility. For instance, the consensus functionality can be treated as a pluggable/replaceable code package, making it convenient for developers to customise. -Notwithstanding the aforementioned points, the current mainchain-sidechain architecture of aelf experiences performance bottlenecks, particularly in terms of its TPS capacity. aelf will be introducing a new Layer 2 chain utilising [ZK Rollup technology](https://ethereum.org/en/developers/docs/scaling/zk-rollups/) that would considerably enhance aelf's performance, scalability, and compatibility with the Ethereum Virtual Machine (EVM). +Notwithstanding the aforementioned points, the current mainchain-dAppChain architecture of aelf experiences performance bottlenecks, particularly in terms of its TPS capacity. aelf will be introducing a modular chain structure that would considerably enhance aelf's performance, scalability, and compatibility with the other blockchain Virtual Machines (VMs). -Consequently, we have initiated the **Modular + ZK Rollup project** to address these challenges. +Consequently, we have initiated the **Modular Blockchain project** to address these challenges. ## The aelf solution @@ -43,7 +43,7 @@ The aelf ZK-rollup utilises Polygon CDK, an advanced open-source framework desig Operating in the validium mode while maintaining seamless interoperability with all other EVM chains, aelf ZK-rollup offers a high-performance Layer 2 scaling solution. As transaction data is not stored on the aelf mainnet but executed and stored off-chain, this significantly enhances scalability. Validium, under the premise of ensuring security, reduces L1 gas storage costs, thereby lowering transaction costs for users on Layer 2 while significantly improving user privacy and experience. -Unlike traditional rollups and sidechains, aelf ZK-rollup only shares proofs of validity, which are used to confirm transaction outcomes with Layer 1, rather than the actual executed transaction data. Its operation works as follows: A verifier smart contract is deployed on aelf Layer 1, and validium submits proofs of validity to this contract. These proofs, inherently zero-knowledge, contain transaction results without revealing specific transaction data. +Unlike traditional rollups and dAppChains, aelf ZK-rollup only shares proofs of validity, which are used to confirm transaction outcomes with Layer 1, rather than the actual executed transaction data. Its operation works as follows: A verifier smart contract is deployed on aelf Layer 1, and validium submits proofs of validity to this contract. These proofs, inherently zero-knowledge, contain transaction results without revealing specific transaction data. The verifier smart contract assesses the validity of the proofs. Should any batch submitted by validium be found invalid, it will be rejected and not stored on the aelf Layer 1. @@ -68,9 +68,9 @@ Advantages of DAC include: 1. reduce transaction fees; less computation equals lower costs. 2. state privacy; maintaining secure records of state changes for data integrity. -### aelf ZK-rollup Node + #### zkEVM / ZKProver diff --git a/docs/resources/whitepaper-2/roadmap/index.md b/docs/resources/whitepaper-2/roadmap/index.md index 15c64941..dbe18c47 100644 --- a/docs/resources/whitepaper-2/roadmap/index.md +++ b/docs/resources/whitepaper-2/roadmap/index.md @@ -7,7 +7,7 @@ description: 10 This roadmap outlines aelf's strategic integration of AI technologies, focusing on enhancing user and developer experiences, optimising smart contract operations, and ensuring robust, scalable blockchain solutions that is on par with leading technologies. -![aelf Roadmap](/img/aelf_roadmap.png "aelf Roadmap") +![aelf Roadmap](/img/aelf_roadmap_2.png "aelf Roadmap") ## Q3 2024 @@ -29,9 +29,9 @@ This roadmap outlines aelf's strategic integration of AI technologies, focusing 2. [AI Oracle on aelf](/resources/whitepaper-2/ai-integration-points-in-the-aelf-ecosystem/operational-excellence/#ii-ai-oracle-on-aelf) Deploy an AI based oracle to facilitate the development of AI-powered dApps, improve interaction capabilities, and support collaborations with AI Agent platforms on the aelf blockchain. -3. [aelf as a Modular + ZK-rollup Layer 2 Blockchain](/resources/whitepaper-2/modular-blockchain/) +3. [aelf as a Modular Blockchain](/resources/whitepaper-2/modular-blockchain/) - Advance aelf's modular architecture to allow for greater customisation and scalability, catering to diverse application needs and enhancing overall network flexibility, while implementing ZK-Rollup as a Layer 2 solution for optimal TPS, efficiency and EVM compatibility. + Advance aelf's modular architecture to allow for greater customisation and scalability, catering to diverse application needs and enhancing overall network flexibility, while implementing modular blockchain solution for optimal TPS, efficiency and EVM compatibility. ## Q1 2025 diff --git a/docs/tools/aelf-playground/index.md b/docs/tools/aelf-playground/index.md index d00be68f..c05be8b4 100644 --- a/docs/tools/aelf-playground/index.md +++ b/docs/tools/aelf-playground/index.md @@ -10,6 +10,8 @@ description: Play with aelf in your browser. aelf Playground is a sandbox for new developers who want to experience smart contract development with aelf without installing any tools on their local computer. + + ## 2. Setting up No setup is needed. Simply visit [aelf Playground](https://playground.aelf.com) in your browser. @@ -48,79 +50,86 @@ The interaction with the workspace project code inside `src` and `test` folders ![drag-and-drop-3](/img/playground-7.png) -- Also, you can choose to import the project directly from the github. - 1. Click on `enter a GitHub repo url`. - 2. Enter the github URL. - 3. Choose the required `.csproj` file. - 4. Enter the workspace name and click Submit. +- Also, you can choose to import the project directly from the github. + + 1. Click on `enter a GitHub repo url`. + 2. Enter the github URL. + 3. Choose the required `.csproj` file. + 4. Enter the workspace name and click Submit. ![drag-and-drop-3](/img/playground-8.png) ### Features of the aelf-playground Now as the workspace setup is done and project is setup inside aelf's playground. The user can now edit the smart contract logic according to the user needs. The changes will majorly takes place inside the below files: + - src/Protobuf/contract/`contract_proto_file_name`.proto file - src/`ContractName`.cs - src/`ContractName`State.cs Once all the changes are done in the above files and all other required files (whereever nacessary). Then below operations can be performed on the selected workspace project: -1. **AI Audit**: Complete the AI audit of the writtwn smart contract. Result similar to below image will be visible once the AI audit completes. The interpretation of the AI audit results will be shown when you hover over the smart contract code once the audit finishes. - - ![AI-Audit](/img/playground-9.png) +1. **AI Audit**: Complete the AI audit of the written smart contract. Result similar to below image will be visible once the AI audit completes. The interpretation of the AI audit results will be shown when you hover over the smart contract code once the audit finishes. + +![AI-Audit](/img/playground-9.png) -2. **Save Gas Fee**: Optimise the smart contract to save gas fee. It will suggest to make changes to the smart contract if the smart contract is not optimised. If the smart contract is already optimed then result like below will appear. +2. **Save Gas Fee**: Optimise the smart contract to save gas fee. It will suggest to make changes to the smart contract if the smart contract is not optimised. If the smart contract is already optimed then result like below will appear. - ![Save-Gas-Fee](/img/playground-10.png) +![Save-Gas-Fee](/img/playground-10.png) 3. **Build**: Build the smart contract code. It will show `building` status when the user clicks the `Build` button and will output below result including whether build was successful or failed once the build process ends. - ![Build](/img/playground-11.png) - +![Build](/img/playground-11.png) + 4. **Test**: Test the smart contract code. It will show `Running Tests` status when the user clicks the `Test` button and will output below result including how many tests have passed and failed once the test process ends. - ![Test](/img/playground-12.png) - +![Test](/img/playground-12.png) + 5. **Deploy**: Deploy the smart contract code on the aelf blockchain. It will show `Deploying` status when the user clicks the `Deploy` button and will output below result including `transactionId`, `proposal status` and `contract address` once the build process ends. You can verify the contract address by visiting [aelf testnet explorer](https://testnet.aelfscan.io/tDVW). ![Deploy](/img/playground-13.png) + +6. **Contract Viewer**: The Contract Viewer in the Playground automatically appears after a smart contract is deployed, allowing users to test and interact with the contract immediately. This feature displays all available contract functions, both read and write, enabling users to execute them directly within the Playground. It provides a streamlined way to explore and perform actions on the contract without additional setup, making contract testing and function execution more accessible. + + ![Deploy](/img/contract-viewer.png) -6. **Export**: Export the project in a local directory. It will open an alert to save the workspace in the local directory. Users can rename the local directory. +7. **Export**: Export the project in a local directory. It will open an alert to save the workspace in the local directory. Users can rename the local directory. ![Export](/img/playground-14.png) -7. **Share**: Share the project with a sharable link. It will show `Generating share link` status when the user clicks the `Share` button and will output below result including the sharable link. +8. **Share**: Share the project with a sharable link. It will show `Generating share link` status when the user clicks the `Share` button and will output below result including the sharable link. - ![Share](/img/playground-15.png) +![Share](/img/playground-15.png) -8. **Command Line Options**: Command line additionally provides options to check txID and clear terminal including above options. Use the help command to see all the options inside terminal. `check txID` helps in checking the transaction details. +9. **Command Line Options**: Command line additionally provides options to check txID and clear terminal including above options. Use the help command to see all the options inside terminal. `check txID` helps in checking the transaction details. ![Upload Files](/img/playground-16.png) -9. **Upload Files**: Upload more files to the project when necessary. It will show a `drag and drop files` section to drop files from the local directory. +10. **Upload Files**: Upload more files to the project when necessary. It will show a `drag and drop files` section to drop files from the local directory. ![Upload Files](/img/playground-17.png) -10. **Add a New File**: Manually add a new file in the playground project structure. It will allow users to add a new file in the workspace project structure add smart contract code, new proto files, etc. +11. **Add a New File**: Manually add a new file in the playground project structure. It will allow users to add a new file in the workspace project structure add smart contract code, new proto files, etc. - ![Add a New File](/img/playground-18.png) +![Add a New File](/img/playground-18.png) -11. **Rename & Delete File**: `Renames` & `Deletes` the chosen file or folders in the project directory structure. +12. **Rename & Delete File**: `Renames` & `Deletes` the chosen file or folders in the project directory structure. - ![Add a New File](/img/playground-19.png) +![Add a New File](/img/playground-19.png) -12. **Tutorials**: Some pre-compiled tutorials are curated under `Tutorials` section of aelf-playground. It provides an option to filter the tutorials based on the difficulty level (`Beginner`, `Intermediate` & `Advanced`) and smart contracts languages (C# & Solidity). +13. **Tutorials**: Some pre-compiled tutorials are curated under `Tutorials` section of aelf-playground. It provides an option to filter the tutorials based on the difficulty level (`Beginner`, `Intermediate` & `Advanced`) and smart contracts languages (C# & Solidity). ![Add a New File](/img/playground-20.png) +14. **Deployments**: `Deployments` section provides a list of all deployed tutorials along with the wallet address used to deploy smart contracts on the aelf blockchain. You can click on the wallet address to view wallet details on the aelf explorer. -13. **Deployments**: `Deployments` section provides a list of all deployed tutorials along with the wallet address used to deploy smart contracts on the aelf blockchain. You can click on the wallet address to view wallet details on the aelf explorer. +![Add a New File](/img/playground-21.png) - ![Add a New File](/img/playground-21.png) +15. **Privatekey**: You can export your wallet's private key from the `Deployments` section. Simply click the eye icon to reveal the private key, which you can then copy. +![Add a New File](/img/playground-24.png) -14. **Themes**: Users can also choose to toggle between `dark` and `light` themes. - - ![Add a New File](/img/playground-22.png) +16. **Themes**: Users can also choose to toggle between `dark` and `light` themes. +![Add a New File](/img/playground-22.png) ## 4. Example @@ -142,6 +151,8 @@ Now it's time to creat a Todo-dApp using playground. ![playground-example-img-3](/img/playground-example-img-3.png) +### Rename File Name + - Rename the proto file name `hello_world_contract.proto` inside folder `src/Protobuf/contract/` to `todo_app.proto` ![playground-example-img-4](/img/playground-example-img-4.png) @@ -239,7 +250,7 @@ namespace AElf.Contracts.ToDo - The `State.cs` file in an aelf blockchain smart contract holds the variables that store the contract's data, making sure this data is saved and accessible whenever the contract needs it. -#### Implement ToDo Smart Contract +#### Implement ToDo Smart Contract The implementation of the ToDo App smart contract inside file `src/todo-dapp.cs` is as follows: @@ -354,13 +365,23 @@ namespace AElf.Contracts.ToDo } ``` +### Ai Audit Report + +- Click on AI Audit Icon to generate the AI Audit report. + + ![ai-audit-button-playground](/img/ai-audit-button-playground.png) + +- The Report will be visible once the AI audit completes. It will provides suggestion for Todo functions as shown below so apply the suggetion and make your Todo smart contract more better. + + ![ai-audit-suggestion-playground](/img/ai-audit-suggestion-playground.png) + + ### Save Gas Fee -- Click on Save Gas Fee Button and It will suggest to make changes if contract need to be optimised otherwise it shows result like below. +- Click on Save Gas Fee Icon and It will suggest to make changes if contract need to be optimised otherwise it shows result like below. ![gas-fees-example-playground](/img/gas-fees-example-playground.png) - ### Building Smart Contract - Click on Build Icon for generate the build. @@ -371,6 +392,15 @@ namespace AElf.Contracts.ToDo ![playground-example-img-7](/img/playground-example-img-7.png) + + + ### Deploy Smart Contract - Click on Deploy Icon for deploy the smart contract. @@ -381,7 +411,44 @@ namespace AElf.Contracts.ToDo ![playground-example-img-9](/img/playground-example-img-9.png) +### Contract Viewer + +- The Contract Viewer will appear once your contract is successfully deployed, allowing you to execute all functions directly within the Playground. + + ![Deploy](/img/contract-viewer.png) + +### Export Smart Contract + +- Click on Export Icon for download the smart contract. + + ![export-button-playground](/img/export-button-playground.png) + +- Once your smart contract exported successfully, You will get it in zip format like below. + + ![export-success-playground](/img/export-success-playground.png) + +### Share Link + +- Click on Share Icon to generate the share link of the smart contract. + + ![share-button-playground](/img/share-button-playground.png) + +- Share link will be generated and You will get it in terminal. + + ![share-link-playground](/img/share-link-playground.png) + +### Deployment + +- Click on Deployment link to get deployment data of our recent deployed smart contract. + + ![deployment-button-playground](/img/deployment-button-playground.png) + +- You will receive data about the deployed contract and wallet address, and you can click on them to view more details related to the wallet and contract. + + ![deployment-data-playground](/img/deployment-data-playground.png) + 🎉 Congratulations, We got the contract address after successful deployment of todo-dapp smart contract using playground. ## Conclusion -The aelf Playground offers a seamless and accessible platform for developers to build, test, and deploy smart contracts without the need for any local setup. With built-in features like AI audit, gas fee optimization, and GitHub integration, it simplifies the entire smart contract development process. Whether you're writing new code or modifying existing templates, the aelf Playground provides all the essential tools in one place, making it an ideal sandbox for both beginners and experienced developers. \ No newline at end of file + +The aelf Playground offers a seamless and accessible platform for developers to build, test, and deploy smart contracts without the need for any local setup. With built-in features like AI audit, gas fee optimization, and GitHub integration, it simplifies the entire smart contract development process. Whether you're writing new code or modifying existing templates, the aelf Playground provides all the essential tools in one place, making it an ideal sandbox for both beginners and experienced developers. diff --git a/docs/tools/aelf-studio-extention/index.md b/docs/tools/aelf-studio-extention/index.md index f9661bbf..954156b1 100644 --- a/docs/tools/aelf-studio-extention/index.md +++ b/docs/tools/aelf-studio-extention/index.md @@ -139,7 +139,6 @@ description: A tool to simplify building, testing, and deploying smart contracts - It's advised to wait for sometime and click on **Check Audit Report** button to see the audit report. - ### Deploy the smart contract: - Click the **aelf icon** again in the bottom right corner. diff --git a/docs/tools/faucet/index.md b/docs/tools/faucet/index.md index da24f605..f620f2f6 100644 --- a/docs/tools/faucet/index.md +++ b/docs/tools/faucet/index.md @@ -20,33 +20,11 @@ To deploy smart contracts or execute on-chain transactions on aelf, you'll requi **Get ELF Tokens** - - - -Run the following command to get testnet ELF tokens from faucet. Remember to either export your wallet address or replace $WALLET_ADDRESS with your wallet address. - -```bash title="Terminal" -curl -X POST "https://faucet.aelf.dev/api/claim?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` -To check your wallet's current ELF balance: -```bash title="Terminal" -aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx -a $WALLET_ADDRESS -p $WALLET_PASSWORD -e https://tdvw-test-node.aelf.io GetBalance -``` -You will be prompted for the following: -Enter the required param \: **ELF** -Enter the required param \: **$WALLET_ADDRESS** - -You should see the Result displaying your wallet's ELF balance. - - - - -Go to this url [https://faucet-ui.aelf.dev](https://faucet-ui.aelf.dev). Enter your address and click `Get Tokens`. +- Go to this url [https://faucet-ui.aelf.dev](https://faucet-ui.aelf.dev). +- Enter your address and click `Get Tokens`. ![result](/img/get-token-ui.png) - - ### 2.2 Getting Testnet Token Type SEED Token @@ -54,24 +32,12 @@ To acquire testnet Token type SEED for creating fungible or non-fungible tokens **Get Token Type Seed Token** - - - -Run the following command to get testnet SEED token from faucet. Remember to either export your wallet address or replace $WALLET_ADDRESS with your wallet address. - -```bash title="Terminal" -curl -X POST "https://faucet.aelf.dev/api/claim-seed?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` - - - - -Go to this url [https://faucet-ui.aelf.dev](https://faucet-ui.aelf.dev). Click on the dropdown to select "Token Seed". Enter your address and click `Get Seed`. +- Go to this url [https://faucet-ui.aelf.dev](https://faucet-ui.aelf.dev). +- Click on the dropdown to select **"Token Seed"**. +- Enter your address and click `Get Seed`. ![result](/img/get-testnet-token-seed.png) - - ### 2.3 Getting Testnet NFT Type SEED Token @@ -79,21 +45,9 @@ To acquire testnet NFT type SEED for creating fungible or non-fungible tokens on **Get NFT Type Seed Token** - - - -Run this command to get testnet NFT type SEED token from faucet. Remember to either export your wallet address or replace $WALLET_ADDRESS with your wallet address. - -```bash title="Terminal" -curl -X POST "https://faucet.aelf.dev/api/claim-nft-seed?walletAddress=$WALLET_ADDRESS" -H "accept: application/json" -d "" -``` - - - - -Go to this url [https://faucet-ui.aelf.dev](https://faucet-ui.aelf.dev). Click on the dropdown to select "NFT Seed". Enter your address and click `Get Seed`. +- Go to this url [https://faucet-ui.aelf.dev](https://faucet-ui.aelf.dev). +- Click on the dropdown to select **"NFT Seed"**. +- Enter your address and click `Get Seed`. ![result](/img/get-testnet-nft-seed.png) - - \ No newline at end of file diff --git a/docs/tools/smart-contract-templates/deploying-contracts-with-bp-approval/index.md b/docs/tools/smart-contract-templates/deploying-contracts-with-bp-approval/index.md index 8ff8ac1f..b3d881e0 100644 --- a/docs/tools/smart-contract-templates/deploying-contracts-with-bp-approval/index.md +++ b/docs/tools/smart-contract-templates/deploying-contracts-with-bp-approval/index.md @@ -13,8 +13,8 @@ Contracts can be deployed or updated via two methods: aelf explorer or aelf-comm In these cases, **BP approval is needed for contract updates:** - Upgrading system contracts on MainChain. -- Upgrading system contracts on exclusive SideChains. -- Upgrading system contracts on shared SideChains. +- Upgrading system contracts on exclusive dAppChains. +- Upgrading system contracts on shared dAppChains. System contracts can only be deployed in the Genesis block. After launch, only updates are supported. This guide focuses on contract deployment on aelf Mainnet with `ContractDeploymentAuthorityRequired` set to true. diff --git a/docs/tools/smart-contract-templates/deploying-contracts-without-bp-approval/index.md b/docs/tools/smart-contract-templates/deploying-contracts-without-bp-approval/index.md index 4e00104a..1908d073 100644 --- a/docs/tools/smart-contract-templates/deploying-contracts-without-bp-approval/index.md +++ b/docs/tools/smart-contract-templates/deploying-contracts-without-bp-approval/index.md @@ -12,11 +12,11 @@ Contracts can be deployed/updated via aelf explorer or aelf-command. Ensure npm In these 6 cases, **BP approval is not needed for contract deployment/updates:** -- Deploying user contracts on shared SideChains (initiated by users or BPs). -- Updating user contracts on shared SideChains (initiated by contract creators). -- Deploying user contracts on exclusive SideChains (initiated by SideChain creators). -- Updating user contracts on exclusive SideChains (initiated by contract creators). -- Deploying user contracts on MainChain (initiated by BPs, recommended on SideChains). +- Deploying user contracts on shared dAppChains (initiated by users or BPs). +- Updating user contracts on shared dAppChains (initiated by contract creators). +- Deploying user contracts on exclusive dAppChains (initiated by dAppChain creators). +- Updating user contracts on exclusive dAppChains (initiated by contract creators). +- Deploying user contracts on MainChain (initiated by BPs, recommended on dAppChains). - Updating user contracts on MainChain (initiated by contract creators). ![Deploying Contract without BP Approval](/img/No-BP-approval-required.webp) diff --git a/docusaurus.config.ts b/docusaurus.config.ts index f3880a9c..ef20bbf4 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -35,7 +35,6 @@ const config: Config = { defaultLocale: "en", locales: ["en"], }, - presets: [ [ "classic", @@ -110,6 +109,9 @@ const config: Config = { indexName: "aelf", }, } satisfies Preset.ThemeConfig, + customFields: { + FEEDBACK_CONTENT_SET_ID: process.env.FEEDBACK_CONTENT_SET_ID || "", + }, stylesheets: [ { href: "/katex/katex.min.css", diff --git a/package-lock.json b/package-lock.json index e7248605..fafa64c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,12 @@ "name": "aelf-docs-cms", "version": "0.0.0", "dependencies": { + "@amplitude/analytics-browser": "^2.11.7", + "@amplitude/plugin-ga-events-forwarder-browser": "^0.3.4", + "@amplitude/plugin-session-replay-browser": "^1.8.0", "@docusaurus/core": "3.4.0", "@docusaurus/preset-classic": "3.4.0", + "@feelback/react": "^0.3.4", "@mdx-js/react": "^3.0.0", "@sinm/react-file-tree": "^1.1.1", "chaingpt-component": "^0.2.0-beta.3", @@ -18,6 +22,9 @@ "prism-react-renderer": "^2.3.0", "react": "^18.0.0", "react-dom": "^18.0.0", + "react-ga4": "^2.1.0", + "react-gtm-module": "^2.0.11", + "react-hotjar": "^6.3.1", "rehype-katex": "^7.0.0", "remark-math": "^6.0.0" }, @@ -210,6 +217,173 @@ "@algolia/requester-common": "4.23.3" } }, + "node_modules/@amplitude/analytics-browser": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-2.11.8.tgz", + "integrity": "sha512-lFv8deROLwBfSlg92+r1NitWJ6BN45IKwpPLoixA0fZytScXEJqc0Gl5O+BY4qScbFECYt9PFKblhB+jC+IvPg==", + "license": "MIT", + "dependencies": { + "@amplitude/analytics-client-common": "^2.3.4", + "@amplitude/analytics-core": "^2.5.3", + "@amplitude/analytics-remote-config": "^0.4.0", + "@amplitude/analytics-types": "^2.8.3", + "@amplitude/plugin-autocapture-browser": "^1.0.2", + "@amplitude/plugin-page-view-tracking-browser": "^2.3.4", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/analytics-client-common": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-client-common/-/analytics-client-common-2.3.4.tgz", + "integrity": "sha512-3oqdvca5W4BPblTaxf60YRtlh2uC+N3rA99wowDAhTBJoMJJaauOBoXu5BbiQO1u8Zw/c8ymyr8E20+glyptUg==", + "license": "MIT", + "dependencies": { + "@amplitude/analytics-connector": "^1.4.8", + "@amplitude/analytics-core": "^2.5.3", + "@amplitude/analytics-types": "^2.8.3", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/analytics-connector": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-connector/-/analytics-connector-1.5.0.tgz", + "integrity": "sha512-T8mOYzB9RRxckzhL0NTHwdge9xuFxXEOplC8B1Y3UX3NHa3BLh7DlBUZlCOwQgMc2nxDfnSweDL5S3bhC+W90g==", + "license": "MIT" + }, + "node_modules/@amplitude/analytics-core": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-core/-/analytics-core-2.5.3.tgz", + "integrity": "sha512-dvx3PS0adnHRS22VbuP9YtWg//bQGF2c61Pj5IYXVsemtRRHqiS7XJ860brk3WeQgOkqf3Gyc023DoYcsWGoNQ==", + "license": "MIT", + "dependencies": { + "@amplitude/analytics-types": "^2.8.3", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/analytics-remote-config": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-remote-config/-/analytics-remote-config-0.4.1.tgz", + "integrity": "sha512-BYl6kQ9qjztrCACsugpxO+foLaQIC0aSEzoXEAb/gwOzInmqkyyI+Ub+aWTBih4xgB/lhWlOcidWHAmNiTJTNw==", + "license": "MIT", + "dependencies": { + "@amplitude/analytics-client-common": ">=1 <3", + "@amplitude/analytics-core": ">=1 <3", + "@amplitude/analytics-types": ">=1 <3", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/analytics-types": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-types/-/analytics-types-2.8.3.tgz", + "integrity": "sha512-HNmKVd0ACoi3xTi86xi+is7WgqKT78JA4fYLcM25/ckFkZ1zVCqD1AubaADEh26m34nJ3qDLK5Pob4QptQNPAg==", + "license": "MIT" + }, + "node_modules/@amplitude/plugin-autocapture-browser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-autocapture-browser/-/plugin-autocapture-browser-1.0.3.tgz", + "integrity": "sha512-XUQWUAw9VqtJPlmOyWjnhsEspyVakd9LuSjVNtLjhwlWv+f/yZM1AAQVUdq/Os1+b5OptSgJQ2pPfRJJHZDXTw==", + "license": "MIT", + "dependencies": { + "@amplitude/analytics-client-common": ">=1 <3", + "@amplitude/analytics-types": "^2.8.2", + "rxjs": "^7.8.1", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/plugin-ga-events-forwarder-browser": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-ga-events-forwarder-browser/-/plugin-ga-events-forwarder-browser-0.3.4.tgz", + "integrity": "sha512-DrwZJZ6zhT70UIfT8Lg9qnCIXRX3HVgDp1Hviyu66uqLr0GitycbFFLQaJlJK+ipOfCgCcy5OpKp0DjQXLErBA==", + "license": "MIT", + "dependencies": { + "@amplitude/analytics-client-common": ">=1 <3", + "@amplitude/analytics-types": ">=1 <3", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/plugin-page-view-tracking-browser": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-view-tracking-browser/-/plugin-page-view-tracking-browser-2.3.4.tgz", + "integrity": "sha512-l7RS5gssG0BPYlgirV0NQ94EPzTOdDkp0z2jqU45D3DQAJXkoloUyw5lw/cbUXYwNulHZTG/BExcERfdvVWkLA==", + "license": "MIT", + "dependencies": { + "@amplitude/analytics-client-common": "^2.3.4", + "@amplitude/analytics-types": "^2.8.3", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/plugin-session-replay-browser": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-session-replay-browser/-/plugin-session-replay-browser-1.8.1.tgz", + "integrity": "sha512-FlaIawFN57VflRN0Gj6/KYfA8p0PxphFoAybLrS37dDpLoyC+UBvG0aUNhtF7GzjHbKxGNntCPqFSMv4VNlk6w==", + "license": "MIT", + "dependencies": { + "@amplitude/analytics-client-common": ">=1 <3", + "@amplitude/analytics-core": ">=1 <3", + "@amplitude/analytics-types": ">=1 <3", + "@amplitude/session-replay-browser": "^1.15.0", + "idb-keyval": "^6.2.1", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/rrdom": { + "version": "2.0.0-alpha.25", + "resolved": "https://registry.npmjs.org/@amplitude/rrdom/-/rrdom-2.0.0-alpha.25.tgz", + "integrity": "sha512-GTdwpDJmwAZcllNmGH3xmLEfKkMhOqmqkpG9G0MVGdhRmL3pTAhmSZuyPUYUho71ZjKQtGnHMDPgfOtniWsWbw==", + "license": "MIT", + "dependencies": { + "@amplitude/rrweb-snapshot": "^2.0.0-alpha.25" + } + }, + "node_modules/@amplitude/rrweb": { + "version": "2.0.0-alpha.21", + "resolved": "https://registry.npmjs.org/@amplitude/rrweb/-/rrweb-2.0.0-alpha.21.tgz", + "integrity": "sha512-Ry5J4U7jBcqG2i7cXwo9v1JSQqh0wh4nTRKOgIxM3vXvNti1hzS88I4nsCjrytm8aaCTNB6SCVa3n+yrGE3b8A==", + "license": "MIT", + "dependencies": { + "@amplitude/rrdom": "^2.0.0-alpha.21", + "@amplitude/rrweb-snapshot": "^2.0.0-alpha.21", + "@amplitude/rrweb-types": "^2.0.0-alpha.21", + "@types/css-font-loading-module": "0.0.7", + "@xstate/fsm": "^1.4.0", + "base64-arraybuffer": "^1.0.1", + "fflate": "^0.4.4", + "mitt": "^3.0.0" + } + }, + "node_modules/@amplitude/rrweb-snapshot": { + "version": "2.0.0-alpha.25", + "resolved": "https://registry.npmjs.org/@amplitude/rrweb-snapshot/-/rrweb-snapshot-2.0.0-alpha.25.tgz", + "integrity": "sha512-sXNJHGGqFeVoua7qXKd8cuI4s4RtWZyse1ovKmTLyKVLIWDNtv+kbubpR6ze4EAy5ciOvLe7H41L8ps6JZZg7g==", + "license": "MIT", + "dependencies": { + "postcss": "^8.4.38" + } + }, + "node_modules/@amplitude/rrweb-types": { + "version": "2.0.0-alpha.25", + "resolved": "https://registry.npmjs.org/@amplitude/rrweb-types/-/rrweb-types-2.0.0-alpha.25.tgz", + "integrity": "sha512-KtHn3Bu9EhTPJ5bRbf6Qs8+uz4PUlmk4qg+c4N5b1P36erHnhX5tuk9bfwzJawtDYX7x5a4jEdeqFBwLQrt//g==", + "license": "MIT", + "dependencies": { + "@amplitude/rrweb-snapshot": "^2.0.0-alpha.25" + } + }, + "node_modules/@amplitude/session-replay-browser": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@amplitude/session-replay-browser/-/session-replay-browser-1.15.0.tgz", + "integrity": "sha512-66Y7iDu03NM3xYzzV2PAzG4TR3qU23hP1JJB/yJENXkLCVxrFQQ+32+8ZQJxokfso3lpN/COnYlv2qtTGJNB3Q==", + "license": "MIT", + "dependencies": { + "@amplitude/analytics-client-common": ">=1 <3", + "@amplitude/analytics-core": ">=1 <3", + "@amplitude/analytics-remote-config": "^0.4.1", + "@amplitude/analytics-types": ">=1 <3", + "@amplitude/rrweb": "2.0.0-alpha.21", + "idb": "^8.0.0", + "tslib": "^2.4.1" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -2732,6 +2906,27 @@ "node": ">=18.0" } }, + "node_modules/@feelback/js": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@feelback/js/-/js-0.3.4.tgz", + "integrity": "sha512-xr7gTqSJcVUYQlELs1TntYovCBjMcYUr/hGKTnDoF64/lig5CbX4bOmqLoF50IImCy5q3oIwg9w+TSFvtBwsIA==", + "license": "MIT" + }, + "node_modules/@feelback/react": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@feelback/react/-/react-0.3.4.tgz", + "integrity": "sha512-ZWzUQAmPwl4nYR2olzBKddHzoLtGW/2pb8TiesiJCirxhaDW2E/XBx2ZaB4fL5TGXtjBt4eYq/qZxJZ0fIE0kg==", + "license": "MIT", + "dependencies": { + "@feelback/js": "0.3.4" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=17" + } + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -3316,6 +3511,12 @@ "@types/node": "*" } }, + "node_modules/@types/css-font-loading-module": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz", + "integrity": "sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==", + "license": "MIT" + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -3754,6 +3955,12 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@xstate/fsm": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@xstate/fsm/-/fsm-1.6.5.tgz", + "integrity": "sha512-b5o1I6aLNeYlU/3CPlj/Z91ybk1gUsKT+5NAJI+2W4UjvS5KLG28K9v5UvNoFVjHV8PajVZ00RH3vnjyQO7ZAw==", + "license": "MIT" + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -4156,6 +4363,15 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -6123,12 +6339,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", - "license": "MIT" - }, "node_modules/express/node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -6220,6 +6430,12 @@ "node": ">=0.4.0" } }, + "node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", + "license": "MIT" + }, "node_modules/file-loader": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", @@ -7520,6 +7736,18 @@ "postcss": "^8.1.0" } }, + "node_modules/idb": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/idb/-/idb-8.0.0.tgz", + "integrity": "sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==", + "license": "ISC" + }, + "node_modules/idb-keyval": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", + "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==", + "license": "Apache-2.0" + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -10589,6 +10817,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, "node_modules/mrmime": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", @@ -12147,6 +12381,18 @@ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" }, + "node_modules/react-ga4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-2.1.0.tgz", + "integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ==", + "license": "MIT" + }, + "node_modules/react-gtm-module": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.11.tgz", + "integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw==", + "license": "MIT" + }, "node_modules/react-helmet-async": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", @@ -12163,6 +12409,12 @@ "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-hotjar": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/react-hotjar/-/react-hotjar-6.3.1.tgz", + "integrity": "sha512-EwMqL+ROSlKzatMhT/aqRq7XWWfzlnHynSBSTJh5M2O78mBiPohiSl4Ysls3HOQkkD9y6L22BW0c9bxK2JguwQ==", + "license": "MIT" + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -12842,6 +13094,15 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", diff --git a/package.json b/package.json index cb26fa0a..e763f8d6 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,12 @@ "typecheck": "tsc" }, "dependencies": { + "@amplitude/analytics-browser": "^2.11.7", + "@amplitude/plugin-ga-events-forwarder-browser": "^0.3.4", + "@amplitude/plugin-session-replay-browser": "^1.8.0", "@docusaurus/core": "3.4.0", "@docusaurus/preset-classic": "3.4.0", + "@feelback/react": "^0.3.4", "@mdx-js/react": "^3.0.0", "@sinm/react-file-tree": "^1.1.1", "chaingpt-component": "^0.2.0-beta.3", @@ -25,6 +29,9 @@ "prism-react-renderer": "^2.3.0", "react": "^18.0.0", "react-dom": "^18.0.0", + "react-ga4": "^2.1.0", + "react-gtm-module": "^2.0.11", + "react-hotjar": "^6.3.1", "rehype-katex": "^7.0.0", "remark-math": "^6.0.0" }, @@ -48,5 +55,8 @@ }, "engines": { "node": ">=18.0" + }, + "overrides": { + "path-to-regexp": "^1.9.0" } } diff --git a/sidebars.ts b/sidebars.ts index 9d90856d..f66d0d29 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -71,7 +71,7 @@ const sidebars: SidebarsConfig = { type: "category", label: "Oracle", link: { type: "doc", id: "tools/oracle/index" }, - customProps: { description: "Oracle is" }, + customProps: { description: "Decentralized oracle network" }, items: [{ type: "autogenerated", dirName: "tools/oracle" }], }, { diff --git a/src/css/custom.css b/src/css/custom.css index e65fc459..3e33d61d 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -70,4 +70,41 @@ .mobile-only { display: none; } +} + +/* +Feedback widget CSS customization +https://www.feelback.dev/docs/guides/stripe-like-documentation-feedback-for-docusaurus/ +*/ +@import "@feelback/react/styles/feelback.css"; + +.feedback-component{ + margin-top: 2rem; +} + +.feedback-component .feelback-container .feelback-buttons{ + gap: 10px; +} + +.feedback-component .feelback-container .feelback-btn { + background-color: var(--ifm-color-primary); + color: white; + height: 37px; + padding-inline: 15px; + border-radius: 7px; +} + +.feedback-component .feelback-container .feelback-btn:hover{ + background-color: var(--ifm-color-primary-dark); + +} + +.feedback-component .feelback-container textarea { + border: 1px solid var(--ifm-color-primary-lightest); + border-radius: 10px; + padding: 0.7rem; +} + +.feedback-component .feelback-radio-side label{ + font-weight: 600; } \ No newline at end of file diff --git a/src/theme/DocPaginator/index.tsx b/src/theme/DocPaginator/index.tsx new file mode 100644 index 00000000..fab1cadf --- /dev/null +++ b/src/theme/DocPaginator/index.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import Translate, { translate } from "@docusaurus/Translate"; +import PaginatorNavLink from "@theme/PaginatorNavLink"; +import type { Props } from "@theme/DocPaginator"; +import Feedback from "../Feedback"; + +export default function DocPaginator(props: Props): JSX.Element { + const { previous, next } = props; + return ( + + ); +} diff --git a/src/theme/Feedback/index.tsx b/src/theme/Feedback/index.tsx new file mode 100644 index 00000000..28f3e714 --- /dev/null +++ b/src/theme/Feedback/index.tsx @@ -0,0 +1,86 @@ +import { useState } from "react"; +import { + FeelbackTaggedMessage, + Question, + PRESET_YESNO_LIKE_DISLIKE, +} from "@feelback/react"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; + +const YES_TAGS = [ + { + value: "accurate", + title: "Accurate", + description: "Accurately describes the product or feature.", + }, + { + value: "problem-solved", + title: "Solved my problem", + description: "Helped me resolve an issue.", + }, + { + value: "clear", + title: "Easy to understand", + description: "Easy to follow and comprehend.", + }, + { + value: "product-chosen", + title: "Helped me decide to use the product", + description: "Convinced me to adopt the product or feature.", + }, + { value: "other-yes", title: "Another reason" }, +]; + +const NO_TAGS = [ + { + value: "inaccurate", + title: "Inaccurate", + description: "Doesn't accurately describe the product or feature.", + }, + { + value: "missing-info", + title: "Couldn't find what I was looking for", + description: "Missing important information.", + }, + { + value: "unclear", + title: "Hard to understand", + description: "Too complicated or unclear.", + }, + { + value: "bad-examples", + title: "Code samples errors", + description: "One or more code samples are incorrect.", + }, + { value: "other-no", title: "Another reason" }, +]; + +const Feedback = () => { + const [choice, setChoice] = useState<"y" | "n">(); + const { siteConfig } = useDocusaurusContext(); + const { FEEDBACK_CONTENT_SET_ID } = siteConfig.customFields; + + return ( +
+
+ {!choice ? ( + setChoice(option)} + /> + ) : ( + + )} +
+
+ ); +}; + +export default Feedback; diff --git a/src/theme/Root.tsx b/src/theme/Root.tsx index 999a7069..b33af026 100644 --- a/src/theme/Root.tsx +++ b/src/theme/Root.tsx @@ -1,11 +1,16 @@ // https://docusaurus.io/docs/3.4.0/swizzling#wrapper-your-site-with-root import BrowserOnly from "@docusaurus/BrowserOnly"; -import React from "react"; +import React, { useEffect } from "react"; import ChatComponent from "./ChatPAAL"; +import { analytics } from "./analytics"; // Default implementation, that you can customize export default function Root({ children }) { + useEffect(() => { + analytics(); + }, []); + return ( <> {children} diff --git a/src/theme/analytics.ts b/src/theme/analytics.ts new file mode 100644 index 00000000..b56f9dbe --- /dev/null +++ b/src/theme/analytics.ts @@ -0,0 +1,22 @@ +import * as amplitude from "@amplitude/analytics-browser"; +import { gaEventsForwarderPlugin } from "@amplitude/plugin-ga-events-forwarder-browser"; +import { sessionReplayPlugin } from "@amplitude/plugin-session-replay-browser"; +import ReactGA from "react-ga4"; +import TagManager from "react-gtm-module"; +import { hotjar } from "react-hotjar"; + +export const analytics = () => { + const gaEventsForwarder = gaEventsForwarderPlugin(); + amplitude.add(gaEventsForwarder); + amplitude.init("7652218546e8f6cc3d045e43a68830f6", { autocapture: true }); + const sessionReplayTracking = sessionReplayPlugin({ + sampleRate: 1, + }); + amplitude.add(sessionReplayTracking); + + hotjar.initialize({ id: 5120800, sv: 6 }); + ReactGA.initialize("G-PFZ0BCQHMY"); + TagManager.initialize({ + gtmId: "GTM-NKWDMQ52", + }); +}; diff --git a/static/img/aelf_roadmap_2.png b/static/img/aelf_roadmap_2.png new file mode 100644 index 00000000..5b591a59 Binary files /dev/null and b/static/img/aelf_roadmap_2.png differ diff --git a/static/img/ai-audit-button-playground.png b/static/img/ai-audit-button-playground.png new file mode 100644 index 00000000..c953653a Binary files /dev/null and b/static/img/ai-audit-button-playground.png differ diff --git a/static/img/ai-audit-suggestion-playground.png b/static/img/ai-audit-suggestion-playground.png new file mode 100644 index 00000000..7dfd7982 Binary files /dev/null and b/static/img/ai-audit-suggestion-playground.png differ diff --git a/static/img/allowance-connect-wallet.png b/static/img/allowance-connect-wallet.png new file mode 100644 index 00000000..55cb4de8 Binary files /dev/null and b/static/img/allowance-connect-wallet.png differ diff --git a/static/img/allowance-home-page.png b/static/img/allowance-home-page.png new file mode 100644 index 00000000..ee8af331 Binary files /dev/null and b/static/img/allowance-home-page.png differ diff --git a/static/img/allowance-wallet-connect-success.png b/static/img/allowance-wallet-connect-success.png new file mode 100644 index 00000000..3f5a6c57 Binary files /dev/null and b/static/img/allowance-wallet-connect-success.png differ diff --git a/static/img/click-login-option.png b/static/img/click-login-option.png new file mode 100644 index 00000000..fee94ab5 Binary files /dev/null and b/static/img/click-login-option.png differ diff --git a/static/img/click-login-portkey.png b/static/img/click-login-portkey.png new file mode 100644 index 00000000..5edd9d3b Binary files /dev/null and b/static/img/click-login-portkey.png differ diff --git a/static/img/contract-viewer.png b/static/img/contract-viewer.png new file mode 100644 index 00000000..a93247df Binary files /dev/null and b/static/img/contract-viewer.png differ diff --git a/static/img/copy-wallet-address.png b/static/img/copy-wallet-address.png new file mode 100644 index 00000000..517a4fec Binary files /dev/null and b/static/img/copy-wallet-address.png differ diff --git a/static/img/create-nft-indexer.png b/static/img/create-nft-indexer.png new file mode 100644 index 00000000..d3d0a0c4 Binary files /dev/null and b/static/img/create-nft-indexer.png differ diff --git a/static/img/deploy-nft-indexer-template.png b/static/img/deploy-nft-indexer-template.png new file mode 100644 index 00000000..74e55f0e Binary files /dev/null and b/static/img/deploy-nft-indexer-template.png differ diff --git a/static/img/deployment-button-playground.png b/static/img/deployment-button-playground.png new file mode 100644 index 00000000..fb0db068 Binary files /dev/null and b/static/img/deployment-button-playground.png differ diff --git a/static/img/deployment-data-playground.png b/static/img/deployment-data-playground.png new file mode 100644 index 00000000..701da53c Binary files /dev/null and b/static/img/deployment-data-playground.png differ diff --git a/static/img/dice-approve-login-request.png b/static/img/dice-approve-login-request.png new file mode 100644 index 00000000..64168d9c Binary files /dev/null and b/static/img/dice-approve-login-request.png differ diff --git a/static/img/dice-click-login-button.png b/static/img/dice-click-login-button.png new file mode 100644 index 00000000..c08fdbdd Binary files /dev/null and b/static/img/dice-click-login-button.png differ diff --git a/static/img/dice-game-faucet-claim-token.png b/static/img/dice-game-faucet-claim-token.png new file mode 100644 index 00000000..4b85310a Binary files /dev/null and b/static/img/dice-game-faucet-claim-token.png differ diff --git a/static/img/dice-game-homepage.png b/static/img/dice-game-homepage.png new file mode 100644 index 00000000..c360b0ec Binary files /dev/null and b/static/img/dice-game-homepage.png differ diff --git a/static/img/dice-game-processing.png b/static/img/dice-game-processing.png new file mode 100644 index 00000000..a7f629b4 Binary files /dev/null and b/static/img/dice-game-processing.png differ diff --git a/static/img/dice-game-result.png b/static/img/dice-game-result.png new file mode 100644 index 00000000..f23b6f90 Binary files /dev/null and b/static/img/dice-game-result.png differ diff --git a/static/img/dice-home-page-post-login.png b/static/img/dice-home-page-post-login.png new file mode 100644 index 00000000..5f9581e3 Binary files /dev/null and b/static/img/dice-home-page-post-login.png differ diff --git a/static/img/dice-npm-run-console.png b/static/img/dice-npm-run-console.png new file mode 100644 index 00000000..5202092f Binary files /dev/null and b/static/img/dice-npm-run-console.png differ diff --git a/static/img/dice-select-price-option.png b/static/img/dice-select-price-option.png new file mode 100644 index 00000000..2c622844 Binary files /dev/null and b/static/img/dice-select-price-option.png differ diff --git a/static/img/download-nft-indexer-template.png b/static/img/download-nft-indexer-template.png new file mode 100644 index 00000000..7123e96a Binary files /dev/null and b/static/img/download-nft-indexer-template.png differ diff --git a/static/img/export-button-playground.png b/static/img/export-button-playground.png new file mode 100644 index 00000000..1db75fd8 Binary files /dev/null and b/static/img/export-button-playground.png differ diff --git a/static/img/export-success-playground.png b/static/img/export-success-playground.png new file mode 100644 index 00000000..f7067454 Binary files /dev/null and b/static/img/export-success-playground.png differ diff --git a/static/img/get-approval-token-request.png b/static/img/get-approval-token-request.png new file mode 100644 index 00000000..68d41ecd Binary files /dev/null and b/static/img/get-approval-token-request.png differ diff --git a/static/img/get-game-transaction-request.png b/static/img/get-game-transaction-request.png new file mode 100644 index 00000000..3a751768 Binary files /dev/null and b/static/img/get-game-transaction-request.png differ diff --git a/static/img/logs-nft-indexer.png b/static/img/logs-nft-indexer.png new file mode 100644 index 00000000..7d89c903 Binary files /dev/null and b/static/img/logs-nft-indexer.png differ diff --git a/static/img/name-nft-indexer.png b/static/img/name-nft-indexer.png new file mode 100644 index 00000000..de42eec3 Binary files /dev/null and b/static/img/name-nft-indexer.png differ diff --git a/static/img/playground-21.png b/static/img/playground-21.png index 782cdb50..c9c692e8 100644 Binary files a/static/img/playground-21.png and b/static/img/playground-21.png differ diff --git a/static/img/playground-24.png b/static/img/playground-24.png new file mode 100644 index 00000000..ff5b59cb Binary files /dev/null and b/static/img/playground-24.png differ diff --git a/static/img/query-nft-indexer.png b/static/img/query-nft-indexer.png new file mode 100644 index 00000000..6e2244ea Binary files /dev/null and b/static/img/query-nft-indexer.png differ diff --git a/static/img/share-button-playground.png b/static/img/share-button-playground.png new file mode 100644 index 00000000..df1362e9 Binary files /dev/null and b/static/img/share-button-playground.png differ diff --git a/static/img/share-link-playground.png b/static/img/share-link-playground.png new file mode 100644 index 00000000..53ea0854 Binary files /dev/null and b/static/img/share-link-playground.png differ diff --git a/static/img/step-1-allowance.png b/static/img/step-1-allowance.png new file mode 100644 index 00000000..9c981c13 Binary files /dev/null and b/static/img/step-1-allowance.png differ diff --git a/static/img/step-10-allowance.png b/static/img/step-10-allowance.png new file mode 100644 index 00000000..24fef26f Binary files /dev/null and b/static/img/step-10-allowance.png differ diff --git a/static/img/step-11-allowance.png b/static/img/step-11-allowance.png new file mode 100644 index 00000000..3f1fc053 Binary files /dev/null and b/static/img/step-11-allowance.png differ diff --git a/static/img/step-12-allowance.png b/static/img/step-12-allowance.png new file mode 100644 index 00000000..40618c1b Binary files /dev/null and b/static/img/step-12-allowance.png differ diff --git a/static/img/step-13-allowance.png b/static/img/step-13-allowance.png new file mode 100644 index 00000000..91605081 Binary files /dev/null and b/static/img/step-13-allowance.png differ diff --git a/static/img/step-14-allowance.png b/static/img/step-14-allowance.png new file mode 100644 index 00000000..06e48ce6 Binary files /dev/null and b/static/img/step-14-allowance.png differ diff --git a/static/img/step-15-allowance.png b/static/img/step-15-allowance.png new file mode 100644 index 00000000..11fca9af Binary files /dev/null and b/static/img/step-15-allowance.png differ diff --git a/static/img/step-16-allowance.png b/static/img/step-16-allowance.png new file mode 100644 index 00000000..7bbff9d1 Binary files /dev/null and b/static/img/step-16-allowance.png differ diff --git a/static/img/step-17-allowance.png b/static/img/step-17-allowance.png new file mode 100644 index 00000000..048e48ba Binary files /dev/null and b/static/img/step-17-allowance.png differ diff --git a/static/img/step-2-allowance.png b/static/img/step-2-allowance.png new file mode 100644 index 00000000..deda9d34 Binary files /dev/null and b/static/img/step-2-allowance.png differ diff --git a/static/img/step-3-allowance.png b/static/img/step-3-allowance.png new file mode 100644 index 00000000..22e087b7 Binary files /dev/null and b/static/img/step-3-allowance.png differ diff --git a/static/img/step-4-allowance.png b/static/img/step-4-allowance.png new file mode 100644 index 00000000..742ccafb Binary files /dev/null and b/static/img/step-4-allowance.png differ diff --git a/static/img/step-5-allowance.png b/static/img/step-5-allowance.png new file mode 100644 index 00000000..45a06687 Binary files /dev/null and b/static/img/step-5-allowance.png differ diff --git a/static/img/step-6-allowance.png b/static/img/step-6-allowance.png new file mode 100644 index 00000000..b9c41842 Binary files /dev/null and b/static/img/step-6-allowance.png differ diff --git a/static/img/step-7-allowance.png b/static/img/step-7-allowance.png new file mode 100644 index 00000000..ad768c35 Binary files /dev/null and b/static/img/step-7-allowance.png differ diff --git a/static/img/step-8-allowance.png b/static/img/step-8-allowance.png new file mode 100644 index 00000000..40363cfa Binary files /dev/null and b/static/img/step-8-allowance.png differ diff --git a/static/img/step-9-allowance.png b/static/img/step-9-allowance.png new file mode 100644 index 00000000..2ba45b05 Binary files /dev/null and b/static/img/step-9-allowance.png differ diff --git a/static/img/subscription-nft-indexer.png b/static/img/subscription-nft-indexer.png new file mode 100644 index 00000000..329b7956 Binary files /dev/null and b/static/img/subscription-nft-indexer.png differ diff --git a/static/img/test-button-playground.png b/static/img/test-button-playground.png new file mode 100644 index 00000000..7fe3fef1 Binary files /dev/null and b/static/img/test-button-playground.png differ diff --git a/static/img/token-claim-success.png b/static/img/token-claim-success.png new file mode 100644 index 00000000..03348676 Binary files /dev/null and b/static/img/token-claim-success.png differ diff --git a/static/pdf/aelf_whitepaper_v2.0.pdf b/static/pdf/aelf_whitepaper_v2.0.pdf index 01f5e210..7d285946 100644 Binary files a/static/pdf/aelf_whitepaper_v2.0.pdf and b/static/pdf/aelf_whitepaper_v2.0.pdf differ