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!

Found a typo or error? Open up a pull request! This post is available as markdown on Github
comments powered by Disqus