-
Notifications
You must be signed in to change notification settings - Fork 12
Example 1: Your first project
Once you are able to compile and execute the tests, you should be able to create your first project.
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.
Create a new project and select Qt Console Application
Select a location and project name >> I will use Example1.
Select build system qmake.
It will also ask you for languages to use – in case you want to define any
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.
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.
The main.cpp contains:
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
return a.exec();
}
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.
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.
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();
}
This means that you should initialize the required content for your application between the construction of the QCoreApplication and the call to exec.
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();
}
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.
include($$PWD/../StellarQtSDK/StellarQtSDK.pri)
If it is correctly added, the StellarQtSDK will be displayed in the project tree.
- 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:
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/
}
- 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.
- Copy the friend bot link to your browser; the account will be created
- The app will confirm the account created. If the account receives any further transfers this will be logged in the app.