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 · 30 minutes

Atomic Transactions Web and Console Applications

This tutorial teaches you how to:

How to create Web Applications and Console Applications Using the C#/.NET Framework
How to install and use the Algorand Package in your application
Interact between your application and the Algorand Network
Perform Atomic Transactions

Requirements

Visual Studio for Mac or Visual Studio Community 2019 for Windows
.NET SDK Packages for Windows

Learn more on how to create an ASP.NET Core MVC Application using Visual Studio, VS Code and Visual Studio for Mac in the Link below:
https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/start-mvc?view=aspnetcore-5.0&tabs=visual-studio

Using VS Code
https://code.visualstudio.com/docs/languages/dotnet
Using VS for Mac
https://docs.microsoft.com/en-us/dotnet/core/tutorials/with-visual-studio-mac
Using Visual Studio
https://docs.microsoft.com/en-us/dotnet/core/tutorials/with-visual-studio
Debugging a console app with C# in VS Code
https://developer.algorand.org/tutorials/vs-code-csharp/
Learn more
Can one create a project solution with two projects in VS Code?
Check the link below:
https://code.visualstudio.com/docs/editor/multi-root-workspaces

Background

This is a Web Application through which one can generate account addresses and mnemonic keys, fund the account, check the account details and also perform transactions on the Algorand Network on TestNet. This is built using the C#/.NET framework to communicate with the Algorand Blockchain.

Steps

1. Create a Web Application and a Console Application

Open Visual Studio or Visual Studio Code and create a Web Application (.NET Core) and a Console Application in the same project solution.
Visual Studio IDE was used for this Tutorial.
EditorImages/2021/01/26 12:13/2021-01-26_13_11_13-Window.png

Fig 1-1
Select the ASP.NET Core Web Application Template as shown in Fig 1-2 below:
EditorImages/2021/01/26 12:15/2021-01-26_13_14_27-Window.png
Fig 1-2
Name your project and create
EditorImages/2021/01/26 12:16/2021-01-26_13_16_24-Window.png
Fig 1-3
Select the Web Application with (Model-View-Controller) running on the .Net Core 3.1 and click on create
EditorImages/2021/01/26 12:18/2021-01-26_13_17_34-Window.png
Fig 1-4

2. Install the Algorand SDK

To Open the NuGet Package Manager, Right Click on the Project solution
EditorImages/2021/01/26 11:31/2021-01-22_12_23_58-Window.png
Fig 2-1
EditorImages/2021/01/26 11:29/2021-01-22_12_21_43-.png

Fig 2-2
Search for Algorand in the Browse Window and Install the SDK as shown in Fig 2-1 above:

3. Create an Account on the Algorand Network

Open the program.cs class in the Console Application created.
Now, add the following code snippet to create an account address and key:

EditorImages/2021/01/26 11:35/2021-01-26_12_33_48-Window.png

Fig 3-1

Account acccount = new Account();
var address = acccount.Address;
var key = acccount.ToMnemonic();
Console.WriteLine($"Account Address: {address}\nKey: {key}");

Select the Console Application as the startup project as shown in Fig 3-2 below:
EditorImages/2021/01/26 11:37/2021-01-26_12_37_01-Window.png

Fig 3-2

Now, Run the Application to create an account:
EditorImages/2020/12/30 23:07/2020-12-31_00_06_25-Window.png
Run the application three time to create three accounts.
Copy the account addresses and their respective keys. They will be used to perform the transactions.
The First account will fund the other two accounts created.
Fig 3-3

4. Fund/Dispense Main Account

To fund the main account, visit the Algorand Dispenser, link: https://bank.testnet.algorand.network/
To fund the account. Copy the Address and Paste it in the field and click on the dispense button as shown below in Fig 1-11
EditorImages/2020/12/30 23:27/2020-12-31_00_26_57-Window.png
Fig 4-1

Visit: https://testnet.algoexplorer.io/
Paste in your account address in the search bar and click on the search icon to monitor the account and the transactions.

EditorImages/2021/01/26 11:48/2021-01-22_14_10_02-Window.png
Fig 4-2

After funding the account using the Algorand Dispenser, use the testnet.algoexplorer.io link to check the account balance. There should be 100 Algos as balance.
Note: The Application is running on TestNet

5. Perform Atomic Transaction

In the program.cs class, update the class to the following code snippet below:
Full code snippet of program.

using System;
using System.Collections.Generic;
using Algorand;
using Algorand.Client;
using Algorand.V2;

namespace AtomicTransactionConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Account acccount = new Account();
            var address = acccount.Address;
            var key = acccount.ToMnemonic();
            Console.WriteLine($"Account Address: {address}\nKey: {key}");
            //Account 1
            //Address: DZLN2QPBURBXHGHYY2Z5B3BOBZQS4BXIHJMOVXXDBDF66ZFWLFOXZG4OWE
            //Key: hood industry indicate catch erode return wage gas wrong museum lesson renew acid erupt victory swallow distance spy orchard tomorrow organ traffic hen ability drift

            //Account 2
            //Address: QQNTMX62E2UZF3264V3OB3O3F6CURWBBHR3MQZPRM26CFVMXUYWOXIKG6E
            //Key: salt priority million dignity cage roast enemy visual solid impose vocal cost quiz list result festival brother rain elder crisp jewel husband trim abandon brisk

            //Acount 3 
            //Address: RP2HQNAY4F4FWJ6OGOBSLCB73PXHVAQ36R6RAQTYPUEIPR4C7M2YJS4SSE
            //Key: race sure wagon prevent about powder rely enable erosion almost lens moment rain mechanic carry sense permit venue parent between permit upset lens able circle
            AtomicTransaction();

        }
        //Atomic Transaction Method
        public static void AtomicTransaction()
        {
            //Performing Atomic Transactions

            //PureStake Configuration with AlgodApi
            AlgodApi algodApiInstance = new AlgodApi("https://testnet-algorand.api.purestake.io/ps2", "B3SU4KcVKi94Jap2VXkK83xx38bsv95K5UZm2lab");
            //First Account Address - acc1
            var acc1 = "QQNTMX62E2UZF3264V3OB3O3F6CURWBBHR3MQZPRM26CFVMXUYWOXIKG6E";
            //Second Account Address - acc2
            var acc2 = "RP2HQNAY4F4FWJ6OGOBSLCB73PXHVAQ36R6RAQTYPUEIPR4C7M2YJS4SSE";
            //Key of the Main account that will fund other Accounts
            var key = "hood industry indicate catch erode return wage gas wrong museum lesson renew acid erupt victory swallow distance spy orchard tomorrow organ traffic hen ability drift";
            //Account that will fund other accounts
            var accountAddress = "DZLN2QPBURBXHGHYY2Z5B3BOBZQS4BXIHJMOVXXDBDF66ZFWLFOXZG4OWE";
            Account src = new Account(key);
            //Creating a transactionParams on the V2
            Algorand.V2.Model.TransactionParametersResponse transParams;
            try
            {
                transParams = algodApiInstance.TransactionParams();
            }
            catch (ApiException e)
            {
                throw new Exception("Could not get params", e);
            }

            // let's create a transaction group

            //amount to fund other accounts
            var amount = Utils.AlgosToMicroalgos(1);
            //First Transaction
            var tx = Utils.GetPaymentTransaction(new Address(accountAddress), new Address(acc1), amount, "pay message", transParams);
            //Second Transaction
            var tx2 = Utils.GetPaymentTransaction(new Address(accountAddress), new Address(acc2), amount, "pay message", transParams);
            //Grouping the Transactions (Atomic Transactions)
            Digest gid = TxGroup.ComputeGroupID(new Transaction[] { tx, tx2 });
            tx.AssignGroupID(gid);
            tx2.AssignGroupID(gid);
            // already updated the groupid, sign
            var signedTx = src.SignTransaction(tx);
            var signedTx2 = src.SignTransaction(tx2);
            try
            {
                //contact the signed msgpack
                List<byte> byteList = new List<byte>(Algorand.Encoder.EncodeToMsgPack(signedTx));
                byteList.AddRange(Algorand.Encoder.EncodeToMsgPack(signedTx2));
                var id = algodApiInstance.RawTransaction(byteList.ToArray());
                Console.WriteLine($"Successfully sent tx group with first tx id: {id}");
                Console.WriteLine(Utils.WaitTransactionToComplete(algodApiInstance, id.TxId));
            }
            catch (ApiException e)
            {
                // This is generally expected, but should give us an informative error message.
                Console.WriteLine("Exception when calling algod#rawTransaction: " + e.Message);
            }
            Console.WriteLine("You have successefully arrived the end of this test, please press and key to exit.");
        }
    }
}

The above code performs Atomic transfers which funds multiple accounts at once.

A static method called AtomicTransaction was created and called from the main method.

In an atomic transfer, if any of the transactions fail in the transaction group, all will fail.

Make an instance of the AlgodApi passing in the Purestake token and address as shown in the above code snippet:

AlgodApi algodApiInstance = new AlgodApi("https://testnet-algorand.api.purestake.io/ps2", "B3SU4KcVKi94Jap2VXkK83xx38bsv95K5UZm2lab");

This will enable us make transactions running on the Purestake TestNet V2.

After the call for rawtransaction, call the waitforconfirmation utils. This will make the program wait until the transaction is complete.

6. Run/Debug the Console Application

Run/Debug the Console Application to fund the other accounts from the main account.
Use the testnet.algoexplorer.io link to monitor and check the accounts funded.

7. Setup the Web Application

Open the Web Application (Atomic Transactions) and Navigate to the HomeController located in the the Controllers folder as shown in Fig 7-1 below:
EditorImages/2021/01/26 12:09/2021-01-26_13_09_12-Window.png
Fig 7-1

8. Setup the Controller

Ensure you include the using namespaces for Algorand as shown below in the Home Controller:
EditorImages/2021/01/26 11:53/2021-01-26_12_53_22-Window.png
Fig 8-1
Now, create an IAction method as shown below called Atomic and add the code snippet below:

public IActionResult AtomicTransaction()
        {
            //Performing Atomic Transactions

            //PureStake Configuration with AlgodApi
            AlgodApi algodApiInstance = new AlgodApi("https://testnet-algorand.api.purestake.io/ps2", "B3SU4KcVKi94Jap2VXkK83xx38bsv95K5UZm2lab");
            //First Account Address - acc1
            var acc1 = "QQNTMX62E2UZF3264V3OB3O3F6CURWBBHR3MQZPRM26CFVMXUYWOXIKG6E";
            //Second Account Address - acc2
            var acc2 = "RP2HQNAY4F4FWJ6OGOBSLCB73PXHVAQ36R6RAQTYPUEIPR4C7M2YJS4SSE";
            //Key of the Main account that will fund other Accounts
            var key = "hood industry indicate catch erode return wage gas wrong museum lesson renew acid erupt victory swallow distance spy orchard tomorrow organ traffic hen ability drift";
            //Account that will fund other accounts
            var accountAddress = "DZLN2QPBURBXHGHYY2Z5B3BOBZQS4BXIHJMOVXXDBDF66ZFWLFOXZG4OWE";
            Account src = new Account(key);
            //Creating a transactionParams on the V2
            Algorand.V2.Model.TransactionParametersResponse transParams;
            try
            {
                transParams = algodApiInstance.TransactionParams();
            }
            catch (ApiException e)
            {
                throw new Exception("Could not get params", e);
            }

            // let's create a transaction group

            //amount to fund other accounts
            var amount = Utils.AlgosToMicroalgos(1);
            //First Transaction
            var tx = Utils.GetPaymentTransaction(new Address(accountAddress), new Address(acc1), amount, "pay message", transParams);
            //Second Transaction
            var tx2 = Utils.GetPaymentTransaction(new Address(accountAddress), new Address(acc2), amount, "pay message", transParams);
            //Grouping the Transactions (Atomic Transactions)
            Digest gid = TxGroup.ComputeGroupID(new Transaction[] { tx, tx2 });
            tx.AssignGroupID(gid);
            tx2.AssignGroupID(gid);
            // already updated the groupid, sign
            var signedTx = src.SignTransaction(tx);
            var signedTx2 = src.SignTransaction(tx2);
            try
            {
                //contact the signed msgpack
                List<byte> byteList = new List<byte>(Algorand.Encoder.EncodeToMsgPack(signedTx));
                byteList.AddRange(Algorand.Encoder.EncodeToMsgPack(signedTx2));
                var id = algodApiInstance.RawTransaction(byteList.ToArray());
                TempData["Message"] = $"Successfully sent tx group with first tx id: {id}";
                //Console.WriteLine($"Successfully sent tx group with first tx id: {id}");
                Console.WriteLine(Utils.WaitTransactionToComplete(algodApiInstance, id.TxId));
            }
            catch (ApiException e)
            {
                // This is generally expected, but should give us an informative error message.
                Console.WriteLine("Exception when calling algod#rawTransaction: " + e.Message);
            }
            return RedirectToAction(nameof(Index));
        }

9. Setup the View Page

Open the Views folder, and navigate to the Home folder, click on the Index.cshtml class to open it as shown in Fig 9-1 below:
EditorImages/2021/01/26 12:05/2021-01-26_13_01_20-Window.png
Fig 9-1

Code snippet of Index.cshtml page shown above in Fig 9-1:

@{
    ViewData["Title"] = "Home Page";
}

@if (TempData["Message"] != null)
{
    <div class="alert-message success">
        <p>
            <span>@TempData["Message"]</span>
        </p>
    </div>
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    <form asp-action="AtomicTransaction" asp-controller="Home">
        <button>Atomic Transfer</button>
    </form>
</div>

Fig 9-1
Add the form as shown in the image above and run the Application.
Again, set the Web Application as the startup project and run the application.
EditorImages/2021/01/26 12:07/2021-01-26_13_00_17-Window.png
Fig 9-2

10. Solution/Project

GitHub Project Link: https://github.com/Sethmichael01/AtomicTransaction

YouTube Tutorial: