<html>

<head>
  <title>XRPL Token Test Harness</title>
  <link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
  <script src='https://unpkg.com/xrpl@2.6.0'></script>
  <script>
    if (typeof module !== "undefined") {
      const xrpl = require('xrpl')
    }
  </script>

</head>

<body>
  <div id="selectLedger">
    <div class="appField">
      <strong>Choose your ledger instance:</strong><br />
      <input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233" checked>
      <label for="testnet">Testnet</label>
      &nbsp;&nbsp;
      <input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233">
      <label for="devnet">Devnet</label>
    </div>
    <div class="appField">
      <button type="button" onClick="getAccountsFromSeeds()">Get Accounts From Seeds</button><br />
      <textarea id="seeds" cols="40" rows="2"></textarea>
    </div>
  </div>
  <div id="flexContainer">
    <div class="flexColumn">
      <div id="standbyApp">
        <button type="button" onClick="getAccount('standby')">Create Standby Account</button><br />

        <h2>Standby Account Info</h2>
        <div class="appField">Account<br />
          <div id="standbyAccountField" class="appValue"></div>
        </div>
        <div class="appField">Public Key<br />
          <div id="standbyPubKeyField" class="appValue"></div>
        </div>
        <div class="appField">Private Key<br />
          <div id="standbyPrivKeyField" class="appValue"></div>
        </div>
        <div class="appField"> Seed<br />
          <div id="standbySeedField" class="appValue"></div>
        </div>
        <div class="appField"> XRP Balance<br />
          <div id="standbyBalanceField" class="appValue"></div>
        </div>

        <div id="standbyTransact">
          <p><strong>Send XRP or Currency</strong></p>
          <div class="appField">
            Amount<br />
            <input id="standbyAmountField" class="appValue"></input>
          </div>
          <div class="appField">
            Destination Account <br />
            <input id="standbyDestinationField" class="appValue"></input>
          </div>
          <div class="appField">
            Currency<br />
            <input type="text" class="appValue" id="standbyCurrencyField" size="30" value="USD"></input>
          </div>
          <br /><br />
          <button type="button" onClick="configureAccount('standby',document.querySelector('#standbyDefault').checked)">Configure Account</button><br />
          <input type="checkbox" id="standbyDefault" checked="true" />
          <label for="standbyDefault">Allow Rippling</label>
          <p>
            <button type="button" onClick="createTrustline()">Create TrustLine</button>
            <button type="button" onClick="sendCurrency()">Send Currency</button>
            <button type="button" onClick="getBalances()">Get Balances</button>
            <button type="button" onClick="sendXRP()">Send XRP &#8594;</button>
          </p>
          <p><strong>Transaction Log</strong></p>
          <div id="standbyResultField"></div>
        </div>

      </div>
    </div>
    <div class="flexColumn">
      <div id="operationalApp">
        <button type="button" onClick="getAccount('operational')">Create Operational Account</button><br />

        <h2>Operational Account Info</h2>
        <div class="appField">Account<br />
          <div id="operationalAccountField" class="appValue"></div>
        </div>
        <div class="appField">Public Key<br />
          <div id="operationalPubKeyField" class="appValue"></div>
        </div>
        <div class="appField">Private Key<br />
          <div id="operationalPrivKeyField" class="appValue"></div>
        </div>
        <div class="appField"> Seed<br />
          <div id="operationalSeedField" class="appValue"></div>
        </div>
        <div class="appField"> XRP Balance<br />
          <div id="operationalBalanceField" class="appValue"></div>
        </div>

        <div id="operationalTransact">
          <p><strong>Send XRP</strong></p>
          <div class="appField">
            Amount<br />
            <input id="operationalAmountField" class="appValue"></input>
          </div>
          <div class="appField">
            Destination Account <br />
            <input id="operationalDestinationField" class="appValue"></input>
          </div>
          <div class="appField">
            Currency<br />
            <input type="text" class="appValue" id="operationalCurrencyField" size="30" value="USD"></input>
          </div>
          <br /><br />
          <button type="button" onClick="configureAccount('standby',document.querySelector('#standbyDefault').checked)">Configure Account</button><br />
          <input type="checkbox" id="operationalDefault" checked="true" />
          <label for="operationalDefault">Allow Rippling</label>
          <p>
            <button type="button" onClick="oPcreateTrustline()">Create TrustLine</button>
            <button type="button" onClick="oPsendCurrency()">Send Currency</button>
            <button type="button" onClick="oPgetBalances()">Get Balances</button>
            <button type="button" onClick="oPsendXRP()"> &#8592; Send XRP</button>
          </p>
          <p><strong>Transaction Log</strong></p>
          <div id="operationalResultField"></div>
        </div>

      </div>
    </div>
  </div>
</body>

</html>
body {
  font-family: "Work Sans", sans-serif;
  padding: 40px;
  background: #fafafa;
  font-size: 0.8em;
}
h1 {
  font-weight: bold;
}
button {
  padding: 12px;
  margin-bottom: 8px;
  font-size: 1em;
  background: #fff;
  border-radius: 0.5em;
  border: solid 2px #444;
}
button {
  font-weight: bold;
  font-family: "Work Sans", sans-serif;
}
button:hover {
  background: #eee;
  cursor: pointer;
}
td {
  vertical-align: top;
  padding-right: 10px;
}
#selectLedger {
  background: #ff78bb;
  padding: 1em 1em 0 1em;
  border-radius: 1em;
  width: 80%;
  margin: 0 0 1em 0;
  font-size: 1.25em;
  line-height: 2em;
}

.appField {
  vertical-align: top;
  display: inline-block;
  margin: 0 1em 0 0;
}
.appValue {
  display: inline-block;
  overflow-wrap: break-word;
  padding: 0.25em;
  height: 2.5em;
  font-size: 10px;
  background: #efefef;
  min-width: 100px;
  max-width: 300px;
  border-radius: 0.5em;
  margin: 0.25em 0 0.5em 0;
}
#flexContainer {
  display: flex;
  align-content: flex-start;
  margin: 0 -0.5em;
}
.flexColumn {
  width: 100%;
  flex: 1 0 50%;
  max-width: 50%;
  margin: 0 0.5em;
}

#standbyApp {
  background: #86e3b0;
  padding: 1.5em;
  border-radius: 1em;
}
#standbyTransact {
  display: inline-block;
  background: #42df89;
  border-radius: 0.5em;
  display: inline-block;
  margin: 0.5em 0;
  padding: 0 1.5em;
  min-width: 90%;
}

#standbyResultField {
  display: inline-block;
  padding: 0.25em;
  border: solid 1px white;
  height: 2em;
  font-size: 1em;
  background: #efefef;
  width: 100%;
  border-radius: 3px;
  margin: 0.25em 0 0.5em 0;
  height: 100px;
  overflow-y: scroll;
}

#operationalApp {
  background: #58bbfd;
  padding: 1.5em;
  border-radius: 1em;
}
#operationalTransact {
  display: inline-block;
  background: #19a3ff;
  border-radius: 0.5em;
  display: inline-block;
  margin: 0.5em 0;
  padding: 0 1.5em;
  min-width: 90%;
}
#operationalResultField {
  display: inline-block;
  padding: 0.25em;
  border: solid 1px white;
  height: 2em;
  font-size: 1em;
  background: #efefef;
  width: 100%;
  border-radius: 3px;
  margin: 0.25em 0 0.5em 0;
  height: 100px;
  overflow-y: scroll;
}
input {
  border: none;
}
// **************** Configure Account ********************

async function configureAccount(type, rippleDefault) {
  let net = getNet();
  const client = new xrpl.Client(net);
  results = "Connecting to " + getNet() + "....";
  standbyResultField.innerHTML = results;
  await client.connect();
  results += "<br/>Connected, finding wallet.";
  standbyResultField.innerHTML = results;

  if (type == "standby") {
    my_wallet = xrpl.Wallet.fromSeed(standbySeedField.innerHTML);
  } else {
    my_wallet = xrpl.Wallet.fromSeed(operationalSeedField.innerHTML);
  }
  results += "Ripple Default Setting: " + rippleDefault;
  standbyResultField.innerHTML = results;

  let settings_tx = {};
  if (rippleDefault) {
    settings_tx = {
      TransactionType: "AccountSet",
      Account: my_wallet.address,
      SetFlag: xrpl.AccountSetAsfFlags.asfDefaultRipple
    };
    results += "<br/> Set Default Ripple flag.";
  } else {
    settings_tx = {
      TransactionType: "AccountSet",
      Account: my_wallet.address,
      ClearFlag: xrpl.AccountSetAsfFlags.asfDefaultRipple
    };
    results += "<br/> Clear Default Ripple flag.";
  }
  results += "<br/>Sending account setting.";
  standbyResultField.innerHTML = results;

  const cst_prepared = await client.autofill(settings_tx);
  const cst_signed = my_wallet.sign(cst_prepared);
  const cst_result = await client.submitAndWait(cst_signed.tx_blob);
  if (cst_result.result.meta.TransactionResult == "tesSUCCESS") {
    results += "<br/>Account setting succeeded.";
    standbyResultField.innerHTML = results;
  } else {
    throw "Error sending transaction: ${cst_result}";
    results += "<br/>Account setting failed.";
    standbyResultField.innerHTML = results;
  }

  client.disconnect();
} // End of configureAccount()

// *******************************************************
// ***************** Create TrustLine ********************
// *******************************************************

async function createTrustline() {
  let net = getNet();
  const client = new xrpl.Client(net);
  results = "Connecting to " + getNet() + "....";
  standbyResultField.innerHTML = results;

  await client.connect();

  results += "<br/>Connected.";
  standbyResultField.innerHTML = results;

  const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.innerHTML);
  const operational_wallet = xrpl.Wallet.fromSeed(
    operationalSeedField.innerHTML
  );
  const currency_code = standbyCurrencyField.value;
  const trustSet_tx = {
    TransactionType: "TrustSet",
    Account: standbyDestinationField.value,
    LimitAmount: {
      currency: standbyCurrencyField.value,
      issuer: standby_wallet.address,
      value: standbyAmountField.value
    }
  };
  const ts_prepared = await client.autofill(trustSet_tx);
  const ts_signed = operational_wallet.sign(ts_prepared);
  results +=
    "<br/>Creating trust line from operational account to standby account...";
  standbyResultField.innerHTML = results;
  const ts_result = await client.submitAndWait(ts_signed.tx_blob);
  if (ts_result.result.meta.TransactionResult == "tesSUCCESS") {
    results +=
      "<br/>Trustline established between account <br/>" +
      standbyDestinationField.value +
      " <br/> and account<br/>" +
      standby_wallet.address +
      ".";
    standbyResultField.innerHTML = results;
  } else {
    results += "<br/>TrustLine failed. See JavaScript console for details.";
    standbyResultField.innerHTML = results;
    throw "Error sending transaction: ${ts_result.result.meta.TransactionResult}";
  }
} //End of createTrustline()

// *******************************************************
// *************** Send Issued Currency ******************
// *******************************************************

async function sendCurrency() {
  let net = getNet();
  const client = new xrpl.Client(net);
  results = "Connecting to " + getNet() + "....";
  standbyResultField.innerHTML = results;

  await client.connect();

  results += "<br/>Connected.";
  standbyResultField.value = results;

  const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.innerHTML);
  const operational_wallet = xrpl.Wallet.fromSeed(
    operationalSeedField.innerHTML
  );
  const currency_code = standbyCurrencyField.value;
  const issue_quantity = standbyAmountField.value;

  const send_token_tx = {
    TransactionType: "Payment",
    Account: standby_wallet.address,
    Amount: {
      currency: standbyCurrencyField.value,
      value: standbyAmountField.value,
      issuer: standby_wallet.address
    },
    Destination: standbyDestinationField.value
  };

  const pay_prepared = await client.autofill(send_token_tx);
  const pay_signed = standby_wallet.sign(pay_prepared);
  results +=
    "Sending " +
    standbyAmountField.value +
    standbyCurrencyField.value +
    "to " +
    standbyDestinationField.value +
    "...";
  standbyResultField.innerHTML = results;
  const pay_result = await client.submitAndWait(pay_signed.tx_blob);
  if (pay_result.result.meta.TransactionResult == "tesSUCCESS") {
    results +=
      "Transaction succeeded: https://testnet.xrpl.org/transactions/${pay_signed.hash}";
    standbyResultField.innerHTML = results;
  } else {
    results += "Transaction failed: See JavaScript console for details.";
    standbyResultField.innerHTML = results;
    throw "Error sending transaction: ${pay_result.result.meta.TransactionResult}";
  }
  standbyBalanceField.innerHTML = await client.getXrpBalance(
    standby_wallet.address
  );
  operationalBalanceField.innerHTML = await client.getXrpBalance(
    operational_wallet.address
  );
  getBalances();
  client.disconnect();
} // end of sendIOU()

// *******************************************************
// ****************** Get Balances ***********************
// *******************************************************

async function getBalances() {
  let net = getNet();
  const client = new xrpl.Client(net);
  results = "Connecting to " + getNet() + "....";
  standbyResultField.innerHTML = results;

  await client.connect();

  results += "<br/>Connected.";
  standbyResultField.innerHTML = results;

  const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.innerHTML);
  const operational_wallet = xrpl.Wallet.fromSeed(
    operationalSeedField.innerHTML
  );

  results = "<br/>Getting standby account balances...<br/>";
  const standby_balances = await client.request({
    command: "gateway_balances",
    account: standby_wallet.address,
    ledger_index: "validated",
    hotwallet: [operational_wallet.address]
  });
  results += JSON.stringify(standby_balances.result, null, 2);
  standbyResultField.innerHTML = results;

  results = "<br/>Getting operational account balances...<br/>";
  const operational_balances = await client.request({
    command: "account_lines",
    account: operational_wallet.address,
    ledger_index: "validated"
  });
  results += JSON.stringify(operational_balances.result, null, 2);
  operationalResultField.innerHTML = results;

  operationalBalanceField.innerHTML = await client.getXrpBalance(
    operational_wallet.address
  );
  standbyBalanceField.innerHTML = await client.getXrpBalance(
    standby_wallet.address
  );

  client.disconnect();
} // End of getBalances()

// **********************************************************************
// ****** Reciprocal Transactions ***************************************
// **********************************************************************

// *******************************************************
// ************ Create Operational TrustLine *************
// *******************************************************

async function oPcreateTrustline() {
  let net = getNet();
  const client = new xrpl.Client(net);
  results = "Connecting to " + getNet() + "....";
  operationalResultField.innerHTML = results;

  await client.connect();

  results += "<br/>Connected.";
  operationalResultField.innerHTML = results;

  const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.innerHTML);
  const operational_wallet = xrpl.Wallet.fromSeed(
    operationalSeedField.innerHTML
  );
  const trustSet_tx = {
    TransactionType: "TrustSet",
    Account: operationalDestinationField.value,
    LimitAmount: {
      currency: operationalCurrencyField.value,
      issuer: operational_wallet.address,
      value: operationalAmountField.value
    }
  };
  const ts_prepared = await client.autofill(trustSet_tx);
  const ts_signed = standby_wallet.sign(ts_prepared);
  results +=
    "<br/>Creating trust line from operational account to " +
    operationalDestinationField.value +
    " account...";
  operationalResultField.innerHTML = results;
  const ts_result = await client.submitAndWait(ts_signed.tx_blob);
  if (ts_result.result.meta.TransactionResult == "tesSUCCESS") {
    results +=
      "<br/>Trustline established between account <br/>" +
      standby_wallet.address +
      " <br/> and account<br/>" +
      operationalDestinationField.value +
      ".";
    operationalResultField.innerHTML = results;
  } else {
    results += "<br/>TrustLine failed. See JavaScript console for details.";
    operationalResultField.innerHTML = results;
    throw "Error sending transaction: ${ts_result.result.meta.TransactionResult}";
  }
} //End of oPcreateTrustline

// *******************************************************
// ************* Operational Send Issued Currency ********
// *******************************************************

async function oPsendCurrency() {
  let net = getNet();
  const client = new xrpl.Client(net);
  results = "Connecting to " + getNet() + "....";
  operationalResultField.value = results;

  await client.connect();

  results += "<br/>Connected.";
  operationalResultField.innerHTML = results;

  const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value);
  const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value);
  const currency_code = operationalCurrencyField.value;
  const issue_quantity = operationalAmountField.value;

  const send_token_tx = {
    TransactionType: "Payment",
    Account: operational_wallet.address,
    Amount: {
      currency: currency_code,
      value: issue_quantity,
      issuer: operational_wallet.address
    },
    Destination: operationalDestinationField.value
  };

  const pay_prepared = await client.autofill(send_token_tx);
  const pay_signed = operational_wallet.sign(pay_prepared);
  results +=
    "Sending" +
    operationalAmountField.value +
    operationalCurrencyField.value +
    " to " +
    operationalDestinationField.value +
    "...";
  operationalResultField.innerHTML = results;
  const pay_result = await client.submitAndWait(pay_signed.tx_blob);
  if (pay_result.result.meta.TransactionResult == "tesSUCCESS") {
    results +=
      "Transaction succeeded: https://testnet.xrpl.org/transactions/${pay_signed.hash}";
    operationalResultField.innerHTML = results;
  } else {
    results += "Transaction failed: See JavaScript console for details.";
    operationalResultField.innerHTML = results;
    throw "Error sending transaction: ${pay_result.result.meta.TransactionResult}";
  }
  standbyBalanceField.innerHTML = await client.getXrpBalance(
    standby_wallet.address
  );
  operationalBalanceField.innerHTML = await client.getXrpBalance(
    operational_wallet.address
  );
  getBalances();
  client.disconnect();
} // end of oPsendCurrency()

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://assets.codepen.io/t-4946/get-accounts-send-xrp.js