Skip to content

Fix Solana sponsored sends against the supported RPC surface - #341

Merged
joalavedra merged 3 commits into
mainfrom
centaur/fix-solana-sponsored-send-removed-rpc-method-1789400244
Sep 15, 2026
Merged

joalavedra merged 3 commits into
mainfrom
centaur/fix-solana-sponsored-send-removed-rpc-method-1789400244

Conversation

@condor-agent

Copy link
Copy Markdown

What broke

walletConfig.solana.sponsorFees routes a send through sendViaKora, which asked the paymaster to build the transfer with Kora's transferTransaction method. The Openfort Solana RPC endpoint stopped routing that method in d1bd249 (api, 2026-06-22), two days after the sponsored path shipped in #285. Every sponsored Solana send since then fails before broadcast:

RPC Error: Unknown method: transferTransaction.
Supported methods: getConfig, getPayerSigner, getSupportedTokens, getBlockhash,
estimateTransactionFee, signTransaction, signAndSendTransaction,
signAndSendTransactionWithoutConfirmation, estimateBundleFee, signAndSendBundle

This affects every project, on any sponsorship strategy. Unsponsored sends were never affected — they don't touch Kora.

What this does

Builds the transfer client-side. Native SOL through getTransferSolInstruction; SPL through an idempotent ATA creation (Kora pays the rent, as the fee payer) plus transferChecked. Kora remains the fee payer, the user's signature is injected the same way as before, and submission goes through signAndSendTransaction — all methods the endpoint routes.

Adds sponsorFees: { feeToken }. A gas sponsorship configured to charge the end user in an SPL token needs the user's transaction to carry the fee payment itself; sponsorFees: boolean had no way to name the mint. The payment is quoted with getPaymentInstruction and appended to the transfer. sponsorFees: true is unchanged and still means the project pays.

Replaces the paymaster-response guard. assertKoraInstructionsAreExpected existed because transferTransaction returned instructions the user would then sign blind. Those instructions are now built here, so the guard has nothing left to check. assertKoraPaymentIsExpected takes its place over the one value that is still the server's to decide — the fee payment — and refuses a payment instruction naming an account outside the fee transfer, a mint other than the one requested, or an unusable amount.

sendSplTokenGasless now takes decimals, which transferChecked requires. Both are internal to the package; no public export changed except the new SolanaFeeSponsorship type.

Dropping the marshalling through Kora's JS-number amount also removes the MAX_SAFE_INTEGER ceiling that sponsored SPL transfers used to hit.

Verification

pnpm check, check:types, test:types (896 tests), the unit suite (877 tests), build, size and build:docs all pass.

New tests in transfer.test.ts pin the behaviour that regressed: the sponsored path must not call transferTransaction, must submit through signAndSendTransaction, must append the quoted fee payment when a feeToken is configured, and must refuse a payment routed elsewhere. Per AGENTS.md the guard test was confirmed to fail with the guard removed.

Not covered: this has not been exercised against a live devnet paymaster from a browser. The RPC methods it now uses are the ones a customer's hand-rolled equivalent is already completing sends with in production, but a devnet smoke test through <OpenfortButton /> before release would be worth it.

Context

Reported by a customer on Solana devnet with a user-pays USDC sponsorship, whose own implementation against getPayerSigner / estimateTransactionFee / signAndSendTransaction works — which is the path this change adopts.

Prompted by: Joan Alavedra

The sponsored Send path asked the paymaster to build the transfer with
`transferTransaction`. The Openfort Solana RPC endpoint does not route that
method, so every send with `walletConfig.solana.sponsorFees` set failed
before broadcast with `Unknown method: transferTransaction`.

Build the transfer instructions client-side instead — native SOL through the
system program, SPL through an idempotent ATA creation plus `transferChecked`
— with Kora as the fee payer, and submit through `signAndSendTransaction`.

`sponsorFees` also accepts `{ feeToken }` now, for a gas sponsorship that
charges the end user in an SPL token rather than paying the fee for them. The
fee payment is quoted from the paymaster and appended to the transfer, and is
refused when it names an account outside that fee transfer.
@vercel

vercel Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
playground Ready Ready Preview Sep 15, 2026 4:15pm UTC

Request Review

@pkg-pr-new

pkg-pr-new Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@openfort/react@341

commit: c62ffed

Reattach the `SolanaConfig` JSDoc, which the new `SolanaFeeSponsorship`
type was inserted underneath, and give that type the runnable `@example`
AGENTS.md requires of anything exported from `src/index.ts`.

Replace the `unknown` message and the four `Parameters<...>` casts around
the Kora fee payment with the types the libraries already declare:
`@solana/kora` types `getPaymentInstruction` and returns a `@solana/kit`
instruction, so nothing here needs to be cast to reach it. The runtime
guard on the method stays — it is an optional peer on `^0.1.1 || ^0.2.0`
and the method only exists from 0.2.

Allowlist USDC's mainnet mint for gitleaks. It is a public on-chain
identifier, but high-entropy base58 beside the word "token" is what the
generic-api-key rule matches, so the doc example tripped the scan.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@joalavedra
joalavedra merged commit 4a1ffab into main Sep 15, 2026
19 checks passed
@joalavedra
joalavedra deleted the centaur/fix-solana-sponsored-send-removed-rpc-method-1789400244 branch September 15, 2026 16:22
@github-actions github-actions Bot mentioned this pull request Sep 15, 2026

This branch was successfully deployed

1 active deployment
Preview — c62ffed4 Deployed Sep 15, 2026 by vercel[bot]
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.

2 participants