#Proper way to sendTransaction for read-only ("view") method?

37 messages · Page 1 of 1 (latest)

dense plover
#

I'm using js-soroban-client. This code for simulating a transaction works:

let tx = new SorobanClient.TransactionBuilder(account, {
  fee: fee.toString(10),
  networkPassphrase: NETWORK_PASSPHRASE,
})
  .addOperation(contract.call(method, ...args))
  .setTimeout(SorobanClient.TimeoutInfinite)
  .build()

const simulated = await Server.simulateTransaction(tx)

Then I can successfully check if simulated.results?.[0]?.auth exists and, if so, sign the transaction with Freighter, re-construct it, and use sendTransaction to send it.

But if I just try to sendTransaction instead, in order to have up-to-date information rather than just the stale info returned by simulate, it fails. Here's the code I try:

tx = SorobanClient.assembleTransaction(tx, NETWORK_PASSPHRASE, simulated) as Tx
const sendTransactionResponse = await Server.sendTransaction(tx)

As when example, when using this to call the symbol method of my fungible token, the simulated.results include xdr AAAADQAAAARBQk5E, which decodes as the scvBytes for ABND.

The sendTransactionResponse returns a status: ERROR with errorResultXdr of AAAAAAAAlSH////6AAAAAA==, which decodes in Stellar Laborator as a TransactionResult with result: [txBadAuth] (https://laboratory.stellar.org/#xdr-viewer?input=AAAAAAAAlSH%2F%2F%2F%2F6AAAAAA%3D%3D&type=TransactionResult&network=futurenet)

Why does it say that it has bad auth, when the method I'm calling doesn't require a signature? What's the correct way to assemble this transaction?

sage sedge
#

tx bad auth means that tx auth check failed. I don't think this would even get accepted by the node

#

probably wrong tx signature or seq num

#

do you actually sign the tx?

latent stump
#

yeah signing the tx (tx.sign(...keypairs...)) and contract auth tree is separate

dense plover
sage sedge
#

any stellar transaction requires a signature

#

you still have to pay fees

dense plover
#

even for "view" calls?

sage sedge
#

sure

#

FWIW we probably could reject txs without RW footprint, but someone could just add a dummy entry there, so maybe there isn't much point in doing so

#

sending transactions is not the right thing to do to get fresh data; you should probably spin up your own core instance instead

#

transactions are there to modify the ledger state

dense plover
#

ok, I was under the impression from a previous conversation that relying on the data from the simulateTransaction was the wrong thing to do, and that I should probably send the actual transaction, even for view calls

#

but this conversation is making me think that's wrong. an app has to make a lot of view calls just to render, and popping Freighter for every single one of those would be terrible ux

#

better to have slightly stale data!

#

requiring app developers to spin up their own core instance just to get fresh data in unsigned view calls can't be the actual recommendation here?

sage sedge
#

not necessarily, there could be a service that does that for you

restive pendant
#

How stale is the data?

sage sedge
#

IIUC block explorers do that

dense plover
#

pushing developers toward centralized freemium services for data that could be served fresh from RPC endpoints also seems suboptimal

sage sedge
#

you also can read ledger entries directly from soroban-rpc

#

blockchain is not a database. core nodes can process just 1000 ops per ledger (much less so for soroban) and we don't really want to waste resources for things that can be done via traditional dbs

#

in terms of staleness, I believe the preflight snapshot is just a couple minutes old

#

FWIW we're in a similar situation with horizon anyway. you either use someone else's instance or spin up your own. the same will probably true for soroban rpc. IIUC either one needs to run a core instance.the only difference for soroban is really that in a general case a contract has to be invoked to get the view data. it is normally faster to just read the entry, so if you know the entry format, you'd rather want to read it directly

dense plover
#

What's the RPC method to read ledger entries directly?

fickle mesa
dense plover
#

Thanks!

umbral kestrel
umbral kestrel
# dense plover What's the RPC method to read ledger entries directly?

As a rule of thumb I think we should prefer demonstrating the usage of view functions in simulateTransaction over reading ledger entries directly. Reading ledger entries directly implies making assumptions on the implementation of a contract. This is usually ok when it's the same dev but if you're consuming someone else's code this can break in weird ways

dense plover
#

However, at the current scale of the network, this doesn't seem to be a real problem. I think down the road we may want the js lib generated with soroban contract bindings ts to provide interfaces to getLedgerEntries. But maybe by the time this becomes a real problem we will have other tools we can use, such as lazy VMs that run in the browser and pull in a specific contract's data as needed.

Thanks all!

jade hamlet
# dense plover better to have slightly stale data!

We should probably rephrase that doc. The preflight data is no more or less guaranteed to be stale than data from literally any other source. Stellar is (in some ways) an eventually-consistent database. Network-lag might mean that even if you run your own core, the data you would see is "stale" for a few milliseconds.
(afaik)

#

Also, preflight uses the same data-source as getLedgerEntries, so...