Payments

In this section we will create your first payment transaction.

Creating the main structure of your script

Create a new file or edit index.ts

import {  Client,  Wallet }  from "xrpl" 

const client = new Client("wss://s.altnet.rippletest.net:51233")


const main = async () => {
  console.log("lets get started...");
  await client.connect();

  // do something interesting here


  await client.disconnect();
  console.log("all done!");
};

main();

Running this to make sure everything works should console log a few things. If you are running this from your own node environment, don't forget to runnpm i xrpl to add it to your project.

Creating wallets

Let's add some wallet creation logic, we might as well create 2 wallets to have some fun.

console.log('lets fund 2 accounts...')
const { wallet: wallet1, balance: balance1 } = await client.fundWallet()
const { wallet: wallet2, balance: balance2 } = await client.fundWallet()

console.log('wallet1', wallet1)

console.log({ 
    balance1, 
    address1: wallet1.address, //wallet1.seed
    balance2, 
    address2: wallet2.address 
})

At this point, we should have 2 wallets with balances of 100 XRP.

Transferring XRP from one wallet to the other

Of course, we will want to transfer some XRP from one account to another, because that's why we're here.

const tx:xrpl.Payment  = {
    TransactionType: "Payment",
    Account: wallet1.classicAddress,
    Destination: wallet2.classicAddress,
    Amount: xrpl.xrpToDrops("13")
};

Let's log it to ensure everything is correct, and then submit it to the ledger:

console.log('submitting the payment transaction... ', tx)

const result = await client.submitAndWait(tx, {
    autofill: true,
    wallet: wallet1,
}); 

console.log(result)

When you run this part you should get the following log output:

{
  id: 28,
  result: {
    Account: 'rGGJ71dbSY5yF9BJUDSHsDPSKDhVGGWzpY',
    Amount: '13000000',
    DeliverMax: '13000000',
    Destination: 'rBAbErfjkwFWFerLfAHmbi3qgbRfuFWxEN',
    Fee: '12',
    Flags: 0,
    LastLedgerSequence: 232639,
    Sequence: 232617,
    SigningPubKey: 'ED13EBC7F89545435E82DC19B2C38AF5ECF39CE099C8FA647280C71CD6FA5BEF3B',
    TransactionType: 'Payment',
    TxnSignature: '66D9338B3C93D212F89BB4F6731E7F38A01052F8ED94452D7D2A9BB0B0C6130A5708390E9B6233A98A3B28A1922E57E37317609727409B3D289C456BB3250E08',
    ctid: 'C0038CAD00000001',
    date: 767648991,
    hash: 'CC8241E3C4B57ED9183D6031F4E370AC13B6CE9E2332BD7AF77C25BD6ADFA4F6',
    inLedger: 232621,
    ledger_index: 232621,
    meta: {
      AffectedNodes: [Array],
      TransactionIndex: 0,
      TransactionResult: 'tesSUCCESS',
      delivered_amount: '13000000'
    },
    validated: true
  },
  type: 'response'
}

The most important being TransactionResult: 'tesSUCCESS'

You can verify the transaction on the ledger, as it is readable by anyone at this point. Go to https://testnet.xrpl.org and paste the hash value (in my example case it would be CC8241E3C4B57ED9183D6031F4E370AC13B6CE9E2332BD7AF77C25BD6ADFA4F6. You should see it. Alternatively, check the wallet addresses as well (remember you are using the public key).

I prefer to check the balances programmatically to ensure everything has gone according to plan. Adding this code will do that:

  console.log({
    'balance 1': await client.getBalances(wallet1.classicAddress), 
    'balance 2': await client.getBalances(wallet2.classicAddress)
  })

Putting it all together

Here is the entire index.ts file at this point:

import xrpl  from "xrpl" 

const client = new xrpl.Client("wss://s.altnet.rippletest.net:51233")


const main = async () => {
  console.log("lets get started...");
  await client.connect();

  // do something interesting here
  console.log('lets fund 2 accounts...')
  const { wallet: wallet1, balance: balance1 } = await client.fundWallet();
  const { wallet: wallet2, balance: balance2 } = await client.fundWallet();

  console.log('wallet1', wallet1)

  console.log({ 
    balance1, 
    address1: wallet1.address, //wallet1.seed
    balance2, 
    address2: wallet2.address 
  });

  const tx:xrpl.Payment  = {
    TransactionType: "Payment",
    Account: wallet1.classicAddress,
    Destination: wallet2.classicAddress,
    Amount: xrpl.xrpToDrops("13")
  };

  console.log('submitting the payment transaction... ', tx)

  const result = await client.submitAndWait(tx, {
    autofill: true,
    wallet: wallet1,
  }); 

  console.log(result)

  console.log({
    'balance 1': await client.getBalances(wallet1.classicAddress), 
    'balance 2': await client.getBalances(wallet2.classicAddress)
  })

  await client.disconnect();
  console.log("all done!");
};

main();

Extra credit

Don't you find it limiting that the faucet only gives out 100 XRP? Why not create a function to print money to an address?

You have all the necessary building blocks:

  1. You will need to create and fund new wallets with await client.fundWallet()

  2. Remember, you can only transfer XRP up to the reserve, so a maximum of 90 XRP at a time for brand new accounts, unless you are brave enough to use a new transaction type.? (https://xrpl.org/docs/references/protocol/transactions/types/accountdelete/). However, be warned that you will have to wait a block or two before the account can be deleted.

  3. The final function signature should look something like this `await printMoney({ destinationWallet, client })

I can't wait to see who writes this faster than ChatGPT !

Here is the popular printMoney function

import xrpl from "xrpl";

const printMoney = async ({ destinationWallet, client }: any) => {
  const { wallet: wallet1, balance: balance1 } = await client.fundWallet();

  console.log("wallet1", wallet1);

  const tx: xrpl.Payment = {
    TransactionType: "Payment",
    Account: wallet1.classicAddress,
    Destination: destinationWallet.classicAddress,
    Amount: xrpl.xrpToDrops("90"),
  };

  console.log("submitting the payment transaction... ", tx);

  const result = await client.submitAndWait(tx, {
    autofill: true,
    wallet: wallet1,
  });

  console.log(result);

  console.log({
    "balance 2": await client.getBalances(destinationWallet.classicAddress),
  });
};

export default printMoney;

Last updated