Depending on the item price in USD, users should be able to pay for items with different tokens/currencies (this is made possible with Switchboard Oracles). The payments then go towards a program-owned TreasuryAccount.

For regular tokens, I just send from the buyerTokenAccount to the corresponding treasuryTokenAccount.

For SOL payments, it becomes a bit more troublesome. Let us say an item has an USD cost that is equivalent to 1 SOL.

  1. CASE 1: I can create a buyerTokenAccount for WSOL, then transfer 1 SOL to that account. Now I can transfer from the WSOL buyerTokenAccount to the WSOL treasuryTokenAccount. Although, the issue arises when I have to instantiate the WSOL buyerTokenAccount, since the initial 1 SOL transfer is predetermined and is not subject to change. Whereas the solana program will report a changing price due to the use of an oracle. E.g. it can cost 0.99 SOL or 1.01 SOL. For the former: enter image description here, for the latter: simulation will report "insufficient tokens" and the Tx will fail.

  2. CASE 2: Alternatively, I have done special handling of SOL. If the user wants to make payments with SOL, I just do a regular system transfer (as opposed to token transfer) of 1 SOL directly to the TreasuryAccount address.


  1. Is there a good way to handle multiple tokens + SOL (not WSOL)?

  2. Is it bad practice to store SOL at the account address as per CASE 2? I can see that it would perhaps be an issue since, if you wanted to transfer out the SOL, you might accidentally transfer out the account rent fees as well, thus end up closing the account?

1 Answer 1


You should always use wrapped SOL for these kinds of situations. It's wrapped so it acts like an spl token so you inherit a common interface. You could handle all the wrapping logic client side if you wanted to simplify the on-chain logic. And if the user needs to create a new wsol token account, then you could have them attach 1.002 (dont know exact rentExemption), deposit 0.002 rentExemption, create wsol account, wrap funds, transfer funds, close token account and recoup rent so they only see a net difference of 1 SOL.

The new Switchboard SDK has a useful class for this

import { NativeMint } from "@switchboard-xyz/solana.js";
const mint = NativeMint.load(provider);
const [tokenAddress, wrapSolTxn] = await mint.getOrCreateWrappedUserInstructions({ fundUpTo: 1 });
// add the rest of your program txns to txn object
wrapSolTxn.add(newIxn, []);
const signature = await wrapSolTxn.signAndSend(provider);

Source: https://docs.switchboard.xyz/api/@switchboard-xyz/solana.js/classes/NativeMint.html

As for the fluctuating oracle price, it is normal to have transactions pass simulation but fail on-chain and vice versa. You can use skipPreFlight to skip simulation for these kind of scenarios. Or catch a specific error after simulation and re-send with skipPreFlight enabled.

Do NOT use the program address as a wallet. It's only meant to hold rent exemption and will just introduce added complexity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.