import { Client, Payment } from '../../src'

/**
 * When implementing Reliable Transaction Submission, there are many potential solutions, each with different trade-offs.
 * The main decision points are:
 * 1) Transaction preparation:
 *    - The autofill function as a part of the submitAndWait should be able to correctly populate
 *      values for the fields Sequence, LastLedgerSequence and Fee.
 * 2) Transaction status retrieval. Options include:
 *    - Poll for transaction status:
 *      - On a regular interval (e.g. Every 3-5 seconds), or
 *      - When a new validated ledger is detected
 *      + (To accommodate an edge case in transaction retrieval,
 *         check the sending account's Sequence number to confirm that it has the expected value;
 *         alternatively, wait until a few additional ledgers have been validated before deciding that a
 *         transaction has definitively not been included in a validated ledger)
 *    - Listen for transaction status: scan all validated transactions to see if our transactions are among them
 * 3) What do we do when a transaction fails? It is possible to implement retry logic, but caution is advised.
 *  Note that there are a few ways for a transaction to fail:
 *    A) `tec`: The transaction was included in a ledger but only claimed the transaction fee
 *    B) `tesSUCCESS` but unexpected result: The transaction was successful but did not have the expected result.
 *        This generally does not occur for XRP-to-XRP payments
 *    C) The transaction was not, and never will be, included in a validated ledger [3C].
 *
 * References:
 * - https://xrpl.org/reliable-transaction-submission.html
 * - https://xrpl.org/send-xrp.html
 * - https://xrpl.org/look-up-transaction-results.html
 * - https://xrpl.org/monitor-incoming-payments-with-websocket.html.
 *
 * For the implementation in this example, we have made the following decisions:
 * 1) We allow the autofill function as a part of submitAndWait to fill up the account sequence,
 *    LastLedgerSequence and Fee. Payments are defined upfront, and idempotency is not needed.
 *    If the script is run a second time, duplicate payments will result.
 * 2) We will rely on the xrpl.js submitAndWait function to get us the transaction submission result after the wait time.
 * 3) Transactions will not be automatically retried. Transactions are limited to XRP-to-XRP payments
 *     and cannot "succeed" in an unexpected way.
 */

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

void sendReliableTx()

async function sendReliableTx(): Promise<void> {
  await client.connect()

  // creating wallets as prerequisite
  const { wallet: wallet1 } = await client.fundWallet(null, {
    usageContext: 'code snippets',
  })
  const { wallet: wallet2 } = await client.fundWallet(null, {
    usageContext: 'code snippets',
  })

  console.log('Balances of wallets before Payment tx')
  console.log(
    await client.getXrpBalance(wallet1.classicAddress),
    await client.getXrpBalance(wallet2.classicAddress),
  )

  // create a Payment tx and submit and wait for tx to be validated
  const payment: Payment = {
    TransactionType: 'Payment',
    Account: wallet1.classicAddress,
    Amount: '1000',
    Destination: wallet2.classicAddress,
  }

  const paymentResponse = await client.submitAndWait(payment, {
    wallet: wallet1,
  })
  console.log('\nTransaction was submitted.\n')
  const txResponse = await client.request({
    command: 'tx',
    transaction: paymentResponse.result.hash,
  })
  // With the following reponse we are able to see that the tx was indeed validated.
  console.log('Validated:', txResponse.result.validated)

  console.log('Balances of wallets after Payment tx:')
  console.log(
    await client.getXrpBalance(wallet1.classicAddress),
    await client.getXrpBalance(wallet2.classicAddress),
  )

  await client.disconnect()
}
