XRPL-Labs / xrpl-client

Connect to the XRP Ledger using WebSockets
https://www.npmjs.com/package/xrpl-client
MIT License
12 stars 8 forks source link

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

Closed tequdev closed 6 months ago

tequdev commented 6 months ago

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);
        });
      }
    });
  }
tequdev commented 6 months ago

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

WietseWind commented 6 months ago

@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?
tequdev commented 6 months ago
  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().
tequdev commented 6 months ago

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')
WietseWind commented 6 months ago

@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?

tequdev commented 6 months ago

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
      }
    });
  }
WietseWind commented 6 months ago

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

2.4.0 published :)

tequdev commented 6 months ago

Thank you👍