feat(graphql): add transactions_by_digest - #1450
Conversation
Backed by `transactionsByDigests`, which — unlike the `transactionIds` filter of `transactionBlocks` — also covers transactions that are not checkpointed yet. The server pages that field, but the caller already bounds the result by the digests it passes, so the pages are walked internally and the digests come back as a map. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
For what are we adding this? |
|
Ok just because it's in the schema |
| TransactionBlocksQueryArgs, TransactionBlocksWithEffectsQuery, TransactionsByDigestsPage, | ||
| TransactionsByDigestsQuery, TransactionsByDigestsQueryArgs, TransactionsFilter, |
There was a problem hiding this comment.
Maybe more of a general question, but why are we making these part of the public API?
There was a problem hiding this comment.
So, the thing is a user can use these types to interact with graphql when using Client::run_query. Without them, the user would have to define these types themselves.
There was a problem hiding this comment.
And do they really need to interact with Client::run_query if we offer all the high lever APIs?
There was a problem hiding this comment.
Well, I don't know. But we added that fn so they could
| pub async fn transactions_by_digest( | ||
| &self, | ||
| digests: Vec<Arc<TransactionDigest>>, | ||
| ) -> Result<HashMap<Arc<TransactionDigest>, SignedTransaction>> { |
There was a problem hiding this comment.
Apparently, HashMap in return position like that is unusable in Go and TS
There was a problem hiding this comment.
Hmm, do you know what the alternative is?
There was a problem hiding this comment.
Probably just a Vector in the same order as the request
There was a problem hiding this comment.
that's a bummer
| nodes_seen += page.nodes.len(); | ||
| for node in page.nodes.into_iter().flatten() { | ||
| let transaction: SignedTransaction = node.try_into()?; | ||
| transactions.insert(transaction.transaction.digest(), transaction); |
There was a problem hiding this comment.
We already have the digests, order is kept, can we avoid recomputing them, it's actually quite heavy
There was a problem hiding this comment.
although I feel a bit uneasy trusting the server here
| let operation = TransactionsByDigestsQuery::build(TransactionsByDigestsQueryArgs { | ||
| digests: digest_strings.clone(), | ||
| limit, | ||
| cursor, | ||
| }); |
There was a problem hiding this comment.
What about chunking the request itself? What if I want to request more digests than the maximum body size allowed? Default payload size is 5000 bytes so header excluded, there wouldn't be any way to request more than ~90 digests
There was a problem hiding this comment.
I'm a little unclear about what the max length refers to. The doc comment says it's the length of the string, but is it actually byte length?
Adds a batched transaction fetch to the GraphQL client, backed by
transactionsByDigests.That field, unlike the
transactionIdsfilter oftransactionBlocks, also returns transactions that are not checkpointed yet. It is paged, but the caller already bounds the result by the digests it passes, so the pages are walked internally rather than handed back as aPage; a response that runs out of pages before every digest is accounted for is an error, so aHashMapshort of a key always means "not found".The test needs a localnet (
make test-with-localnet) and has not been run here.🤖 Generated with Claude Code