What you’ll learn
- Prepare the Stellar wallet to hold USDC
- Create a MoneyGram session on your server for the user’s Para wallet
- Sign the cash-out payment with the Para Stellar signer
- Open the MoneyGram widget for cash-out or cash-in
- Track each transaction until it settles
How it works
The widget runs in an iframe on your page. Your server creates a short-lived session for the wallet address, and the browser opens the widget with it. On cash-out, the widget asks your app for a USDC payment to MoneyGram, and the Para wallet signs it. On cash-in, the user pays cash at a MoneyGram location and MoneyGram sends USDC to the wallet, so your app signs nothing.MoneyGram’s crypto services are not available in Alaska, Louisiana, or Hawaii.
Before you start
You need a React app withParaProvider and a login flow, plus a server that can keep a secret key. Your Para API key must have Stellar enabled in the Developer Portal. These guides cover the Para setup:
You also need MoneyGram Ramps partner access. Register through MoneyGram’s , then get Playground keys and an allowlisted domain from the partner portal. On a domain that MoneyGram has not allowlisted, the widget does not load.
A Stellar account does not exist on the network until it receives XLM. Fund the Para wallet’s address before its first transaction, then keep enough XLM for fees and the trustline reserve. Stellar’s shows how to fund a testnet account.
Install the packages
Install the Para React SDK and the Stellar SDK. The versions below are the ones used for this guide.Connect to Stellar
MoneyGram Playground keys run on Stellar testnet, and production keys run on mainnet. The snippets in this guide use these testnet values for the network passphrase, the Horizon server, and the USDC asset:ParaProvider:
stellarSigner.address is the wallet address you send to MoneyGram, and stellarSigner.signTransaction signs Stellar transactions with the Para wallet. Run the steps below after the user logs in and stellarSigner is set.
Add a USDC trustline
A Stellar account can hold USDC only after it adds a trustline to the USDC issuer. Cash-in needs the trustline so MoneyGram can deliver USDC to the wallet. Cash-out needs USDC in the wallet, so the trustline already exists by then. Load the account from Horizon and look for a USDC balance. If there is none, sign and submit achangeTrust operation:
Create a session on your server
Each widget opens with a MoneyGram session. Send the wallet address from the browser to your server. Your server then creates the session with the MoneyGram secret key:https://playground.xramps.moneygram.com/api.
Check the response status, then return sessionToken and widgetUrl to the browser, which needs both to open the widget. An error response has neither field. A 401 means the secret key does not match the API URL, such as a Playground key sent to the production API.
A session token expires after one hour, so create a new session each time the widget opens. Send the same wallet address for the same user every time. MoneyGram binds each session to that address, which lets the user reopen earlier transactions and lets the session token read their status.
Before production, confirm the user’s Para session on your server with a , check that the wallet address belongs to that user, and rate-limit session creation.
Sign the cash-out payment
When the user commits a cash-out, the widget callsonSignTransaction with the payment MoneyGram expects. The payload carries the deposit address, the amount, and the network. It also carries the USDC asset and a memo when MoneyGram sets them.
The callback checks the network, then builds the USDC payment, signs it with the Para wallet, and submits it. It returns the transaction hash to the widget:
tokenAddress holds the asset code (USDC), not a contract address. The issuer comes from issuer. Widgets deployed before MoneyGram added issuer leave it out, so the callback falls back to the testnet USDC issuer.
Open the widget
Load MoneyGram’s SDK on the page that shows the widget:window.RampsSDK and has no TypeScript types, so declare the fields you use in a TypeScript project.
To open the widget, pass the session, the Para wallet, and your callbacks to createRamps. container is the page element that holds the widget’s iframe:
mode to off-ramp for cash-out or on-ramp for cash-in. The session’s widgetUrl always includes mode=off-ramp, so replace that query parameter instead of adding a second one. Pass the same mode in mode and transaction.type.
The widget calls onSignTransaction for cash-out. Standard cash-in flows do not call it. The next section covers onTransactionCreated and onComplete. Call widget.destroy() to remove the iframe when the user leaves the page.
The script URL above is MoneyGram’s Playground build. Confirm the production URL with MoneyGram before you go live. Your Content Security Policy must also allow iframes from MoneyGram’s domains.
Track settlement
onTransactionCreated fires at most once, after MoneyGram validates the transaction and before it commits. MoneyGram does not retry it, so store the record as soon as it arrives. Keep id to look up the status later and mgiTransactionId to match webhook events.
onComplete fires when the widget shows its final screen. For a cash-out, the record includes the referenceNumber the user gives at pickup.
The transaction can still be in progress after onComplete. A cash-in, for example, waits for the user to pay at the counter. Ask MoneyGram for the current status from your server:
For server-to-server updates, add a webhook URL in the MoneyGram partner portal under Settings > Integration. You can save a production webhook URL only after MoneyGram approves your business verification (KYB).
Webhook events use their own status names and can arrive out of order. Find the stored record by
mgiTransactionId, then confirm the status with the request above before you act on it. MoneyGram’s covers the event format and signature verification.
Use Solana instead
The Solana flow keeps the session, widget, and settlement steps from Stellar. You replace the signer and the cash-out callback, and you set twochain values to solana. Your Para API key must have Solana enabled, and the wallet needs SOL to pay the cash-out transaction fee. Solana has no trustlines, so skip that step.
Install the Solana packages. The versions below are the ones used for this guide.
rpc once, outside your components, because the signer hook rebuilds the signer each time it gets a new rpc object:
ParaProvider:
tokenAddress and its decimals in tokenDecimals. MoneyGram reports devnet as testnet in requiredNetwork.
The callback converts the decimal amount to base units. It then sends a USDC transferChecked from the user’s token account to MoneyGram’s token account and returns the transaction signature:
- Create the session with
chain: "solana". - In
createRamps, setwallet.addresstosolanaSigner.addressandwallet.chainto"solana". - Pass the Solana
onSignTransactiontocreateRamps.
Go live
Switch every network value to mainnet at the same time. MoneyGram picks the network from your key, and a key sent to the other environment’s API returns401.
To get production keys, complete these steps with MoneyGram:
- Complete KYB in the partner portal.
- Submit verified Playground transaction IDs for MoneyGram’s integration tests.
- Configure your product fees.
- Request production activation.