# Join the Asset Chain Academy

Welcome Asset Chain Warriors......

This is a free online school dedicated to onboarding developers, into the world of building Decentralized Applications; for the future of the Web. We are here to help you level up your skills, every step of the way. There are levels that a student can achieve, while progressing on this learning journey.


# Introduction to Asset Chain

Overview of Asset Chain.

Asset Chain is the native blockchain for Xend Finance Real-World Asset OAE (Onchain Asset Environment); with its consensus based on Fantom's Lachesis consensus.

This enables a fast, scalable, and secure smart contract platform.

[Lachesis](https://docs.fantom.foundation/technology/lachesis-abft), is a revolutionary aBFT consensus mechanism, that allows Asset Chain to be faster and cheaper than previous technologies while retaining security.

Asset Chain is:

* Permissionless
* Decentralized
* Open source

Learn more about how AssetChain works here:

{% embed url="<https://docs.assetchain.org/readme/introducing-asset-chain>" %}


# Environment Setup & Installation

Get started with Asset Chain

Download and install the following repository by the Asset Chain team to setup your assetchain development environment!

The Dapp example uses several libraries that will help you develop, but make sure that you have [Git](https://git-scm.com/downloads), [Node](https://nodejs.org/en/download/), and [Yarn ](https://classic.yarnpkg.com/en/docs/install/#windows-stable)installed already.

Use any of your favorite code editors with [Solidity support](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity).[ ](https://github.com/foundry-rs/foundry)[Foundry ](https://book.getfoundry.sh/)or [Hardhat (recommended) ](https://hardhat.org/)would also be good to use in any of your new dApp projects as they provide local blockchain development environments.

{% embed url="<https://github.com/xendfinance/assetchain-starterkits>" %}

{% hint style="info" %}
Do make sure you star the respository
{% endhint %}


# Contributing

The Academy is designed in a way that makes it easy for new Asset Chain developers to contribute educational resources.

If you'd like to create your own tutorial on building with Asset Chain, or would like to suggest an existing tutorial, please submit it at the link below. We are open to all forms of educational content; blog posts, courses, videos, GitHub repositories, even infographics!

{% embed url="<https://github.com/xendfinance/assetchain-academy-home?tab=readme-ov-file#want-to-contribute>" %}
contribution and submission link
{% endembed %}

In addition, please report any issues or bugs as issues specific to each Asset Chain Academy Dapp repo. Including steps on what went wrong, also helps the bug-fixing process.

The [Asset Chain Academy Repo](https://github.com/xendfinance/assetchain-academy-home) is open-sourced and actively maintained.


# Asset Chain Starter Kits

Get started building Dapps supporting Asset Chain

## Web Starter Kit

Download and install this repository to use as a boilerplate for building your web apps on Asset Chain. This contains all the NextJS code you need to start, as well as starter solidity contracts for smart contract development.

{% @github-files/github-code-block %}

Also, you can run the cmd below to start a new project using the Asset Chain NextJS StarterKit:

```sh
> npx create-next-app@latest --example "https://github.com/xendfinance/assetchain-web-starterkit" [your-project-name]
```

## React native (Expo) Mobile Starter Kit

Clone the repository below to use as a boilerplate to build Dapp on mobile using React native.

There are two templates in separate branches: the main branch contains the template for using Wagmi, while the ethers branch contains the template for using Ethers v6.

{% @github-files/github-code-block %}

Alternatively, to start a new project using the Asset Chain React Native Starterkit, run:

```bash
> npx create-expo-app project-name --template assetchain-react-native-starterkit
```

## Telegram App Starter Kit

Clone the repository below to use as a boilerplate to build Telegram Apps on Asset Chain using NextJS.

{% @github-files/github-code-block %}

Alternatively, to start a new project using the Asset Chain Telegram App Starter Kit, run:

```bash
> npx create-next-app@latest --example "https://github.com/xendfinance/assetchain-telegram-demo-app" [your-project-name]
```


# Resources Explained

The resources in this module are extensive in their depth, browse through each of them as you'd like. You don't have to complete all associated projects within each resource, just familiarize yourself with them; later on in the academy you'll refer back to them to complete assignments.

* Cyfrin Updraft
* Learnweb3
* Chainlink Bootcamp
* Alchemy University
* Smart Contract Programmer


# Cyfrin Updraft

Cyfrin Updraft is a free education platform to learn web3 and smart contracts development. Helping developers kickstarting and levelling up their careers as blockchain engineers, and security auditors. It offers the very same courses that taught tens of thousands of developers how to get into the web3 industry, completely for free.

{% embed url="<https://updraft.cyfrin.io/>" %}
cyfrin updraft website
{% endembed %}


# Learnweb3

LearnWeb3 is an educational ecosystem in Web3. They offer a wide range of educational courses, resources, and tools that are designed to help developers learn and grow in the Web3 space.

{% embed url="<https://learnweb3.io/>" %}
learnWeb3 website
{% endembed %}


# Chainlink Bootcamps

Chainlink bootcamps are educational programs designed to teach developers how to create and deploy smart contracts, primarily using Solidity for all Evm chains (including AssetChain). These bootcamps are offered by Chainlink, a decentralized oracle network that provides reliable inputs and outputs for smart contracts on any blockchain.

{% embed url="<https://www.youtube.com/playlist?list=PLVP9aGDn-X0QM3cipOC9YGrFkrhio4Lzw>" %}
chainlink 2024 bootcamp
{% endembed %}

{% embed url="<https://chain.link/bootcamp>" %}
bootcamp on demand
{% endembed %}


# Alchemy University

Alchemy University offers programs and courses focused on blockchain and cryptocurrency education. They provide resources for developers, entrepreneurs, and enthusiasts looking to deepen their knowledge and skills in the blockchain space

{% embed url="<https://www.alchemy.com/university>" %}
alchemy university's website
{% endembed %}


# Smart Contract Programmer

This channel provides free education about smart contracts on open decentralized blockchains. Their courses explore cutting edge innovations in smart contract programming, security and applications.

{% embed url="<https://www.youtube.com/@smartcontractprogrammer/playlists>" %}


# Create a Token

In this section we'll get you to create a token on Asset Chain in less than 10 minutes.

Let’s see how to deploy a smart contract on Asset Chain using the [Remix IDE](https://remix.ethereum.org/) for simplicity.

#### Get everything ready <a href="#get-everything-ready" id="get-everything-ready"></a>

Before getting started:

1. Follow for the step-by-step on how to add Asset Chain testnet to [Metamask](https://ebubes-organization.gitbook.io/asset-chain-docs/general-info/add-assetchain)[.](https://docs.assetchain.org/general-info/add-asset-chain#testnet)
2. This guide assumes you have got Testnet RWA and connected to the Asset Chain Testnet Network. Learn how to do that in [Testnet Faucets](https://docs.assetchain.org/tools/faucets).

We are ready to get started!

#### Remix & Sample Code <a href="#remix-and-sample-code" id="remix-and-sample-code"></a>

[Remix](https://remix.ethereum.org/) is a no-setup tool for developing smart contracts. It’s easy to get started allowing a simple deployment process, debugging, interacting with smart contracts, and more. It’s a great tool to test quick changes and interact with deployed smart contracts.

<figure><img src="https://ebubes-organization.gitbook.io/~gitbook/image?url=https%3A%2F%2F1906945388-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FfOxLaEO4KRS4jU54Jd4B%252Fuploads%252F8cCcVj21VWwlHNfIR1Nd%252FScreenshot%25202024-05-14%2520at%252011.24.15%25E2%2580%25AFAM.png%3Falt%3Dmedia%26token%3Df878a3ac-3cd8-487b-8dc1-060e8557fc9e&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=86800c2ffbabf40093a9dc4b1fa8d1d42c88bc889926efce051df940c75297f9" alt=""><figcaption><p>smart contract code sample</p></figcaption></figure>

For the sake of this tutorial, we will be deploying the ‘ERC20Token.sol’ smart contract for minting a fungible token, but you can use any of your code.

You can copy and then paste this in Remix or use your own contract code. Here's the sample code:

ERC20Token.sol

Copy

```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.3/contracts/token/ERC20/ERC20.sol";

contract ERC20Token is ERC20 {
    constructor(string memory _name, string memory _symbol)
        ERC20(_name, _symbol)
    {
        _mint(msg.sender, 1000000000 * 10**decimals());
    }
}
```

#### Steps to deploy <a href="#steps-to-deploy" id="steps-to-deploy"></a>

1. Copy the sample code and paste it in one of the .sol files in Remix
2. To compile your smart contract, go to the `Solidity Compiler tab` and select the contract you want to compile
3. Click on "Compile", you can also enable "Auto Compile" for automatic compilation whenever you change the contract code.

Make sure to open the advanced configurations and setting the EVM version to London. This is to avoid an issue with the `PUSH0` opcode.

1. Once the smart contract is compiled successfully, switch to the "`Deploy & Run Transactions`" tab.
2. In the "`Environment`" dropdown menu, select "`Injected Provider - MetaMask`"; this will connect your MetaMask to Remix and will allow you to make transactions from that connected wallet.

Make sure to have AssetChain Testnet as your selected network in Metamask before deploying.

1. Select the compiled contract you want to deploy and click ‘Deploy.’

Now, MetaMask should pop up and ask you to confirm the transaction with super low fees.

<figure><img src="https://ebubes-organization.gitbook.io/~gitbook/image?url=https%3A%2F%2F1906945388-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FfOxLaEO4KRS4jU54Jd4B%252Fuploads%252Fe7GWwqbZDLKk1GRKIHKy%252FScreenshot%25202024-05-17%2520at%25204.06.07%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3Dc1c47380-58a5-44ff-aa1f-849b6eee223a&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=991f9332bdaf8b79e063e0534dc538dd54818e9ad862d6f18f361555f30575af" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
**Congratulations! You just deployed your first smart contract to Asset Chain.**
{% endhint %}

If you have questions, join our [Telegram](https://t.me/XendFinanceDevs) and say hello 👋. We're Active!


# Write & Deploy an NFT

With NFTs bringing blockchain into the public eye, now is an excellent opportunity to understand the hype yourself by publishing your own NFT contract (ERC-721 Token) on the Asset Chain blockchain!.

In this tutorial, we will walk through creating and deploying an ERC-721 smart contract on the Asset Chain test network using [MetaMask](https://metamask.io/), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), and [Hardhat](https://hardhat.org/),

### STEP 1: CREATE AN ASSET CHAIN ACCOUNT (ADDRESS) <a href="#connect-to-ethereum" id="connect-to-ethereum"></a>

We need an Asset Chain account to send and receive transactions. For this tutorial, we’ll use MetaMask, a virtual wallet in the browser used to manage your Asset chain account address.

You can download and create a MetaMask account for free [here](https://metamask.io/download.html). When you are creating an account, or if you already have an account, make sure to switch over to the “[Asset Chain Testnet](https://docs.assetchain.org/general-info/add-asset-chain#testnet)”

<figure><img src="/files/kTDm5U1i6mR8oKFYDON4" alt=""><figcaption></figcaption></figure>

### STEP 2: ADD RWA FROM A FAUCET <a href="#step-4-add-ether-from-a-faucet" id="step-4-add-ether-from-a-faucet"></a>

In order to deploy our smart contract to the test network, we’ll need some fake RWA. To get RWA you can go to the [$RWA Faucet](https://faucet.assetchain.org/), enter your account address, click “start mining”. You should see RWA in your MetaMask account soon after!

<figure><img src="/files/mLxwubuXdtQ8X2hVed4h" alt=""><figcaption></figcaption></figure>

### STEP 3: FORK AND CLONE THIS STARTER KITS <a href="#connect-to-ethereum" id="connect-to-ethereum"></a>

{% embed url="<https://github.com/xendfinance/Write-Deploy-an-NFT/>" %}

go to your terminal , navigate to the folder and install neccssary dependencies using `yarn install`.

### STEP 4: WRITE OUR CONTRACT <a href="#write-contract" id="write-contract"></a>

Now that our environment is set up, on to more exciting stuff: *writing our smart contract code!*

Open up the my-nft project in your favorite editor (we like [VSCode](https://code.visualstudio.com/)). Smart contracts are written in a language called Solidity which is what we will use to write our NFT.sol smart contract.‌

1. Navigate to the `contracts` folder and create a new file called NFT.sol
2. Below is our NFT smart contract code, which we based on the [OpenZeppelin](https://docs.openzeppelin.com/contracts/3.x/erc721) library’s ERC-721 implementation. Copy and paste the contents below into your NFT.sol file.

```solidity
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {ERC721URIStorage} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";

contract NFT is ERC721URIStorage {
	uint256 private _nextTokenId;

    constructor() ERC721("MyNFT", "ATM") {}
     function mintNft(address  recipient, string memory tokenURI)
        public
        returns (uint256)
    {
        uint256 tokenId = _nextTokenId++;
        _mint(recipient, tokenId);
        _setTokenURI(tokenId, tokenURI);

        return tokenId;
    }
}


```

So, what does this code *do* exactly? Let’s break it down, line-by-line.

At the top of our smart contract, we import three [OpenZeppelin](https://openzeppelin.com/) smart contract classes:

* The [`ERC721URIStorage`](https://docs.openzeppelin.com/contracts/5.x/api/token/ERC721#ERC721URIStorage) contract is an implementation of ERC721 that includes the metadata standard extensions ([`IERC721Metadata`](https://docs.openzeppelin.com/contracts/5.x/api/token/ERC721#IERC721Metadata)) as well as a mechanism for per-token metadata. That’s where the [`_setTokenURI`](https://docs.openzeppelin.com/contracts/5.x/api/token/ERC721#ERC721-_setTokenURI-uint256-string-) method comes from: we use it to store an item’s metadata.
* @openzeppelin/contracts/access/Ownable.sol sets up [access control](https://docs.openzeppelin.com/contracts/3.x/access-control) on our smart contract, so only the owner of the smart contract (you) can mint NFTs. (Note, including access control is entirely a preference. If you'd like anyone to be able to mint an NFT using your smart contract, remove the word Ownable on line 10 and onlyOwner on line 17.)

After our import statements, we have our custom NFT smart contract, which is surprisingly short — it only contains a counter, a constructor, and single function! This is thanks to our inherited OpenZeppelin contracts, which implement most of the methods we need to create an NFT, such as `ownerOf` which returns the owner of the NFT, and `transferFrom`, which transfers ownership of the NFT from one account to another.

In our ERC-721 constructor, you’ll notice we pass 2 strings, “MyNFT” and “NFT.” The first variable is the smart contract’s name, and the second is its symbol. You can name each of these variables whatever you wish!

Finally, we have our function `mintNFT(address recipient, string memory tokenURI)` that allows us to mint an NFT! You'll notice this function takes in two variables:

* `address recipient` specifies the address that will receive your freshly minted NFT
* `string memory tokenURI` is a string that should resolve to a JSON document that describes the NFT's metadata. An NFT's metadata is really what brings it to life, allowing it to have configurable properties, such as a name, description, image, and other attributes. In part 2 of this tutorial, we will describe how to configure this metadata.

`mintNFT` calls some methods from the inherited ERC-721 library, and ultimately returns a number that represents the ID of the freshly minted NFT.

### STEP 5: CONNECT METAMASK TO YOUR PROJECT <a href="#connect-metamask-and-alchemy" id="connect-metamask-and-alchemy"></a>

Now that we’ve created a MetaMask wallet and written our smart contract, it’s time to connect the two.

Every transaction sent from your virtual wallet requires a signature using your unique private key. To provide our program with this permission, we can safely store our private key in an environment file.

create a `.env` file in the root directory of our project, and add your MetaMask private key

* Follow [these instructions](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) to export your private key from MetaMask

Your `.env` should now look like this:

```
DEPLOYER_PRIVATE_KEY="your-metamask-private-key"
```

### STEP 6: UPDATE OUR DEPLOYMENT SCRIPTS <a href="#compile-contract" id="compile-contract"></a>

Now that our contract is written and our configuration file is good to go, it’s time to write our contract deploy script.

Navigate to the `deploy/00_deploy_your_contract.ts` folder , adding the following contents to it:

```

import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";

/**
 * Deploys a contract named "YourContract" using the deployer account and
 * constructor arguments set to the deployer address
 *
 * @param hre HardhatRuntimeEnvironment object.
 */
const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
  /*

    When deploying to live networks (e.g `yarn deploy --network assetchain_testnet`), the deployer account
    should have sufficient balance to pay for the gas fees for contract creation.

    You can generate a random account with `yarn generate` which will fill DEPLOYER_PRIVATE_KEY
    with a random private key in the .env file (then used on hardhat.config.ts)
    You can run the `yarn account` command to check your balance in every network.
  */
  const { deployer } = await hre.getNamedAccounts();
  const { deploy } = hre.deployments;

  const myNft = await deploy("NFT", {
    from: deployer,
    log: true,
    // autoMine: can be passed to the deploy function to make the deployment process faster on local networks by
    // automatically mining the contract deployment transaction. There is no effect on live networks.
    autoMine: true,
  });


  console.log("👋 NFT Contract Address:", myNft.address);
};

export default deployYourContract;

// Tags are useful if you have multiple deploy files and only want to run one of them.
// e.g. yarn deploy --tags NFT
deployYourContract.tags = ["NFT"];


```

### STEP 16: DEPLOY OUR CONTRACT <a href="#deploy-contract" id="deploy-contract"></a>

We’re finally ready to deploy our smart contract! Navigate back to the root of your project directory, and in the command line run:

```
yarn deploy --network assetchain_testnet
```

You should then see something like:

```
👋 NFT Contract Address: 0x342E4f63a50D2328fe127fbC5cfdFD5a16e047eA
```

{% hint style="success" %}
Congratulations! Your contract is successfully depolyed on Asset Chain Blockchain.
{% endhint %}

If we go to the [Asset Chain explorer ](https://testnet.assetchain.org/)and search for our contract address we should be able to see that it has been deployed successfully.

See the Completed Code Below 👇

{% embed url="<https://github.com/xendfinance/Write-Deploy-an-NFT/tree/updated>" %}

If you have questions, join our [Telegram](https://t.me/XendFinanceDevs) and say hello 👋. We're Active!


# Mint an NFT

This tutorial describes how to mint an NFT using the viem and the smart contract from Part I:  Write & deploy an Nft.

### Step 1: Download NFT Minter starterkits

Download the starter kits below that contains the contract code from the previous project: Write and Deploy an Nft.

{% embed url="<https://github.com/xendfinance/Mint-an-Nft>" %}
mint nft starter kits
{% endembed %}

follow the guidlines on the [README.md](https://github.com/xendfinance/Mint-an-Nft/blob/main/README.md) file to get your starter kits ready.

Doing so should open <http://localhost:3000/> in your browser, where you'll see the frontend for our project. It should consist of 3 fields: a place to input a link to your NFT's asset, enter the name of your NFT, and provide a description.

<figure><img src="/files/EdJfzXI4Dh4DYG6j3yuf" alt=""><figcaption><p>What your UI should look like.</p></figcaption></figure>

### Step 2: NFT Metadata 101

So remember the NFT metadata we just talked about in Step 1 of this tutorial—it brings an NFT to life, allowing it to have properties, such as a digital asset, name, description, and other attributes.

We're going to need to configure this metadata as a JSON object and store it, so we can pass it in as the `tokenURI` parameter when calling our smart contract's `mintNFT` function.

The text in the "Link to Asset", "Name", "Description" fields will comprise the different properties of our NFT's metadata. We'll format this metadata as a JSON object, but there are a couple options for where we can store this JSON object:

* We could store it on the Asset Chain blockchain; however, doing so would be SUPER expensive (we're talking upwards of hundreds of dollars).
* We could store it on a centralized server, like AWS or Firebase. But that would defeat our decentralization ethos. ❌
* We could use IPFS, a decentralized protocol and peer-to-peer network for storing and sharing data in a distributed file system. As this protocol is decentralized and free, it is our best option! ✅

To store our metadata on IPFS, we will use [Pinata](https://pinata.cloud/), a convenient IPFS API and toolkit. In the next step, we'll explain exactly how to do this!

### Step 3: Use [Pinata](https://pinata.cloud/) to pin your metadata to IPFS

If you don't have a Pinata account, sign up for a free account [here](https://pinata.cloud/signup) and complete the steps to verify your email and account.

#### Create your Pinata API key

Navigate to the <https://app.pinata.cloud/developers/api-keys> page, then select the "New Key" button at the top, set the Admin widget as enabled, and name your key.

<figure><img src="/files/RqYOBMNkpWQnu1kzwuqQ" alt=""><figcaption><p>Create your Pinata API key</p></figcaption></figure>

You'll then be shown a popup with your API info. Make sure to put this somewhere safe.

<figure><img src="/files/tXIYl9bEOQ33oH9jAPHt" alt=""><figcaption><p>Make sure to save your API key and secret in a safe place</p></figcaption></figure>

Create a .env file

create a `.env` file in the root directory of your frontend and navigate to your `.env` file and add your Pinata API key and API secret to it, like so:

```
NEXT_PUBLIC_PINATA_KEY=<pinata-api-key>
NEXT_PUBLIC_PINATA_SECRET=<pinata-api-secret>
```

Save the file, and then you're ready to start writing the function to upload your JSON metadata to IPFS!

#### Implement `pinJSONToIPFS`

Fortunately for us, Pinata has an [API specifically for uploading JSON data to IPFS](https://pinata.cloud/documentation#PinJSONToIPFS) and a convenient JavaScript with axios example that we can use, with some slight modifications.

In your `utils` folder, let's create another file called `pinPinata.ts` and then import our Pinata secret and key from the .env file like so:

```typescript
const key = process.env.NEXT_PUBLIC_PINATA_KEY;
const secret = process.env.NEXT_PUBLIC_PINATA_SECRET;
```

Next, paste the additional code from below into your `pinPinata.ts` file. Don't worry, we'll break down what everything means!

```typescript
import axios from "axios";
import toast from "react-hot-toast";

const key = process.env.NEXT_PUBLIC_PINATA_KEY;
const secret = process.env.NEXT_PUBLIC_PINATA_SECRET;


export const pinJsontoIPFS = async (JsonFile: any) => {
  const url = "https://api.pinata.cloud/pinning/pinJSONToIPFS";


  try {
    const res = await axios.post(url, JsonFile, {
      headers: {
        'pinata_api_key': key,
        'pinata_secret_api_key': secret,
      },
    });
    return "https://gateway.pinata.cloud/ipfs/" + res.data.IpfsHash;

  } catch (e: any) {
    toast.error(e.message);
  }
};

```

So what does this code do exactly?

First, it imports [axios](https://www.npmjs.com/package/axios), a promise based HTTP client for the browser and node.js, which we will use to make a request to Pinata.

Then we have our asynchronous function `pinJSONToIPFS`, which takes a `JSONBody` as its input and the Pinata api key and secret in its header, all to make a POST request to their`pinJSONToIPFS` API.

* If this POST request is successful, then our function returns a`hashstring` where our metadata was pinned. We will use this `hashstring` returned as the `tokenURI` input to our smart contract's mint function.
* If this post request fails, then our function returns a JSON object with the a `message` string that relays our error.

### Step 4: Implement the `MintNFt` function

Inside your `Debug.tsx` file, let's define our function, `MintNFt` , which will mint our NFT as the name implies.

The three inputs to our function will be the `url` of our digital asset, `name`, and `description`.

#### Input error handling

Naturally, it makes sense to have some sort of input error handling at the start of the function, so we exit this function if our input parameters aren't correct. Inside our function, let's add the following code:

```typescript
 if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
      toast.error(
        "❗Please make sure all fields are completed before minting."
      );
      setLoading(false);
    }
```

Essentially, if any of the input parameters are an empty string, then we return a JSON object where the `toast.error` string relays that all fields in our UI must be complete.

#### Upload the metadata to IPFS

Once we know our metadata is formatted properly, the next step is to wrap it into a JSON object and upload it to IPFS via the `pinJSONToIPFS` we wrote!

To do so, we firstly need to import the `pinJSONToIPFS` function into our `Debug.tsx` file. At the very top of the `Debug.tsx`, let's add:

```typescript
import { pinJsontoIPFS } from "@/utils/pinPinata";
```

Recall that `pinJSONToIPFS` takes in a JSON body. So before we make a call to it, we're going to need to format our `url`, `name`, and `description` parameters into a JSON object.

```typescript

 if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
      toast.error(
        "❗Please make sure all fields are completed before minting."
      );
      setLoading(false);
    }

    setLoading(true);
    const metaData = {
      url: url,
      name: name,
      description: description,
    };
    const pinataResponse = await pinJsontoIPFS(metaData);

```

The last thing to add in our `mintNFT` function is our Ethereum transaction:

```typescript

 if (!account) return;
    const { request } = await publicClient.simulateContract({
      address: deployedContracts.assetchain_testnet.address as `0x${string}`,
      abi: deployedContracts.assetchain_testnet.abi,
      functionName: "mintNft", //refrence to the smartcontract code to get the function name
      //This args object takes in the two arguments needed in the mintNft function
      args: [account, pinataResponse],
      account,
    });
    const hash = await walletClient.writeContract(request);

```

That's a giant function! Below is the full code example of the MintNFT function

```typescript
const MintNFt = async () => {
    if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
      toast.error(
        "❗Please make sure all fields are completed before minting."
      );
      setLoading(false);
    }

    setLoading(true);
    const metaData = {
      url: url,
      name: name,
      description: description,
    };
    const pinataResponse = await pinJsontoIPFS(metaData);

    toast.success("Successfully Upload Metadata to IPFS", {
      duration: 4000,
    });
    toast.loading("Minting Nft.........", {
      duration: 8000,
    });

    if (!account) return;
    const { request } = await publicClient.simulateContract({
      address: deployedContracts.assetchain_testnet.address as `0x${string}`,
      abi: deployedContracts.assetchain_testnet.abi,
      functionName: "mintNft",
      args: [account, pinataResponse],
      account,
    });
    console.log("pinataResponse", pinataResponse);
    const hash = await walletClient.writeContract(request);
    setTransactionHash(hash);
     toast.success("Successfully Minted your NFT", {
       duration: 4000,
     });
     setLoading(false);
  };
```

{% hint style="success" %}
Hurray, Your`NFtMinter Project` is Complete.
{% endhint %}

Below are link to preview project and the Completed Code for the Nft Minter

{% embed url="<https://mint-an-nft.pages.dev/>" %}
live link to preview the nft minter
{% endembed %}

{% embed url="<https://github.com/xendfinance/Mint-an-Nft/tree/updated>" %}
updated codebase
{% endembed %}

If you have questions, join our [Telegram](https://t.me/XendFinanceDevs) and say hello 👋. We're Active!


# Asset Chain Explorers

View all transactions carried out on the asset chain!!!

{% embed url="<https://www.loom.com/share/e9c8bf9346a64c6dada9da66f8fb3a64?sid=f99b44ce-69d2-4af5-889c-b5efabde9074>" %}


# Payments

In this Tutorial, we will be building a simple payment project where we get to donate to a smart contract using the `RWA` token.

### Step 1: DOWNLOAD THE STARTERKITS

Download the starter kits below to get started in building fundme projects

{% embed url="<https://github.com/xendfinance/assetchain-starterkits>" %}

follow the guidlines on the [README.md](https://github.com/xendfinance/assetchain-starterkits/blob/main/README.md) file to get your starter kits ready.

### Step 2: WRITING OUR FUNDME CONTRACT

Now that our environment is set up, on to more exciting stuff: *writing our smart contract code*

Open up the `hardhat` project in your favorite editor (we like [VSCode](https://code.visualstudio.com/)). Smart contracts are written in a language called Solidity which is what we will use to write our NFT.sol smart contract.‌

Navigate to the `contracts` folder and create a new file called `FundMe.sol`

Below is our smart contract code, Copy and paste the contents below into your `FundMe.sol` file.

```solidity
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

contract FundMe {
    address public owner;
    uint256 public totalDonations;
    address[] donators;
    
    mapping(address => uint256) public donations;

    event DonationReceived(address donor, uint256 amount);
    event FundsWithdrawn(address owner, uint256 amount);

    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can perform this action");
        _;
    }
    constructor() {
        owner = msg.sender;
    }

    function donate() external payable {
        require(msg.value > 0, "Donation amount should be greater than zero");

        donations[msg.sender] += msg.value;
        totalDonations += msg.value;
        donators.push(msg.sender);

        emit DonationReceived(msg.sender, msg.value);
    }

    function withdrawFunds() external onlyOwner {
        uint256 amount = address(this).balance;
        require(amount > 0, "No funds to withdraw");
        payable(owner).transfer(amount);
        emit FundsWithdrawn(owner, amount);
    }

    function getDonationDetails(address _donor) external view returns (uint256) {
        return donations[_donor];
    }
}
```

So, what does this code *do* exactly? Let’s break it down, line-by-line.

1. **License Declaration(**`// SPDX-License-Identifier: MIT` ): Specifies the software license for the code, which is the MIT license in this case.
2. **Pragma Directive(**`pragma solidity >=0.8.0 <0.9.0;` ): Specifies the version of Solidity compiler that can compile this contract, which should be any version from 0.8.0 up to, but not including, 0.9.0.
3. **Contract Declaration(**`contract FundMe`): Declares the start of a smart contract named `FundMe`.
4. **State Variables**:
   * `address public owner;`: Stores the address of the contract owner and makes it publicly accessible.
   * `uint256 public totalDonations;`: Stores the total amount of donations received and makes it publicly accessible.
   * `address[] donators;`: Stores a list of addresses that have donated.
   * `mapping(address => uint256) public donations;`: Maps donor addresses to the amount they have donated and makes it publicly accessible.
5. **Events**:
   * `event DonationReceived(address donor, uint256 amount);`: Declares an event that is emitted when a donation is received, including the donor's address and the donation amount.
   * `event FundsWithdrawn(address owner, uint256 amount);`: Declares an event that is emitted when funds are withdrawn, including the owner's address and the withdrawn amount.
6. **Modifier**: `modifier onlyOwner()`
   * `require(msg.sender == owner, "Only owner can perform this action");`: Ensures that the function using this modifier can only be called by the contract owner.
   * `_;`: Placeholder that represents the function's body where the modifier is applied.
7. **Constructor**: `constructor()`
   * `owner = msg.sender;`: Sets the owner of the contract to the address that deploys the contract.
8. **Function to Donate**: `function donate()`
   * `external payable`: A function declared as `external` can only be called from outside the contract and When a function is marked as `payable`, it can receive `RWA token`, and the value sent with the transaction (in Wei) can be accessed using `msg.value`.
   * `require(msg.value > 0, "Donation amount should be greater than zero");`: Ensures that the donation amount is greater than zero.
   * `donations[msg.sender] += msg.value;`: Updates the donation amount for the sender's address.
   * `totalDonations += msg.value;`: Increases the total donations by the amount sent.
   * `donators.push(msg.sender);`: Adds the donor's address to the list of donators.
   * `emit DonationReceived(msg.sender, msg.value);`: Emits the `DonationReceived` event.
9. **Function to Withdraw Funds**: `function withdrawFunds()`
   * `external onlyOwner` : A function declared as `external` can only be called from outside the contract and when a function is marked `onlyOwner` It ensures that only the owner of the contract can call this function.
   * `uint256 amount = address(this).balance;`: Retrieves the contract's current balance.
   * `require(amount > 0, "No funds to withdraw");`: Ensures that there are funds available to withdraw.
   * `payable(owner).transfer(amount);`: Transfers the contract's balance to the owner's address.
   * `emit FundsWithdrawn(owner, amount);`: Emits the `FundsWithdrawn` event.
10. **Function to Get Donation Details**: `function getDonationDetails(address _donor) external view returns (uint256)`
    * `return donations[_donor];`: Returns the donation amount for the specified donor address.

### STEP 3: UPDATE OUR DEPLOYMENT SCRIPTS <a href="#compile-contract" id="compile-contract"></a>

Navigate to the `deploy/00_deploy_your_contract.ts` folder , adding the following contents to it:

```typescript
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";

/**
 * Deploys a contract named "YourContract" using the deployer account and
 * constructor arguments set to the deployer address
 *
 * @param hre HardhatRuntimeEnvironment object.
 */
const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
  /*

    When deploying to live networks (e.g `yarn deploy --network assetchain_testnet`), the deployer account
    should have sufficient balance to pay for the gas fees for contract creation.

    You can generate a random account with `yarn generate` which will fill DEPLOYER_PRIVATE_KEY
    with a random private key in the .env file (then used on hardhat.config.ts)
    You can run the `yarn account` command to check your balance in every network.
  */
  const { deployer } = await hre.getNamedAccounts();
  const { deploy } = hre.deployments;

  await deploy("FundMe", {
    from: deployer,
    // Contract constructor arguments
    log: true,
    // autoMine: can be passed to the deploy function to make the deployment process faster on local networks by
    // automatically mining the contract deployment transaction. There is no effect on live networks.
    autoMine: true,
  });

  // Get the deployed contract to interact with it after deploying.
  // const yourContract = await hre.ethers.getContract<Contract>("Greeter", deployer);
 
};

export default deployYourContract;


// Tags are useful if you have multiple deploy files and only want to run one of them.
// e.g. yarn deploy --tags Greeter
deployYourContract.tags = ["FundMe"];

```

### STEP 4: DEPLOY OUR CONTRACT <a href="#deploy-contract" id="deploy-contract"></a>

We’re finally ready to deploy our smart contract! Navigate back to the root of your hardhat project directory, and in the command line run:

```
yarn deploy --network assetchain_testnet
```

You should then see something like:

`"FundMe" at 0xcaa32C250fbC0cDd13A09c385e33b83e7D3e15F7`

{% hint style="success" %}
Congratulations! Your Fundme contract is successfully depolyed on Asset Chain Blockchain.
{% endhint %}

If we go to the [Asset Chain explorer ](https://testnet.assetchain.org/)and search for our contract address or transaction hash. we should be able to see that it has been deployed successfully.

{% embed url="<https://github.com/xendfinance/fund-me-tutorial/tree/updated/hardhat>" %}
updated codebase for the smart contract
{% endembed %}

### STEP 5: BUILDING OUR FRONTEND AND INTERACTING WITH OUR FRONTEND <a href="#deploy-contract" id="deploy-contract"></a>

coming soon....

Below are link to preview project

{% embed url="<https://fund-me-tutorial.pages.dev/>" %}

### STEP 5: ASSIGNMENT <a href="#deploy-contract" id="deploy-contract"></a>

coming soon....

if you have questions, join our [Telegram](https://t.me/XendFinanceDevs) and say hello 👋. We're Active!


# Building with Thirdweb

Thirdweb simplify the process of building and deploying Web3 applications. it provides a variety of tools and SDKs (Software Development Kits) for developers to integrate blockchain functionality into their apps with minimal code and it also supports Asset Chain.

### Features of Thirdweb

* **Smart Contract Development**: Thirdweb offers pre-built smart contracts that can be easily deployed on various blockchain networks, such as Asset Chain. These contracts cover areas like NFTs, tokens, and marketplaces.
* **Developer SDKs**: It provides SDKs for **JavaScript**, **React**, **Python**, and other languages to interact with smart contracts, enabling developers to manage blockchain operations like token creation, minting, and transferring assets.
* **User Authentication**: Thirdweb supports Web3 wallet integrations (e.g., MetaMask, WalletConnect), making it easy for users to interact with decentralized apps securely.
* **Gasless Transactions**: Thirdweb provides solutions for gasless transactions, where users can interact with the blockchain without paying fees, by allowing the developer to sponsor gas fees.
* **Analytics & Dashboards**: It includes built-in analytics to track contract activity and manage dApps through a visual interface.

### AssetChain on Thirdweb

Through Thirdweb, developers can easily interact with AssetChain via its comprehensive tools and services. visit [AssetChain-Thirdweb](https://thirdweb.com/assetchain-testnet)

* **Leveraging Thirdweb’s Pre-built Contracts:** Thirdweb offers a wide range of pre-built contracts tailored for specific use cases, which can streamline the development process. With AssetChain, you can deploy these contracts to tokenize assets or manage interactions with the blockchain without writing code from scratch. This is particularly useful for asset management, staking, and automated processes.
* **Faucets:** Thirdweb supports AssetChain Faucets, This faucet allows developers to test dApps, deploy contracts, and perform token transactions on the AssetChain testnet without incurring real costs, making it a valuable tool for development.
* **Thirdweb RPC Edge:** A specialized endpoint that allows developers to connect their applications to the AssetChain testnet.
* **Thirdweb Engine:** Thirdweb Engine is an open-source backend server that enhances how developers interact with the **Asset Chain** blockchain at production scale. By integrating Thirdweb Engine with AssetChain, your application can:

1. Send multiple transactions at once, resubmitting any stuck ones.
2. Manage nonce, gas settings, and RPC errors automatically.
3. Deploy contracts and handle smart account interactions.
4. Control backend wallet access for your team.
5. Sponsor gas fees for users, improving their experience.
6. Subscribe to contract events for real-time dApp functionality.

This significantly simplifies the development and scaling of asset-tokenization applications on AssetChain.

<figure><img src="/files/risvZcA9OOkPxWqmvUPY" alt=""><figcaption><p><a href="https://thirdweb.com/assetchain-testnet">https://thirdweb.com/assetchain-testnet</a></p></figcaption></figure>

### Getting Started

To connect your application to Thirdweb, you'll need to create a project on the Thirdweb Dashboard and obtain the Project ID.

#### Sign Up or Log In to the Thirdweb Dashboard

* Visit the [Thirdweb Dashboard](https://thirdweb.com/dashboard).
* If you don't have an account, connect either your wallet , your socials or google account and create an account. If you already have an account, log in.

#### Create a New Project

* After logging in, go to settings
* In the API Key Section, Click on the **Create API Key**

<figure><img src="/files/nf3nx4TC301td7xcmSFQ" alt=""><figcaption></figcaption></figure>

* fill in the necessary details, such as the API key Name and toogle or add domains that will make use of this API key
* confirm that you have saved your Client ID and Secret Key.

<figure><img src="/files/swdcHRJDzeqaXUwLYtlG" alt=""><figcaption></figcaption></figure>

### Setting Up the ReactJs Project

Use any of this Templates Below

* [NextJS Kit for ThirdWeb](https://github.com/thirdweb-example/next-starter)
* [Vite Kit for ThirdWeb](https://github.com/thirdweb-example/vite-starter)

### Configuring Codebase

For this tutorial, we will be making use of the [Vite Kit](https://github.com/thirdweb-example/vite-starter)

Clone the repo to your computer

{% hint style="info" %}
Make sure you have git, nodejs, yarn and npm installed on your computer
{% endhint %}

```sh
git clone https://github.com/thirdweb-example/vite-starter.git
```

Navigate to the folder path

```sh
cd vite-starter
```

Install this packages

```sh
yarn install
```

create a `.env` file in the vite-starter folder and add this code below:

```javascript
VITE_TEMPLATE_CLIENT_ID=5e96774aa6a3b1c72ac45dd1b4ca1e91 //Replace with your own client ID
```

create a `client.ts` file within the `src` folder and add the following codes:

```typescript

import { createThirdwebClient } from "thirdweb";

// Replace this with your client ID string
// refer to https://portal.thirdweb.com/typescript/v5/client on how to get a client ID
const clientId = import.meta.env.VITE_TEMPLATE_CLIENT_ID;
console.log(clientId, "Client ID: ", clientId);
export const client = createThirdwebClient({
  clientId: clientId,
});

```

in your `main.tsx` file, update it with the following codes:

```typescript

import React from "react";
import { createRoot } from "react-dom/client";
import { App } from "./App";
import { ThirdwebProvider } from "thirdweb/react";
import "./index.css";


createRoot(document.getElementById("root")!).render(
  <React.StrictMode >
    <ThirdwebProvider>
      <App />
    </ThirdwebProvider>
  </React.StrictMode>
);


```

create a `assetchain.testnet.ts` file within the `src` folder and the following codes:

```typescript

import { defineChain } from "thirdweb/chains";

export const assetChainTestnet = /* @__PURE__ */ defineChain({
  id: 42421,
  name: "AssetChain Testnet",
  nativeCurrency: {
    name: "Real World Asset",
    symbol: "RWA",
    decimals: 18,
  },
  blockExplorers: [
    {
      name: "Asset Chain Testnet Explorer",
      url: "https://scan-testnet.assetchain.org",
      apiUrl: "https://scan-testnet.assetchain.org/api",
    },
  ],
  testnet: true,
});

```

in your `App.tsx` file , update it with the codes below,

```typescript

import { ConnectButton } from "thirdweb/react";
import thirdwebIcon from "./thirdweb.svg";
import { client } from "./client";
import { assetChainTestnet} from "./assetchain.testnet";

export function App() {
	return (
    <main className="p-4 pb-10 min-h-[100vh] flex items-center justify-center container max-w-screen-lg mx-auto">
      <div className="py-20">
        <Header />

        <div className="flex justify-center mb-20">
          <ConnectButton
            client={client}
            appMetadata={{
              name: "ThirdwebConnect",
              url: "https://example.com",
            }}
            chain={assetChainTestnet}
          />
        </div>

        <ThirdwebResources />
      </div>
    </main>
  );
}

function Header() {
	return (
		<header className="flex flex-col items-center mb-20 md:mb-20">
			<img
				src={thirdwebIcon}
				alt=""
				className="size-[150px] md:size-[150px]"
				style={{
					filter: "drop-shadow(0px 0px 24px #a726a9a8)",
				}}
			/>

			<h1 className="text-2xl md:text-6xl font-bold tracking-tighter mb-6 text-zinc-100">
				thirdweb SDK
				<span className="text-zinc-300 inline-block mx-1"> + </span>
				<span className="inline-block -skew-x-6 text-violet-500"> vite </span>
			</h1>

			<p className="text-zinc-300 text-base">
				Read the{" "}
				<code className="bg-zinc-800 text-zinc-300 px-2 rounded py-1 text-sm mx-1">
					README.md
				</code>{" "}
				file to get started.
			</p>
		</header>
	);
}

function ThirdwebResources() {
	return (
		<div className="grid gap-4 lg:grid-cols-3 justify-center">
			<ArticleCard
				title="thirdweb SDK Docs"
				href="https://portal.thirdweb.com/typescript/v5"
				description="thirdweb TypeScript SDK documentation"
			/>

			<ArticleCard
				title="Components and Hooks"
				href="https://portal.thirdweb.com/typescript/v5/react"
				description="Learn about the thirdweb React components and hooks in thirdweb SDK"
			/>

			<ArticleCard
				title="thirdweb Dashboard"
				href="https://thirdweb.com/dashboard"
				description="Deploy, configure, and manage your smart contracts from the dashboard."
			/>
		</div>
	);
}

function ArticleCard(props: {
	title: string;
	href: string;
	description: string;
}) {
	return (
		<a
			href={`${props.href}?utm_source=vite-template`}
			target="_blank"
			className="flex flex-col border border-zinc-800 p-4 rounded-lg hover:bg-zinc-900 transition-colors hover:border-zinc-700"
			rel="noreferrer"
		>
			<article>
				<h2 className="text-lg font-semibold mb-2">{props.title}</h2>
				<p className="text-sm text-zinc-400">{props.description}</p>
			</article>
		</a>
	);
}

```

Once everything is updated, open your terminal and run the command below to start the server:

```sh
yarn dev
```

To conclude, the code example demonstrates how to successfully connect to the Asset Chain Network using Thirdweb.

Thirdweb paves the way for efficient and scalable blockchain development, empowering developers to build decentralized applications (dApps) with less friction while maintaining performance and security standards.


# Mobile Apps on Asset Chain

## React Native (Expo) demo App

In this section, we are going to **build a demo application using React Native**, a popular framework for creating mobile apps that work on both iOS and Android platforms. The development environment we will use is **Expo**, which simplifies the process of building and testing React Native applications by providing tools and services for running the app on devices and emulators without needing to deal with complex setup processes. The application will connect to the **Assetchain testnet network**. The application will enable users to send **test RWA native tokens**

{% embed url="<https://github.com/xendfinance/assetchain-expo-demo-app.git>" %}

## Requirements

Before you begin, you need to install the following tools:

* [Node (>= v18.17)](https://nodejs.org/en/download/)
* [Yarn](https://yarnpkg.com/getting-started/install)
* [Git](https://git-scm.com/downloads)
* Metamask([IOS](https://apps.apple.com/us/app/metamask-blockchain-wallet/id1438144202), [Android](https://play.google.com/store/apps/details?id=io.metamask\&hl=en_US)) Ensure you download and install Metamask Wallet on your Target Mobile Device
* Expo go ([IOS](https://apps.apple.com/us/app/expo-go/id982107779), [Android](https://play.google.com/store/apps/details?id=host.exp.exponent\&hl=en_US)) Ensure you download and install Expo go App on your Target Mobile Device

## Technology Used

* [Expo](https://docs.expo.dev/)
* [Wallet Connect](https://walletconnect.com/)
* [Wagmi](https://wagmi.sh/)

## Environment Setup

To get started with Asset Chain Mobile Demo App, follow the steps below:

1. Clone this repo & install dependencies

```bash
git clone https://github.com/xendfinance/assetchain-expo-demo-app.git
cd assetchain-expo-demo-app
yarn
```

2. Add enivoronmental Variables. To connect your application to WalletConnect, you'll need to create a project on the WalletConnect Dashboard and obtain the Project ID.

### Sign Up or Log In to the WalletConnect Dashboard

* Visit the [WalletConnect Dashboard](https://cloud.walletconnect.com/)
* If you don't have an account, sign up with your email and create a new account. If you already have an account, log in.

### Create a New Project

* After logging in, you’ll see an option to create a new project.
* Click on **"Create"** and fill in the necessary details, such as the project name
* Once the project is created, you’ll be redirected to the project’s dashboard.

<figure><img src="/files/tc3s2GkXnon7WMrYsFoF" alt=""><figcaption></figcaption></figure>

### Obtain Your Project ID

* In the project dashboard, you’ll find the **Project ID** under the project details.
* Copy the Project ID. You will use this ID in your ReactJS project to configure WalletConnect.

<figure><img src="/files/kHLhQ2T7YtHFlW6lbp28" alt=""><figcaption></figcaption></figure>

Generate .env file to your project root folder by running the command:

```bash
$ cp .env.example .env
```

In your .env file generated set WALLECT\_CONNECT\_PROJECTID to your Wallet conect project Id

3. Running Application To Start Application, Run the command

```bash
yarn start
```

then, scan the QR code displayed on your terminal using the Expo Go app on your mobile device.

## setting up the web3modal

in the entry file (App.tsx)

```typescript
import "@walletconnect/react-native-compat";
import { WagmiProvider } from "wagmi";
import { RootSiblingParent } from "react-native-root-siblings";
import { assetChainTestnet } from "@wagmi/core/chains";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
  createWeb3Modal,
  defaultWagmiConfig,
  Web3Modal,
} from "@web3modal/wagmi-react-native";
import { Application } from "./navigation/app";
import { StatusBar } from "react-native";
import { useFonts } from "expo-font";
import { useEffect } from "react";
import { hideAsync } from "expo-splash-screen";

const queryClient = new QueryClient();

// Get projectId at https://cloud.walletconnect.com
const projectId = process.env.EXPO_PUBLIC_WALLECT_CONNECT_PROJECTID as string;

const metadata = {
  name: "AppKit RN",
  description: "AppKit RN Example",
  url: "https://walletconnect.com",
  icons: ["https://avatars.githubusercontent.com/u/37784886"],
  redirect: {
    native: "YOUR_APP_SCHEME://",
    universal: "YOUR_APP_UNIVERSAL_LINK.com",
  },
};

const chains = [assetChainTestnet] as const;

const wagmiConfig = defaultWagmiConfig({ chains, projectId, metadata });

createWeb3Modal({
  projectId,
  wagmiConfig,
  defaultChain: assetChainTestnet,
});

export default function App() {
  const [loaded] = useFonts({
    SpaceMono: require("./assets/fonts/SpaceMono-Regular.ttf"),
  });

  useEffect(() => {
    if (loaded) {
      hideAsync();
    }
  }, [loaded]);

  if (!loaded) {
    return null;
  }
  return (
    <WagmiProvider config={wagmiConfig}>
      <QueryClientProvider client={queryClient}>
        <RootSiblingParent>
          <Application />
          <StatusBar />
          <Web3Modal />
        </RootSiblingParent>
      </QueryClientProvider>
    </WagmiProvider>
  );
}
```

The above code Snippet sets up the environment for a project using the WalletConnect. The app initializes a wagmiConfig object using the WalletConnect project ID (Ensure you obtain your project Id from Wallet Connect Cloud) and metadata for the dApp, and configures the Web3Modal interface for connecting external wallets to assetChainTestnet network which is imported from wagmi

To test the application Visit our [Faucet](https://faucet.assetchain.org/) to obtain test RWA and USDT tokens


# ⁠ Connecting to wallet


# Wallet Connect

An Open protocol for connecting Wallets to Dapps, supports Asset Chain. Wallet Connect's, Wallet Kit boasts features that provide a simple, secure way for your wallet users to easily connect with thousands of apps.

### Getting Started

To connect your application to WalletConnect, you'll need to create a project on the WalletConnect Dashboard and obtain the Project ID.

#### Sign Up or Log In to the WalletConnect Dashboard

* Visit the [WalletConnect Dashboard](https://cloud.walletconnect.com/)
* If you don't have an account, sign up with your email and create a new account. If you already have an account, log in.

#### Create a New Project

* After logging in, you’ll see an option to create a new project.
* Click on **"Create"** and fill in the necessary details, such as the project name
* Once the project is created, you’ll be redirected to the project’s dashboard.

<figure><img src="/files/tc3s2GkXnon7WMrYsFoF" alt=""><figcaption></figcaption></figure>

#### Obtain Your Project ID

* In the project dashboard, you’ll find the **Project ID** under the project details.
* Copy the Project ID. You will use this ID in your ReactJS project to configure WalletConnect.

<figure><img src="/files/kHLhQ2T7YtHFlW6lbp28" alt=""><figcaption></figcaption></figure>

### Setting Up the Reactjs Project

Before we start, ensure you have the following tools installed on your system:

* **Node.js and npm:** Make sure you have Node.js installed, as it comes with npm, the Node package manager.

let's create a new React project using `vite`.

```shell
npm create vite@latest
```

Then follow the prompts!

after you're done installing reactjs using vite, navigate to your project directory and install this necessary packages:

```sh
npm i @rainbow-me/rainbowkit @tanstack/react-query viem wagmi
```

### Configuring Wallet Connect

create a `config.js` file in the src folder and add this code below:

```javascript

import { assetChainTestnet } from "viem/chains";
import { getDefaultConfig } from "@rainbow-me/rainbowkit";


export const config = getDefaultConfig({
  appName: "Wallet Connect Demo", //Update App Name
  projectId: "77a78cdc46a724d6e05ce4ae785d24d7", // Update ProjectID and for security purposes , put it in a .env file.
  chains: [assetChainTestnet],
  ssr: false, // If your dApp uses server side rendering (SSR)-true
});

```

in the `main.jsx` file, add this code below:

```javascript

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { RainbowKitProvider } from "@rainbow-me/rainbowkit";
import App from './App.jsx'
import './index.css'
import "@rainbow-me/rainbowkit/styles.css";
import { WagmiProvider } from "wagmi";
import {
  QueryClient,
  QueryClientProvider,
} from "@tanstack/react-query";
import { config } from "./config"; // replace with your own wallet-connect configuration

/* 
  connect users wallet to a dapp on assetchain, through wallet-connect.
  - user clicks connect wallet.
  - shows them qr code to scan with phone.
  - user scans with phone wallet, and connects to this app(running on a-chain)
 */

const queryClient = new QueryClient();

createRoot(document.getElementById("root")).render(
  <StrictMode>
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <RainbowKitProvider>
          {" "}
          <App />
        </RainbowKitProvider>
      </QueryClientProvider>
    </WagmiProvider>
  </StrictMode>
);

```

and finally in your `App.jsx` file, add the code below:

```javascript

import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";
import { ConnectButton } from "@rainbow-me/rainbowkit";

function App() {
  return (
    <>
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <ConnectButton />
    </>
  );
}

export default App;

```

Open your terminal, in the your project directory , run the command below to start up the server:

```bash
npm run dev
```

{% embed url="<https://github.com/xendfinance/assetchain-wallet-connect-demo>" %}
Demo on Wallet Connect
{% endembed %}


# Smart Contract Verification

Lets verify our contracts on Asset Chain.

{% hint style="info" %}
Pro tip: If you deployed your contract with Hardhat, use the Hardhat guide to verify it.
{% endhint %}

### With Advanced Explorer

#### Get Started <a href="#get-started" id="get-started"></a>

1. Visit the [Asset Chain Advanced Explorer](https://scan-testnet.assetchain.org)

<figure><img src="/files/LhQ89N8XCnmB1kPbQdNM" alt=""><figcaption></figcaption></figure>

2. On the Sidebar, hover on the \`Other\` link and click on \`verify contract\` link.

<figure><img src="/files/UyIjsFkdVEflWz1KxI8L" alt=""><figcaption><p>click on the verify contract</p></figcaption></figure>

3. Clicking verify contract\` should open up a form similar to the one below.\
   Proceed to enter the parameters with which you compiled your contract.

<figure><img src="/files/q2L1cUSCKz1BHfeADh32" alt=""><figcaption></figcaption></figure>

4. If you submitted the form successfully, your contract has been verified. Visiting the contract page, you should see a page similar to the one below; with an alert showing verified, and your contract code being displayed.

<figure><img src="/files/PuYrTPvcz5MtRFJ6OzCg" alt=""><figcaption></figcaption></figure>

### &#x20;<a href="#hardhat-verification-plugin" id="hardhat-verification-plugin"></a>

{% hint style="success" %}
Congratulations on verifying your contract with our Explorer.
{% endhint %}

### &#x20;<a href="#hardhat-verification-plugin" id="hardhat-verification-plugin"></a>

### WIth Hardhat <a href="#hardhat-verification-plugin" id="hardhat-verification-plugin"></a>

[Hardhat ](https://hardhat.org/)is a full-featured development environment for contract compilation, deployment and verification. The [Hardhat Etherscan plugin](https://hardhat.org/plugins/nomiclabs-hardhat-etherscan.html) supports contract verification on BlockScout.

#### Get Started <a href="#get-started" id="get-started"></a>

1. **Install Hardhat**

If you are starting from scratch, create an npm project by going to an empty folder, running `npm init`, and following the instructions. Recommend npm 7 or higher.

Once your project is ready:

**NPM instructions**

```bash
npm install --save-dev hardhat
```

**YARN instructions**

```bash
yarn add --dev hardhat
```

2. **Create a project**

Run `npx hardhat` in your project folder and follow the instructions to create ([more info here](https://hardhat.org/getting-started/#quick-start)).

3. **Install plugin**

Install the [hardhat-etherscan plugin](https://hardhat.org/plugins/nomiclabs-hardhat-etherscan.html) (requires **v3.0.0+).**

**npm**

```bash
npm install --save-dev @nomiclabs/hardhat-etherscan
```

**yarn**

```bash
yarn add --dev @nomiclabs/hardhat-etherscan
```

4. **Add plugin reference to config file**

Add the following statement to your `hardhat.config.js`.

```bash
require("@nomiclabs/hardhat-etherscan");
```

If using TypeScript, add this to your `hardhat.config.ts.` [More info on using typescript with hardhat available here](https://hardhat.org/guides/typescript.html#typescript-support).

```
import "@nomiclabs/hardhat-etherscan";
```

#### Config File <a href="#config-file" id="config-file"></a>

Your basic [Hardhat config file](https://hardhat.org/config/) (`hardhat.config.js` or `hardhat.config.ts`) will be setup to support the network you are working on. In this example we use the Asset Chain test network and a `.js` file.

Asset Chain is not directly supported by the plugin (to check run `npx hardhat verify --list-networks`)

But we can add it in a `customChains` object, to the config file. It includes:

* `chainID` - 42421
* `apiURL` - "<https://scan-testnet.assetchain.org/api>"
* `browserURL` - "<https://scan-testnet.assetchain.org/>"

The network name in `customChains` must match the network name in the `apiKey` object.

```javascript
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-etherscan");
require('hardhat-deploy');

let secret = require("./secret");

module.exports = {
  solidity: "0.8.9",
  networks: {
    localhost: {
      url: "http://127.0.0.1:8545/",
      accounts: [secret.key],
    }
  },
  etherscan: {
    apiKey: {
      assetchain_test: "abc"
    },
    customChains: [
      {
        network: "assetchain_test",
        chainId: 42421,
        urls: {
          apiURL: "https://scan-testnet.assetchain.org/api",
          browserURL: "https://scan-testnet.assetchain.org/"
        }
      }
    ]
  }
};
```

#### Deploy and Verify <a href="#deploy-and-verify" id="deploy-and-verify"></a>

**Deploy**

```bash
D:\hard_hat> npx hardhat run scripts\deploy.js --network assetchain_test
Contract deployed to: 0x8595e22825Ba499dB8C77C5c830c235D80f9C0fa
```

**Verify**

You can include constructor arguments with the verify task.

```bash
npx hardhat verify --network <network> DEPLOYED_CONTRACT_ADDRESS "Constructor argument 1"
```

For info on more complex constructor arguments(arrays, tuples..) please [visit here](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-verify#complex-arguments).

Example (no constructors).

```bash
D:\hard_hat>npx hardhat verify --network assetchain_test 0x263E6d3E8b98fB0393A108825E2DcE3063F66713  --constructor-args ./scripts/arguments.js 
[INFO] Sourcify Verification Skipped: Sourcify verification is currently disabled. To enable it, add the following entry to your Hardhat configuration:

sourcify: {
  enabled: true
}

Or set 'enabled' to false to hide this message.

For more information, visit https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-verify#verifying-on-sourcify
Successfully submitted source code for contract
contracts/MultiSigWallet.sol:MultiSigWallet at 0x263E6d3E8b98fB0393A108825E2DcE3063F66713
for verification on the block explorer. Waiting for verification result...

Successfully verified contract MultiSigWallet on the block explorer.
https://scan-testnet.assetchain.org/address/0x263E6d3E8b98fB0393A108825E2DcE3063F66713#code
```

#### Confirm Verification on BlockScout <a href="#confirm-verification-on-blockscout" id="confirm-verification-on-blockscout"></a>

Go to our BlockScout Explorer and paste the contract address into the search bar.

<figure><img src="/files/jlfxmfKa6lgfQkBFbO0L" alt=""><figcaption></figcaption></figure>

Scroll down to see verified status. A green checkmark ✅ means the contract is verified.

<figure><img src="/files/eeb6xYNSjDHwKdPfIIM8" alt=""><figcaption></figcaption></figure>

You can now scroll down in the explorer to see and interact with the contract code.

{% hint style="success" %}
Congratulations! Your contract is successfully verified on Asset Chain Explorer.
{% endhint %}


# MultiSig Wallet

### Introduction

In this section we'll build a MultiSig wallet on AssetChain.

This is a type of wallet in which Funds stored in it can only be moved, if the multiple signatures belonging to the different owners of the wallet, are provided.

**Features include:**

* The MultiSig wallet is a 2-of-3 signature address application.
* Each address that is a part of the quorum can create a transfer by specifying an amount and a recipient.
* Each approved address can also authorize a transfer.
* Each transfer needs two approvals to release and send a payment.
* Any unauthorized address that attempts to perform the actions of a member will be denied.
* Allows interaction with external contracts using their deployed address and ABI, extending the wallet's functionality.

We will learn some basic Solidity such as mapping or struct and how to deploy it on the Asset Chain (test network). For the frontend, we will use Reactjs.

{% embed url="<https://github.com/xendfinance/basic-multisig>" %}
multsig wallet
{% endembed %}

### Tutorial

Before getting started:

1. Follow for the step-by-step on how to add AssetChain testnet to [Metamask](https://docs.assetchain.org/general-info/add-asset-chain#testnet).
2. This guide assumes you have got Testnet RWA and connected to the AssetChain Testnet Network. Learn how to do that in [Testnet Faucets](https://docs.assetchain.org/tools/faucets).
3. Finally, clone the app files stored in the repo above.

We are ready to get started!

### Project Structure

* **contracts**: Contains the Hardhat-based Smart Contracts.
* **client**: Contains the React Application that interacts with the Smart Contracts.

#### Contracts

The Contracts projects includes;

* **MultiSig Wallet Contract**: The `MultiSigWallet` contract's core functions revolve around creating, approving, and executing token transfers and transactions, managed by a set list of approvers. The constructor initializes the contract with approvers, a quorum, and a name. Approvers can create new transfer requests using `createTransfer` and approve them with `approveTransfer`, which executes the transfer if the quorum is met. Similarly, they can create transactions with arbitrary data using `createTransaction` and approve them with `approveTransaction`, executing the transaction upon reaching the quorum. The contract can receive funds through the `receive` function, and the `onlyApprover` modifier ensures only authorized approvers can initiate or approve actions. Functions like `getApprovers`, `getTransfers`, and `getTransaction` provide visibility into the approvers, transfers, and transactions, respectively.. [View Contract](https://github.com/xendfinance/basic-multisig/blob/main/contracts/contracts/MultiSigWallet.sol)
* **MultiSig Wallet Factory Contract**: The `MultiSigWalletFactory` contract facilitates the creation and tracking of multi-signature wallets (`MultiSigWallet` instances) on the Ethereum blockchain. It includes functionality to create new wallets with specified sets of approvers and a quorum requirement. Upon creation, each wallet's address is associated with the participating approvers through a mapping, allowing easy retrieval of wallets associated with any given approver. The factory contract maintains a list of all created wallet addresses, enabling visibility into all active wallets spawned from it. Key functions include `createWallet`, which initializes a new `MultiSigWallet` instance, updates mappings, emits an event upon creation, and returns the wallet's address. This design supports decentralized applications needing secure multi-party approval mechanisms by providing a scalable and transparent method to manage multiple multi-signature wallets and their signers/approvers. [View Contract](https://github.com/xendfinance/basic-multisig/blob/main/contracts/contracts/MultiSigWalletFactory.sol)
* **Sample Smart Contract (ExternalContract)**: A contract used to test the MultiSig wallet's transaction builder feature. [View Contract](https://github.com/xendfinance/basic-multisig/blob/main/contracts/contracts/ExternalContract.sol)

#### Client

If you re done cloning the repo above, then proceed to setup the React app on your machine. Navigate to the client sub-folder

```bash
$ cd client

```

then install dependancies and start the application

```bash
# Install dependencies
$ yarn install

# Run app
$ yarn dev
```

#### Client Contract Interaction

The React application contains two Js classes for interacting with the core contracts. which are

* [MultiSigWallet](https://github.com/xendfinance/basic-multisig/blob/main/client/src/utils/MultiSigWallet.ts)
* [MultiSigWalletFactory](https://github.com/xendfinance/basic-multisig/blob/main/client/src/utils/MultiSigWalletFactory.ts)

#### Client features

1. Viewing and Creating MultiSig Wallets: After successfully connecting a web3 wallet (e.g., MetaMask), the index page ("/") displays a list of multisig wallets where the connected address is one of the approvers (signers). The output of the page is shown below.

   <figure><img src="/files/s8wNXiIPPYzwau6QJB0l" alt=""><figcaption><p>multisig wallets List</p></figcaption></figure>

   To add a new multisig wallet, click on the "Create Wallet" button, fill in the necessary details in the form that appears, and submit the form.

   <figure><img src="/files/uwlB0SPo0xbp6Ou9h72b" alt=""><figcaption><p>Create Wallet</p></figcaption></figure>
2. Transfers: On the index page, clicking the `View Wallet` button for a specific multisig wallet will navigate to a page that displays a list of transfers (both approved and pending) for the selected wallet. The connected approver can approve any transfer on the list by clicking the `Approve` button for that particular transfer.

   <figure><img src="/files/Dy0BJBuzDdYgjCi9KH1h" alt=""><figcaption><p>Transfer List</p></figcaption></figure>

   To create a new transfer, click on the `Add Transfer` button, fill in the necessary details in the form that appears, and submit the form.

   <figure><img src="/files/QWd6V3Slfr3q8FqbfTUo" alt=""><figcaption><p>Create Transfer</p></figcaption></figure>
3. Transactions: After selecting a multisig wallet on the index page, click on the `Transactions` tab button to navigate to a page that displays a list of transactions (both executed and pending) for the selected wallet. The connected approver can approve any transaction on the list by clicking the "Approve" button for that particular transfer.

   <figure><img src="/files/NeKhBtEf19PcqTA6qNSd" alt=""><figcaption><p>Transactions List</p></figcaption></figure>

   To create a new transaction, click on the "Create Transfer" button. In the form that appears, you can either use the sample external contract address and ABI or another contract deployed on the AssetChain Testnet network. Select the function you want to execute, fill in the selected function's parameters, and submit the form.

   <figure><img src="/files/0OflX6AD26fKVOWw5dSF" alt=""><figcaption><p>Create Transaction</p></figcaption></figure>

{% hint style="success" %}
Congratulations Champ! If you made it this far, you've built a MultiSig wallet on Asset Chain.
{% endhint %}

If you have questions, join our [Telegram](https://t.me/XendFinanceDevs)[ ](https://discord.gg/QGHb7jp2GV)and say hello 👋. We're Active!


# Setup a node

Hello Asset Chain Warrior, Anticipate!!!!

coming soon...........


# Staking

To learn more about why you should stake on Asset Chain, please visit the url below.

{% embed url="<https://docs.assetchain.org/general-info/staking>" %}

If you're ready to start staking, proceed with our guide below.

Users can decide to stake on Mainnet or Testnet. Of course staking on Testnet will use test RWA.

### Native Staking

**Mainnet:**

**Testnet:** [https://testnet-stake.assetchain.org](https://testnet-stake.assetchain.org/)

1. Once you visit the urls above, you will see a page similar to the one below.\
   Please click on stake to begin native staking.

<figure><img src="/files/4kwsATYDgmMfi0MHR9SF" alt=""><figcaption></figcaption></figure>

2. Clicking the stake button opens a modal, proceed to select the type of staking you prefer. Flexible allows you to withdraw at any time, Locked prevents you from withdrawing staked tokens for a particular period of time. Enter amount and select type. Then click on stake.

<figure><img src="/files/2DdopES41ibEFcBjFsYW" alt=""><figcaption></figcaption></figure>

3. Once you've gone through the process, you should see a similar modal to the one below.

<figure><img src="/files/1M43wLkGW79cLjbXOHUK" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Congratulations! Your Native staking was successfull.
{% endhint %}

####

### Validator Staking

**Mainnet:**

**Testnet:** <https://testnet.assetchain.org/>

1. Visit the url above, then click on staking on the navigation bar on top.

<figure><img src="/files/2SHm1oIxxGPNw4BmubFj" alt=""><figcaption></figcaption></figure>

2. When the staking page loads, click on the connect wallet button on the top right, then select a wallet provider to proceed.
3. After connect your wallet, you should see a page similar to the one below. Click on Add Stake to begin Validator Staking.

<figure><img src="/files/xHTudsTggLtzPUF5ASYn" alt=""><figcaption></figcaption></figure>

4. Next, if you see the form below please enter the amount you want to stake, then select a validator you want to delegate your RWA tokens to. Finally click Continue.
5. Clicking continue prompts a modal where you confirm the details of your staking action. Click Delegate to proceed.

<figure><img src="/files/KfQHYDw1XcqaIY1wq28l" alt=""><figcaption></figcaption></figure>

6. The above action might take a few secs to process, but once your staking is successfull you'll get the modal below. Click on done.
7. After clicking on done above, you should now see your staking action added to your history of staking in the table below. You can stake as many times you want.

<figure><img src="/files/sZdWZLUceHgbl6tdFf79" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Congratulations for participating in securing Asset Chain! We're glad to have you onboard.
{% endhint %}


# Setting up an Indexer

SubQuery is a fast, flexible, and reliable open-source data decentralised infrastructure network, providing both RPC and indexed data to consumers around the world.

In this guide, we will walk through the steps required to set up an indexer using SubQuery on AssetChain.

### Prerequisites

Before starting, ensure the following tools are installed on your machine:

* **Node.js**: Install Node.js (LTS version recommended) from the [official site](https://nodejs.org/).
* **Docker**: Required for running SubQuery locally. Install from the [Docker website](https://www.docker.com/).
* **SubQuery CLI**: Install using the command

```sh
# NPM
npm install -g @subql/cli

# Test that it was installed correctly
subql --help
```

### Getting Started

Once you're done installing the Subquery CLI, Initialize[ ](https://academy.subquery.network/indexer/quickstart/quickstart.html#_2-initialise-a-new-subquery-project)a new Subquery project. Run the following command inside the directory that you want to create a SubQuery project in:

```sh
subql init
```

You'll be asked certain questions as you proceed ahead:

* **Project Name**: Choose a name for your SubQuery project.
* **Network Family**: Select the EVM . Use the arrow keys to browse the available options (there may be multiple pages to scroll through).
* **Network**: Pick the specific network(i.e `Asset Chain Testnet`) to be indexed by this SubQuery project. Use the arrow keys to scroll through the available networks.
* **Template Project**: Select a template project to kickstart the development process(`asset-chain-testnet-starter` ).
* **RPC Endpoint**: Provide the HTTP or websocket URL for a running RPC endpoint. This can be a public endpoint, a private node, or the default endpoint. Ensure the node has the full state of the data you wish to index—archive nodes are recommended.
* **Git Repository**: Enter the Git URL for the repository where your SubQuery project will be hosted.
* **Authors**: Specify the owner or author of this project (e.g., your name) or use the default provided.
* **Description**: Write a brief description explaining the data your project indexes and what users can do with it, or use the provided default.
* **Version**: Enter a custom version number or keep the default.
* **License**: Provide a software license for the project or leave it as the default (MIT).

Let's look at an example

```shell
subql init
? Project name indexer-tutorial
? Select a network family EVM
? Select a network Asset Chain Testnet
? Select a template project asset-chain-testnet-starter     This SubQuery project indexes all transfers and approval events for the WRWA Token on Asset Chain Test Network
? RPC endpoint: https://enugu-rpc.assetchain.org
? Author KodeSage
? Description This is my subquery tutorial
indexer-tutorial is ready
? Do you want to generate scaffolding from an existing contract abi? no
```

Finally, run the following command to install the new project’s dependencies from within the new project's directory

```sh
cd indexer-tutorial // Replace with you project name
yarn install
```

You have now initialised your first SubQuery project with just a few simple steps. Let’s now customise the asset-chain-testnet template for our project.

### Building the Project

For this Project, we are going to be indexing this [MultitokenLauncher Contract](https://scan-testnet.assetchain.org/address/0x6fCc46E73E5B96479F6fA731893534b6Ec6bf5E1?tab=contract). Specifically, we will be indexing the `TokenCreated`Event.

Inside your Project, you `abis` directory and rename the `erc20.abi.json` file to `multitokenlauncher.abi.json` and replace the file content with this content below

```json
 [
      {
        anonymous: false,
        inputs: [
          {
            indexed: true,
            internalType: "address",
            name: "previousOwner",
            type: "address",
          },
          {
            indexed: true,
            internalType: "address",
            name: "newOwner",
            type: "address",
          },
        ],
        name: "OwnershipTransferred",
        type: "event",
      },
      {
        anonymous: false,
        inputs: [
          {
            indexed: true,
            internalType: "address",
            name: "tokenAddress",
            type: "address",
          },
          {
            indexed: true,
            internalType: "address",
            name: "deployer",
            type: "address",
          },
          {
            indexed: false,
            internalType: "string",
            name: "tokenname",
            type: "string",
          },
          {
            indexed: false,
            internalType: "string",
            name: "tokensymbol",
            type: "string",
          },
        ],
        name: "TokenCreated",
        type: "event",
      },
      {
        inputs: [
          {
            internalType: "address",
            name: "tokenAddress",
            type: "address",
          },
          {
            internalType: "uint256",
            name: "amount",
            type: "uint256",
          },
        ],
        name: "burnTokens",
        outputs: [],
        stateMutability: "nonpayable",
        type: "function",
      },
      {
        inputs: [
          {
            internalType: "string",
            name: "name",
            type: "string",
          },
          {
            internalType: "string",
            name: "symbol",
            type: "string",
          },
        ],
        name: "createToken",
        outputs: [],
        stateMutability: "nonpayable",
        type: "function",
      },
      {
        inputs: [],
        name: "getTokens",
        outputs: [
          {
            internalType: "address[]",
            name: "",
            type: "address[]",
          },
        ],
        stateMutability: "view",
        type: "function",
      },
      {
        inputs: [],
        name: "owner",
        outputs: [
          {
            internalType: "address",
            name: "",
            type: "address",
          },
        ],
        stateMutability: "view",
        type: "function",
      },
      {
        inputs: [],
        name: "renounceOwnership",
        outputs: [],
        stateMutability: "nonpayable",
        type: "function",
      },
      {
        inputs: [
          {
            internalType: "uint256",
            name: "",
            type: "uint256",
          },
        ],
        name: "tokens",
        outputs: [
          {
            internalType: "address",
            name: "",
            type: "address",
          },
        ],
        stateMutability: "view",
        type: "function",
      },
      {
        inputs: [
          {
            internalType: "address",
            name: "newOwner",
            type: "address",
          },
        ],
        name: "transferOwnership",
        outputs: [],
        stateMutability: "nonpayable",
        type: "function",
      },
    ]
```

We will edit the SubQuery project by changing the following files:

* The project manifest in `project.ts` defines the key project configuration and mapping handler filters
* The GraphQL Schema (`schema.graphql`) defines the shape of the resulting data that you are using SubQuery to index
* The Mapping functions in `src/mappings/` directory are typescript functions that handle transformation logic

In the `schema.graphql` file, replace the content with this:

```graphql
type TokenCreated @entity {
  id: ID!
  tokenAddress: String!
  owner: String!
  name: String!
  symbol: String!
}

```

In the `mappings/mappingHandlers.ts`file, replace the content with this:

```typescript
export async function handleTokenCreated(): Promise<void> {
}

```

In the `project.ts`file, replace the content with this:

```typescript

import {
  EthereumProject,
  EthereumDatasourceKind,
  EthereumHandlerKind,
} from "@subql/types-ethereum";

import * as dotenv from 'dotenv';
import path from 'path';

const mode = process.env.NODE_ENV || 'production';

// Load the appropriate .env file
const dotenvPath = path.resolve(__dirname, `.env${mode !== 'production' ? `.${mode}` : ''}`);
dotenv.config({ path: dotenvPath });

// Can expand the Datasource processor types via the generic param
const project: EthereumProject = {
  specVersion: "1.0.0",
  version: "0.0.1",
  name: "indexer tutorials",
  description: "This is a sample implementation of the indexer tutorials",
  runner: {
    node: {
      name: "@subql/node-ethereum",
      version: ">=3.0.0",
    },
    query: {
      name: "@subql/query",
      version: "*",
    },
  },
  schema: {
    file: "./schema.graphql",
  },
  network: {
    /**
     * chainId is the EVM Chain ID, for Asset Chain Testnet this is 42421
     * https://chainlist.org/chain/42421
     */
    chainId: process.env.CHAIN_ID!,
    /**
     * These endpoint(s) should be public non-pruned archive node
     * We recommend providing more than one endpoint for improved reliability, performance, and uptime
     * Public nodes may be rate limited, which can affect indexing speed
     * When developing your project we suggest getting a private API key
     * If you use a rate limited endpoint, adjust the --batch-size and --workers parameters
     * These settings can be found in your docker-compose.yaml, they will slow indexing but prevent your project being rate limited
     */
    endpoint: process.env.ENDPOINT!?.split(",") as string[] | string,
  },
  dataSources: [
    {
      kind: EthereumDatasourceKind.Runtime,
      startBlock: 141381, //The Block Number where your contract was created
      options: {
        abi: "multitokenlauncher",
        // This is the contract address for MultiTokenlauncher
        address: "0x6fCc46E73E5B96479F6fA731893534b6Ec6bf5E1",
      },
      assets: new Map([
        ["multitokenlauncher", { file: "./abis/multitokenlauncher.abi.json" }],
      ]),
      mapping: {
        file: "./dist/index.js",
        handlers: [
          {
            kind: EthereumHandlerKind.Event,
            handler: "handleTokenCreated",
            filter: {
              /**
               * Follows standard log filters https://docs.ethers.io/v5/concepts/events/
               * address: "0x6fCc46E73E5B96479F6fA731893534b6Ec6bf5E1"
               */
              topics: [
                "TokenCreated(address indexed tokenAddress, address indexed deployer, string tokenname, string tokensymbol)",
              ],
            },
          },
        ],
      },
    },
  ],
  repository: "https://github.com/subquery/ethereum-subql-starter", // Replace with your own repository
};

// Must set default to the project instance
export default project;

```

Afterwards , Then Open your terminal and run the following code below

```
yarn codegen
```

This Generates types from the GraphQL schema definition and contract ABIs and saves them in the `/src/types` directory. This must be done after each change to the `schema.graphql` file or the contract ABIs and Updating the `project.ts`file.

Update `mappings/mappingHandlers.ts` file with this content below:

```javascript

import { TokenCreated } from "../types";
import { TokenCreatedLog } from "../types/abi-interfaces/MultitokenlauncherAbi";
import assert from "assert";

export async function handleTokenCreated(log: TokenCreatedLog): Promise<void> {
  logger.info(`New TokenCreated event log at block ${log.blockNumber}`);
  assert(log.args, "No log.args");

  const token = TokenCreated.create({
    id: log.transactionHash,
    tokenAddress: log.args.tokenAddress,
    owner: log.args.deployer,
    name: log.args.tokenname,
    symbol: log.args.tokensymbol,
  });

  await token.save();
}

// This handles the Transformation Logic and make the data's indexed. 
```

Now that our Project is Completed, we need to build out the `dist` file and test it.

in your terminal, run the following command:

```sh
yarn build
```

Once the Build Passes, Kudos your Subgraph Project is Ready.

### Testing

You need to test the project locally and make sure it is working before deploying.

{% hint style="info" %}
To Test, make sure you have your Docker Environment is running.
{% endhint %}

in your terminal, run the following commands:

```sh
docker-compose pull && docker-compose up
```

Open your Browser and Navigate to this URL <http://localhost:3000/>

query the graphql using the code below to get all Tokens created

```graphql
query GetTokenCreated {
  tokenCreateds{
    edges {
      node {
        id
        tokenAddress
        owner
        name
        symbol
      }
    }
  }
}
```

to get a a Single Token created,

```graphql
query GetSingleToken {
  tokenCreated(id: "0xbb5d708468aefcbca97711c99d7c7db270c7c521059367c64703b7edf785472c") {
    id
    tokenAddress
    owner
    name
    symbol
  }
}

```

You should see the different output of this project in Browser.

### Deploying our Subquery Project

Before you deploy your subquery project, you need to publish it first on the network.

**Prepare your SUBQL\_ACCESS\_TOKEN**

* Step 1: Go to [SubQuery Managed Service](https://managedservice.subquery.network/) and log in.
* Step 2: Click on your profile at the top right of the navigation menu, then click on ***Refresh Token***.
* Step 3: Copy the generated token.
* Step 4: To use this token:
  * Add SUBQL\_ACCESS\_TOKEN in your environment variables. `EXPORT SUBQL_ACCESS_TOKEN=<token>` (Windows) or `export SUBQL_ACCESS_TOKEN=<token>` (Mac/Linux)

**Publish your project**

In your project directory, run the following command

```sh
subql publish
```

you should then see a similar output below

```sh
SubQuery Project project.yaml uploaded to IPFS: QmPWDhbqBqN4peb5BQKuFZPFt1qfAP6b6aQNmzEYzaWg9M
```

**Deploying Our Project to The Network**

To create your first project, head to [SubQuery Managed Service](https://managedservice.subquery.network/). You'll need to authenticate with your GitHub account to login.

SubQuery Projects is where you manage all your hosted projects uploaded to the SubQuery platform. You can create, delete, and even upgrade projects all from this application.

<figure><img src="/files/gM78Gp1Bzw5216hK1Ngs" alt=""><figcaption></figcaption></figure>

Click on the `Create Project` Buttton to Create your Project, A Modal will pop up, then you Click on the `Subquery Project` and click the Next Button.

<figure><img src="/files/uYkrZsf7dLfvANXrlHGv" alt=""><figcaption></figcaption></figure>

and then follow the steps and enter the following:

{% hint style="info" %}
The information you are filling should tally with the same information you used while setting up the project using the CLI
{% endhint %}

* **Project Name:** Name your project.
* **Description:** Provide a description of your project.
* **Database:** Premium customers can access dedicated databases to host production SubQuery projects from. If this interests you, you can contact <sales@subquery.network> to have this setting enabled.
* **Visible in Explorer:** If selected, this will show the project from the public SubQuery explorer to share with the community.\\

<figure><img src="/files/5zT6BY8U73mCTPMYZ5Zm" alt=""><figcaption><p>create a project</p></figcaption></figure>

Below is the final code for our indexer project

{% embed url="<https://github.com/xendfinance/setting-up-an-indexer>" %}


# Asset Chain Telegram Mini App Demo

This project shows builders how to develop Telegram Mini Apps on Asset Chain. It uses Next.js, wagmi for Asset Chain wallet connections, and various injected providers for ease of use.

## Table of content

* [Getting Started](https://github.com/xendfinance/assetchain-telegram-demo-app#getting-started)
* [Contributing](https://github.com/xendfinance/assetchain-telegram-demo-app#contributing)
* [License](https://github.com/xendfinance/assetchain-telegram-demo-app#license)
* [Support](https://github.com/xendfinance/assetchain-telegram-demo-app#support)

## Getting Started

1. **Clone the Repository**:

   ```bash
   git clone https://github.com/xendfinance/assetchain-telegram-demo-app.git demo-app
   cd demo-app
   ```
2. **Install Dependencies**:\
   Run the following command to install the necessary packages:

   ```bash
   npm install
   ```
3. **Start the Development Server**:\
   Run the server locally:

   ```bash
   npm run dev
   ```
4. **Environment Variables**:
   * Rename `.env.example` to `.env.local` and configure the following parameters:
     * `NEXT_PUBLIC_PROJECT_ID=""`: Add your project ID from [Reown](https://cloud.reown.com).
     * `NEXT_PUBLIC_INFURA_KEY=""`: Add your Infura API key from [Infura](https://www.infura.io).
     * `NEXT_PUBLIC_MANIFEST_URL=""`: Add a manifest URL.\
       Example: `"https://ton-connect.github.io/demo-dapp-with-react-ui/tonconnect-manifest.json"`.

## Connecting to Injected Providers

To connect the app with different Ethereum wallet providers, you can modify the default connector in your `src/hooks/useEvmWallet.tsx` file based on your needs.

### Injected Providers Setup

1. **Use Injected Provider**:\
   This sets the default connector to detect and use any wallet injected into the browser, such as MetaMask or Coinbase Wallet.

   ```ts
   import { injected } from "@wagmi/core";
   const defaultConnector = injected();
   ```
2. **Use Coinbase Provider**:\
   To connect with Coinbase Wallet, change the configuration:

   ```ts
   import { coinbaseConfig } from "../configs/wagmiConfig";
   const defaultConnector = coinbaseConfig;
   ```
3. **Use MetaMask Provider**:\
   If you prefer MetaMask as your default wallet provider, configure it like so:

   ```ts
   import { metaMaskConfig } from "../configs/wagmiConfig";
   const defaultConnector = metaMaskConfig;
   ```
4. **Use WalletConnect Provider**:\
   To integrate WalletConnect, which supports mobile wallets, adjust the default connector to:

   ```ts
   import { walletConnectConfig } from "../configs/wagmiConfig";
   const defaultConnector = walletConnectConfig;
   ```

***

## Network Configuration

```typescript
const defaultChainId = AssetChainMainnet.id; // AssetChainTestnet.id
```

### Explanation

* `defaultChainId`: Sets the initial chain ID configuration for connecting.
* `AssetChainMainnet.id`: The default chain ID is currently set to the AssetChain mainnet ID. This is useful for production use.
* `AssetChainTestnet.id`: You can switch to the testnet for testing and development purposes by changing the comment.

With this setup, you'll be able to connect your Telegram mini app to various Asset Chain, giving your users flexibility in interacting with blockchain-enabled features.

## Contributing

See [CONTRIBUTING.md](https://github.com/xendfinance/assetchain-telegram-demo-app/CONTRIBUTING.md) for contribution and pull request protocol. We expect contributors to follow our guide when submitting code or comments.

## License

[![License: GPL v3.0](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)

This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.

## Contact

For questions or suggestions, just say Hi on [Telegram](https://t.me/assetchainbuilders).\
We're always glad to help.


# EVM-Gas-Optimizations

The repo below documents all of the gas optimization techniques that the creator have come across / experimented with. Each optimization has a brief explanation with a code snippet.

Experiment with each optimization technique and see the gas changes occur in your smart contract; as they become gas efficient.

{% embed url="<https://github.com/0xKitsune/EVM-Gas-Optimizations>" %}

{% embed url="<https://www.evm.codes/>" %}

If you have questions, join our [Telegram](https://t.me/XendFinanceDevs)[ ](https://discord.gg/QGHb7jp2GV)and say hello 👋. We're Active!


# Smart Contract Audit

Auditing your smart contracts in development with AI tools.

Conducting a smart contract audit involves a thorough examination of the code to ensure it is secure, efficient, and free of vulnerabilities.

{% hint style="info" %}
AI tools are very helpful for development purposes, but we also recommend submitting your smart contracts to a professional Audit firm before deploying to the Mainnet.
{% endhint %}

Here are the steps typically involved in a smart contract audit:

1. **Pre-Audit Preparation:**
   * **Code Review:** Collect all the smart contract code, including any dependencies and libraries.
   * **Documentation:** Gather all relevant documentation, including the whitepaper, design documents, and specifications.
2. **Static Analysis:**
   * **Automated Tools:** Use automated tools like Mythril, Slither, and Oyente to perform static analysis on the code. These tools can help identify common vulnerabilities like reentrancy, integer overflows, and underflows.
   * **Code Linting:** Ensure the code follows best practices and coding standards.
3. **Manual Review:**
   * **Line-by-Line Analysis:** Manually review the code line-by-line to identify any potential vulnerabilities that automated tools might have missed.
   * **Logic Review:** Verify that the logic of the smart contract aligns with the intended behavior and specifications.
   * **Access Control:** Ensure proper implementation of access controls and permissions.
   * **Gas Optimization:** Check for areas where the gas usage can be optimized.
4. **Testing:**
   * **Unit Testing:** Write and run comprehensive unit tests to ensure individual functions work as expected.
   * **Integration Testing:** Test how different parts of the smart contract interact with each other.
   * **Simulation:** Use tools like Ganache or Hardhat to simulate various scenarios and edge cases.
5. **Security Analysis:**
   * **Vulnerability Scanning:** Scan for known vulnerabilities such as reentrancy, front-running, and denial of service.
   * **Formal Verification:** For critical contracts, consider using formal verification methods to mathematically prove the correctness of the code.
   * **Penetration Testing:** Perform penetration testing to identify potential attack vectors.
6. **Reporting:**
   * **Audit Report:** Compile a detailed audit report that includes all findings, potential vulnerabilities, and recommended fixes.
   * **Recommendations:** Provide clear and actionable recommendations for improving the security and performance of the smart contract.
7. **Post-Audit:**
   * **Remediation:** Work with the development team to address and fix the identified issues.
   * **Re-Audit:** If significant changes are made, conduct a re-audit to ensure all issues have been resolved and no new issues have been introduced.

#### Smart Contract Audit AI Tools

* [ChatGPT](https://chatgpt.com/)
* [Google Gemini](https://gemini.google.com/app)
* [Meta AI](https://ai.meta.com/meta-ai/)


# Decentralized Exchanges

Hello Asset Chain Warrior, Anticipate!!!!

coming soonn


# Arbitrage Bots

Hello Asset Chain Warrior, Anticipate!!!!

coming soon......


# References

* [Ethereum Developers](https://ethereum.org/en/developers/tutorials)
* [Guild Audits](https://guildaudits.com/)


