Direct Solana Payments for MedusaJS: Now in Public Beta!
What if your webshop could accept peer-to-peer payments using a simple npm package running on your own server? No third-party processors, no intermediaries. TLDR; this article guides you through setting it up using the Solana blockchain in MedusaJS.

If you are curious about how the module works under the hood, why I decided to go down this rabbit hole, and all the design decisions that went into it, please read my earlier article, which dives much deeper into the payment module’s architecture with a supporting sequence diagram. This article will focus on getting a MedusaJS webshop up and running with Solana checkout. If you don’t already know what MedusaJS is, you can read about it here.
Thanks to all the closed beta testers
In the previous article, I offered early access to anyone interested. A total of four individual developers and teams reached out and were granted access. Thank you to all of you who took the time to discuss design choices, share ideas, and provide valuable feedback.
Official release
How to setup, step by step.
To make your life easy, we are going to deploy a fully preconfigured MedusaJS boilerplate on Railway. This template has been maintained by me for over a year and is loved by many. It will get you a fully operational webshop in just a few minutes. Once deployed, you’ll need to take a few steps to switch to a branch where the Solana payment module is integrated.
If you already have a MedusaJS webshop or want to test the module locally instead of on Railway, this guide is a start-from-nothing setup and may not cover all details. However, it can still serve as a useful reference alongside the module’s README if you are familiar with the Medusa ecosystem.
Video instructions
Step 1: Deploy Medusa 2.0 Template on Railway
You will need a GitHub account, and a Railway account with at least the hobby user tier (5$/month). If you don't already have a Railway user, make you to "sign up with GitHub" this will link your user accounts which is required in next step.
Click the button above to deploy the standard MedusaJS 2.0 webshop starter. You do not need to configure any of the services, just click deploy and wait for the build to finish - this should take 5-10 minutes.
Step 2: Eject from source repo, to your own fork
On your Railway project canvas, select the "Backend" service with the purple MedusaJS logo. Once selected, go to the "Settings" tab in the right menu. On the settings page, under "Upstream repo," find the red "Eject" button and click it. A pop-up will appear showing your GitHub username.
If you don't see your GitHub user, your accounts are not correctly linked. In that case, click your user avatar in the top right corner, go to "Account Settings," scroll down to "Account Integrations," and connect your GitHub account. Then return to your project and click the eject button again.
Select your GitHub user in the pop-up window to start the ejection process. This will take a few seconds and will eject both the Backend and the Storefront from the official boilerplate repo, creating a fork under your GitHub account and connecting both services to your fork.
Step 3: Add the solana-pay Branch to Your Fork
While still on the Settings page of the Backend service, note that the "Source repo" now points to your fork. Click it to go to your new repository.
You need to clone this repository to your local machine to add the solana-pay branch. At least, I couldn't find another way to do it. Run the following git commands to add the branch to your fork:
git clone <your forked repo URL>
cd medusajs-2.0-for-railway-boilerplate/
git remote add upstream https://github.com/rpuls/medusajs-2.0-for-railway-boilerplate.git
git fetch upstream
git checkout -b solana-pay upstream/solana-pay
git push origin solana-pay
Once pushed, you should see the solana-pay branch on your repo after refreshing the page. Don't close the terminal just yet, you will need it again very soon.
Step 4: Switch Branch on Railway
Now that your forked repo contains the solana-pay branch, you can point your Railway services (Backend and Storefront) to this branch.
Switch back to the Railway dashboard and refresh your browser to fetch the new branch. While still on the Backend Settings page, scroll down to the "Branch connected to production" dropdown and switch it from "main" to "solana-pay." Repeat this for the Storefront service.
This will trigger indicators showing two changes and prompt you to deploy those changes, do not deploy yet. A few more changes need to be made before deploying anything.
Step 5: Backend Environment Variables
The payment module requires a few environment variables that you need to configure. Below is a template for the variables, but you must replace the placeholders with your own values. This section will explain how to obtain each value.
SOLANA_RPC_URL=https://api.devnet.solana.com
SOLANA_MNEMONIC="word word word word word word word word word word word word word word word word word word word word"
SOLANA_COLD_STORAGE_WALLET=<a valid solana devnet wallet address>
COINGECK_API_KEY=<your coingecko api key for currency conversion>
It is highly recommended to start on devnet while testing. The SOLANA_RPC_URL
value above points to devnet and can be changed later to connect to mainnet when ready.
For SOLANA_MNEMONIC
, this is your 20-word passphrase used to generate one-time wallets for each transaction. It must remain private and secure because it is also used to sign transactions when moving funds to your cold storage wallet. If you don’t know how to generate a passphrase, the module includes a script to do so. Remember when you were told not to close the terminal at the end of Step 3? Now switch to that terminal and run:
cd backend/
npm install
node node_modules/medusa-payment-solana/dist/script/generatePassPhrase.js
This will generate a unique 20-word passphrase for you.
For SOLANA_COLD_STORAGE_WALLET
, use a valid wallet address on the Solana devnet. Phantom is a commonly used wallet for devnet if you need a recommendation. Use the address of your secure wallet where you want to receive the funds.
To convert currency from EUR or USD to SOL, the module relies on a real-time currency conversion API, currently supported only via Coingecko. To get your own COINGECK_API_KEY
, you can ask ChatGPT how to obtain an API key for Coingecko.
Comment at the end of this article if you know of any better conversion APIs I should consider adding support for!
Step 6: Enable Solana in Medusa Admin Dashboard
The last step is to configure your backend to accept Solana as a payment method.
Go to your Medusa Admin dashboard. You can find the URL in Railway by selecting the Backend service and opening the "Deployments" tab. You will need to add /app
at the end of the URL so it looks something like this:https://ghost-production-1234.up.railway.app/app
On the login page, enter your admin email and password. These credentials are auto-generated during deployment and can be found in the Railway Backend service's "Variables" tab. Look for MEDUSA_ADMIN_EMAIL
and MEDUSA_ADMIN_PASSWORD
.
After logging in, navigate to Settings -> Regions -> click Edit (...) on your region. Within your region settings, open the payment method dropdown, add Solana, and then click Save.
Done 🥳
That's all for the setup. Now you can open your Storefront and perform a checkout, where you should see the Solana payment option available.
How It Works
- Fiat-first: Store prices stay in EUR/USD. The module fetches live crypto prices and convert total cart price at checkout.
- Unique, one-time wallet per order: A new one-time-wallet address in generated for each order checkout.
- QR code checkout: Storefront will display the wallet as a QR code for easy mobile wallet payment completion.
- Automatic detection: A scheduled job tracks the blockchain and captures payments as soon as they’re received.
- Cold wallet security: Once complete, funds move to cold storage for added safety.
- Automatic price renewal: By default, every 5 minute a new price will be calculated to account for crypto price volatility.
Visual diagram of the updated workflow coming soon.
Live Price Updates Now Supported!
The first demo highlighted a tricky missing piece: payment session expiration.
- What if a customer starts checkout at one SOL price, but pays later after the exchange rate swings?
- What if they send just part of the SOL, or pay just after a session “expires”?
It’s more complex than a simple timeout.
In reality, partial/late/underpayments are common and need graceful handling, otherwise, users lose payments or get frustrated asking support for help.
The Solution in Beta
After testing, feedback, and rethinking, the latest release supports:
- Session pricing windows: By default, the conversion is locked for 5 minutes, but this is fully configurable.
- Smart partial payments: All partial transfers are credited to an ongoing session field (
received_sol_amount
), allowing for multiple payments until the full due amount is tracked. - Automatic order placement: Once the session’s full amount is met or exceeded, the module finalizes and places the order.
- Resilience for late/underpayments: Users are never asked to “start over” and lose their funds, outstanding balances and new prices are dynamically calculated.
Security vs. Privacy Challenge (TBD)
Currently, the module requires a cold storage wallet for automatic stashing (security first). However, someone reached out and pointed out that this compromises privacy, as the cold wallet address can be tracked by following the one-time wallet address and seeing where it next transfers its balance. This challenge has not been resolved in the beta release.
The current planned solution is to modify the module to accept an array of cold storage wallet addresses. This allows stores to either use no cold storage wallet, keeping funds on the one-time wallets for full privacy, or use multiple cold storage wallets to provide some level of masking (more secure but less privacy and more administration).
If you know of any better way to tackle this issue that doesn’t involve third-party services, please reach out to me!
If you have questions or want to contribute, reach out anytime! You can also check out the module’s roadmap here.
Disclaimer ⚠️
This Solana payment module is (or will be) provided as free, open-source software, with no warranties, guarantees, or liability of any kind. Use it at your own risk.
I do not charge for this module, nor do I offer insurance, customer support, or any guarantees against software bugs, user mistakes, or lost funds.
Always test thoroughly on testnet before using it with real funds, and make sure you understand how blockchain payments work.
It is your responsibility to ensure that your use of this software complies with all applicable laws and regulations in your country or jurisdiction, including but not limited to anti-money laundering (AML) and cryptocurrency regulations. I am not liable for any legal issues, penalties, or consequences resulting from the use or misuse of this software.
By using this module, you accept full responsibility for any transactions, losses, errors, or legal issues that may occur.
If you have questions or need help, feel free to reach out-but please remember: you are ultimately responsible for your own funds, compliance, and security.