Client SDKs
Typed TypeScript and Rust clients for the Rewind API, with helpers for the common workflows.
Rewind ships two thin, typed clients. Both expose one method per RPC method, typed params and results, a typed error carrying the JSON-RPC code and data, and the same set of helpers on top. You can always call the JSON-RPC API directly — the SDKs add no server-side behaviour — but they remove the boilerplate around cursors, anchors, chunking and retries.
npm
TypeScript
Node 18+ or any browser with fetch. Zero runtime dependencies.
Install
TypeScript
npm install @solanavibestation/rewindRust
[dependencies]
svs-rewind = "0.3"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
# Optional: decode base64+zstd account data
# svs-rewind = { version = "0.3", features = ["zstd"] }Create a client
Point the client at https://rewind.solanavibestation.com and pass your API key. The key is sent as the Authorization header — the same scheme as every other SVS endpoint.
TypeScript
import { RewindClient } from "@solanavibestation/rewind";
const rewind = new RewindClient("https://rewind.solanavibestation.com", {
apiKey: process.env.SVS_API_KEY,
timeoutMs: 30_000, // default 30 s
});Other options: fetch (custom implementation — useful in older Node or test harnesses), retry (see Retry policy), apiKeyHeader (only if you need something other than Authorization).
Rust
Other builders: .with_http(reqwest::Client) to supply your own HTTP client (timeouts, proxies, connection pooling), .with_retry(RetryPolicy) (see Retry policy), .with_api_key_header(name, key) if you need a header other than Authorization.
Methods
Every RPC method has a one-to-one typed wrapper. Results keep the same shape the wire returns ({ context, value }) except where noted.
getHistoricalAccountInfo
rewind.getHistoricalAccountInfo(pubkey, config)
client.get_historical_account_info(pubkey, &cfg)
getMultipleHistoricalAccounts
rewind.getMultipleHistoricalAccounts(pubkeys, config)
client.get_multiple_historical_accounts(&pubkeys, &cfg)
getAccountChanges
rewind.getAccountChanges(pubkey, config)
client.get_account_changes(pubkey, &cfg)
getAccountDiff
rewind.getAccountDiff(pubkey, config)
client.get_account_diff(pubkey, &cfg)
getRewindCoverage
rewind.getRewindCoverage(config?)
client.get_rewind_coverage(&cfg)
getHistoricalFeatureSet
rewind.getHistoricalFeatureSet(slot, includeInactive?) → returns value directly
client.get_historical_feature_set(slot, include_inactive) → returns FeatureSet directly
simulateHistoricalTransaction
rewind.simulateHistoricalTransaction(txBase64, config)
client.simulate_historical_transaction(tx_b64, &cfg)
getHealth
rewind.getHealth() → resolves when healthy, throws otherwise
client.get_health() → Ok(()) when healthy
There is also an escape hatch — rewind.call(method, params) / client.call(method, params) — which sends any method with the retry policy applied. The typed wrappers are built on it.
Positioning
The three positioning modes from the overview map onto the SDKs like this:
TypeScript
Config objects are plain literals — the same JSON you'd send on the wire, with types.
Rust
Positions are an enum; ReadConfig::at(position) builds a read config you can chain options onto.
Other chainable options: .data_slice(offset, length), .tolerate_gaps(true).
For the other methods: ChangesConfig::range(from, to), DiffConfig::between(a, b) / DiffConfig::around_transaction(sig), SimulateConfig::at_slot(n) / SimulateConfig::around_transaction(sig, after). Remaining fields on each config struct are public and named after their wire counterparts (limit, include_data, inner_instructions, account_overrides, …).
Helpers
Both SDKs ship the same six helpers. They compose the raw calls; nothing here needs server support.
1. Change walker
Pages through getAccountChanges for you, handling the next cursor and collecting gaps as it goes.
TypeScript
Rust
2. Transaction view
"What did this transaction do to this account?" — before/after state plus the structural diff, in one call. The many-account variant makes two getMultipleHistoricalAccounts calls sharing the anchor.
TypeScript
Rust
3. Coverage guard
Classify a slot offline before spending a request on it. Fetches getRewindCoverage once and refreshes on a timer; classify returns one of answerable, aboveTip (-32014), belowFloor (-32015), inGap (-32018, with the gap), or unknown.
The result is advisory — a gap can appear between refreshes — so still handle -32018 on the actual call.
TypeScript
Rust
4. Batch reader
Read any number of accounts at one position. Chunks to the server's 100-account limit, runs chunks concurrently, and — when a chunk comes back truncatedByBytes — resubmits the unattempted tail with a halved chunk size. Results are in request order.
TypeScript
Rust
5. Data decoding
Turn the [encoded, encoding] data pair into bytes. base64 and base58 are built in; base64+zstd needs a zstd decoder (pass one in TypeScript; enable the zstd feature in Rust).
TypeScript
Rust
6. Retry policy
Off by default. When enabled: transport errors and -32603 retry with exponential backoff and jitter; -32018 retries with a fixed delay (the archive's healer debounces for ~15 s, so 15–30 s is sensible). The policy never retries -32602, -32014, -32015, -32016 or -32017 — those won't change on retry.
TypeScript
Rust
Error handling
JSON-RPC errors surface as a typed error carrying the code, message and any structured data (for example the gap bounds on -32018). Transport failures surface separately.
TypeScript
Rust
The full code table is in the overview.
Compatibility
Account results are wire-compatible supersets of Solana's
AccountInfo.toWeb3AccountInfo(TypeScript) converts one for@solana/web3.js; in Rust,HistoricalAccounthas the same fields plusrewind_slot/rewind_write_version.SDK versions track the API: the
0.3.xline targetsrewind-0.4.context.apiVersionon every response tells you what the server is running.Both SDKs are Apache-2.0. Source lives alongside the service; issues and feature requests go through the SVS team via Discord or your customer portal.
Last updated