Skip to content

fix(signer): bound unbounded fetch calls with 30s AbortSignal.timeout - #2572

Open
hermiondev wants to merge 1 commit into
alchemyplatform:v4.x.xfrom
hermiondev:fix/v4-signer-timeout
Open

hermiondev wants to merge 1 commit into
alchemyplatform:v4.x.xfrom
hermiondev:fix/v4-signer-timeout

Conversation

@hermiondev

@hermiondev hermiondev commented Sep 27, 2026 •

Copy link
Copy Markdown

Problem

Two production fetch sites in the shipped, actively-released @account-kit/signer (v4.x.x line, latest publish 4.88.5 on 2026-08-11) have no timeout and no AbortSignal:

  1. account-kit/signer/src/client/base.ts — BaseSignerClient.request(): every signer API POST (signup, sign-payload, session/MFA routes) to api.g.alchemy.com hangs forever if the endpoint accepts the connection but stalls.
  2. account-kit/signer/src/utils/solana.ts — createSolanaSponsoredTransaction(): the alchemy_requestFeePayer RPC hangs transaction construction forever on a stalled RPC.

This is the same defect class already reported/fixed for the v5 REST client in #2571; the v4 signer surface was missed.

Reproduction

Node 20/24 against a stall server (accept socket, never reply), replicating the exact call shape from the published dist/esm/client/base.js:845:

  • Unfixed shape: promise never settles past an 8s watchdog (hang).
  • Patched shape: TimeoutError at ~3001ms (3s demo value; PR uses 30s).

Fix

Attach AbortSignal.timeout(30_000) at both sites, feature-detected so runtimes without AbortSignal.timeout (older browsers / React Native) keep previous behavior rather than crashing.

Validation

  • tsc package build (build:esm + build:types): 0 errors on the patched tree (node@20/24, yarn 1.22.22, frozen lockfile).
  • prettier --check clean after formatting.
  • vitest suite in this workspace fails identically before and after the change (util.isString in shared .vitest/setupTests.ts — pre-existing environment breakage, unrelated to this diff; verified via git stash A/B).

Static scan note: my fetch-boundary scanner still flags the solana.ts site as REVIEW because the signal is threaded through the local options object (config-indirect) rather than inline — the runtime probe above is the ground truth.


PR-Codex overview

This PR introduces timeout handling for fetch requests in the solana.ts and base.ts files, ensuring that stalled requests do not hang indefinitely. It implements a default timeout of 30 seconds for API requests, improving error handling for unresponsive endpoints.

Detailed summary

  • Added timeout handling for fetch requests in solana.ts to prevent indefinite hanging.
  • Introduced a constant SIGNER_REQUEST_TIMEOUT_MS in base.ts for default timeout duration (30 seconds).
  • Enhanced error handling for stalled requests in both solana.ts and base.ts using AbortSignal.timeout.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

BaseSignerClient.request (signer API POST) and createSolanaSponsoredTransaction
(fee-payer RPC) call fetch with no timeout or AbortSignal. A stalled
api.g.alchemy.com / RPC endpoint leaves these promises pending forever,
hanging auth flows and sponsored-transaction construction in the shipped
@account-kit/signer@4.88.5 artifact.

Both sites now attach AbortSignal.timeout(30000), feature-detected so
runtimes without it (older browsers/RN) keep the previous behavior.
Reproduced vs a stall server: unfixed shape hangs past 8s watchdog;
patched shape rejects TimeoutError at 30s.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant