Ripple is a popular blockchain protocol. It is
closely tied to the cryptocurrency XRP. It also has a solid Node.js library for creating transactions
and placing orders. In this article, I'll demonstrate using the
ripple-lib
package to transfer XRP between two accounts on Ripple's
XRP Test Net.
Hello, Ripple
In order to get started, first go to the XRP Test Net site and click "Generate credentials" to get an address and a secret.
Once you have an address, install the ripple-lib
npm module and run the below
test.js
file to query the state of the account.
const { RippleAPI } = require('ripple-lib');
const api = new RippleAPI({
server: 'wss://s.altnet.rippletest.net:51233' // XRP Test Net
});
run().catch(error => console.error(error.stack));
async function run() {
await api.connect();
const info = await api.getAccountInfo(process.env.RIPPLE_ADDRESS);
console.log('Done', info);
process.exit(0);
}
Keep in mind the above JavaScript uses destructuring assignments and async/await, so you should use Node.js >= 7.6.0. Running the above script will show you the state of your test Ripple address, including the fact that you now have 10000 fake XRP to play with.
$ env RIPPLE_ADDRESS=raJsStZf83aRh5Q92A1CVFchZjruxnnJNS node info.js
Done { sequence: 1,
xrpBalance: '10000',
ownerCount: 0,
previousAffectingTransactionID: '9910B28EE8D6671EFE7460B092AD084466DEB2790DF0B9E9BE8BF5C93655A6FC',
previousAffectingTransactionLedgerVersion: 9410953 }
$
Transferring XRP
Generate a second Ripple address on the XRP Test Net site. Run the info.js
script to verify the 2nd account also has 10000 fake XRP.
$ env RIPPLE_ADDRESS=re2H6BDYpbJEh1rGZHGD77F7WCBsS1LMM node info.js
Done { sequence: 1,
xrpBalance: '10000',
ownerCount: 0,
previousAffectingTransactionID: 'C060DB82373EF9111B7F2DBA1F341BC4E4299007B76DA784E85C424D7A8DDA06',
previousAffectingTransactionLedgerVersion: 9411702 }
$
Creating a Ripple payment in JavaScript is easy, payment objects look like the below JavaScript object. Here are the full docs on what properties a Ripple payment object has.
// Ripple payments are represented as JavaScript objects
const payment = {
source: {
address: process.env.RIPPLE_FROM_ADDRESS,
maxAmount: {
value: '10.00',
currency: 'XRP'
}
},
destination: {
address: process.env.RIPPLE_TO_ADDRESS,
amount: {
value: '10.00',
currency: 'XRP'
}
}
};
Below is a standalone script for transferring 10 XRP from the address
specified in the RIPPLE_FROM_ADDRESS
environment variable to the
address specified in the RIPPLE_TO_ADDRESS
environment variable. You
also need to put the sender's secret in the RIPPLE_FROM_SECRET
environment variable.
const { RippleAPI } = require('ripple-lib');
const assert = require('assert');
assert.ok(process.env.RIPPLE_FROM_ADDRESS, 'Please specify a RIPPLE_FROM_ADDRESS');
assert.ok(process.env.RIPPLE_TO_ADDRESS, 'Please specify a RIPPLE_TO_ADDRESS');
assert.ok(process.env.RIPPLE_FROM_SECRET, 'Please specify a RIPPLE_FROM_SECRET');
const api = new RippleAPI({
server: 'wss://s.altnet.rippletest.net:51233' // XRP Test Net
});
run().catch(error => console.error(error.stack));
async function run() {
await api.connect();
// Ripple payments are represented as JavaScript objects
const payment = {
source: {
address: process.env.RIPPLE_FROM_ADDRESS,
maxAmount: {
value: '10.00',
currency: 'XRP'
}
},
destination: {
address: process.env.RIPPLE_TO_ADDRESS,
amount: {
value: '10.00',
currency: 'XRP'
}
}
};
// Get ready to submit the payment
const prepared = await api.preparePayment(process.env.RIPPLE_FROM_ADDRESS, payment, {
maxLedgerVersionOffset: 5
});
// Sign the payment using the sender's secret
const { signedTransaction } = api.sign(prepared.txJSON, process.env.RIPPLE_FROM_SECRET);
console.log('Signed', signedTransaction)
// Submit the payment
const res = await api.submit(signedTransaction);
console.log('Done', res);
process.exit(0);
}
Below is the output of running this script with 2 accounts on the XRP Test Net:
$ env RIPPLE_FROM_ADDRESS="raJsStZf83aRh5Q92A1CVFchZjruxnnJNS" env RIPPLE_TO_ADDRESS="re2H6BDYpbJEh1rGZHGD77F7WCBsS1LMM" env RIPPLE_FROM_SECRET="OMITTED" node transfer.js
Signed 12000022800000002400000001201B008F9E3761400000000098968068400000000000000C7321038A271B6430679F6E39990E64A34D1C5D1774E32F667DEDBE9D60147814FDD2C174463044022029DA0502EFE4E630E71C2B7A4E47574BD79080BB3636B97FD215E0EB7E586A40022010F58C5BBED24C41C55631B5E960B9CECCA8C6E9430A537028C7A910383B6D4181143A11BE0D1AF2A02DAD1437B43D8B6109410DD1158314071B2D8758FAD2840A8582A345A44275427FA951
Done { resultCode: 'tesSUCCESS',
resultMessage: 'The transaction was applied. Only final in a validated ledger.' }
$
Technically you need to wait for the Ripple ledger to validate before you can consider this payment complete, but in this case
the validation is very fast. Run the info.js
script again and you
should see the "to" account now has 10010 XRP, and the "from" account
now has approximately 9989 XRP as shown below.
$ env RIPPLE_ADDRESS=re2H6BDYpbJEh1rGZHGD77F7WCBsS1LMM node info.js
Done { sequence: 1,
xrpBalance: '10010',
ownerCount: 0,
previousAffectingTransactionID: '99042EF14E9FD6352E8C3BB6C64DC4BCB452A33FE999F00F9D17F8F127CCBDA8',
previousAffectingTransactionLedgerVersion: 9412148 }
$ env RIPPLE_ADDRESS=raJsStZf83aRh5Q92A1CVFchZjruxnnJNS node info.js
Done { sequence: 2,
xrpBalance: '9989.999988',
ownerCount: 0,
previousAffectingTransactionID: '99042EF14E9FD6352E8C3BB6C64DC4BCB452A33FE999F00F9D17F8F127CCBDA8',
previousAffectingTransactionLedgerVersion: 9412148 }
$
Why does the from account have less than 9990 XRP? The Ripple protocol has a variable transaction fee built in to defend against denial-of-service attacks and spam. The sender of a payment is responsible for paying the transaction cost.
Moving On
Node.js is a great tool for building services that talk to other services
over the network and don't have to do CPU-intensive calculations
on their own. Ripple is a great example: the Ripple infrastructure does
the hard work, and your Node.js program can seamlessly connect via
web socket and make payments. Check out ripple-lib
and start learning
about Ripple!