Remember when I recently created a bunch of developer content around cryptocurrency and blockchain development? I had been writing tutorials for each of the cryptocurrencies that I'm currently holding, and there are a few more that I've yet to cover.
Take Reddcoin (RDD), for example. Reddcoin was designed to be a social currency to credit creators and others that might be losing to the ever-changing advertisement industry. Being that my Google Adsense has been suffering recently, this sounded like a promising future, which is why I got involved.
We're going to see how to work with RDD coins in the sense of sending, managing, and maintaining these coins with Node.js and JavaScript.
So what exactly are we going to accomplish in this example?
With any cryptocurrency, you're going to want to generate keys or addresses, check your wallet balance, check the market value, and send coins to other addresses. To do this with Reddcoin, we can leverage the explorer APIs, which are conveniently made by BitPay.
To keep things simple and easy to understand, we're going to work with a fresh project. Assuming that you've already installed Node.js, execute the following from the command line:
npm init -y
The above command will create a new project, or specifically a package.json file. The next step is to install the dependencies that will be used in the project.
From the command line, execute the following:
npm install request --save
npm install bitcore-lib --save
The request package will allow us to do asynchronous HTTP requests from our Node.js application. We'll be using it to work with the Reddsight API and the CoinMarketCap API.
The bitcore-lib package will allow us to create keys and sign transactions that will eventually be broadcasted to the Reddcoin network. Now, there is technically a reddcore library that does something similar, but I have a few issues with that. The reddcore library was last updated in 2014, which is a little scary because it is now 2018. Also, it is the full package, which includes the library and Reddcoin node mechanics, which is overkill.
With the project created and the dependencies downloaded, we can start the development of our application.
We want to create a clean and easy-to-maintain project. The best way to accomplish this is through an ES6 class with a set of functions. Within your project, create a file called reddcoin.js and make sure it includes the following:
const Request = require("request");
const Bitcore = require("bitcore-lib");
class Reddcoin {
constructor(secret) { }
getPrivateKey() { }
getAddress() { }
getMarketValue() { }
getWalletBalance() { }
getWalletValue() { }
getUnspentTransactionOutput() { }
createTransaction(destination, satoshis) { }
broadcastTransaction(transaction) { }
}
module.exports = Reddcoin;
Notice that we have a Reddcoin
class with a bunch of functions that have yet to be filled with code. This is the template that we're going to base our application on.
Let's go down the line starting with the constructor
method:
constructor(secret) {
this.marketUrl = "https://api.coinmarketcap.com/v1/ticker";
this.explorerUrl = "https://live.reddcoin.com"
Bitcore.Networks.add({
name: "reddcoin",
alias: "rdd",
pubkeyhash: 0x3d,
privatekey: 0xbd,
scripthash: 0x05,
dnsSeeds: [
"seed.reddcoin.com"
]
});
this.network = Bitcore.Networks.get("reddcoin");
if(!secret) {
this.secret = new Bitcore.PrivateKey(this.network);
} else {
this.secret = Bitcore.PrivateKey.fromWIF(secret);
}
}
What we have in the constructor
method is probably the most confusing part of our application. What we're doing is defining our API URLs and either creating a secret key or loading a secret key, if provided. The difficulty comes with defining our Reddcoin network.
The bitcore-lib
package was designed for Bitcoin, not Reddcoin. If we were to use the default network, we'd end up with keys for Bitcoin, not Reddcoin. Instead, we need to add a custom network with the correct key prefixes.
Bitcore.Networks.add({
name: "reddcoin",
alias: "rdd",
pubkeyhash: 0x3d,
privatekey: 0xbd,
scripthash: 0x05,
dnsSeeds: [
"seed.reddcoin.com"
]
});
So where did I get those byte values that make up the pubkeyhash
, privatekey
, and the scripthash
? I actually got them from the reddcore package that I was previously against.
Inside the networks.js file of the reddcore package, we have the following:
exports.livenet = {
name: 'livenet',
magic: hex('fbc0b6db'),
addressVersion: 61,
privKeyVersion: 189,
P2SHVersion: 5,
hkeyPublicVersion: 0x0488b21e,
hkeyPrivateVersion: 0x0488ade4,
genesisBlock: {
hash: hex('CCDEC174EBD4FA10314B3B9EF9CB8ADCF9AA87E57EC6AD0D0E3C3C5AD9E068B8'),
merkle_root: hex('FF79AF16A9FFEB1B826DE1EA7F24539A2FE3702FE987912B09072BC41DBC02B5'),
height: 0,
nonce: 222583475,
version: 1,
prev_hash: buffertools.fill(new Buffer(32), 0),
timestamp: 1390280400,
bits: 504365040
},
dnsSeeds: [
'seed.reddcoin.com'
],
defaultClientPort: 45444,
lastPoWBlock: 260799
};
The above network information is obviously dated in comparison to what the bitcore-lib package expects. However, we can take the values for addressVersion
, privKeyVersion
, and P2SHVersion
and run them through a hexadecimal tool to get our byte values.
Now that our constructor
is good to go, we can get the secret key and public address on demand. For example, take the getPrivateKey
function:
getPrivateKey() {
return this.secret.toWIF();
}
We're taking the secret key and returning the WIF formatted version of it. Likewise, with the getAddress
function, we have the following:
getAddress() {
return this.secret.toAddress().toString();
}
Since we have a public key, we can check our balance at any time using the Reddsight API explorer. The getWalletBalance
function would look like the following:
getWalletBalance() {
return new Promise((resolve, reject) => {
Request.get(this.explorerUrl + "/api/addr/" + this.secret.toAddress().toString(), (error, response, body) => {
if(error) {
reject(error);
}
var data = JSON.parse(body);
resolve({ balance: data.balance, satoshi: data.balanceSat });
});
});
}
Using the request
package, we can issue a GET request to the explorer API and pass the public address. The response will be a formatted JSON object with only the data that we care about, which is the balance as well as the balance in satoshis.
A raw wallet balance may not be the most useful to use. Using the CoinMarketCap API, we can get the USD and BTC value of Reddcoin:
getMarketValue() {
return new Promise((resolve, reject) => {
Request.get(this.marketUrl + "/reddcoin/", (error, response, body) => {
if(error) {
reject(error);
}
var data = JSON.parse(body)[0];
resolve({ symbol: data.symbol, usd: data.price_usd, btc: data.price_btc });
});
});
}
Using the market data and the wallet balance data that were returned, we can use that information to get the value of the wallet in USD or BTC.
Take the getWalletValue
function for example:
getWalletValue() {
return this.getWalletBalance().then(wallet => {
return this.getMarketValue().then(market => {
return { value: (wallet.balance * market.usd).toFixed(2) };
});
});
}
By chaining promises, we call each of our previously created functions, do a little math, and return a USD value.
Up until now, we've created pretty much only wallet management functions. The next step is to create functions for sending Reddcoin to other wallets. The process behind this includes creating a transaction and then signing that transaction using the private key. Once you have the signed transaction, you can broadcast it on the Reddcoin network.
Transactions are created using what is called unspent transaction output (UTXO). Every time you receive coins, a new transaction is created with the amount of coins received. Each transaction maintains the unspent balance. The UTXO values are necessary when creating new transactions.
To get the UTXO for an address, we can create the following function:
getUnspentTransactionOutput() {
return new Promise((resolve, reject) => {
Request.get(this.explorerUrl + "/api/addr/" + this.secret.toAddress().toString() + "/utxo", (error, response, body) => {
if(error) {
reject(error);
}
resolve(JSON.parse(body));
});
});
}
To create a transaction with the UTXO, we might have a function such as createTransaction
like the following:
createTransaction(destination, satoshis) {
return new Promise((resolve, reject) => {
this.getUnspentTransactionOutput().then(utxos => {
if(utxos.length == 0) {
return reject({ "message": "The source address has no unspent transactions" });
}
var transaction = new Bitcore.Transaction();
for(var i = 0; i < utxos.length; i++) {
transaction.from(utxos[i]);
}
transaction.to(destination, satoshis);
transaction.sign(this.secret);
resolve(transaction);
}, error => {
reject(error);
});
});
}
If you have no funds for a particular address, you cannot create a transaction. You don't have anything to send. If you do have UTXO records, you can create a transaction for a destination address and sign it.
Finally, if we wanted to send or broadcast a transaction, we can POST to the Reddsight API:
broadcastTransaction(transaction) {
return new Promise((resolve, reject) => {
Request.post({
"headers": { "content-type": "application/json" },
"url": this.explorerUrl + "/api/tx/send",
"body": JSON.stringify({
"rawtx": transaction.serialize()
})
}, (error, response, body) => {
if(error) {
reject(error);
}
resolve(JSON.parse(body));
});
});
}
Be careful when you broadcast. If you've messed something up, you'll likely be out of luck for anything you lost.
Now let's take a look at using each of these functions.
As of right now, we have a reddcoin.js file for our class. Now create an app.js file which will contain all of our driving logic.
Inside the app.js file, include the following:
const Reddcoin = require("./reddcoin");
var rdd = new Reddcoin();
console.log(rdd.getPrivateKey());
console.log(rdd.getAddress());
rdd.getMarketValue().then(result => {
console.log(result);
});
rdd.getWalletBalance().then(result => {
console.log(result);
});
rdd.getWalletValue().then(result => {
console.log(result.value);
})
rdd.createTransaction("RtPqTTvk3WqcyAyWugNF8zBVex4pdKK2Ys", 10000).then(result => {
console.log(result);
}, error => {
console.error(error);
});
In the above file, we're including our class, instantiating it, and running each of our functions. In the above example, we're creating a new set of keys rather than using an existing key.
The RtPqTTvk3WqcyAyWugNF8zBVex4pdKK2Ys public address is my personal address for Reddcoin in case you're in the donating spirit.
You just saw how to create your own Reddcoin application for RDD coins using Node.js and a few JavaScript libraries. If you're a Reddcoin holder, this could be useful for creating your own wallet rather than putting your trust in someone else's closed-source wallet.
Other coins that use the Insight API by BitPay will be similar in design. Take, for example, my previous tutorial on DigiByte titled, Send And Manage DigiByte DGB Coins With Node.js. Much of the same code can be used to manage all your coins.