Add getTransactionsForAddress to RPC API - #1776
Conversation
🦋 Changeset detectedLatest commit: b961e5a The changes in this PR will be included in the next version bump. This PR includes changesets to release 48 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
BundleMonFiles updated (4)
Unchanged files (146)
Total files change +224B +0.04% Final result: ✅ View report in BundleMon website ➡️ |
trevor-cortex
left a comment
There was a problem hiding this comment.
Summary
Adds GetTransactionsForAddressApi to @solana/rpc-api, exposing the new method that combines getSignaturesForAddress-style address-history discovery with getTransaction-style per-transaction fetching, plus server-side filtering, bidirectional sorting, and cursor-based pagination. As part of the change, the shared transaction-meta types (TransactionMetaBase, TransactionJson/TransactionJsonParsed, inner-instruction/loaded-address shapes, etc.) move out of getTransaction.ts into a new transaction-meta.ts module so they can be reused by both methods, and an optional meta.costUnits: bigint field is added — which now also surfaces on getTransaction.
The extraction itself is mechanical and looks clean: the moved types are byte-identical to the originals, just re-exported (now public types in transaction-meta.ts) and re-imported by getTransaction.ts. Index wiring (SolanaRpcApiForAllClusters, exports, numeric-keypath entries) is consistent with the existing patterns for getTransaction and getSignaturesForAddress.
Things to watch out for
versionis not surfaced on full-mode responses. ComparegetTransaction, which conditionally addsversion: TransactionVersionwhenmaxSupportedTransactionVersionis set. The full-mode return types here omit it entirely, even though the underlying response per the spec/Helius/Triton docs includesversionfor versioned transactions. Worth confirming whether this was intentional or an oversight — see inline comment.OptionalTransactionAddressTableLookupsandPartial<TransactionMetaLoadedAddresses>are always-optional, regardless ofmaxSupportedTransactionVersion.getTransactionkeys these off the type parameter (required when versioned, absent when legacy-only). This PR takes a more permissive stance — the fields are always optional. Defensible, but worth flagging as a deliberate divergence from thegetTransactionmodeling.limitdefault doc may be incomplete. Helius docs note a cap of 100 fortransactionDetails: 'full'vs 1000 for signatures. The JSDoc currently states a single 1000 cap. If providers cap full-mode lower, callers may be surprised.- Overload resolution for invalid combinations. The overloads correctly require
transactionDetails: 'full'whenencodingis one of the full encodings, but there's no typetest covering what happens if a caller passes{ encoding: 'jsonParsed' }withouttransactionDetails. Excess-property checks should catch this on object literals, but a@ts-expect-errortest would lock the behavior in. - No runtime tests.
getTransactionhas all-it.todotests too, so this is the established pattern in this package — coverage is provided by the typetest. Calling that out so subsequent reviewers don't go looking for unit tests.
Notes for subsequent reviewers
- The
transaction-meta.tsextraction makes previously-private types part of the package's public surface (they're not exported fromindex.ts, but the module is now importable from the package by virtue of being a non-private.tsfile). That's not necessarily wrong, but worth being aware of — any future changes to these shapes are now potentially observable. - The
costUnitsfield addition is a soft user-visible change ongetTransactiontoo. The changeset (correctly) calls this out and the bump level isminor, which is appropriate. - Allowed-numeric-keypath entries for
getTransactionsForAddressare a straight port of thegetTransactionentries with a['data', KEYPATH_WILDCARD, ...]prefix — looks correct given the response envelope shape. - Worth a second pair of eyes on the spec mapping (filters, sortOrder enum, status enum values, paginationToken semantics) against the superbank source-of-truth linked in the PR description, since that's the canonical reference and providers differ in the details they document.
|
Missing
// getTransaction.ts
(TMaxSupportedTransactionVersion extends void
? Record<string, never>
: { version: TransactionVersion })The Helius/Triton/superbank docs all show (Anchoring here on |
|
Documentation Preview: https://kit-docs-hzpyks5xq-anza-tech.vercel.app |
|
Excluding version was intentional because that's the current behaviour of Superbank and the Triton docs don't mention it, but Helius does include it. I've opened a PR to add it to Superbank: solana-rpc/superbank#20 If that gets merged then we can add the |
e3b3ddd to
37bd1f2
Compare
|
Updated after solana-rpc/superbank#20 was merged, we now include Please re-review this PR @trevor-cortex |
trevor-cortex
left a comment
There was a problem hiding this comment.
Re-review — LGTM (posting as COMMENT since I can't APPROVE without repo access).
The main open point from my prior pass was that version (and the other version-gated fields) needed to be conditional on maxSupportedTransactionVersion. That's now modelled correctly:
- Each
fullencoding has a paired legacy / version-specified overload. The version-specified overloads intersect inGetTransactionsForAddressVersion(version: TransactionVersion),TransactionMetaLoadedAddresses, andTransactionAddressTableLookups; the legacy overloads omit all three. - The typetest asserts the presence/absence in both directions with
@ts-expect-erroronversion,addressTableLookups, andmeta.loadedAddressesfor each ofjson/jsonParsed/base58/base64. Nice coverage. - The
signaturesoverload sits last and correctly rejectsencodingandprocessedcommitment via the negative tests.
Other things I re-checked and am happy with:
limitcaps are now documented (1000 signatures / 100 full).paginationTokenformat is documented as"<slot>:<position>", matching the example in the typetest.- Response envelope (
{ data, paginationToken }) is intentionally bare (notcontext/value), and the typetest calls that out explicitly. transaction-meta.tsextraction is internal only — none of those types are re-exported frompackages/rpc-api/src/index.ts, so the public surface remains justGetTransactionsForAddressApi. Good call keeping them un-exported.- Keypath registration for
getTransactionsForAddressmirrorsgetTransaction's exactly (transposed under['data', KEYPATH_WILDCARD, ...]) and additionally coverstransactionIndex, which is the non-obvious one. meta.costUnitsongetTransactionis optional, so it's a non-breaking widening. Flagged in the changeset — good.Exclude<TransactionVersion, 'legacy'>formaxSupportedTransactionVersionis a nice constraint that lines up with the existinggetTransactionsemantics ("set to0to include version-0").
Two very small things, none blocking:
getTransactionuses a genericTMaxSupportedTransactionVersionparameter with conditional types;getTransactionsForAddressdoubles the overloads (legacy + version-specified) with concrete configs. Both work — the doubled form gives clearer per-case JSDoc, so I don't think it's worth changing, but it does mean the two files now diverge in style. Worth being aware of if a third method ever wants to pick a house pattern.minContextSlotis in the common config but I didn't verify against the superbank source-of-truth that it's actually a supported knob for this method (the linked Triton/Helius docs don't mention it either way). Worth a quick sanity check before merge, but low risk — extra fields are typically ignored server-side.
Happy to see this go in. Nice work on the version modelling and the typetest expansion — the negative assertions make the intent unambiguous.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
Confirmed that |
|
Because there has been no activity on this PR for 14 days since it was merged, it has been automatically locked. Please open a new issue if it requires a follow up. |

Problem
It's not part of the JSON-RPC spec, but most major RPC providers have
getTransactionsForAddress. The types are complex and annoying to use without a Kit helper.Summary of Changes
This PR adds
getTransactionsForAddressto the Kit RPC.While this isn't part of the current spec or the Agave RPC, it's part of the new RPC spec and is already widely supported.
The refactor pulls the shared types from
getTransaction.Also added
meta.costUnits: bigintto bothgetTransactionandgetTransactionsForAddress, see https://solana.com/docs/rpc/http/gettransactionSee: