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
Beginner · 15 minutes or less

Create an Account on TestNet and Send Your First Transaction using C#

This tutorial demonstrates the steps involved in creating a basic Standalone Algorand Account using the Community Algorand .NET SDK and funding it using the Algorand Testnet Faucet. The tutorial also covers send a payment transaction between two accounts.

Requirements

Algorand Community .NET SDK - Follow this tutorial to see how to install the SDK as a Nuget package.

Algorand Sandbox Installation or set up a node as described here.

Optional: API testing tool such as Postman.

Visual Studio 2019. You can download the community edition here. Other C#/.NET editors also work (VS Code, JetBrains Rider etc.).

Background

Many tutorials will need accounts to perform transactions on. Code samples will typically call a restore account function from a mnemonic code. Storing this mnemonic code in the source code is for demonstration purposes only.

Copy off the account addresses and mnemonics generated from this tutorial for later use.

Note: In production code, you would never hard-code account mnemonics, instead these would be injected.

Steps

1. Create a new VS Project and install the Algorand Community .NET SDK

Start off by creating a new Visual Studio project. Use the template named “Console Application”. After creating the new project, left-click on your C# project in the Solution Explorer and select “Manage Nuget Packages”.

Select the “Browse” tab to the right when the Nuget Package Manager has opened and type in “Algorand”. Download the latest stable version (select and then click “Install”). Accept all license agreements and proceed.

2. Generate an Algorand Key Pair

Navigate back to your “Program.cs” file and erase the contents of the Main method. Add, as the first line of your file, this line: using Algorand;. It will allow you to skip specifying the full namespace of certain classes in the Algorand .NET SDK. Now create a new Account instance using the empty constructor in your main method and print the address of your new account.

Your Main method should now look like:

static void Main(string[] args)
{
    // Generate new account.
    var account = new Account();
    Console.WriteLine("Account Address: " + account.Address.ToString());
}

Note: In this tutorial only using directives related to the Algorand .NET SDK will be explicitly mentioned. In order to resolve other missing types from e.g. the standard library, use ALT+Enter or similar depending on your configuration to automatically add missing types.

3. Retrieve the Private Key Mnemonic

Retrieve the private key Mnemonic by invoking the ToMnemonic on the Account instance. Append the following two lines of code to your main method:

// Access private key mnemonic.
var mnemonic = account.ToMnemonic();
Console.WriteLine("Account mnemonic: " + mnemonic);

Execute the program (press F5) and note down your public address and private key mnemonic.

4. Send Algos to the New Account

Let’s send Algos to the new account by visiting the TestNet faucet.

Enter the Algorand Public Address in the textbox, complete the recaptcha, and click “Dispense”. If you receive a 200 status code, your account should now be funded with 10 Algos.

5. Check your Balance

You can check your balance with any block explorer connected to TestNet. Make sure when you have selected a block explorer to switch to TESTNET, otherwise you won’t see your account.

You can also connect to a node through the .NET Algorand Client. Make sure to first retrieve an IP address and access token through one of the methods described in the Workspace Setup. Also make sure to replace the placeholder values with your own address and token.

Once you have an address and token, erase all contents of your Main method. Now declare a new const string for your Program class called AccountMnemonic with the value of your private key mnemonic. On mainnet you would read this as an environment variable or similar due to security concerns. Furthermore declare two new const strings, ApiAddress and ApiToken with your target API address and token retrieved by following the steps described in the link above.

private const string ApiAddress = "http://localhost:4001" // sandbox API address
private const string ApiToken = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" // sandbox API token

Furthermore, add a using directive at the top of your “Program.cs” file: using Algorand.V2;.

Now replace your Main method with:

// Initialize account from your private key mnemonic.
var account = new Account(AccountMnemonic);
var accountAddress = account.Address.EncodeAsString();

// Create a new instance of the V2 Algod API .NET Client.
var algodApi = new AlgodApi(ApiAddress, ApiToken);


// Access account information using the API.
var accountInformation = algodApi.AccountInformation(accountAddress);

// Print the current balance.
Console.WriteLine("Current balance for account " + accountAddress + " is " + accountInformation.Amount + " MicroAlgos");

Execute the program (press F5) and you should see that your address has 10 million MicroAlgos which is equivalent to 10 algos.

6. Optional - Import Account into Mobile Wallet

The mnemonic you just generated is compatible with Algorand’s mobile wallet. Tap the “Recover from passphrase” button to import this account into your mobile wallet. Your balance should now update.

Note that before you can view your funds you have to switch to using the TestNet. Start by navigating to your settings page, and then follow the screenshot progression below:

Image 1.

Navigate to your settings page and scroll to the bottom. Tap Developer Settings.

Image 2.

Tap Node Settings.

Image 3.

Tap TestNet to connect your Algorand Wallet to TestNet.

Note: Any account on TestNet exists in MainNet, and vice versa. However, the same account on each will have different assets and funds, etc.

7. Send a transaction between two Accounts

Create three accounts in total.

static void Main(string[] args)
{
    var account1 = CreateNewAccount(1);
    var account2 = CreateNewAccount(2);
    var account3 = CreateNewAccount(3);
}

private static Account CreateNewAccount(int number)
{
    // Generate new account.
    var account = new Account();
    Console.WriteLine("Account #" + number + " Address: " + account.Address.ToString());

    // Access private key mnemonic.
    var mnemonic = account.ToMnemonic();
    Console.WriteLine("Account #" + number + " mnemonic: " + mnemonic);

    var recoveredAccount = new Account(mnemonic);
    var isValid = Address.IsValid(recoveredAccount.Address.ToString());
    Console.WriteLine("Account #" + number + " is valid: " + isValid);

    Console.WriteLine("Save account address and mnemonic listed above for account #" + number);

    return account;
}

Now send a transaction between account 1 and account 2, by appending the following code to your Main method:

// Put a breakpoint on the line below to fill your test accounts with some Algo using the test net dispenser.
var algodApi = new AlgodApi(ApiAddress, ApiToken);

// Get the suggested transaction parameters.
var transactionParams = algodApi.TransactionParams();

// Send 1 Algo from account 1 to account 2.
var paymentTransaction = Utils.GetPaymentTransaction(account1.Address, account2.Address, 1000000, "Payment", transactionParams);

// Sign the transaction using account 1.
var signedPaymentTransaction = account1.SignTransaction(paymentTransaction);

Console.WriteLine("Signed transaction with transaction ID: " + signedPaymentTransaction.transactionID);

// Send the transaction to the network.
var id = Utils.SubmitTransaction(algodApi, signedPaymentTransaction);
Console.WriteLine("Successfully sent transaction with ID: " + id.TxId);

// Wait for the transaction to complete.
var response = Utils.WaitTransactionToComplete(algodApi, id.TxId);
Console.WriteLine("The confirmed round is: " + response.ConfirmedRound);

Here we are sending 1 Algo from account 1 to account 2. By having access to the Account instance of account 1, we can sign the transaction and thereby approve it.

8. Completed Code

Here is the completed code to generate 3 accounts, send a transaction of 1 Algo between account 1 and 2 and view all three accounts balance. Utilize the debugger to use the test net dispenser before proceeding.

static void Main(string[] args)
{
    var account1 = CreateNewAccount(1);
    var account2 = CreateNewAccount(2);
    var account3 = CreateNewAccount(3);

    // Put a breakpoint on the line below to fill your test accounts with some Algo using the test net dispenser.
    var algodApi = new AlgodApi(ApiAddress, ApiToken);

    // Get the suggested transaction parameters.
    var transactionParams = algodApi.TransactionParams();

    // Send 1 Algo from account 1 to account 2.
    var paymentTransaction = Utils.GetPaymentTransaction(account1.Address, account2.Address, 1000000, "Payment", transactionParams);

    // Sign the transaction using account 1.
    var signedPaymentTransaction = account1.SignTransaction(paymentTransaction);

    Console.WriteLine("Signed transaction with transaction ID: " + signedPaymentTransaction.transactionID);

    // Send the transaction to the network.
    var id = Utils.SubmitTransaction(algodApi, signedPaymentTransaction);
    Console.WriteLine("Successfully sent transaction with ID: " + id.TxId);

    // Wait for the transaction to complete.
    var response = Utils.WaitTransactionToComplete(algodApi, id.TxId);
    Console.WriteLine("The confirmed round is: " + response.ConfirmedRound);

    GetAndPrintAccountInformation(algodApi, account1, 1);
    GetAndPrintAccountInformation(algodApi, account2, 2);
    GetAndPrintAccountInformation(algodApi, account3, 3);
}

private static Account CreateNewAccount(int number)
{
    // Generate new account.
    var account = new Account();
    Console.WriteLine("Account #" + number + " Address: " + account.Address.ToString());

    // Access private key mnemonic.
    var mnemonic = account.ToMnemonic();
    Console.WriteLine("Account #" + number + " mnemonic: " + mnemonic);

    var recoveredAccount = new Account(mnemonic);
    var isValid = Address.IsValid(recoveredAccount.Address.ToString());
    Console.WriteLine("Account #" + number + " is valid: " + isValid);

    Console.WriteLine("Save account address and mnemonic listed above for account #" + number);

    return account;
}

private static void GetAndPrintAccountInformation(AlgodApi algodApi, Account account, int number)
{
    var accountInformation = algodApi.AccountInformation(account.Address.ToString());
    Console.WriteLine("Account #" + number + " information: " + Environment.NewLine + accountInformation.ToJson());
}

/* Sample output:
Account #1 Address: B2N2DQCGEROOYJZLME5QDEQPLKGAAY6VEODYJZYUOK76DRS7W3RA6QTEBI
Account #1 mnemonic: story sheriff track wisdom amazing eye burden essence burger gossip library future peanut drum youth fiction shuffle vacuum knock vivid trick group physical able yellow
Account #1 is valid: True
Save account address and mnemonic listed above for account #1
Account #2 Address: M3FGYVMPEWK4WMOG7SFSC6E6AD5QMCR6XT2VGYSKWKKIE2NOKVB37TG4NU
Account #2 mnemonic: toss tonight grape army hospital worry act sugar fever pitch purity explain runway august snow rug improve tone tissue put nest radio shed about prepare
Account #2 is valid: True
Save account address and mnemonic listed above for account #2
Account #3 Address: O3SBYZS3H5JPLDW3FERCNKPB6DA6QV7GLO6ITWP7JYELF5PLZ4YUAVAPVQ
Account #3 mnemonic: cruise rely universe lock choice book affair deposit ensure firm fiscal course outer juice amused voice grape faculty another tomorrow goose clump minute abstract annual
Account #3 is valid: True
Save account address and mnemonic listed above for account #3
Signed transaction with transaction ID: K4HBW7JOYISZ6I3I43MBSLFCFBTZ7FCU5ZHZYSB4KHQ7NKMNI57Q
Successfully sent transaction with ID: K4HBW7JOYISZ6I3I43MBSLFCFBTZ7FCU5ZHZYSB4KHQ7NKMNI57Q
The confirmed round is: 14282356
Account #1 information:
{
  "address": "B2N2DQCGEROOYJZLME5QDEQPLKGAAY6VEODYJZYUOK76DRS7W3RA6QTEBI",
  "amount": 8999000,
  "amount-without-pending-rewards": 8999000,
  "apps-local-state": [],
  "apps-total-schema": {
    "num-uint": 0,
    "num-byte-slice": 0
  },
  "assets": [],
  "created-apps": [],
  "created-assets": [],
  "pending-rewards": 0,
  "reward-base": 27521,
  "rewards": 0,
  "round": 14282356,
  "status": "Offline"
}
Account #2 information:
{
  "address": "M3FGYVMPEWK4WMOG7SFSC6E6AD5QMCR6XT2VGYSKWKKIE2NOKVB37TG4NU",
  "amount": 11000000,
  "amount-without-pending-rewards": 11000000,
  "apps-local-state": [],
  "apps-total-schema": {
    "num-uint": 0,
    "num-byte-slice": 0
  },
  "assets": [],
  "created-apps": [],
  "created-assets": [],
  "pending-rewards": 0,
  "reward-base": 27521,
  "rewards": 0,
  "round": 14282356,
  "status": "Offline"
}
Account #3 information:
{
  "address": "O3SBYZS3H5JPLDW3FERCNKPB6DA6QV7GLO6ITWP7JYELF5PLZ4YUAVAPVQ",
  "amount": 10000000,
  "amount-without-pending-rewards": 10000000,
  "apps-local-state": [],
  "apps-total-schema": {
    "num-uint": 0,
    "num-byte-slice": 0
  },
  "assets": [],
  "created-apps": [],
  "created-assets": [],
  "pending-rewards": 0,
  "reward-base": 27521,
  "rewards": 0,
  "round": 14282356,
  "status": "Offline"
}
*/

The full source code for this project can be viewed in this GitHub Repository.