#SorobanClient `getLedgerEntries` throwing error in 1.0.0-beta.4

66 messages · Page 1 of 1 (latest)

weary coral
#

Hello!

Wanted to flag an error I've been seeing in soroban-client 1.0.0-beta.4.

The Blend-Sdk makes use of getLedgerEntries pretty extensively to fetch contract data from chain. (this is mostly so we can fetch multiple entries at once from the RPC)

See this block of example code reading from testnet for the error:

  const backstop_id = 'CDTPZ5PCK5COX73S5MABIZ3G3A6CLC3HDYQOHSXH6ZMN2VWHVRXAJO74';
  const pool_id = 'CAMUSVYFN6LUKIZTKCFVP536GDU3GOBIFVGG6OJKU4EDUW6OMDTM3UZK';
  const poolEpsDataKey = xdr.LedgerKey.contractData(
    new xdr.LedgerKeyContractData({
      contract: Address.fromString(backstop_id).toScAddress(),
      key: xdr.ScVal.scvVec([
        xdr.ScVal.scvSymbol('PoolEPS'),
        Address.fromString(pool_id).toScVal(),
      ]),
      durability: xdr.ContractDataDurability.persistent(),
    })
  );

  const backstopPoolDataPromise = await stellar_rpc.getLedgerEntries(poolEpsDataKey);
  console.log('Result: ', backstopPoolDataPromise);

with 1.0.0-beta.2 this produces:

Result:  {
  entries: [
    {
      key: 'AAAABgAAAAHm/PXiV0Tr/3LrABRnZtg8JYtnHiDjyuf2WN1Wx6xuBAAAABAAAAABAAAAAgAAAA8AAAAHUG9vbEVQUwAAAAASAAAAARlJVwVvl0UjM1CLV/d+MOmzOCgtTG85KqcIOlvOYObNAAAAAQ==',
      xdr: 'AAAABgAAAAAAAAAB5vz14ldE6/9y6wAUZ2bYPCWLZx4g48rn9ljdVsesbgQAAAAQAAAAAQAAAAIAAAAPAAAAB1Bvb2xFUFMAAAAAEgAAAAEZSVcFb5dFIzNQi1f3fjDpszgoLUxvOSqnCDpbzmDmzQAAAAEAAAAKAAAAAAAAAAAAAAAAABt3QA==',
      lastModifiedLedgerSeq: '2535782'
    }
  ],
  latestLedger: '2537751'
}

with 1.0.0-beta.4

TypeError: expiration not set
    at ChildUnion.get (/Users/mootz12/dev/blend/blend-utils/node_modules/js-xdr/lib/xdr.js:1727:95)
    at ChildUnion.get [as expiration] (/Users/mootz12/dev/blend/blend-utils/node_modules/js-xdr/lib/xdr.js:1836:25)
    at /Users/mootz12/dev/blend/blend-utils/node_modules/soroban-client/lib/server.js:636:104
    at Array.forEach (<anonymous>)
    at mergeResponseExpirationLedgers (/Users/mootz12/dev/blend/blend-utils/node_modules/soroban-client/lib/server.js:626:135)
    at /Users/mootz12/dev/blend/blend-utils/node_modules/soroban-client/lib/server.js:230:24
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async temp (file:///Users/mootz12/dev/blend/blend-utils/lib/scripts/temp.js:164:37)
    at async file:///Users/mootz12/dev/blend/blend-utils/lib/scripts/temp.js:191:1

Suggestions on how to move forward? My current thought is patching the sequence number bug manually on the 1.0.0-beta.2 release.

#

Update - it appears this failure is not consistent. I am able to sometimes load the information and sometimes not.

Here is a quick output of my running the script a few times every couple seconds:

mootz12@Alexs-MacBook-Pro blend-utils % node ./lib/scripts/temp.js testnet
Result:  {
  latestLedger: '2537934',
  entries: [
    {
      lastModifiedLedgerSeq: '2535782',
      key: [ChildUnion],
      val: [ChildUnion],
      expirationLedgerSeq: 2777702
    }
  ]
}
mootz12@Alexs-MacBook-Pro blend-utils % node ./lib/scripts/temp.js testnet
/Users/mootz12/dev/blend/blend-utils/node_modules/js-xdr/lib/xdr.js:1727
    if (this._arm !== _void__WEBPACK_IMPORTED_MODULE_0__.Void && this._arm !== armName) throw new TypeError(`${armName} not set`);
                                                                                              ^

TypeError: expiration not set
    at ChildUnion.get (/Users/mootz12/dev/blend/blend-utils/node_modules/js-xdr/lib/xdr.js:1727:95)
    at ChildUnion.get [as expiration] (/Users/mootz12/dev/blend/blend-utils/node_modules/js-xdr/lib/xdr.js:1836:25)
    at /Users/mootz12/dev/blend/blend-utils/node_modules/soroban-client/lib/server.js:636:104
    at Array.forEach (<anonymous>)
    at mergeResponseExpirationLedgers (/Users/mootz12/dev/blend/blend-utils/node_modules/soroban-client/lib/server.js:626:135)
    at /Users/mootz12/dev/blend/blend-utils/node_modules/soroban-client/lib/server.js:230:24
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async temp (file:///Users/mootz12/dev/blend/blend-utils/lib/scripts/temp.js:164:37)
    at async file:///Users/mootz12/dev/blend/blend-utils/lib/scripts/temp.js:191:1

Node.js v18.18.0
mootz12@Alexs-MacBook-Pro blend-utils % node ./lib/scripts/temp.js testnet
/Users/mootz12/dev/blend/blend-utils/node_modules/js-xdr/lib/xdr.js:1727
    if (this._arm !== _void__WEBPACK_IMPORTED_MODULE_0__.Void && this._arm !== armName) throw new TypeError(`${armName} not set`);
                                                                                              ^

TypeError: expiration not set
    at ChildUnion.get (/Users/mootz12/dev/blend/blend-utils/node_modules/js-xdr/lib/xdr.js:1727:95)
    at ChildUnion.get [as expiration] (/Users/mootz12/dev/blend/blend-utils/node_modules/js-xdr/lib/xdr.js:1836:25)
    at /Users/mootz12/dev/blend/blend-utils/node_modules/soroban-client/lib/server.js:636:104
    at Array.forEach (<anonymous>)
    at mergeResponseExpirationLedgers (/Users/mootz12/dev/blend/blend-utils/node_modules/soroban-client/lib/server.js:626:135)
    at /Users/mootz12/dev/blend/blend-utils/node_modules/soroban-client/lib/server.js:230:24
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async temp (file:///Users/mootz12/dev/blend/blend-utils/lib/scripts/temp.js:164:37)
    at async file:///Users/mootz12/dev/blend/blend-utils/lib/scripts/temp.js:191:1

Node.js v18.18.0
mootz12@Alexs-MacBook-Pro blend-utils % node ./lib/scripts/temp.js testnet
Result:  {
  latestLedger: '2537938',
  entries: [
    {
      lastModifiedLedgerSeq: '2535782',
      key: [ChildUnion],
      val: [ChildUnion],
      expirationLedgerSeq: 2777702
    }
  ]
}
wheat mortar
#

You can try migrating to stellar sdk but lets tell @vivid dragon also

vivid dragon
#

lol wtf - that's so weird

#

it implies that the returned val is not an ExpirationEntry but there's a very explicit check beforehand that the key is a LedgerKeyExpiration 😕

wheat mortar
#

Yep

weary coral
#

the code snippet above should be everything needed to reproduce, FWIW.

wheat mortar
#

I was just looking at the commits briefly but i dont see what would cause it. Can check again later when more time

#

Can u test it with stellar-sdk @ latest?

weary coral
vivid dragon
#

trying to repro locally. can you try beta.4, first? should be easier than porting to the sdk right now (but you should do that, btw)

weary coral
#

The error was on beta.4

vivid dragon
#

oh you said beta.2

#

oh wait nvm

#

reading comprehension 🤦

#

what's the soroban rpc testnet url again 🙈

weary coral
#

confusingly different than futurenet, lol -> https://soroban-testnet.stellar.org

vivid dragon
#

lol yeah I remembered it was diff but not what it actually changed, ty!

#

ok I repro'd on third try

#

wtf it's a contract data entry

#

this makes no sense

weary coral
#

Tested with "stellar-sdk": "11.0.0-beta.6" and am getting the same results

#

My guess would be some race condition between loading the expirationLedgerSeq and the contract data entry? Maybe the expiration is null in the failure case? not sure what else would make it fail randomly

vivid dragon
#

bless up, thanks for checking that

#

(btw you should port to stellar-sdk permanently when you have time lol, soroban-client is gonna be deprecated)

#

(but that's an aside)

weary coral
vivid dragon
wheat mortar
#

Maybe theres an await missing

#

I just dont see any errors in the diff but maybe im not looking hard enough

#

Or ya lack of null handling but i dont see any handlers in the old not in the new

vivid dragon
#

nah - the workaround we did was basically "insert lookups for the corresponding expiration key for each ledger key when you call getLedgerEntries, then inject the resulting expiration into the response as if it was alongside the original key"

wheat mortar
#

Ah

vivid dragon
#

the fact that it's returning a contractdatanetry instead of an expirationentry is pure bizarro world

wheat mortar
#

Do update to release beta 12 :laughing

vivid dragon
#

point is this should never happen

wheat mortar
#

Interesting. Well looks like a fun problem to solve. I envy you?

#

Is that the pr where the error started?

vivid dragon
#

well that's the PR that adds expiration info to getLedgerEntries requests

#

btw @weary coral there's a Server.getContractData so you don't have to build the entry yourself

#

(again an aside but just wanted to point it out)

weary coral
#

Yeah I saw that, I like the getLedgerEntries as it lets me fetch a bunch of things in one rpc call.

wheat mortar
#

Would it work to get ledger entries with the preflight and using a getter and then in simulation it will look up the key? Not on topic sorry

weary coral
#

I don't expose any "frontend" getters on the pool to minimize the contract size, so some of this information is only accessible via directly reading contract entries.

wheat mortar
#

Makes sense. But i struggle to figure out how to retrieve the key and the value in a single call?

#

Ill look at your repo probably has an example. Ive gotten so much help from your code you dont even know

vivid dragon
#

whelp I'm almost certain this is an rpc bug

#

there appear to be instances in which key.type != val.type when there are multiple keys requested

#

yep, confirmed

wheat mortar
#

Ordering issue?

vivid dragon
#

I think rpc assumes entries are returned in the same order they're requested

wheat mortar
#

We were discussing an ordering issue with scmaps the other day and them not matching the lexical ordering of scval.maps

#

I dont have a clue if it could be related bht just something thst popped in my mind

vivid dragon
#

nah that's def unrelated here

weary coral
vivid dragon
#

yeah I mean that would be ideal but that may be beyond the RPCs control

#

this is an actual bug where the val belongs to a different key

wheat mortar
#

Did u make an issue for this bug mootz

craggy zodiac
vivid dragon
#

sure! we'll write something more formal up but the basic idea is that many stellar apps need both horizon and soroban rpc, especially if they've been around since before protocol 20. so stellar-sdk will have everything you need to use the network. of course, if you just need soroban rpc, you'll still be able to use just those pieces. so this shouldn't affect anyone negatively (besides the small amount of effort needed to adapt your imports)

#

having them in separate places causes bloated, incompatible codebases for people who use both parts as well as confusion about why certain things are available in some places but not others

craggy zodiac
#

It's a reasonable decision. Thank you for the explanation @vivid dragon

weary coral
wheat mortar