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' }); 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.

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' }); run().catch(error => console .error(error.stack)); async function run ( ) { await api.connect(); 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' } } }; const prepared = await api.preparePayment(process.env.RIPPLE_FROM_ADDRESS, payment, { maxLedgerVersionOffset: 5 }); const { signedTransaction } = api.sign(prepared.txJSON, process.env.RIPPLE_FROM_SECRET); console .log( 'Signed' , signedTransaction) 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