XRPL-Labs/xrpl-client

`ready()` sometimes gets stuck on standalone network.

Closed this issue · 8 comments

If the result of an if using the result of this.getState() is false, the ledger does not proceed automatically in a standalone environment, so it stacks in else.

  ready(): Promise<XrplClient> {
    return new Promise((resolve, reject) => {
      const state = this.getState();
      if (
        state.online &&
        state.secLastContact &&
        state.secLastContact < 10 &&
        state.ledger.last
      ) {
        // We're good
        return resolve(this);
      } else {
        // Let's wait to make sure we're really connected
        this.on("ledger", () => {
          resolve(this);
        });
      }
    });
  }

utils.networkTxFee in xrpl-accountlib was affected and stuck.

@tequdev I'm afraid I don't understand. I have three questions:

  1. Can you explain what you mean with 'stuck': the entire class doesn't respond anymore? Or the single promise doesn't return?

  2. And do you mean with this:

ledger does not proceed automatically in a standalone environment

... Running rippled/xahaud in a manner where you manually have to advance the ledger?

  1. You refer to both ready() and utils.networkTxFee, can you explain what the problem is with either one?
  1. resolve() is not executed in my situation, so the promise does not return.
  2. Yes, I’m using ledger_accept in the script.
  3. ready() has a problem. My script uses utils.networkTxFee and after searching for the cause, I found a problem with ready().

Reproduce:

use xrpld-net-gen (https://github.com/Transia-RnD/xrpld-network-gen)

pip3 install xrpld-netgen
xrpld-netgen up:standalone

If you run the following code several times, the process may not complete.

import { XrplClient } from 'xrpl-client'

const client = new XrplClient('ws://localhost:6006')

await client.ready()
console.log('ready')

@tequdev But... If ledgers don't close (because you manually advance) the script is technically right: the network isn't ready ;)

So I guess an initializer would be preferred here, where, if you construct, you can pass an option to declare that it's ledger_accept mode, so it doesn't await ready?

Yes, technically correct.
If we try to pass the option, I think it would require changes to other libraries that use this library as well.

For example, how about the following code?
Wait with setInterval until this.getState() returns the expected value.

it works for me.

  ready(): Promise<XrplClient> {
    return new Promise((resolve, reject) => {
      const state = this.getState();
      if (
        state.online &&
        state.secLastContact &&
        state.secLastContact < 10 &&
        state.ledger.last
      ) {
        // We're good
        return resolve(this);
      } else {
        // Let's wait to make sure we're really connected
        this.on("ledger", () => {
          resolve(this);
        });
        // Additional code start
        const id = setInterval(() => {
          const state = this.getState();
          if (
            state.online &&
            state.secLastContact &&
            state.secLastContact < 10 &&
            state.ledger.last
          ) {
            clearInterval(id);
            resolve(this);
          }
        }, 200)
       // Additional code end
      }
    });
  }

@tequdev That works for me, good solution. I'll add this to the source now & publish an update.

2.4.0 published :)

Thank you👍