Create Publication

We are looking for publications that demonstrate building dApps or smart contracts!
See the full list of Gitcoin bounties that are eligible for rewards.

Tutorial Thumbnail
Intermediate · 1 hour

Build an Algorand Web Wallet Interface Using Reach and React

The business value of this tutorial is to teach how to use the Reach frontend to connect to an Algorand wallet and sign transactions using MyAlgo Wallet and Algosigner with React.The reason for choosing Reach and React for this project is because Reach is the fastest and easiest way to create DApps which can be deployed on multiple platforms and React is one of the most popular frontend library of choice for most developers and organizations.

Connecting to a wallet is one important requirements most DApp developers will have to integrate in their application when creating a DApp on the Algorand Blockchain.

This tutorial will guide you in connecting your DApp to an Algorand wallet using either MyAlgo Wallet or AlgoSigner. The tutorial and code solution is divided into two sections. MyAlgo Wallet Connect with Reach and Algosigner independent of Reach.

Connecting to MyAlgo Wallet is part of the inbuilt integration in reach which provides a fallback to connect to the wallet. AlgoSigner is not integrated in reach and so integrating AlgoSigner in your DApp does not require Reach.

To get the complete code here is the github repo and here is the link to the hosted Demo on netlify.

Requirements

Background

Reach is a domain-specific language for building decentralized applications (DApps).Reach is a blockchain-agnostic programming language which has similar syntax as JavaScript. Reach automatically verify smart contracts at a lower cost, and compile them to multiple blockchains. Reach currently compiles to Algorand, Ethereum and Conflux, and plans to expand to more soon.

Reach also has created a front-end library to connect to devnet wallets or directly to Algosigner, MyAlgo Wallet or Metamask if deploying to Etherum blockchain. This project uses the front-end library with React to create a simple Algorand wallet interface. This tutorial makes use of the Algorand TestNet to enable the user to check account balance, fund account and transfer fund to another account using Reach and React. The user can connect to either MyAlgo Wallet or AlgoSigner.

MyAlgo Wallet is a web based wallet and AlgoSigner is chrome extension used for for connecting DApps for signing transactions on the Algorand blockchain.

Note

AlgoSigner is not integrated in Reach, we will add it manually if we want to Sign transactions with AlgoSigner.

For more information on Reach, check out the Reach site, docs, and Discord server.

At the end of this tutorial the UI should look like this.
EditorImages/2021/11/18 03:46/Screenshot_2021-11-16_at_03.28.28.png
Fig 0-1 App UI

Steps

1. Project Setup and React Installation

To create an App with React, first you need to have installed node and then install react globally if you are installing it for the first time to avoid installing react each time you need to create react app.

EditorImages/2021/11/16 04:15/Screenshot_2021-11-16_at_05.01.37.png
Fig 1-1 helps to confirm that node is installed.
Fig 1-1 Node npm version

npm install -g create-react-app

This will install react globally on your machine. The next thing to do is to enter this command

EditorImages/2021/11/16 03:48/Screenshot_2021-11-16_at_04.44.28.png
Fig 1-2 Create React App

EditorImages/2021/11/16 03:48/Screenshot_2021-11-16_at_04.44.37.png
Fig 1-3 Create React App Installation Files

create-react-app reach-react-wallet. This will create a boilerplate React app with the project name as reach-react. After that navigate into the project folder by doing cd reach-react. Congratulations your boilerplate react app is all set you can run it by using this command npm start

EditorImages/2021/11/16 03:48/Screenshot_2021-11-16_at_04.46.28.png
Fig 1-4 React App UI

For this tutorial we will be using styled component to write our css. To use styled component we will need to install it.
From your terminal type npm install --save styled-components. With this we can setup our css using styled component. Here is the link to learn more about styled component.

Note

Reach has React built in functionality. To have access to React while using Reach you simply need to do the following;

As a convenience for running the React development server, you can call:
./reach react

To run the React development server with Algorand, you can call:

REACH_CONNECTOR_MODE=ALGO ./reach react

But for this tutorial we are running react from scratch and we will delete some of the boilerplate files.

EditorImages/2021/11/16 04:36/Screenshot_2021-11-16_at_05.27.08.png
Fig 1-4 Boilerplate Project Structure

At this point your project structure currently looks like this.Delete everything from the source folder except App.js and index.js then on the public folder delete everything from the index.html

After deleting those files your file structure should look like this.

EditorImages/2021/11/16 04:35/Screenshot_2021-11-16_at_05.35.18.png
Fig 1-5 Modified Boilerplate Project Structure

To avoid running into errors after deleting those files. open index.js and App.js and remove the unused imports.

For now, your App.js file should look like this

EditorImages/2021/11/16 04:39/Screenshot_2021-11-16_at_05.38.31.png
Fig 1-6 App.js

And index.js file should look like this

EditorImages/2021/11/16 04:40/Screenshot_2021-11-16_at_05.38.43.png
Fig 1-7 index.js

The project structure will be updated in step 3.

2. Reach Installation

Note

This setup guide will be important when setting up Reach. Make sure the make, docker and docker compose are all installed. To be sure they are installed you can check up their version from the terminal by doing the following;

make --version
docker --version
docker-compose --version

EditorImages/2021/11/16 04:17/Screenshot_2021-11-16_at_04.59.32.png
Fig 2-1 make, docker and docker-compose

Fig 2-1 help to confirm that the above has been successfully installed.

Once you are sure that they are installed, next download Reach by running
curl https://docs.reach.sh/reach -o reach ; chmod +x reach

EditorImages/2021/11/16 03:55/Screenshot_2021-11-16_at_04.53.26.png
Fig 2-2 Reach download

To get started using Reach JavaScript standard library you need to install Reach using this command. First navigate/cd to the src folder to then run

npm install @reach-sh/stdlib

EditorImages/2021/11/16 03:57/Screenshot_2021-11-16_at_04.56.46.png
Fig 2-3 Reach JavaScript Library Installation

Then run ./reach update (this will download the libraries)

3. Project Structure

EditorImages/2021/11/16 03:40/Screenshot_2021-11-16_at_04.39.46.png
Fig 3-1 Project Structure

For the tutorial, your project structure should look like Fig 3-1 above.

Here is a quick breakdown of the folder/file structure. In order to keep things neat and modular, I have decided to seperate the files. One aspect of clean coding involves seperation of concerns.

The Asset folder takes care of images and css folder. The Component folder takes care of the components which contains AlgoSigner folder, Header folder,MyAlgoWallet folder, Button.Styles.js and Form.style.js.

App.js, constants.js,index.js, Main.styles.js are directly inside the source folder. Assets and Components folder are also inside the src folder. Reach is also inside the src folder.

4. Main Page and Style

App.js

/*global AlgoSigner*/

import React from 'react'
import Header from './components/Header/header'
import MyAlgoWallet from './components/MyAlgoWallet/MyAlgoWallet'
import AlgoSigner from './components/AlgoSigner/AlgoSigner'
import { Main, MainBody } from './Main.styles' 
import './assets/css/app.css'

function App(){ 
        return(

            <MainBody>
                <Header/> 
                <Main>
                    <MyAlgoWallet/>
                    <AlgoSigner/>         
                </Main>
            </MainBody>
        )
}

export default App

Main.styles.js

import styled from "styled-components"

export const Main = styled.div`
    display : flex;
    justify-content : space-evenly;

     @media(max-width : 560px){
        flex-direction   : column;
        align-content : center;
        align-items : center;
    }
`

export const MainBody = styled.div`
    background-color : #F8F9FF;
    height : 100vh;

`

index.js

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

header.js

import React from 'react'
import { MainHeader, HeaderText } from './MainHeader.styles'
const Header = () => {
    return(
       <MainHeader>
          <HeaderText>Welcome to Algorand Wallet Connect</HeaderText>
        </MainHeader>
    )
}

export default Header

MainHeader.styles.js

import styled from "styled-components";

export const MainHeader  = styled.header `
    padding : 20px;
    margin : 0;
    background-color : #F4F1FE;
`


export const HeaderText = styled.h3`
    text-align : center;
    font-family : 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif
`

src/assets/css/app.css

body {
    background: #F8F9FF;
}

constants.js

const ALGOD_SERVER = 'https://testnet-algorand.api.purestake.io/ps2'
const INDEXER_SERVER = 'https://testnet-algorand.api.purestake.io/idx2'
const TOKEN = { 'X-API-Key': 'YOUR PURESTAKE API KEY' }
const PORT = '443';


module.exports = {
    ALGOD_SERVER,
    INDEXER_SERVER,
    TOKEN,
    PORT,
}

5. MyAlgo Wallet

MyAlgo is an Algorand Wallet allowing you to freely interact with the Algorand blockchain.

MyAlgo provides the simplest and most secure way to send and receive Algos and tokens, organize and track all your Algorand wallets, manage your assets and much more.

This section will take care of connecting to My Algo Wallet and performing transactions using Reach. To get started using MyAlgo Wallet you will need to create account on the Algorand TestNet which you will connect to later on in the tutorial. Here is the link to get that setup.

5.1 Connect To MyAlgo Wallet

To connect to MyAlgo Wallet your code should look like this. This code covers the connection and retrieving of the account balance. This also includes the user interface for MyAlgo Wallet, which takes care of Funding and Transfering of Fund.

Note

Here are some things to note about useRef and useState and why it is used in this tutorial. The useRef hook call returns an object that has a property current, which stores the actual value and the useState Hook enables the development of component state for functional components.

To get the user account using Reach this method will be called reach.getDefaultAccount() and to get the account balance of the user will be reach.balanceOf() this takes in one argument the user account.

EditorImages/2021/11/18 02:22/Screenshot_2021-11-18_at_01.07.26.png
Fig 5-1-1 MyAlgo Wallet Connect

EditorImages/2021/11/18 02:25/Screenshot_2021-11-18_at_03.25.37.png
Fig 5-1-2 MyAlgo Wallet Account and Balance

import React, {useState, useRef} from 'react'
import { loadStdlib } from '@reach-sh/stdlib'
import MyAlgoConnect from '@reach-sh/stdlib/ALGO_MyAlgoConnect';
import ConnectWalletButton from './ConnectButton/ConnectWalletBtn';
import TransferFund from './Transferfund';
import FundAccount from './FundWallet';
import myalgo from '../../assets/images/myaglo-logo.png'
import { MyAlgoWalletMain } from './MyAlgoWallet.styles';

const reach = loadStdlib("ALGO")

reach.setWalletFallback(reach.walletFallback({
  providerEnv: 'TestNet', MyAlgoConnect })); 

const MyAlgoWallet = () => {

    const account = useRef()
    const balance = useRef()


    const [accountBal, setAccountBal] = useState(0);
    const [accountAddress, setAccountAddress] = useState('');


    const connectWallet = async () =>{
        try{
            await getAccount()
            await getBalance()

        }catch(err){
            console.log(err)
        }
    }

    const getAccount = async () => {
        try{
           account.current = await reach.getDefaultAccount()
            setAccountAddress(account.current.networkAccount.addr)
            console.log("Account :" + account.current.networkAccount.addr)
        }catch(err){
            console.log(err)
        }
    }

    const getBalance = async () => {
        try{
              let rawBalance = await reach.balanceOf(account.current)
                balance.current = reach.formatCurrency(rawBalance, 4)
                setAccountBal(balance.current)
            console.log("Balance :" + balance.current)
        }catch(err){
            console.log(err)
        }

    }

    return(
        <MyAlgoWalletMain>
            <img src= {myalgo} alt="My Algo" height= "70px"/>
            <ConnectWalletButton accountAddress={accountAddress} connectWallet = {connectWallet} accountBal = {accountBal}/>
            <TransferFund account = {account} getBalance = {getBalance} />
            <FundAccount account = {account} getBalance = {getBalance}/>
        </MyAlgoWalletMain>
    )
}

export default MyAlgoWallet

Note

When using Reach it is important to specify the network you would want to connect to. Otherwise connection defaults to Metamask if you have it installed.

From the above code when trying to connect to the Algorand network using MyAlgo Wallet these lines are important.

import MyAlgoConnect from '@reach-sh/stdlib/ALGO_MyAlgoConnect';
const reach = loadStdlib("ALGO")

reach.setWalletFallback(reach.walletFallback({
  providerEnv: 'TestNet', MyAlgoConnect })); 

5.2 Transfer Fund

This handles transferring of fund to the specified account. To transfer fund this function will be called reach.transfer() this takes in three arguments, the account, receiver and amount.

EditorImages/2021/11/18 02:32/Screenshot_2021-11-18_at_03.30.14.png
Fig 5-2-1 Transfer Fund With MyAlgo Wallet

EditorImages/2021/11/18 02:33/Screenshot_2021-11-18_at_03.30.50.png
Fig 5-2-2 Transfer Fund UI

import React, {useRef, useState} from "react";
import { loadStdlib } from '@reach-sh/stdlib'
import { FormStyle } from "../Form.style";
import { Button, TransactionButton } from "../Button.styles";
import { BodyText } from "./MyAlgoWallet.styles";

const reach = loadStdlib("ALGO")

const TransferFund = ({account, getBalance}) => {
    const transferAmount = useRef()
    const receiverAddress = useRef()
    const [isLoading, setLoading] = useState(false)

    const transferFund = async () =>{
        try{
        setLoading(true)
        const receiver = await reach.connectAccount({
             addr: receiverAddress.current
         })
         console.log(receiver)

         await reach.transfer(account.current, receiver, reach.parseCurrency(transferAmount.current))
         await getBalance()
         setLoading(false)
        }catch(err){
            console.log(err)
            setLoading(false)
        }


     }

    return(
        <div>
            <br/>
            <BodyText>Transfer Fund</BodyText>
            <FormStyle onChange = {(e) => receiverAddress.current = e.target.value} placeholder="Receiver address" /><br/>
            <FormStyle onChange = {(e) => transferAmount.current = e.target.value} placeholder="Amount" /><br/>
            <TransactionButton onClick ={transferFund}>{isLoading ? "loading...": "Transfer Fund"}</TransactionButton>
        </div>
    )
}

export default TransferFund

5.3 Fund Wallet

This handles funding of account from the Reach Dev faucet. When using the Dev faceut to fund wallet this method will be called reach.fundFromFaucet() this takes in two argument the account and amount.

Note

The account balance on the dev faceut is limited to fund wallet you can use the Algorand TestNet Dispenser to fund your wallet.

EditorImages/2021/11/18 03:14/Screenshot_2021-11-12_at_23.28.15.png
Fig 5-3-1 Fund Wallet

EditorImages/2021/11/18 02:36/Screenshot_2021-11-18_at_03.35.56.png
Fig 5-3-2 Fund Wallet UI

import React, {useState} from "react";
import { loadStdlib } from '@reach-sh/stdlib'
import { FormStyle } from "../Form.style";
import {  TransactionButton } from "../Button.styles";
const reach = loadStdlib("ALGO")

const FundAccount = ({account, getBalance}) =>{
    const [isLoading, setLoading] = useState(false)
    const [amount, setAmount] = useState("")

    const fundAccount = async () =>{
        try{
            setLoading(true)
            await reach.fundFromFaucet(account.current, reach.parseCurrency(+amount))
            await getBalance()
            setLoading(false)
            setAmount("")
        }catch(err){
            setLoading(false)
            console.log(err)
        }

    }

    return(
        <div>
        <FormStyle onChange = {(e) => setAmount(e.target.value)} placeholder="Enter amount" />  
            <TransactionButton onClick ={fundAccount} > {isLoading ? "loading...": "Fund Account"}
        </TransactionButton>
        </div>
    )
}

export default FundAccount

6. Testing the Project

From the terminal run
REACH_CONNECTOR_MODE=ALGO ./reach/reach devnet this will set the connector mode to Algo.

Next run npm start on another terminal to run the application

7. MyAlgo Wallet Style

This section handles the UI styling of the MyAlgo Wallet page. Using styled component.

ConnectWalletBtn.js

import React from 'react'
import { loadStdlib } from '@reach-sh/stdlib'
import MyAlgoConnect from '@reach-sh/stdlib/ALGO_MyAlgoConnect';
import ConnectButton from '.';
import { BodyText } from '../MyAlgoWallet.styles';
const reach = loadStdlib("ALGO")
reach.setWalletFallback(reach.walletFallback({
    providerEnv: 'TestNet', MyAlgoConnect })); 


const ConnectWalletButton = ({connectWallet,accountAddress, accountBal }) => {

    return(
        <div>
            <ConnectButton connectWallet = {connectWallet}/>
                <BodyText>Account Address: {accountAddress} </BodyText>
                <BodyText>Account Balance: {accountBal}</BodyText>
        </div>
    )
}

export default ConnectWalletButton

MyAlgoWallet/ConnectButton/index.js

import { Button } from "../../Button.styles";

const ConnectButton = ({connectWallet}) => {
    return(
        <Button onClick ={connectWallet}>
           Connect MyAlgo Wallet
        </Button>
    )
}

export default ConnectButton

MyAlgoWallet.styles.js

import styled from "styled-components";

export const MyAlgoWalletMain = styled.div`
    margin-top : 20px;
`

export const BodyText = styled.h5`
    font-family : -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif
`

Button.styles.js

import styled from "styled-components";


export const Button = styled.button`
    background-color : ${({backgroundColor}) => backgroundColor  ? '#E13E00' : '#245EC7' };
    color: white;
    padding : 16px;
    border-radius: 10px;
    border-color : transparent;
    margin : 20px 0;
    font-family : 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif

`

export const TransactionButton = styled.button`
    background-color : #F8F9FF;
    color: ${({backgroundColor}) => backgroundColor  ? '#E13E00' : '#245EC7' };
    padding : 10px;
    border-radius: 5px;
    border-color : ${({backgroundColor}) => backgroundColor  ? '#E13E00' : '#245EC7' };
    margin : 20px 10px;
    font-family : 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif
`

Form.style.js

import styled from "styled-components";

export const FormStyle = styled.input`
    margin-bottom : 20px;
    width : 200px;
    padding : 10px;
    border-radius : 5px;
    border-color : #245EC7;
`

8. AlgoSigner

The AlgoSigner performs similar function as the MyAlgo Wallet. The major difference is that AlgoSigner has a web extension like Metamask for signing of transactions on the Algorand blockchain.

AlgoSigner injects a JavaScript library into every web page the browser user visits, which allows the site to interact with the extension. The dApp can use the injected library to connect to the user’s Wallet, discover account addresses it holds, query the Network (make calls to AlgoD v2 or the Indexer) and request AlgoSigner to request for the user to sign a transaction initiated by the application. All methods of the injected library return a Promise that needs to be handled by the dApp.

To get started using AlgoSigner. You will need to install the AlgoSigner chrome extension and setup your TestNet account.Also go to the settings section of the extension to configure your network.

EditorImages/2021/11/18 02:59/Screenshot_2021-11-16_at_06.32.25.png
Fig 8-1 AlgoSigner Settings

8.1 AlgoSigner Main Page

Note

It is important to include /*global AlgoSigner*/ at the top level of your project to enable you have access to the Algod SDK to avoid running into errors.

/*global AlgoSigner*/
import React, {useRef} from "react";
import ConnectAlgoSigner from "./ConnectAlgoSigner";
import SignPayTransaction from "./SignPayTransaction";
import algoSignerlogo from '../../assets/images/algosigner.jpeg'
import { AlgoSignerMain } from "./AlgoSigner.styles";
import CreateAsset from "./CreateAsset";
import AssetOptin from "./AssetOptin"

const AlgoSigner =  ()  =>{
    const userAccount = useRef()
    const receipient = useRef()
    const amount = useRef()


    return(

        <AlgoSignerMain>
            <img src= {algoSignerlogo} alt ="AlgoSigner Logo" height= "70px"/> 
            <ConnectAlgoSigner userAccount = {userAccount}/>           
            <SignPayTransaction userAccount = {userAccount} amount = {amount} receipient = {receipient} />
            <CreateAsset userAccount = {userAccount} />
            <AssetOptin userAccount = {userAccount} />
        </AlgoSignerMain>
    )
}

export default AlgoSigner

EditorImages/2021/11/18 02:38/Screenshot_2021-11-16_at_06.38.20.png
Fig 8-1-1 AlgoSigner Main UI

EditorImages/2021/11/18 02:39/Screenshot_2021-11-16_at_06.38.30.png
Fig 8-1-2 AlgoSigner Main UI

8.2 Connect to AlgoSigner

This handles connection to AlgoSigner web extension. This will fail if AlgoSigner is not installed.
The AlgoSigner.connect() function is required to connect to the AlgoSigner, and the AlgoSigner.accounts({ledger: 'TestNet'}) function is used to get the user account in on the TestNet.

/*global AlgoSigner*/

import React from "react";
import { Button } from "../Button.styles";

const ConnectAlgoSigner = ({userAccount}) => {

    const connectAlgoSigner = async () =>{
        let resp = await AlgoSigner.connect()
        console.log(resp)
        getUserAccount()
      }

      const getUserAccount = async () =>{
         userAccount.current =  await AlgoSigner.accounts({
              ledger: 'TestNet'
            })
      // console.log(userAccount.current[0]['address'])
      console.log(userAccount.current)

      }
      return(
        <div>
          <Button backgroundColor='blue' onClick={connectAlgoSigner}>
          Connect Algo Signer
          </Button>
        </div>

      )
}

export default ConnectAlgoSigner

EditorImages/2021/11/18 02:40/Screenshot_2021-11-15_at_15.28.46.png
Fig 8-2-1 Connect to AlgoSigner

EditorImages/2021/11/18 02:42/Screenshot_2021-11-18_at_03.41.41.png
Fig 8-2-2 Grant Wallet Accesss

8.3 Sign Pay Transaction

This handles signing of payment transactions. To handle payment using the algosdk this function will be called algosdk.makePaymentTxnWithSuggestedParamsFromObject() this takes in some arguments like from account owner, to the receipient, amount the amount to be transfered note description of the transfer which is optional and suggestedParams this is gotten after setting up the client. This is gotten by calling this function client.getTransactionParams().do().

After making the payment the transaction will be signed and sent to the network.

/*global AlgoSigner*/
import React,{useState, useRef} from "react";
import { FormStyle } from "../Form.style";
import { TransactionButton } from "../Button.styles";
import { BodyText } from "../MyAlgoWallet/MyAlgoWallet.styles";
import { TOKEN, ALGOD_SERVER, PORT } from "../../constants";
const algosdk = require("algosdk");

const SignPayTransaction = ({userAccount, amount, receipient}) => {
    const [isLoading, setLoading] = useState(false)

    const MICROALGOS_TO_ALGOS_RATIO = 1e6;
    const INVALID_MICROALGOS_ERROR_MSG =
    'Microalgos should be positive and less than 2^53 - 1.';

    /**
     * microalgosToAlgos converts microalgos to algos
     * @param microalgos - number
     * @returns number
     */
    const  microalgosToAlgos = (microalgos ) => {
    if (microalgos < 0 || !Number.isSafeInteger(microalgos)) {
        throw new Error(INVALID_MICROALGOS_ERROR_MSG);
    }
    return microalgos / MICROALGOS_TO_ALGOS_RATIO;
    }

    /**
     * algosToMicroalgos converts algos to microalgos
     * @param algos - number
     * @returns number
     */
    const algosToMicroalgos = (algos) => {
    const microalgos = algos * MICROALGOS_TO_ALGOS_RATIO;
    return Math.round(microalgos);
    }

    const signPayTransaction = async () =>{
        // await AlgoSigner.connect();
        setLoading(true)
        let client = new algosdk.Algodv2(TOKEN, ALGOD_SERVER, PORT)

        //Query Algod to get testnet suggested params
        let suggestedParams = await client.getTransactionParams().do()

        try{
            const txn = await new algosdk.makePaymentTxnWithSuggestedParamsFromObject({
                from:  userAccount.current[0].address,
                to: receipient.current,
                amount:parseInt(amount.current),
                // note: "document.getElementById('note').value",
                suggestedParams: {...suggestedParams}
              });

            // Use the AlgoSigner encoding library to make the transactions base64
              let txn_b64 = AlgoSigner.encoding.msgpackToBase64(txn.toByte());

            let signedTxs = await AlgoSigner.signTxn([{txn: txn_b64}])

            // Get the base64 encoded signed transaction and convert it to binary
            let binarySignedTx = AlgoSigner.encoding.base64ToMsgpack(signedTxs[0].blob);

            // Send the transaction through the SDK client
            let id = await client.sendRawTransaction(binarySignedTx).do();
                console.log(id)
                setLoading(false)
        }catch(err){
            console.log(err)
            setLoading(false)
        }  
    }

    return(
    <div>
        <div>
            <BodyText>Make Payment</BodyText>
            <FormStyle onChange = {(e) => amount.current = e.target.value} placeholder="Amount" /><br/>
            <FormStyle onChange = {(e) => receipient.current = e.target.value} placeholder="Receiver address" /><br/>
            <TransactionButton backgroundColor onClick ={signPayTransaction}>{isLoading ? "loading...": "Sign Transaction"}</TransactionButton>
        </div>
    </div>
    )
}

export default SignPayTransaction

EditorImages/2021/11/18 02:50/Screenshot_2021-11-18_at_03.49.21.png

Fig 8-3-1 Payment UI

EditorImages/2021/11/18 02:47/Screenshot_2021-11-18_at_03.46.06.png

Fig 8-3-2 Sign Pay Transaction

Once the transaction is signed and sent to the network you will get the transaction id
{txId: "5PHUOS7F6OAFGMFKOZIBURKWTH2CDYK6DGM7L44Q7QX6S7PZYQTA"}

EditorImages/2021/11/18 03:17/Screenshot_2021-11-18_at_04.17.14.png

Fig 8-3-2 Transaction Detail From AlgoExplorer

8.4 Create Algorand Standard Asset (ASA)

The below code is used to create an Asset from AlgoSigner. To create an asset this function will be called algosdk.makeAssetCreateTxnWithSuggestedParamsFromObject() this takes in some arguments the assetName the name of the asset, unitName the name of the unit total the total unit of the asset, decimals the decimals, note and suggestedParams are as explained in 5.3.
After creating the asset the transaction will be signed and sent to the network.

/*global AlgoSigner*/
import React, {useRef, useState} from "react";
import { FormStyle } from "../Form.style";
import { TransactionButton } from "../Button.styles";
import { BodyText } from "../MyAlgoWallet/MyAlgoWallet.styles";
import { TOKEN, ALGOD_SERVER, PORT, RECEIVER } from "../../constants";
const algosdk = require("algosdk");

const CreateAsset = ({userAccount}) => {

    const assetName = useRef()
    const unitName = useRef()
    const totalUnit = useRef()
    const note = useRef()
    const decimals = useRef()
    const [isLoading, setLoading] = useState(false)

    const createAsset = async () =>{
        // await AlgoSigner.connect();
        setLoading(true)
        let client =   new algosdk.Algodv2(TOKEN, ALGOD_SERVER, PORT)

        //Query Algod to get testnet suggested params
        let txParamsJS = await client.getTransactionParams().do()

        try{

            const txn = await new algosdk.makeAssetCreateTxnWithSuggestedParamsFromObject({
                from: userAccount.current[0].address,
                assetName: assetName.current,
                unitName: unitName.current,
                total: +totalUnit.current,
                decimals: +decimals.current,
                note: AlgoSigner.encoding.stringToByteArray(note.current),
                suggestedParams: {...txParamsJS}
              });

            const txn_b64 = await AlgoSigner.encoding.msgpackToBase64(txn.toByte());

             let signedTxs  = await AlgoSigner.signTxn([{txn: txn_b64}])
              console.log(signedTxs)

              // Get the base64 encoded signed transaction and convert it to binary
            let binarySignedTx = await AlgoSigner.encoding.base64ToMsgpack(signedTxs[0].blob);

             // Send the transaction through the SDK client
            let id = await client.sendRawTransaction(binarySignedTx).do();
                console.log(id)
                setLoading(false)

        }catch(err){
            console.log(err)
            setLoading(false)
        }
    }

    return(
    <div>
        <div>
            <BodyText>Create Asset</BodyText>
            <FormStyle onChange = {(e) => assetName.current = e.target.value} placeholder="Asset name" /><br/>
            <FormStyle onChange = {(e) => unitName.current = e.target.value} placeholder="Unit name" /><br/>
            <FormStyle onChange = {(e) => totalUnit.current = e.target.value} placeholder="Total units" /><br/>
            <FormStyle onChange = {(e) => decimals.current = e.target.value} placeholder="Decimals" /><br/>
            <FormStyle onChange = {(e) => note.current = e.target.value} placeholder="Enter note" /><br/>
            <TransactionButton backgroundColor onClick ={createAsset}>{isLoading ? "loading...": "Sign Create Asset"}</TransactionButton>
        </div>
    </div>
    )
}

export default CreateAsset

EditorImages/2021/11/18 02:54/Screenshot_2021-11-18_at_03.53.57.png
Fig 8-4-1 Create Asset UI

EditorImages/2021/11/18 02:54/Screenshot_2021-11-18_at_03.53.20.png
Fig 8-4-2 Sign Asset

Once the transaction is signed. It will return the transaction id to checkup the transaction details on the algoexplorer.io.
{txId: "BZSBJ2A2RAV22SNLQVR25BECX4GX3CTDIAJKJX73PU7DUHQ3SIZQ"}

8.5 Optin to An Asset

This function enables a user to optin to an assets. Only optin user/address can receive an asset.
To optin to an asset this function will be called algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject() this takes in some arguments like from the account creator, to the receipient, assetIndex the index number generated when the asset was created, note, amount and suggestedParams are as explained in 5.3.
After Opt in the transaction will be signed and sent to the network.

/*global AlgoSigner*/
import React, { useRef, useState } from "react";
import { FormStyle } from "../Form.style";
import { TransactionButton } from "../Button.styles";
import { BodyText } from "../MyAlgoWallet/MyAlgoWallet.styles";
import { TOKEN, ALGOD_SERVER, PORT } from "../../constants";
const algosdk = require("algosdk");

const CreateAsset = ({userAccount}) => {
    const receiver = useRef()
    const assetIndex = useRef()
    const note = useRef()
    const [isLoading, setLoading] = useState(false)


    const optInToAnAsset = async () =>{
        setLoading(true)
        let client =   new algosdk.Algodv2(TOKEN, ALGOD_SERVER, PORT)

        //Query Algod to get testnet suggested params
        let txParamsJS = await client.getTransactionParams().do()
       try{
           const txn = await new algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({
               from: userAccount.current[0].address,
               to: receiver.current,
               assetIndex: +assetIndex.current,
               note: AlgoSigner.encoding.stringToByteArray(note.current),
               amount: 0,
               suggestedParams: {...txParamsJS}
             });

             // Use the AlgoSigner encoding library to make the transactions base64
             const txn_b64 = AlgoSigner.encoding.msgpackToBase64(txn.toByte());

           const signedTxs = await AlgoSigner.signTxn([{txn: txn_b64}]) 
            console.log(signedTxs)

            // Get the base64 encoded signed transaction and convert it to binary
            let binarySignedTx = await AlgoSigner.encoding.base64ToMsgpack(signedTxs[0].blob);

            // Send the transaction through the SDK client
           let id = await client.sendRawTransaction(binarySignedTx).do();
               console.log(id)
               setLoading(false)
       }catch(err){
           console.log(err)
           setLoading(false)
       }
   }

    return(
    <div>
        <div>
            <BodyText>Asset Optin</BodyText>
            <FormStyle onChange = {(e) => receiver.current = e.target.value} placeholder="Receiver address" /><br/>
            <FormStyle onChange = {(e) => assetIndex.current = e.target.value} placeholder="Asset index" /><br/>
            <FormStyle onChange = {(e) => note.current = e.target.value} placeholder="Note" /><br/>
            <TransactionButton backgroundColor onClick ={optInToAnAsset}>{isLoading ? "loading...": "Sign Asset Optin"}</TransactionButton>
        </div>
    </div>
    )
}

export default CreateAsset

EditorImages/2021/11/18 03:06/Screenshot_2021-11-18_at_04.02.51.png
Fig 8-5-1 AlgoSigner Asset Details

EditorImages/2021/11/18 03:05/Screenshot_2021-11-18_at_04.03.02.png
Fig 8-5-2 Asset Optin UI

EditorImages/2021/11/18 03:05/Screenshot_2021-11-18_at_04.03.24.png
Fig 8-5-3 Sign Optin Transaction

Asset optin transaction id {txId: "4AV3LRS743XBN4SSJG6M2MMSHXLZKLRUKKGYXBSGNW25MCSWESNA"}

9. AlgoSigner UI Styles

This handles the UI Styling of AlgoSigner using styled-component.

AlgoSigner.styles.js

import styled from "styled-components";

export const AlgoSignerMain = styled.div`
    margin-top : 20px;
    @media(max-width : 767px) {
        width : 90%;
        margin : 36px auto;
    }
`

10. Next Step

  • Areas not covered in this tutorial like other capabilities of ASA that can be done with AlgoSigner, including Atomic transfer and creating of multisig accounts. Will be worked on in future tutorial.
  • Also a deeper look into Reach to create sample smart contracts using reach both on the backend and frontend.

11. Further Study

Warning

This tutorial is intended for learning purposes only. It does not cover error checking and other edge cases. Therefore, it should not be used as a production application