Repository navigation
Fix Solana sponsored sends against the supported RPC surface - #341
Merged
joalavedra merged 3 commits intoSep 15, 2026
Merged
joalavedra merged 3 commits into
joalavedra merged 3 commits into
Conversation
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.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
commit: |
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
deleted the
centaur/fix-solana-sponsored-send-removed-rpc-method-1789400244
branch
September 15, 2026 16:22
Merged
This was referenced Sep 16, 2026
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What broke
walletConfig.solana.sponsorFeesroutes a send throughsendViaKora, which asked the paymaster to build the transfer with Kora'stransferTransactionmethod. The Openfort Solana RPC endpoint stopped routing that method ind1bd249(api, 2026-06-22), two days after the sponsored path shipped in #285. Every sponsored Solana send since then fails before broadcast: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) plustransferChecked. Kora remains the fee payer, the user's signature is injected the same way as before, and submission goes throughsignAndSendTransaction— 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: booleanhad no way to name the mint. The payment is quoted withgetPaymentInstructionand appended to the transfer.sponsorFees: trueis unchanged and still means the project pays.Replaces the paymaster-response guard.
assertKoraInstructionsAreExpectedexisted becausetransferTransactionreturned instructions the user would then sign blind. Those instructions are now built here, so the guard has nothing left to check.assertKoraPaymentIsExpectedtakes 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.sendSplTokenGaslessnow takesdecimals, whichtransferCheckedrequires. Both are internal to the package; no public export changed except the newSolanaFeeSponsorshiptype.Dropping the marshalling through Kora's JS-number
amountalso removes theMAX_SAFE_INTEGERceiling that sponsored SPL transfers used to hit.Verification
pnpm check,check:types,test:types(896 tests), the unit suite (877 tests),build,sizeandbuild:docsall pass.New tests in
transfer.test.tspin the behaviour that regressed: the sponsored path must not calltransferTransaction, must submit throughsignAndSendTransaction, must append the quoted fee payment when afeeTokenis 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/signAndSendTransactionworks — which is the path this change adopts.Prompted by: Joan Alavedra