# Welcome 👨‍💻

Welcome to Vertices! The place to build secure and advanced IoT applications using blockchain technology.

![](https://3444584021-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY5cgxyYAI0pHdVffOt%2F-MYdydPptl1R5uBPjop_%2F-MYdz8AboLnL9y1d2bU4%2Fvertices_stack.png?alt=media\&token=b7643633-2810-46e2-b65b-2c54ddef09eb)

{% content-ref url="/pages/-MY5eYBZS8LN0Dhn7Ijp" %}
[⚙️ Vertices SDK](/vertices-sdk/quickstart)
{% endcontent-ref %}


# Quickstart

Get started with the Vertices SDK in a few easy steps.

## Overview

{% hint style="info" %}
The Vertices SDK currently supports the [Algorand Blockchain](https://www.algorand.com/technology/algorand-protocol). The following information relates to Algorand's ecosystem.
{% endhint %}

In this tutorial, we are going to run an example on your machine where **Alice** sends a payment transaction to **Bob**.

![](https://3444584021-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY5cgxyYAI0pHdVffOt%2F-MYejyvJzaS0E6qe2v6c%2F-MYekXXgxmavul2rTK8-%2Falice_bob.png?alt=media\&token=f8c62847-fc28-4910-afc3-8b01900cf17d)

Here **Alice** sends 1 Algo to **Bob**.\
**Alice** is the **sender**, **Bob** the **receiver**.

## Before starting off

{% hint style="danger" %}
The Vertices SDK is still in beta. \
**This must not be used for production.**
{% endhint %}

## Get the source

Start by downloading the source of the repository along with the submodules:

```bash
# clone into current directory including its submodules
git clone --recurse-submodules https://github.com/vertices-network/c-vertices-sdk
cd c-vertices-sdk
```

## Set up your environment

We recommend using Conda to isolate your development environment and keep up to date with the dependencies.&#x20;

Install [miniconda](https://docs.conda.io/en/latest/miniconda.html) if you're running on x86\_64 architecture and [miniforge](https://github.com/conda-forge/miniforge) for ARM CPUs.

{% tabs %}
{% tab title="macOS" %}

```bash
brew install libsodium curl cmake python3 ccache
```

{% endtab %}

{% tab title="Linux" %}

```bash
apt-get install curl cmake python3 ccache libsodium-dev
```

{% endtab %}

{% tab title="Conda" %}

```
# create 'vertices' environment
conda env create -f utils/environment.yml

# when checking out another commit,  you might want 
# to make sure you're up to date with dependencies:
conda env update -f utils/environment.yml

# remember to activate your environment
conda activate vertices

# you are ready to code
```

{% endtab %}
{% endtabs %}

## Let's go

You can run Vertices on several targets. Get started quickly on your machine or try the example on your ESP32-based board:

{% content-ref url="/pages/-Ma-DTjiI5hAQJ2\_rZ2g" %}
[Unix](/vertices-sdk/quickstart/unix)
{% endcontent-ref %}

{% content-ref url="/pages/-Ma-DOWLyCJa2L43J97T" %}
[Microcontrollers](/vertices-sdk/quickstart/microcontrollers)
{% endcontent-ref %}


# Unix

Run the Vertices SDK on your machine.

## Setup

Make sure you've followed the previous steps.

{% content-ref url="/pages/-MY5hWk4TbmFb9sFn8bE" %}
[Quickstart](/vertices-sdk/quickstart)
{% endcontent-ref %}

## Compile

Let's build the example. Go to the root directory and follow those steps:

```
mkdir build && cd build
cmake ..

# build the Unix example
make unix_example
```

### Binary location

The executable is located at: `./examples/unix/unix_example`&#x20;


# New account

The Unix example allows you to create a new random account.

## Create a new account

The first time you launch the example, you might want to generate a new account that will then be used.  There are two ways to do so: from the Unix example we provide or using Algorand's `algokey` tool.

Both ways will use the same format to store the keys using two files:

1. `private_key.bin` for the private key, stored in binary format;
2. `public_b32.txt` for the account address in plain text (base-32 format).

{% hint style="info" %}
In any case, you will then be asked to [fund your account](https://bank.testnet.algorand.network/) in order to execute new transactions.
{% endhint %}

### Using the Unix example

```
./examples/unix/unix_example [-n]
```

Use the flag `-n` to allow `unix_example` to generate a new random account. The account is then stored inside a binary file where the private and public keys are concatenated in binary format.

Below is the example running:

```
$ ./examples/unix/unix_example -n
🟢 [examples/unix/main.c:217] 😎 Vertices SDK running on Unix-based OS
🟢 [examples/unix/main.c:137] 🔑 Loading private key from: /path/to/c-vertices-sdk/examples/unix/config/private_key.bin
🟠 [examples/unix/main.c:145] 🧾 Creating new random account and storing it (path /path/to/c-vertices-sdk/examples/unix/config/)
🟢 [examples/unix/main.c:194] 💳 Alice's account IZV2H3YRLCPOTUL5ATG5T3TRMUEXKLOGFWYO34NVKRMTXKZO2OOAJ34IWI
🟢 [examples/unix/main.c:250] 🏎 Running on testnet-v1.0 v.2.5.0
🟢 [src/account.c:42] 👛 Added account to wallet: #0
🟢 [src/account.c:42] 👛 Added account to wallet: #1
🟢 [examples/unix/main.c:263] 🤑 0.000000 Algos on Alice's account (IZV2H3YRLCPOTUL5ATG5T3TRMUEXKLOGFWYO34NVKRMTXKZO2OOAJ34IWI)
🔴 [examples/unix/main.c:268] 🙄 Amount available on account is too low to pass a transaction, consider adding Algos
🟢 [examples/unix/main.c:270] 👉 Go to https://bank.testnet.algorand.network/, dispense Algos to: IZV2H3YRLCPOTUL5ATG5T3TRMUEXKLOGFWYO34NVKRMTXKZO2OOAJ34IWI
🟢 [examples/unix/main.c:271] 😎 Then wait for a few seconds for transaction to pass...
```

Taking a look at the log, you will see that:

1. The path to the file storing the keys is displayed `/path/to/c-vertices-sdk/examples/unix/config/`.&#x20;
2. The created account is also displayed in base-32 format: `IZV2H3YRLCPOTUL5ATG5T3TRMUEXKLOGFWYO34NVKRMTXKZO2OOAJ34IWI`.
3. Following the last two lines, you then need to go to <https://bank.testnet.algorand.network/> to fund the freshly generated account: `IZV2H3YRLCPOTUL5ATG5T3TRMUEXKLOGFWYO34NVKRMTXKZO2OOAJ34IWI`.

Once you have dispensed money on the account, you can go to the next step! 🙂

{% hint style="info" %}
You can use `-n` flag whenever you want to create a new account but make sure to have copied the generated files somewhere else if you want to keep the account otherwise, it will be overwritten and forever lost.
{% endhint %}

### Using Algokey

You can also choose to generate a new account using the tool provided with the Algorand node: [`algokey`](https://developer.algorand.org/docs/reference/cli/algokey/algokey/):

```bash
./algokey generate -f path_to/examples/unix/config/private_key.bin -p path_to/examples/unix/config/public_b32.txt

# to get the account public address:
cat path_to/examples/unix/config/public_b32.txt 
```

In order to use the account, you need to store the files in the example `config` folder. The example program will then be ready to use, as soon as you [dispense money on the account](https://bank.testnet.algorand.network/). You will find the public key in `public_b32.txt`.

You are now ready to send your first transaction 😎.


# Pay transaction

Make Alice send money to Bob.

You should now have money in the previously created account: Alice's account.

You can now run the Unix example program to send money to Bob with the `-p` flag:

```
$ ./examples/unix/unix_example -p
🟢 [examples/unix/main.c:217] 😎 Vertices SDK running on Unix-based OS
🟢 [examples/unix/main.c:137] 🔑 Loading private key from: /Users/cyril/Documents/work/vertices/c-vertices-sdk/examples/unix/config/private_key.bin
🟢 [examples/unix/main.c:194] 💳 Alice's account IZV2H3YRLCPOTUL5ATG5T3TRMUEXKLOGFWYO34NVKRMTXKZO2OOAJ34IWI
🟢 [examples/unix/main.c:250] 🏎 Running on testnet-v1.0 v.2.5.0
🟢 [src/account.c:42] 👛 Added account to wallet: #0
🟢 [src/account.c:42] 👛 Added account to wallet: #1
🟢 [examples/unix/main.c:263] 🤑 10.000000 Algos on Alice's account (IZV2H3YRLCPOTUL5ATG5T3TRMUEXKLOGFWYO34NVKRMTXKZO2OOAJ34IWI)
🟢 [src/algorand/algorand_transaction.c:307] 🧾 Transaction executed, ID: I5CG4PC7V6XKEGHZUUZF25I3JXBQKLU4AUV4HANQYAHH4TCPVWWQ
🟢 [examples/unix/main.c:290] 💸 Alice sent 1 algo to Bob
🟢 [src/account.c:89] 👛 Deleted account from wallet: #0
🟢 [src/account.c:89] 👛 Deleted account from wallet: #1
```

Now you can check the transaction status on [AlgoExplorer for Testnet](https://testnet.algoexplorer.io/), using the transaction ID printed `I5CG4PC7V6XKEGHZUUZF25I3JXBQKLU4AUV4HANQYAHH4TCPVWWQ`.

![Alice sent 1 Algo to Bob](https://3444584021-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY5cgxyYAI0pHdVffOt%2F-MYemy_b8Yox2k8ELvKS%2F-MYenaGruUt4TtUcIj3h%2Fimage.png?alt=media\&token=78e7d698-2dc6-4495-bb56-7709cb7cdefe)

Below we can see the Sender and Receiver along with the Note added to the transaction: `Alice sent 1 Algo to Bob`.


# Application call

Interact with a decentralised application: store a value on the blockchain.

We have set up a really simple **stateful smart contract** to test the application calls. This smart contract is expecting an integer as a parameter. \
It then stores the **sum of values** and the **number of values** as global states within the application and the **last value** sent as a local state in the user account.&#x20;

![Overview of the Smart Contract's behavior](https://3444584021-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY5cgxyYAI0pHdVffOt%2F-Mcp0qIsOgXHOHKZkoLs%2F-Mcp5vXJE8NJDDlo800f%2FSimple_Storage.png?alt=media\&token=4295d200-144b-4dfc-9de5-bbdeee54a1bc)

{% hint style="info" %}
The smart contract source can be found [here](https://github.com/vertices-network/SimpleStorage/tree/main/SimpleStorage_algoDEA/src).
{% endhint %}

Once you've put some money into your account, you can run the Unix example program with the `-a` flag:

```
$ ./examples/unix/unix_example -a
🟢 [examples/unix/main.c:245] 😎 Vertices SDK running on Unix-based OS
🟢 [examples/unix/main.c:140] 🔑 Loading private key from: /Users/cyril/Documents/work/vertices/c-vertices-sdk/examples/unix/config/private_key.bin
🟢 [examples/unix/main.c:201] 💳 Alice's account E3PGTXKDOODVQ3E2ZB5PMJF2W3YOKIPUPLFDTESSP6562QE4GTLAKO4VXY
🟢 [examples/unix/main.c:278] 🏎 Running on testnet-v1.0 v.2.6.0
🟢 [src/account.c:42] 👛 Added account to wallet: #0
🟢 [src/account.c:42] 👛 Added account to wallet: #1
🟢 [examples/unix/main.c:293] 🤑 2.907842 Algos on Alice's account (E3PGTXKDOODVQ3E2ZB5PMJF2W3YOKIPUPLFDTESSP6562QE4GTLAKO4VXY)
🟢 [src/algorand/algorand_transaction.c:435] 🧾 Transaction executed, ID: WEXZJNY4UIVTZLYP2DXMZZTA5FMEEOLCQCVM6J66DZDCAW6YJWZQ
🟢 [src/account.c:104] 👛 Deleted account from wallet: #0
🟢 [src/account.c:104] 👛 Deleted account from wallet: #1
```

Now you can check the transaction status on [AlgoExplorer for Testnet](https://testnet.algoexplorer.io/), using the transaction ID printed `WEXZJNY4UIVTZLYP2DXMZZTA5FMEEOLCQCVM6J66DZDCAW6YJWZQ`.

Here is the status of the transaction:

![Application call transaction](https://3444584021-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY5cgxyYAI0pHdVffOt%2F-Mbv18xMDMukIzYDl97S%2F-Mbv6Lj_WlSmft7Ekj_l%2Fimage.png?alt=media\&token=e2fef225-357b-4821-904d-9c8c84793576)

## Opt-In

If the account calling the smart contract never opted in the application, it will be **automatically** done.


# Microcontrollers

Run the Vertices SDK on microcontrollers.

{% hint style="warning" %}
At this point, the Vertices SDK has only been tested on the ESP32.
{% endhint %}

## Accounts

Transacting on the blockchain implies having accounts. In order to send assets, we need the private and public keys of the **Sender** account. Make sure you have followed that step:

{% content-ref url="/pages/-Mbv1\_5t8YtwjGELXH1R" %}
[New account](/vertices-sdk/quickstart/unix/new-account)
{% endcontent-ref %}

You should have two files:

1. `private_key.bin` for the private key, stored in binary format;
2. `public_b32.txt` for the account address in plain text (base-32 format).

Before we proceed to the next step:

1. Copy-paste them into `examples/esp32/main`.&#x20;
2. Dispense money on the account using the public key, if you haven't already done it.

You can now choose which platform you want to use:

{% content-ref url="/pages/-Ma-E0Y3ozsuZ79BYI7j" %}
[PlatformIO](/vertices-sdk/quickstart/microcontrollers/platformio)
{% endcontent-ref %}

{% content-ref url="/pages/-Ma-EBGoknbZb7X2SCGj" %}
[ESP-IDF](/vertices-sdk/quickstart/microcontrollers/esp-idf)
{% endcontent-ref %}


# PlatformIO

Run the Vertices SDK on the ESP32 using PlatformIO.

PlatformIO provides great tools to easily get started with your development board. As we want the SDK to be easily accessible, we made it a PlatformIO library.

PIO is running on top of VSCode so make sure to have [VSCode](https://code.visualstudio.com/download) and [install PlatformIO](https://platformio.org/install/ide?install=vscode).

## From source code repository

If you've downloaded the [source from Github](https://github.com/vertices-network/c-vertices-sdk), the easiest way to get started is to open the example available 🚀

On VSCode, go to the PlatformIO tab > open a project (PIO Home > Open > Open Project) and open the example at that location:

```
path/to/c-vertices-sdk/examples/esp32
```

You will then need to fetch the dependencies such as the Espressif Framework. Click on the `build` button to get the packages and then, head to the [Configure](https://docs.vertices.network/vertices-sdk/quickstart/microcontrollers/platformio#configure) paragraph as we have some configuration to be made. 🛠

## Using an existing project

If you have created a project using PlatformIO, you will only need to install the library.&#x20;

### Install the Vertices SDK

Go to the **Libraries** tab and search for `vertices-sdk`. You should find the library in its latest version, click **Add to Project,** and select your project

![The Vertices SDK in PlatformIO](https://3444584021-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY5cgxyYAI0pHdVffOt%2F-Ma-Gb0TCEJsApCsKWSB%2F-Ma-H33eE31dll8y1lLm%2FScreenshot%202021-05-18%20at%2014.45.55.png?alt=media\&token=2b7db8ae-17ac-410c-9f14-1632473d80a5)

You can then use the files provided in the **Examples** tab to easily get started.

## Configure

### WiFi

The example provided with the SDK is based on a WiFi example so you need to configure the WiFi credentials to have the board connect to the Internet.

From `PlatformIO > Project Tasks > esp32-example > Platform`, click on `Run Menuconfig`. If you don't have the `Platform` tab, it probably means that you didn't install the Espressif32 platform yet. Try to `build` the project to force PlatformIO to get the packages.

You'll then be able to set the WiFi router SSID and password. Navigate to `Example Connection configuration` > `WiFi SSID` and `WiFi Password` to set the parameters. Then save ( type `S`) and exit (`Q`).

![](https://3444584021-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY5cgxyYAI0pHdVffOt%2F-MaSkQrW5sCZ0UvRbdI-%2F-MaSnjRqnPdPZOgxVPGm%2Fimage.png?alt=media\&token=411b9603-8047-4099-99fd-8890d2b703dd)

You should now be able to build and run the example using `Build`, `Upload` and `Monitor` buttons.&#x20;

## Monitor

Once built, you'll be able to monitor the example using the Monitor button on PlatformIO. A terminal will then be opened and the serial interface will be printed:

```
[...]
I (6705) vertices_example: Connected to AP, begin http example
I (6715) vertices_example: 💳 Alice's account E3PGTXKDOODVQ3E2ZB5PMJF2W3YOKIPUPLFDTESSP6562QE4GTLAKO4VXY
I (6725) http_esp: HTTP init: https://api.testnet.algoexplorer.io
I (9475) http_esp: HTTP GET Status = 200, content_length = 5
I (9745) http_esp: HTTP GET Status = 200, content_length = 232
I (9755) vertices_example: 🏎 Running on testnet-v1.0 v.2.5.0
🟢 [/Users/cyril/Documents/work/vertices/c-vertices-sdk/src/account.c:42] 👛 Added account to wallet: #0
I (9985) http_esp: HTTP GET Status = 200, content_length = 27
I (9995) vertices_example: 🤑 10.968642 Algos on Alice's account (E3PGTXKDOODVQ3E2ZB5PMJF2W3YOKIPUPLFDTESSP6562QE4GTLAKO4VXY)
🟢 [/Users/cyril/Documents/work/vertices/c-vertices-sdk/src/account.c:42] 👛 Added account to wallet: #1
I (10135) http_esp: HTTP GET Status = 200, content_length = 27
I (10525) http_esp: HTTP GET Status = 200, content_length = 249
I (10585) http_esp: Adding header: Content-Type: 
I (11025) http_esp: HTTP POST Status = 200, content_length = 64
🟢 [/Users/cyril/Documents/work/vertices/c-vertices-sdk/src/algorand/algorand_transaction.c:307] 🧾 Transaction executed, ID: AMBREJ5C6OLZHT3ZEITT5ROSO3N5QTENSS6QKFFE4V7YAPOVW6RA
W (11055) vertices_example: Unhandled event: 2
I (11055) vertices_example: 💸 Alice sent 0.000100 algo to Bob
🟢 [/Users/cyril/Documents/work/vertices/c-vertices-sdk/src/account.c:89] 👛 Deleted account from wallet: #0
🟢 [/Users/cyril/Documents/work/vertices/c-vertices-sdk/src/account.c:89] 👛 Deleted account from wallet: #1

```


# ESP-IDF

Run the Vertices SDK on the ESP32 using the ESP-IDF build system.

The Espressif documentation is great to [get started](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/). We advise you to read it if you are not familiar with the ESP-IDF. If you've got any issue setting up the example, the solution can probably be found in the ESP-IDF documentation.

Below is a summary.

## Install ESP-IDF

{% tabs %}
{% tab title="Unix" %}

```
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh
. export.sh
idf.py set-target esp32
```

{% endtab %}
{% endtabs %}

Sourcing `export.sh` will set important environment variables that will be used when compiling the example. Make sure to use the same terminal window afterwards.

## Compile the example

Go to `examples/esp32` and run:

```
idf.py build
```

## Flash onto the Device

From `examples/esp32`, run:

```
idf.py [-p PORT] flash
```

## Monitor

Print the logs:

```
$ idf.py [-p PORT] monitor

[...]

I (4676) example_connect: Got IPv6 event: Interface "example_connect: sta" address: fe80:0000:0000:0000:260a:c4ff:fe00:3a50, type: ESP_IP6_ADDR_IS_LINK_LOCAL
I (6176) esp_netif_handlers: example_connect: sta ip: 192.168.1.26, mask: 255.255.255.0, gw: 192.168.1.254
I (6176) example_connect: Got IPv4 event: Interface "example_connect: sta" address: 192.168.1.26
I (6186) example_connect: Connected to example_connect: sta
I (6186) example_connect: - IPv4 address: 192.168.1.26
I (6196) example_connect: - IPv6 address: fe80:0000:0000:0000:260a:c4ff:fe00:3a50, type: ESP_IP6_ADDR_IS_LINK_LOCAL
I (6206) vertices_example: Connected to AP, begin http example
I (6216) vertices_example: 💳 Alice's account E3PGTXKDOODVQ3E2ZB5PMJF2W3YOKIPUPLFDTESSP6562QE4GTLAKO4VXY
I (6226) http_esp: HTTP init: https://api.testnet.algoexplorer.io
I (9006) http_esp: HTTP GET Status = 200, content_length = 5
I (9276) http_esp: HTTP GET Status = 200, content_length = 232
I (9286) vertices_example: 🏎 Running on testnet-v1.0 v.2.5.0
🟢 [/Users/cyril/Documents/work/vertices/c-vertices-sdk/src/account.c:42] 👛 Added account to wallet: #0
I (9486) http_esp: HTTP GET Status = 200, content_length = 27
I (9496) vertices_example: 🤑 10.974142 Algos on Alice's account (E3PGTXKDOODVQ3E2ZB5PMJF2W3YOKIPUPLFDTESSP6562QE4GTLAKO4VXY)
🟢 [/Users/cyril/Documents/work/vertices/c-vertices-sdk/src/account.c:42] 👛 Added account to wallet: #1
I (9736) http_esp: HTTP GET Status = 200, content_length = 27
I (10536) http_esp: HTTP POST Status = 200, content_length = 64
🟢 [/Users/cyril/Documents/work/vertices/c-vertices-sdk/src/algorand/algorand_transaction.c:307] 🧾 Transaction executed, ID: HRSIHDSQIZWXELQIORV2OX72TXQM2PZ7BMGVBK6WCZMEUZH4CWRQ
W (10556) vertices_example: Unhandled event: 2
I (10566) vertices_example: 💸 Alice sent 0.000100 algo to Bob
🟢 [/Users/cyril/Documents/work/vertices/c-vertices-sdk/src/account.c:89] 👛 Deleted account from wallet: #0
🟢 [/Users/cyril/Documents/work/vertices/c-vertices-sdk/src/account.c:89] 👛 Deleted account from wallet: #1

```


# Zephyr (soon)

Not supported.

{% hint style="warning" %}
Zephyr is not yet supported.
{% endhint %}


# API Reference

Getting into the Vertices SDK

The API reference gives more information about the functions made available to users of the Vertices SDK.

![](https://3444584021-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY5cgxyYAI0pHdVffOt%2F-MdaNIJHnjyJngQksqYJ%2F-MdaVrEYcWp3-laYWeNh%2Fsoftware_block_diagram.png?alt=media\&token=e3411118-2139-4762-b54f-3f94447d3e1f)


# Providers

Instantiate the Vertices library and configure the provider.

## Create

```c
/// Initialize Vertices SDK
/// \param config Pass the configuration such as providers and user-defined event handler
/// \return
ret_code_t
vertices_new(vertex_t *config);
```

### Parameters

* `config` pointer to config.

```c
typedef struct
{
    provider_info_t *provider;
    ret_code_t (*vertices_evt_handler)(vtc_evt_t *evt);
} vertex_t;

typedef struct
{
    char *url;
    short port;
    char *header;
    const char *cert_pem;
} provider_info_t;
```

Here is an example of configuration for a node (`algod`) running locally on my machine. Comments give a configuration with Algoexplorer's API.

```c
static provider_info_t providers =
    {
        .url = (char *) "localhost", // or "https://api.testnet.algoexplorer.io"
        .port = 8080, // 0
        .header = (char *) "X-Algo-API-Token:<api-token>" // ""
        .cert_pem = algoexplorer_root_cert_pem_start
    };
```

```c
static vertex_t m_vertex = {
    .provider = &providers,
    .vertices_evt_handler = vertices_evt_handler
};
```

### Return codes

* `VTC_SUCCESS` on success
* `VTC_ERROR_INTERNAL` if HTTP client cannot be initialized

## Health

```c
ret_code_t
vertices_ping(void);
```

### Return codes

* `VTC_SUCCESS` when API can be reached
* `VTC_HTTP_ERROR` when an error occurs

## Version

```c
ret_code_t
vertices_version(provider_version_t *version);
```

### Parameters

Pointer to `provider_version_t` structure that will be filled by the function.

### Return codes

* `VTC_SUCCESS` when `version` has been filled with node info
* `VTC_ERROR_OFFLINE` when node cannot be reached to get info. Version could still be filled with information from a previous call.

�


# Accounts

Creating accounts that will interact with the blockchain.

Using the SDK starts with creating at least one account.

Whenever a new transaction is to be done, you will need to register the new account **using the public key** (B32 format or binary format).

## Create

```c
ret_code_t
vertices_account_new_from_b32(
                char *public_b32,
                account_info_t **account);
```

### Parameters

* `public_b32`: string containing account address
* `account`: pointer to `account_info_t *`&#x20;

Below is the structure `account_info_t`

```c
typedef struct
{
    char public_b32[PUBLIC_B32_STR_MAX_LENGTH]; //!< b32 public address, with `\0` termination character
    unsigned char public_key[ADDRESS_LENGTH];   //!< 32-bytes public key
    int32_t amount;                             //!< amount of tokens on account
} account_info_t;
```

### Return codes

* `VTC_SUCCESS` : success
* `VTC_ERROR_NO_MEM` : no more room for registering a new account

## Update

Request the last info on the blockchain regarding the account: amount, opted-in apps, etc...

```c
ret_code_t
vertices_account_update(account_info_t *account);
```

### Parameters

* `account` pointer to the account, given by `vertices_account_new_from_b32`.�

### Return codes

* `VTC_SUCCESS` on success

## Delete

Delete the instance of the account, freeing up the spot to store another account.

```
ret_code_t
vertices_account_free(account_info_t *account);
```

### Parameters

* `account` given by `vertices_account_add`.

### Return codes

* `VTC_SUCCESS` on success


# Events

Asynchronous events

Events are responsible to warn the user that an action has to be taken. Those actions can be signing a new payload, or that the transactions went through.

## Scheduling

Schedule new Vertices events. Make sure to process them afterward to have the SDK process the queued events.

### Parameters

* `evt` : event to be processed

```c
typedef struct
{
    vtc_evt_type_t type; ///< \see vtc_evt_type_t
    size_t bufid; ///< internal buffer ID, used to identify a pending transaction
} vtc_evt_t;


typedef enum
{
    VTC_EVT_TX_READY_TO_SIGN = 0, ///< transaction's payload must be signed: the user must provide the signing function and emit the \c VTC_EVT_TX_READY_TO_SEND event.
    VTC_EVT_TX_SENDING, ///< transaction is being sent to the blockchain API. When the user got the event, the transaction has probably been already sent.
    VTC_EVT_TX_SUCCESS, ///< transaction has been successfully sent and executed, after that event, the buffer is freed.
} vtc_evt_type_t;
```

### Return codes

* `VTC_SUCCESS` on success.
* `VTC_ERROR_NO_MEM` when event queue is full: either process events or increase `VTC_EVENTS_COUNT`.

## Processing

Call this function to have the Vertices SDK process pending events. Whenever calling a Vertices function, make sure to process all the events. To make sure all the events are processed, this function should be called from an infinite loop or OS thread/task. This function will call the user-defined callback if one has been passed when using  `vertices_new`

```
/// \param queue_size
/// \return \c VTC_SUCCESS if event has correctly been processed
ret_code_t
vertices_event_process(size_t *queue_size);

```

### Parameters

`queue_size` : Pointer to `size_t` value that will be replaced with the Vertices interval queue size defining the number of events to be processed.

### Return code

* `VTC_SUCCESS` when the event is correctly processed.&#x20;
* Error code from the event.


# Transactions

## Payment

```c
ret_code_t
vertices_transaction_pay_new(
            account_info_t *account, 
            char *receiver, 
            uint64_t amount, 
            void *params);
```

### Parameters

* `account`: sender account. Handle after creating the account using `vertices_account_add`.
* `receiver`: public base-32 address of the receiver account.
* `amount`: the number of tokens to be sent. In Algorand's case in microAlgos.
* `params`: in Algorand's case, `note` that will be included in the transaction.

### Return codes

* `VTC_SUCCESS` if the transaction went through
* `VTC_ERROR_INVALID_PARAM` if one parameter is incorrect
* �`VTC_ERROR_NO_MEM` if there is no room to queue the payment transaction

## Application call

```c
ret_code_t
vertices_transaction_app_call(
    account_info_t *account, 
    uint64_t app_id, 
    void *params);
```

### Parameters

* `account`: sender account. Handle after creating the account using `vertices_account_add`.
* `app_id`: Algorand application ID
* `params`: in Algorand's case, a pointer to `app_values_t` that has been zeroed before.

```c
typedef struct
{
    uint32_t count;
    app_key_value_t values[APPS_KV_MAX_COUNT];
} app_values_t;

typedef struct
{
    char name[APPS_KV_NAME_MAX_LENGTH]; //!< variable name, ASCII-encoded, can contains up to APPS_KV_NAME_MAX_LENGTH bytes
    value_type_t type; //!< type [tt]
    union
    {
        uint64_t value_uint;
        uint8_t value_slice[APPS_KV_SLICE_MAX_SIZE];
    };
} app_key_value_t;

typedef enum
{
    VALUE_TYPE_NONE = 0,
    VALUE_TYPE_BYTESLICE,
    VALUE_TYPE_INTEGER,
} value_type_t;
```

### Return codes

* `VTC_SUCCESS` if the transaction went through
* `VTC_ERROR_INVALID_PARAM` if one parameter is incorrect
* �`VTC_ERROR_NO_MEM` if there is no room to queue the payment transaction


# Applications

Get application data

## Global states

```c
/// Get application global states. Parse variables are put into \c global_states
/// \param app_id Application ID
/// \param global_states Key-value pairs to store variables
/// \return codes
///     * VTC_SUCCESS on success: key-values have been parsed correctly and put into global_states
///     * VTC_ERROR_INTERNAL if unable to instantiate parser
///     * VTC_ERROR_NOT_FOUND if key not found
ret_code_t
vertices_application_get(uint64_t app_id, app_values_t * global_states);
```

### Parameters

* `app_id`: application ID.
* `global_states`: pointer to `app_values`. This structure can store several key-value pairs (integer or byte slices). Make sure to init to 0 before passing to the function.

### Return codes

* `VTC_SUCCESS` if the application data have been parsed into `global_states`
* `VTC_ERROR_INTERAL` if the parser cannot be instantiated.
* �`VTC_ERROR_NOT_FOUND` if JSON keys cannot be correctly parsed
* `VTC_ERROR_OFFLINE` if offline
* `VTC_HTTP_ERROR` on HTTP error


# Porting guide

This guide will let you go through the steps to use the Vertices SDK for your project.

Taking a look at the diagram below, we can see that some parts need to be reimplemented by the user as they are specific depending on the hardware (and most of the time the underlying libraries).

![](https://3444584021-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY5cgxyYAI0pHdVffOt%2F-MdaNIJHnjyJngQksqYJ%2F-MdaVrEYcWp3-laYWeNh%2Fsoftware_block_diagram.png?alt=media\&token=e3411118-2139-4762-b54f-3f94447d3e1f)

In this guide, we are going to port the SDK into your project by using an example I am implementing as I write those lines.&#x20;

{% hint style="info" %}
Links will be given at the end of each step to provide our implementation of the given step.

The [full repository](https://github.com/vertices-network/sdk-porting-guide) can be used as a template.
{% endhint %}


# Starting from scratch

## New project

The Vertices SDK is built to be included in any project as an external component.

The best way to achieve this is probably to make use of [git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules).

So let's say we have a clean repository with empty directories:

* `external`: I like to have a directory keeping external libs
* `components`: provided by the SDK you are building on
* `myproject`: the source code your team is writing
* `utils`: some scripts and tools that are useful
* `build`: generated build files

```bash
mkdir porting_guide
cd porting_guide
mkdir external components myproject utils build
```

The structure is alive. Let's get the SDK.

```bash
# init directory as a git repository
git init
# clone SDK into external/c-vertices-sdk
git submodule add https://github.com/vertices-network/c-vertices-sdk external/c-vertices-sdk
# update submodules of the SDK itself
git submodule update --init --recursive
# check content of the SDK
ls external/c-vertices-sdk
```

Let's create a `main.c` file with the minimum content:

```bash
touch myproject/main.c
```

```c
#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello world\n");

    return 0;
}

```

## CMake

We can now init our project with two CMake files that will be used to build the entire project:

```bash
touch CMakeLists.txt myproject/CMakeLists.txt
```

Here is the minimum content of the root `CMakeLists.txt`:

```
cmake_minimum_required (3.20)
project (porting_guide)

# adding the Vertices SDK
add_subdirectory(external/c-vertices-sdk)

# adding the User code
add_subdirectory(myproject)
```

Now we can add our `main.c` file into `myproject/CMakeLists.txt`:

```
set(PROJECT_NAME myproject)
project(${PROJECT_NAME})

# add source file related to that project
set(SRC_FILES
        main.c
        )

# Add directories to include below (headers folders)
set(INC_FOLDERS
        )

include_directories(${INC_FOLDERS})
add_executable(${PROJECT_NAME} ${SRC_FILES})
```

### The missing link

Before we can start including headers from the Vertices SDK, we need to add the library into `myproject` :

At the end of `myproject/CMakeLists.txt`, append that line:

```
target_link_libraries(${PROJECT_NAME} vertices)
```

Now you can include the Vertices header in the main file:

```c
#include "vertices.h" // ready to use the Vertices SDK library
```

There are still some missing parts that will be covered in the next chapters.

{% hint style="info" %}
Follow the next step to get our implementation of those first two steps 🥳&#x20;
{% endhint %}


# New vertex

Initializing a new vertex.

Each device needs to initialize the Vertices SDK before being able to use it by calling the function `vertices_new()` and passing the vertex configuration. Let's see what are the configuration parameters needed.

## The provider

The provider is the remote API that will be interrogated to interact with the blockchain. In the case of the Algorand API, an HTTP REST API is being used. It comprises 4 pieces of information:

* `url`: the base URL, in the case of Algorand we can think about Algoexplorer, Purestake, or even your local node (`localhost`). Make sure to provide the API on the network you want. The Testnet will always be used in the examples.
* `port`: the server port for the HTTP connection.
* `header`: some API providers require a specific header to pass an authorization token, for example, that's the case of Purestake. The `header` field will let the user pass those specific headers. Other headers might be appended as well in the HTTP calls.
* &#x20;`cert_pem`: some HTTP clients need the provider certificates. That's not the case on Unix when using `libcurl` but the ESP32 example needs the certificate to be linked into the program.

{% hint style="info" %}
To get the Algoexplorer certificates from the command line:

`openssl s_client -showcerts -verify 5 -connect api.testnet.algoexplorer.io:443`
{% endhint %}

Now that we have gathered the provider information, we can create  the structure encapsulating it:

```c
static provider_info_t algoexplorer_provider =
    {.url = (char *) "https://api.testnet.algoexplorer.io", 
    .port = 0, 
    .header = (char *) ""};

static provider_info_t purestake_provider =
    {.url = (char *) "https://testnet-algorand.api.purestake.io/ps2", 
    .port = 0, 
    .header = (char *) "x-api-key:xxx"}; // replace the xxx with your token
```

## The event handler

The user needs to implement a callback function that must be passed when initializing the library:

```c
static ret_code_t
vertices_evt_handler(vtc_evt_t *evt)
{ 
    /* to be implemented in the next chapter */ 
}
```

The next chapter will be dedicated to understanding and responding to the different events emitted by the library.

## Initialization

We can now create the vertex configuration structure and try to init the library. Below is the content of the minimum `main.c` file:

```c
#include <stdio.h>
#include "vertices.h"

static provider_info_t algoexplorer_provider =
    {.url = (char *) "https://api.testnet.algoexplorer.io", 
    .port = 0, 
    .header = (char *) ""};

static ret_code_t
vertices_evt_handler(vtc_evt_t *evt)
{
    /* to be implemented in the next chapters */
    
    return VTC_ERROR_INTERNAL;
}

int main(int argc, char *argv[])
{
    printf("Hello world\n");

    // vertex configuration
    vertex_t vertex = {
        .provider = &algoexplorer_provider,
        .vertices_evt_handler = vertices_evt_handler
    };

    // create new vertex
    ret_code_t err_code = vertices_new(&vertex);
    VTC_ASSERT(err_code);

    return 0;
}
```

## Compile and Run

Let's compile and run the example to see what's happening:

```bash
$ cd build && cmake .. && make myproject
[  0%] Built target cjson
[ 80%] Built target mbedcrypto
[100%] Built target vertices
[100%] Linking C executable myproject
[100%] Built target myproject

$ ./myproject/myproject
Hello world
🔴 [/Users/cyril/Documents/work/vertices/porting_guide/external/c-vertices-sdk/src/http_weak.c:24] Weak implementation of http_init
🔴 [/Users/cyril/Documents/work/vertices/porting_guide/external/c-vertices-sdk/src/vertices_errors.c:23] Fatal error: 0x3 /Users/cyril/Documents/work/vertices/porting_guide/myproject/main.c:29
```

`Weak implementation of http_init` is printed along with a fatal error from `main.c:29`, meaning the Vertices library initialization failed with code error: `0x3`.

### Weak implementation

The Vertices SDK provides a weak implementation of the HTTP functions: `init`, `get`, `post` & `close`. Implementing those functions cannot be done right from the SDK as we don't know the target you are trying to use and the underlying HTTP stack.

Fortunately, the next chapter will be dedicated to implementing those functions on your target.

{% hint style="info" %}
Here is [the link](https://github.com/vertices-network/sdk-porting-guide/commit/7407bc39641759f7dee1fa25784ed28ce823318a) to our implementation of the above step 🤩
{% endhint %}


# HTTP Client

Providing a custom HTTP implementation for the Vertices SDK

## Our header, your implementation

We provide functions signatures in `vertices_http.h` .

The SDK will call those functions when needed.

### Client Init/DeInit

The `http_init` function is called on Vertices SDK initialization.

```c
/// Init HTTP client
/// \param provider Remote API URL, port, specific header and certificate if needed by the client
/// \param response_payload_cb Function callback to call when data is ready to be parsed
/// \return \c VTC_SUCCESS on success, otherwise error depends on implementation
ret_code_t
http_init(const provider_info_t *provider,
          size_t (*response_payload_cb)(char *chunk,
                                        size_t chunk_size));

/// Close/deinit the client
void
http_close(void);
```

The init function is simple: all you have to do is to init the HTTP client using the parameters. The URL, port, specific headers, and certificates are passed with the `provider` parameter.&#x20;

The callback function `reponse_payload_cb` must be kept locally as we will need to call it whenever a response is received after a `GET` or a `POST` method call.

#### The callback

The callback function will be called whenever an HTTP response body is ready to be parsed: a pointer to the received bytes `chunk` and the size `chunk_size` will be provided to the Vertices SDK when calling the callback. The buffer can be a pointer allocated by the underlying HTTP client.

### GET/POST methods

```c
/// HTTP GET request
/// \param provider pointer to provider (url, port..)
/// \param relative_path path to append to the provider base URL
/// \param headers Headers string, each one must have the format "key:value\n\r"
/// \param response_code HTTP response code
/// \return error codes:
/// - \c VTC_SUCCESS on success
/// - \c VTC_ERROR_OFFLINE if offline
/// - \c VTC_HTTP_ERROR on HTTP error: check response_code.
ret_code_t
http_get(const provider_info_t *provider,
         const char *relative_path,
         const char *headers,
         uint32_t *response_code);

/// HTTP POST request
/// \param provider pointer to provider (url, port..)
/// \param relative_path path to append to the provider base URL
/// \param headers Headers string, each one must have the format "key:value\n\r"
/// \param body HTTP body
/// \param body_size size of \c body array
/// \param response_code HTTP response code
/// \return error codes:
/// - \c VTC_SUCCESS on success
/// - \c VTC_ERROR_OFFLINE if offline
/// - \c VTC_HTTP_ERROR on HTTP error: check response_code.
ret_code_t
http_post(const provider_info_t *provider,
          const char *relative_path,
          char *headers,
          const char *body,
          size_t body_size,
          uint32_t *response_code);
```

�Some important information to keep in mind:

* The full URL is  a concatenation of  `provider->url` and `relative_path`.
* Headers are key-value pairs separated by `\r` , `\n` or both. The format of the key-value pair is as follow `key:value\n\r`.
* If the HTTP call fails, the HTTP response code must be set in `response_code` and the function must respond `VTC_HTTP_ERROR`.
* Once the full response is ready to be parsed, you will need to call the callback stored during the initialization of the module with a pointer to the raw buffer and its size: `response_payload_cb(response_data, response_length);`

Now that we are able to receive and send data using a configured provider, we are going to build transactions that will soon be sent on the blockchain. To do so, we will need to handle events.

{% hint style="info" %}
Here is [the link](https://github.com/vertices-network/sdk-porting-guide/commit/d966a30c7f421706ca2b665bba2ed5d1b829ace2) to our (partial) implementation of the above step.

For full implementation, you can take a look at our example for Unix and the ESP32, both using different HTTP clients 😉
{% endhint %}


# Handling events

Responding to the library's events.

## Event handling

Events will be passed to the user using the callback passed to init the Vertices library, from `vertex_t`:

```c
typedef struct
{
    provider_info_t *provider;
    ret_code_t
    (*vertices_evt_handler)(vtc_evt_t *evt);
} vertex_t;
```

�You can see here that the handler `vertices_evt_handler` takes a pointer to `vtc_evt_t`:

```c
/// Events contains a type and a bufid. When implementing the event handler, the `bufid`
/// should be used to retrieve the data to be processed. Data type depends on event type.
typedef struct
{
    vtc_evt_type_t type; ///< \see vtc_evt_type_t
    size_t bufid; ///< internal buffer ID, used to identify a pending transaction
} vtc_evt_t;
```

Two things are passed to the user: the event `type` and a `bufid` which is an identifier to the internal transaction being processed. In order to get the event's transaction, the user must use the function available:

```c
ret_code_t
vertices_event_tx_get(size_t bufid, signed_transaction_t **tx);
```

This function will set a local pointer to the `signed_transaction_t` generating the event.

Here are the different events needing the user attention:

```c
/// Asynchronous operations can be handled using Vertices events types
typedef enum
{
    VTC_EVT_TX_READY_TO_SIGN = 0, ///< transaction's payload must be signed: the user must provide the signing function
    VTC_EVT_TX_SENDING, ///< transaction is being sent to the blockchain API. When the user got the event, the transaction has probably been already sent.
    VTC_EVT_TX_SUCCESS, ///< transaction has been successfully sent and executed, after that event, the buffer is freed.
} vtc_evt_type_t;
```

Let's go through the handling of those events.

### Signing

`VTC_EVT_TX_READY_TO_SIGN`

This is the most critical event to handle: signing the payload. The payload is divided into two parts: the header and the body. Only the body part has to be signed, but with a subtility: we need to add the "TX" string before the body.

![](https://3444584021-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY5cgxyYAI0pHdVffOt%2F-Me9lhr6zBjkdoIo2fd0%2F-MeAUKVzmzXZurMIaxv4%2FTransaction%20payload.png?alt=media\&token=100180a6-b04e-4682-862a-4438abf4e4ea)

The first step is to get a pointer to the `payload` using `vertices_event_tx_get`:

```c
typedef struct
{
    unsigned char payload[TX_PAYLOAD_MAX_LENGTH]; ///< Full payload, comprised of the header + body. The body part is the signed part (prepended with "TX")
    size_t
        payload_header_length;  ///< Header size. Do not use for signing. Full \c payload size is: \c payload_header_length + \c payload_body_length
    size_t
        payload_body_length;  ///< Body size. Length of data to be signed. if not 0, indicates that TX is pending.
    unsigned char signature[SIGNATURE_LENGTH];
    unsigned char id[TRANSACTION_HASH_STR_MAX_LENGTH
    ]; ///< Unique Identifier of the transaction. It can be used to find the transaction in the ledger
} signed_transaction_t;
```

We now have the payload with �`payload_header_length` and `payload_body_length`. \
In order to have the byte array to sign, we need to init a new byte array starting with "TX" and then copy the full body into that byte array.

Now that we have a buffer ready to be signed, sign it using the Ed25519 algorithm. A private key will be necessary. Put the generated signature into the `signed_transaction_t`, `signature` field.

Once done and to send the transaction, we need to emit the event `VTC_EVT_TX_SENDING` using:

```c
evt->type = VTC_EVT_TX_SENDING;
err_code = vertices_event_schedule(evt);
```

### Sending

`VTC_EVT_TX_SENDING`

The transaction is being sent. When the user gets that event in the event handler, the event has already been processed by the library, meaning the transaction has been sent.

We can use that event to have the full payload of the packed transaction (message pack).

### Transaction success

`VTC_EVT_TX_SUCCESS`

Nice! The transaction has passed. I guess you can print a `hoora` message.

## Event processing

Last but not least, for the Vertices SDK to process the event, we need to give the library some CPU time by calling as many times as needed the event processing routine:&#x20;

```c
/// Call this function to have the Vertices SDK process pending events. Whenever calling a Vertices
/// function, make sure to process all the events.
/// To make sure all the events are processed, this function should be called from an infinite loop or OS thread/task.
/// This function will call the user-defined callback passed when using \see vertices_new
/// \param queue_size
/// \return \c VTC_SUCCESS if event has correctly been processed
ret_code_t
vertices_event_process(size_t *queue_size);
```

`queue_size` can give the user an indication about the queued events waiting to be processed but it is not mandatory.

Depending on whether you are using an RTOS or not, you might want to call this function from an indefinite loop.

{% hint style="info" %}
Here is [the link](https://github.com/vertices-network/sdk-porting-guide/commit/2802ffb443dfc8654b1393c2d7e81b3908e5d98a) to our implementation of the given step.

You can use the repository as a template to get you started. 🚀

If you have more questions, don't hesitate to open an issue on the Github repository.
{% endhint %}


