Algorand Payment App
This tutorial will teach us how to:
Build/Develop Mobile (Android/iOS) applications, Install Packages (Algorand SDK) to our Application, Process Payments for sending/transferring Algos from one account to another, Store/Save transaction history in a database on our Application and, Get or View Account Balance of the Account Address.
Requirements
Visual Studio IDE (install here ) with .NET Core Framework installed
Check the system requirements before you begin.
Download Visual Studio 2019 Community, Visual Studio Professional, or Visual Studio Enterprise from the Visual Studio Website
Select the Mobile development with .NET workload from the installation screen.
Algorand .NET SDK Package
Background
This tutorial will teach us how to: Build a DeFi Mobile Application on the Algorand Network to process payments/transactions Online.
This solution was built using the Xamarin Framework.
Steps
- Step 1: Create Project
- Step 2: After successfully creating the project, the next step is to install the Algorand SDK into our application.
- Step 3: Install SQLite Package into the Application to save/store transactions
- Step 4: Create the Transfer Model
- Step 5: Create the Views/Pages
- Step 6: Configure the Pages
- Step 7: Configure TransactionsPage
- Step 8: Configure PaymentPage
- Step 9: Configure Startup Page
- Step 10: Live Application Screenshots/Demo
- Conclusion
Step 1: Create Project
Open Visual Studio and create a new Project and select the (Mobile Application) as shown in Fig 1-1 and Fig 1-2 below:
Fig 1-1
Fig 1-2
Configure the project as shown in Fig 1-2 above and click on Create.
Step 2: After successfully creating the project, the next step is to install the Algorand SDK into our application.
To do that, right click on the Project Name and click on the “Manage NuGet Packages” shown below in Fig 2-1
Fig 2-1
Fig 2-2
Click on the “Browse” Window and Search for Algorand, Click on Install to Install the Algorand Package into our Application as shown in Fig 2-2 above.
Step 3: Install SQLite Package into the Application to save/store transactions
Fig 3-1
Install the Xamarin Essentials package also for secure storage use.
Fig 3-2
Step 4: Create the Transfer Model
Right Click on the Models Folder and Create a class “Transfer.cs
” and add the following code snippets below
using SQLite;
namespace AlgorandPayments.Models
{
public class Transfer
{
[PrimaryKey]
public int Id { get; set; }
public string SenderAddress { get; set; }
public string ReceiverAddress { get; set; }
public int Amount { get; set; }
public override string ToString()
{
return this.Amount + " algos to " + this.ReceiverAddress;
}
}
}
Step 5: Create the Views/Pages
Right Click on the Views Page and add three content pages as shown below in Fig 5-1
Fig 5-1
Fig 5-2
Create: “HomePage
, TransactionsPage
, and PaymentPage
” as shown in Fig 5-1 and Fig 5-2 above.
In Figure 5-2, we can see the three newly created pages (Content Pages).
Step 6: Configure the Pages
Having created the Pages Step 5 we will now configure them to build up our application and its functionalities.
Configure the HomePage
with the following code snippets:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Algorand.Client;
using Algorand;
using Algorand.V2.Model;
using Algorand.V2;
using Account = Algorand.Account;
using Xamarin.Forms;
namespace AlgorandPayments.Views
{
public class HomePage : ContentPage
{
public HomePage()
{
this.Title = "Algorand Payment App";
StackLayout stackLayout = new StackLayout();
Button button = new Button();
button.BackgroundColor = Color.Black;
button.Text = "Make Payment";
button.Clicked += Button_Clicked;
stackLayout.Children.Add(button);
//Second Button
button = new Button();
button.BackgroundColor = Color.Black;
button.Text = "View Transactions";
button.Clicked += Button_Clicked1;
stackLayout.Children.Add(button);
//Third Button
button = new Button();
button.BackgroundColor = Color.Black;
button.Text = "Get Account Balance";
button.Clicked += Button_Clicked2;
stackLayout.Children.Add(button);
Content = stackLayout;
}
private async void Button_Clicked2(object sender, EventArgs e)
{
string ALGOD_API_ADDR = "https://testnet-algorand.api.purestake.io/ps2"; //find in algod.net
string ALGOD_API_TOKEN = "B3SU4KcVKi94Jap2VXkK83xx38bsv95K5UZm2lab"; //find in algod.token
var key = "pet rabbit charge admit cake chapter coyote mandate provide travel victory stamp sleep lizard absurd toward galaxy place kiwi economy indoor innocent grit abandon rose";
string SRC_ACCOUNT = key;
Account src = new Account(SRC_ACCOUNT);
AlgodApi algodApiInstance = new AlgodApi(ALGOD_API_ADDR, ALGOD_API_TOKEN);
var accountInfo = algodApiInstance.AccountInformation(src.Address.ToString());
await DisplayAlert("Account Balance", $"{accountInfo.Address} has {accountInfo.Amount} Microalgos", "Balance", "Ok");
}
private async void Button_Clicked1(object sender, EventArgs e)
{
await Navigation.PushAsync(new PaymentPage());
}
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new TransactionsPage());
}
}
}
NOTE: This is for demo/testing purposes on the TestNet and will not work on MainNet/BetaNet.
DO NOT USE THIS FOR PRODUCTION.
The Mnemonic key of this account address is being displayed to show us how it looks like. !
Update the code snippets of the HomePage with the one above to create the buttons and that will handle events when clicked on.
Make Payment Button: This will take us to the TransactionsPage
where the Transfer/Payment of Algos functionality will be processed.
View Transactions Button: This will take us to the page where we can view our transaction history which will be stored into our application database.
Get Account Balance Button: This will notify us of the balance available in our account address.
Step 7: Configure TransactionsPage
Open the TransactionsPage
and update it with the code snippets below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using SQLite;
using Algorand.Client;
using Algorand;
using Algorand.V2.Model;
using Algorand.V2;
using Account = Algorand.Account;
using Xamarin.Forms;
using AlgorandPayments.Models;
using Xamarin.Essentials;
namespace AlgorandPayments.Views
{
public class TransactionsPage : ContentPage
{
private Entry _AddressEntry;
private Entry _AmountEntry;
private Button _SaveEntry;
//Database
string _dbPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "Mydbs.db3");
public TransactionsPage()
{
this.Title = "Process Transaction";
StackLayout stackLayout = new StackLayout();
//Receiver Address Entry
_AddressEntry = new Entry();
_AddressEntry.Keyboard = Keyboard.Text;
_AddressEntry.Placeholder = "Receiver Address";
stackLayout.Children.Add(_AddressEntry);
//Amount Entry
_AmountEntry = new Entry();
_AmountEntry.Keyboard = Keyboard.Text;
_AmountEntry.Placeholder = "Amount";
stackLayout.Children.Add(_AmountEntry);
//Save Button
_SaveEntry = new Button();
_SaveEntry.Text = "Proceed with Transfer";
_SaveEntry.Clicked += _SaveEntry_Clicked;
stackLayout.Children.Add(_SaveEntry);
Content = stackLayout;
}
private async void _SaveEntry_Clicked(object sender, EventArgs e)
{
var db = new SQLiteConnection(_dbPath);
db.CreateTable<Transfer>();
var maxpk = db.Table<Transfer>().OrderByDescending(i => i.Id).FirstOrDefault();
Transfer payment = new Transfer()
{
Id = (maxpk == null ? 1 : maxpk.Id + 1),
SenderAddress = "4GIK2BGHFB3BTD2URC4FQLK7TO5XDJ6TYU7NSOZOHL7HZVUHDFFWUIOTNA",
ReceiverAddress = _AddressEntry.Text,
Amount = Convert.ToInt32(_AmountEntry.Text)
};
var key = "pet rabbit charge admit cake chapter coyote mandate provide travel victory stamp sleep lizard absurd toward galaxy place kiwi economy indoor innocent grit abandon rose";
try
{
await SecureStorage.SetAsync("token", key);
}
catch (Exception ex)
{
// Possible that device doesn't support secure storage on device.
}
try
{
var Token = await SecureStorage.GetAsync("token");
db.Insert(payment);
key = Token;
FundMethod(Token, payment.ReceiverAddress, payment.Amount, payment.SenderAddress);
await DisplayAlert("Success", "Transfer of " + payment.Amount + " algos to " + payment.ReceiverAddress + " was successfull.", $"Successfully Transfered {payment.Amount} Algos", "Ok");
await Navigation.PopAsync();
}
catch (Exception ex)
{
// Possible that device doesn't support secure storage on device.
}
}
public static void FundMethod(string key, string receiver, int amount, string senderAddr)
{
string ALGOD_API_ADDR = "https://testnet-algorand.api.purestake.io/ps2"; //find in algod.net
string ALGOD_API_TOKEN = "B3SU4KcVKi94Jap2VXkK83xx38bsv95K5UZm2lab"; //find in algod.token
string SRC_ACCOUNT = key;
string DEST_ADDR = receiver;
Account src = new Account(SRC_ACCOUNT);
AlgodApi algodApiInstance = new AlgodApi(ALGOD_API_ADDR, ALGOD_API_TOKEN);
try
{
var trans = algodApiInstance.TransactionParams();
}
catch (ApiException e)
{
Console.WriteLine("Exception when calling algod#getSupply:" + e.Message);
}
TransactionParametersResponse transParams;
try
{
transParams = algodApiInstance.TransactionParams();
}
catch (ApiException e)
{
throw new Exception("Could not get params", e);
}
var amountsent = Utils.AlgosToMicroalgos(amount);
var tx = Utils.GetPaymentTransaction(src.Address, new Address(DEST_ADDR), amountsent, "pay message", transParams);
var signedTx = src.SignTransaction(tx);
Console.WriteLine("Signed transaction with txid: " + signedTx.transactionID);
// send the transaction to the network
try
{
var id = Utils.SubmitTransaction(algodApiInstance, signedTx);
Console.WriteLine("Successfully sent tx with id: " + id.TxId);
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);
}
}
}
}
The _SaveEntry_Clicked
event handler uses the Xamarin Essentials with the Secure Storage to save and retrieve the key (mnemonic key) in the program.
The following code below in the above program handles the secure storage functionality in the code snippet below:
var key = "pet rabbit charge admit cake chapter coyote mandate provide travel victory stamp sleep lizard absurd toward galaxy place kiwi economy indoor innocent grit abandon rose";
try
{
await SecureStorage.SetAsync("token", key);
}
catch (Exception ex)
{
// Possible that device doesn't support secure storage on device.
}
try
{
var Token = await SecureStorage.GetAsync("token");
db.Insert(payment);
key = Token;
FundMethod(Token, payment.ReceiverAddress, payment.Amount, payment.SenderAddress);
await DisplayAlert("Success", "Transfer of " + payment.Amount + " algos to " + payment.ReceiverAddress + " was successfull.", $"Successfully Transfered {payment.Amount} Algos", "Ok");
await Navigation.PopAsync();
}
catch (Exception ex)
{
// Possible that device doesn't support secure storage on device.
}
This will handle the processes involved when transferring Algos from one your account address to another.
The FundMethod
contains the functionality of the transfer of algos from one account to another.
Transaction Details will be stored in our application database created in this step.
NOTE: This is for demo/testing purposes on the TestNet and will not work on MainNet/BetaNet. The Mnemonic key of this account address is being displayed to show us how it looks like. Never share or publicly display your account key with anyone!
Use the https://testnet.algoexplorer.io/ to check your live transactions as shown below running on the TestNet in Fig 7-1
Fig 7-1
To fund an account address on the TestNet, visit https://bank.testnet.algorand.network/
Additional Resource/Tip: If you wish to invoke the dispenser pragmatically from the code, you can pass the address as a parameter on the call to the dispenser site. https://bank.testnet.algorand.network?account=xxxxx
Fig 7-2
Step 8: Configure PaymentPage
Open the PaymentPage
and update it with the code snippets shown below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SQLite;
using AlgorandPayments.Models;
using Xamarin.Forms;
using System.IO;
namespace AlgorandPayments.Views
{
public class PaymentPage : ContentPage
{
private ListView _listView;
string _dbPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "Mydbs.db3");
public PaymentPage()
{
this.Title = "Transactions";
var db = new SQLiteConnection(_dbPath);
StackLayout stackLayout = new StackLayout();
_listView = new ListView();
_listView.ItemsSource = db.Table<Transfer>().OrderBy(n => n.Id).ToList();
stackLayout.Children.Add(_listView);
Content = stackLayout;
}
}
}
This page will display the list of transactions that have been made and stored in our database.
Step 9: Configure Startup Page
Open the App.xaml.cs
file and update the MainPage
as shown below in Fig 8-1.
This will configure the page that will first display when the application opens.
Fig 9-1
Step 10: Live Application Screenshots/Demo
Homepage:
Fig 10-1
Get Account Balance:
Fig 10-2
TransactionsPage:
Fig 10-3
PaymentPage:
Fig 10-4
Conclusion
In this solution, we have learnt how to create a Mobile App with a database and also learnt how to interact with the Algorand Network from our application to handle and process transactions by sending algos from one account address to another.
Source Code: GitHub