Repository navigation
[feat]: optional receiver on swap and swap2 - #121
Open
seekdaseek wants to merge 1 commit into
Open
seekdaseek wants to merge 1 commit into
seekdaseek wants to merge 1 commit into
Conversation
The output goes to the receiver's associated token account; the input still comes from the owner, who still signs. Without receiver the transaction is unchanged.
seekdaseek
added a commit
to seekdaseek/nuntius
that referenced
this pull request
Oct 6, 2026
…c-bonding-curve-sdk#121) The receiver gap in both SDKs, checked in DBC main and cp-amm 1.5.1 as shipped, with the two mainnet buys that use it; the keeper table's "matches"; no event for the migration itself; web3.js v1 under the SDKs; and the smaller things we hit.
This was referenced Oct 10, 2026
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.
Summary
swap,swap2andswap2WithTransferHookderive both token accounts forowner, so a swap can only deliver to the wallet that pays. The program itself has no such limit: the swap accounts take anyoutput_token_accountfor the output mint, and the first-buy builders already expose this asreceiver.We use it on mainnet. nuntius (a Seeker app for recurring, capped backing of DBC launches) runs one transaction per period: a capped pull from the backer through the Solana Subscriptions program, then a DBC swap whose output goes straight to the backer's own token account, with nuntius's executor signing and holding nothing. Because the SDK cannot express that swap, we build the instruction by hand. Example, 6 Oct 2026: https://explorer.solana.com/tx/383VkA2U1MGPb5rkGSv6AWdq1u9HoG6NDZDcdC5d3p5gEiq1MYb6doqWAicDrRyUpz1Y722mDTUD1Ddb8A5X5Fdf
Changes
SwapParamsandSwap2Paramstake an optionalreceiver?: PublicKey. When set, the output account is the receiver's associated token account, created bypayer(orowner) if missing. The input account and the signer stayowner; the receiver does not sign.prepareTokenAccountstakes an optional owner for the token B account. Its other caller is unchanged.owner, the receiver keeps wrapped SOL, because closing its account would need its signature. The owner's own wrapped SOL is still closed when SOL is the input.receiver(or withreceiverequal toowner) the built transaction is the same as before: same accounts, same pre and post instructions.Tests
tests/swapReceiver.test.ts, on the local validator with the repository's fixtures:swapexact-in with a receiver: the receiver's base account holds the output, the owner has no base account, the receiver holds no SOL and only the owner signed.swap2exact-in, the same.swap2exact-out: the receiver gets exactlyamountOut.swap2selling base for SOL with a receiver: the owner's base balance drops by the amount in, the receiver's wrapped SOL account holds the output, and the transaction succeeds without the owner having a wrapped SOL account.Controls:
main(a28b723): the output goes to the owner.receiverin place but the old unwrap rule, the sell test fails withInvalidAccountDataon the close instruction, because the owner's wrapped SOL account does not exist.Validation at a28b723 plus this commit, pnpm 11.3.0 and the frozen lockfile (Node 24.16 locally; CI pins 22.13):
pnpm -w run check-types: passedpnpm -w run lint: passed; the one warning is in unchangedbuildCurve.tspnpm -w run format:check: passedpnpm build: passed#117 reworks the client and public API. If it lands first, I am glad to rebase this onto it.