Skip to content

Example 1: Your first project

bnogalm edited this page Apr 18, 2020 · 1 revision

Once you are able to compile and execute the tests, you should be able to create your first project.

Qt offers various ways to create applications. I recommend QtQuick, but for beginners it may be easier to use the old Qt Widgets. This is up to you and to how brave you are.

I know you are brave enough - as you want to try a blockchain non official SDK with little documentation – so I will start with a simple console app that we will later turn into a QtQuick app.

As a first stage, this simple console app will create a keypair for a new account and listen to operations received by this account printing them on the console.

To fund with stellars, the account we will use is the friend bot from a browser. It will help us to understand how a Qt app runs.

- LET´S START -

Create a new project and select Qt Console Application

Select a location and project name >> I will use Example1.

TIP: I recommend to use short path to your root directory as some build tools have path length limits and save it in a folder close to the SDK.

Select build system qmake.

If you know cmake I invite you to use it and submit a cmake file for the library

It will also ask you for languages to use – in case you want to define any

It is a nice component of Qt to localize your app you may like to explore later

Select the kits to use; the one you want to develop for and as a minimum the kit for your current environment.

Once the new project is created go to Projects.

Uncheck “Run in terminal” option from Run tab for each kit.

As we are creating a console application - if you are under Windows especially - you really want that the output of the application goes to QtCreator console window where you can select, scroll, search, etc...

guide_rev1_html_eab0b16fe1dbfa35

- GET TO KNOW THE ENVIRONMENT -

You start with two files:

  • Example1.pro (if you are using qmake build system)
  • main.cpp

The .pro file defines what sources need to be compiled and how.

Here you can add Qt modules. As our project is “console” type there is a QT -= gui that removes gui module, as we will not use it in this example.

guide_rev1_html_aaff3a57d4e7bbbc

The main.cpp contains:

#include <QCoreApplication>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    return a.exec();
}

guide_rev1_html_662e5ad2bab5af60

This code creates a QCoreApplication object that initializes Qt framework without gui components. It will also parse the arguments making them available from Qt API.

The QCoreApplication object is always accesible using qApp macro that allows you to access multiple things e. g., the parsed arguments.

After creating the QCoreApplication object it calls to the exec method returning it as end of the program. This exec will execute an event loop that keeps looping until something forces it to stop. Then it returns zero, ending the program.

guide_rev1_html_a65d7aaafe1cf373

This means if you add the next lines in between:

qDebug()<< “Hello world”;

And:

#include <QDebug>  

to be able to use qDebug, and play button, you will have your first Hello world application in Qt. But it will stay in the event loop until you stop the application.

#include <QCoreApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug() << "Hello world!";
    
    return a.exec();
}

guide_rev1_html_a73a41eaa2906ca0

This means that you should initialize the required content for your application between the construction of the QCoreApplication and the call to exec.

NOTE: Keep in mind that anything asynchronous, such as network replies, will only be executed once method exec() is called.
If you don’t need anything from the events and you want the application to finish, you could just replace the call to exec method by return 0;

guide_rev1_html_9088bdac9b67f768

Another way to end the application using events would be using a timer. The next code will print the Hello world!; create a timer that will execute quit method after 5 seconds; and execute the event loop.

#include <QCoreApplication>
#include <QDebug>
#include <QTimer>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug() << "Hello world!";
    QTimer::singleShot(5000,&a,&QCoreApplication::quit);
    return a.exec();
}

- LET´S PROGRAM -

Now as we know how the environment works, let´s go back to our first example app.

Our example application will create a random KeyPair; create a listening callback to print when the account is funded; and print the public key so we can fund it using the friend bot.

  • We will start by including the StellarQtSDK to our project.

In Example1.pro we will add the below line - assuming StellarQtSDK.pri is in the folder StellarQtSDK outside of our current folder. Adapt the path to your case. You can also use $$PWD to get “.pro” path, so you can define relative paths easier.

IMPORTANT: Use Crtl+S to save you file once the path is added.
include($$PWD/../StellarQtSDK/StellarQtSDK.pri)

If it is correctly added, the StellarQtSDK will be displayed in the project tree.

guide_rev1_html_4c15d7243c651c87

NOTE: If you see * behind the file extension this means the file has not been saved.
  • You will also need to include the OpenSSL library. You have to link the correct library according to the target platform. If you are in Windows, you can include the compiled library we installed with Qt adding the following paths:
You may need to adapt the path, or move it locally to your project.
windows {
LIBS += -LC:/Qt/Tools/OpenSSL/Win_x64/bin -llibssl-1_1-x64
LIBS += -LC:/Qt/Tools/OpenSSL/Win_x64/bin -llibcrypto-1_1-x64
#INCLUDEPATH += C:/Qt/Tools/OpenSSL/Win_x64/include/
#DEPENDPATH += C:/Qt/Tools/OpenSSL/Win_x64/include/
}
If you want to use any of the functions in OpenSSL, you can uncomment (#) the included path lines.
  • The complete code of the main.cpp looks as follows:
#include <QCoreApplication>
#include <QDebug>
#include <QTimer>

#include "network.h"
#include "server.h"
#include "keypair.h"
#include "responses/operations/paymentoperationresponse.h"
#include "responses/operations/createaccountoperationresponse.h"



int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    Network::useTestNetwork();//select the network to use
    Server * server = new Server("https://horizon-testnet.stellar.org");//choose a horizon host
    //Qt removes child QObjects before removing parent, Server is a QObject, so we can use it to remove it before application ends.
    //responses requested to a server object are child of the used server, so they will be removed with the server if you didn't before.
    server->setParent(qApp);

    KeyPair * keypair = KeyPair::random();

    qDebug() << "Created keypair";
    qDebug() << "Public key: "<<keypair->getAccountId();
    qDebug() << "Private key: "<<keypair->getSecretSeed();


    //check if the account is already created, if not, we alert the user to create it
    AccountResponse * accountCheckResponse = server->accounts().account(keypair);

    //here we connect the signal ready of the response to a lambda function, that will be executed as soon response is ready
    QObject::connect(accountCheckResponse,&AccountResponse::ready,[accountCheckResponse,keypair](){
        if(accountCheckResponse->accountID().isEmpty()){
            //account not funded yet
            qDebug() << "Account not funded yet, fund it using friend bot loading the next link:";
            qDebug() << QString("https://friendbot.stellar.org?addr=%1").arg(keypair->getAccountId());
        }
        //response contains account data
        //we remove the response as we don't need anymore
        // note that as we are using a lambda, this pointer is now deleted but not set to nullptr
        // we could get this pointer by reference, to be able to set it to nullptr
        delete accountCheckResponse; //we don't need it anymore. It would be deleted anyway by server destruction, but normally you will have to remove it here

        //we dont need it anymore, note this lambda will not be executed until Qt event loop starts, that is why we can use it the next lines
        delete keypair;
    });

    //stream the all the payment for our account
    OperationPage* paymentsStream =  server->payments().forAccount(keypair).order(RequestBuilder::Order::ASC)
            .stream().execute();



    QObject::connect(paymentsStream,&OperationResponse::ready,[paymentsStream](){
        QList<Response*> records = paymentsStream->getRecords();
        for(Response * r : records)
        {
            if(PaymentOperationResponse * payment = dynamic_cast<PaymentOperationResponse*>(r))
            {
                qDebug() << "Payment detected! Amount: "<< payment->getAmount()<< " Asset: "<< payment->getAsset()->toString()<< " From: "<< payment->getFrom().getAccountId() << " Created at: "<< payment->getCreatedAt();
            }
            else if(CreateAccountOperationResponse * createAccount = dynamic_cast<CreateAccountOperationResponse*>(r))
            {
                qDebug() << "Create account detected! Amount: "<< createAccount->getStartingBalance()<< " From: "<< createAccount->getFunder().getAccountId()<< " Created at: "<<createAccount->getCreatedAt();

            }
        }
        //as is a streaming request, objects will be automatically removed with the next update.
        //you should take this in consideration, as you can't store them to read values later.
    });


    return a.exec();
}
  • If the path of the OpenSSL was correctly defined the application will compile correctly by pressing play.

  • The app creates a private and public address for a Stellar account.

guide_rev1_html_3d7adac4460415a3

  • Copy the friend bot link to your browser; the account will be created

guide_rev1_html_871ace523edcb3bd

  • The app will confirm the account created. If the account receives any further transfers this will be logged in the app.

guide_rev1_html_d5a702c8efa46907

NOTE: You will see that if you stop the application it crashes. It happens because we are not attending and offering a proper way to stop the application.

Congratulations! You have created your first Qt app with StellarQtSDK.

Clone this wiki locally