In this tutorial we modify Tutorial 2 so that when the user clicks a button a transaction is sent into the network.
When this transaction is included and, we process the transaction and update our UI component. This covers the basics of sending and receiving transactions in applications.
Navigate into your /mods
directory and create a folder with the name tutorial03
. Within that directory create the file tutorial03.js
.
Copy the text below into this this file.
var ModTemplate = require('../../lib/templates/modtemplate');
const MainUI = require('./lib/main');
class Tutorial03 extends ModTemplate {
constructor(app) {
super(app);
this.name = "Tutorial03";
this.slug = "tutorial03";
this.description = "Sending and Receiving Transactions";
this.ui = new MainUI(this.app, this);
return this;
}
async render() {
this.ui.render();
}
}
module.exports = Tutorial03
We add the function onConfirmation()
. This function runs automatically whenever the module receives a transaction.
We define this function so that if it receives a Tutorial03
transaction is passes it to the function receiveTutorial03Transaction()
which passes the transaction to our UI component so that it can be rendered onto the screen.
async onConfirmation(blk, tx, conf) {
let txmsg = tx.returnMessage();
if (conf == 0) {
if (txmsg.module == this.name) {
this.receiveTutorial03Transaction(tx);
}
}
}
receiveTutorial03Transaction(tx) {
this.ui.receiveTransaction(tx);
}
onConfirmation
only runs for transactions if module
in the message field of the transaction, newtx.msg.module
, is equivalent to this.name
defined in the app's constructor. You can see in the sendTutorial03Transaction()
function this field being defined. This filters the messages from other applications in the network by default.
In Tutorial 4 you'll learn how to create a module which can listen for transactions marked for any module, not just the currently running one.
To create and send transactions this module can receive, we define the function sendTutorial03Transaction()
as below. This function fetches our wallet address, and then calls the Saito Wallet to create a transaction addressed to our address.
We attach our JSON object to the msg
field of this transaction, and include the name of our module and a random number that we will display when we receive the transaction. Once the transaction has been created, we sign it and propagate it out onto the network.
async sendTutorial03Transaction() {
let address = await this.app.wallet.getPublicKey();
let newtx = await this.app.wallet.createUnsignedTransaction(address);
newtx.msg = {
module: this.name,
data: {
random : Math.random()
}
};
await newtx.sign();
this.app.network.propagateTransaction(newtx);
}
All that remains is to update our UI Component so that it connects to these new functions. Update your /lib/main.js
file so that it contains the following two functions:
render() {
if (document.querySelector("body")) {
document.querySelector("body").innerHTML = Tutorial03MainTemplate();
}
let btn = document.querySelector('.tutorial03-button');
if (btn) {
btn.onclick = (e) => {
this.mod.sendTutorial03Transaction();
}
}
}
receiveTransaction(tx) {
let txmsg = tx.returnMessage();
this.app.browser.addElementToSelector(`TX ${tx.id} - random: ${txmsg.data.random}`, `.tutorial03-received-transactions`);
}
Whereas we previously triggered an alert when our button was clicked, we are now passing control back into our main module and triggering the sendTutorial03Transaction()
function.
We have also added the receiveTransaction(tx)
function, which runs when onConfirmation()
is automatically triggered by an incoming transaction and uses that transaction as input.
receiveTransaction(tx)
looks into our transaction and uses a convenience-function available on app.browser
to display the transaction in the UI along with the random number included in its message.
Recompile Saito with this module active and visit the module page. When you click on the button you will send a transaction out into the network, which will then be returned to you as part of the next block.
At that point (within about 20 seconds) you should see your screen update with the random number that was included in the transaction that you sent. The reason for the delay is that onConfirmation()
waits for the transaction to be included in a block before running.
You can confirm that the random number is the same that was included in the transaction by checking the message field of the transaction you created in the block explorer as previously.
If your browser does not update after you click the button and wait 10-20 seconds, check your console log to see if you have the following error message.
If your browser is showing this, it means that your browser is getting notified that a new block is available, but you need to modify the Saito Core server to permit cross-origin requests. You can do this by opening the file /lib/saito/core/server.ts
. Look for this section and uncomment the two lines necessary. Recompile and restart the server and this issue will go away. You may also be able to avoid the problem by accessing your local server at the IP address "127.0.0.1" instead of "localhost".
//
// CORS -- uncomment for local CORS Cross-Origin Requests by Default
//
//var cors = require('cors');
const expressApp = express();
//expressApp.use(cors());
If you are doing development locally you may want to leave this section uncommented by default. When you deploy your application on the network, host it on a normal domain and you will not need to enable CORS.
tutorial03
code can be referenced here.In our next tutorial we’ll create use what we've learned so far to build an application that