Basics 4: Extended Transactions
TL;DR? Run the demo.
Building on the tutorial Basics 3: Transactions, we’ll augment the basic transaction with an extended transaction to also be able to include a message with it.
Message Input
To get started, let’s add a form field for the transaction message, in the same fashion as the other ones, just before the “Send Transaction” button
<p>
<label class="nq-label" for="tx_message">Message</label>
<input type="text" id="tx_message" placeholder="Optional message">
</p>
In the click
handler in start()
, we extract the message entered by the user:
$('tx_send').addEventListener('click', () => {
const recipient = $('tx_recipient').value;
const amount = parseInt($('tx_amount').value);
const message = $('tx_message').value; // <- get the message
sendTransaction(recipient, amount, message);
});
Now we need to update the sendTransaction(...)
function…
Extended Transaction
If message
contains a string, we’ll create and send out an extended transaction.
Otherwise, a basic transaction will be sent instead.
Basic transactions save bytes in the network and on the blockchain.
And in case you want to send out a lot of transactions,
it will reduce the fees to be paid.
See the note under “Send Transaction” in
Basics 3: Transactions for details.
Step one: move the basic transaction code into it’s own helper function:
async function sendTransaction(address, amount, message) {
async function basicTransaction() {
return nimiq.wallet.createTransaction(
Nimiq.Address.fromUserFriendlyAddress(address),
Nimiq.Policy.coinsToLunas(amount),
0, // fee
await nimiq.client.getHeadHeight()
);
}
...
Step two: add another helper function for extended transactions just below:
...
async function extendedTransaction() {
// turn string into a safely encoded array of bytes
const extraData = Nimiq.BufferUtils.fromUtf8(message);
const transaction = new Nimiq.ExtendedTransaction(
nimiq.wallet.address, // sender address
Nimiq.Account.Type.BASIC, // and account type
Nimiq.Address.fromUserFriendlyAddress(address), // recipient address
Nimiq.Account.Type.BASIC, // and type
Nimiq.Policy.coinsToLunas(amount),
0, // fee
await nimiq.client.getHeadHeight(),
Nimiq.Transaction.Flag.NONE,
extraData // the message
);
// sign transaction with the key pair from our wallet
const keyPair = nimiq.wallet.keyPair;
const signature = Nimiq.Signature.create(
keyPair.privateKey,
keyPair.publicKey,
transaction.serializeContent()
);
const proof = Nimiq.SignatureProof.singleSig(keyPair.publicKey, signature);
transaction.proof = proof.serialize(); // Set the proof with the signature on the transaction
return transaction;
}
...
Finally, after checking if we got a message, we can use the two helper functions to put it all together:
...
// create an extended transaction if a message is set, otherwise a basic transaction
const transaction = message.trim().length > 0
? await extendedTransaction()
: await basicTransaction();
// Send to the Nimiq network
nimiq.client.sendTransaction(transaction);
}
Now, the basic features of your Nimiq Wallet web app are complete: Syncing, consensus, storing keys, sending and receiving transactions!
Your Nimiq Wallet is a full member of the Nimiq network. Transactions are sent directly from your browser to the network. No trusted third parties, no server-side applications, no remote APIs! And all of this with not much more than 100 lines of JavaScript! Congratulations, and welcome to the Nimiq Ecosystem!
What’s next?
How about visualizing the addresses and help our users avoiding typos and clipboard attacks? The next tutorial will show you how to use Nimiq Identicons.
Continue the tutorial: Basics 5, Nimiq Identicons »
Find more help and documentation in the Nimiq Developer Center. Share your ideas and feedback on the Nimiq Community Forum, you’ll also find a dedicated section for discussions and ideas. Or get in touch at sven@nimiq.com.