Skip to main content

Convert currencies

Use this component to let customers convert balance between the currencies in their Nium multicurrency wallet. Nium hosts the component and renders it in an iFrame, so there is no redirect.

This component only moves funds between currencies already in a customer's wallet. It doesn't send money to a beneficiary, create wallets, or onboard customers. To send outbound transfers, use Send payouts.

The component:

  • Guides users through three steps, from amount and currency input to quote confirmation and a completion summary. It validates the balance at each step.
  • Shows a live foreign exchange (FX) rate for the selected currency pair, including the net rate and markup. It holds that quote, by its quoteId, so the transfer runs at the rate the user confirmed.
  • Lists the customer's wallet currencies in the source and destination dropdowns, with the available balance for each.

Live preview​

This is the component running against the Nium sandbox with test data. Choose the currencies and an amount to try a conversion.

Live preview · sandbox

Before you begin​

  • Complete the Quick start to set up PKCE authorization. Use the scope ['mcy-wallet-move-funds'] when your server requests the authorization code. Your client must be provisioned with this scope.
  • Have the customerHashId whose wallet balance you convert. The component resolves the wallet and its currencies from it. You don't pass a wallet ID.
  • Make sure the customer has an active multicurrency wallet with at least two currencies.

Quick example​

After you call init(), create the conversionForm element, mount it, and clean up when you're done.

index.html
<div id="conversion-container"></div>
client.ts
const { createElement } = await import('@nium/nium-sdk')

const element = await createElement('conversionForm', {
customerHashId: '<customer-hash-id>', // required
})

element.on('submit', (e) => showConfirmation(e.result.transfer))
element.on('error', (e) => showErrorToast(e.error.message))
element.on('cancel', () => router.push('/wallet'))

element.mount('#conversion-container')

// When you're done, for example on a route change
element.destroy()

Options​

createElement('conversionForm', options) accepts these options (type NiumConversionFormProperties).

OptionTypeDescription
customerHashIdstringRequired. Customer whose wallet balance is converted.
themeNiumThemeCustom theme overrides: font family, colors, border radius. See Theming.

Events​

Listen to form events with element.on(eventName, handler). All events go from the iFrame to your page. element.on() returns a function that removes that listener. Call it when you remove the component to prevent memory leaks.

  • ready: The iFrame is fully loaded. Remove loading states or show the container.
  • resize: The iFrame content height changed. Use e.height to resize the container. Payload: { height: number }.
  • submit: The transfer runs when the user confirms, and the iFrame then shows a summary. submit fires when the user closes that summary. Payload: { result: { transfer: object } }.
  • error: The token exchange failed, the session expired (AUTH_EXPIRED), or the iFrame failed to load. Quote, balance-validation, and transfer failures appear inside the iFrame only. Always handle this event. Payload: { error: { message: string, code: string } }.
  • cancel: The user closed the flow before converting. Navigate away or reset your UI state.

Submit payload​

The conversion is final once the user confirms

The conversion is final once the user confirms it. By the time submit fires, the iFrame has already called Nium's FX and wallet services, so your client has nothing further to call.

e.result.transfer has the settled figures:

FieldType
sourceAmountnumber
sourceCurrencyCodestring
destinationAmountnumber
destinationCurrencyCodestring
exchangeRatenumber
netExchangeRatenumber
markupAmountnumber
markupRatenumber
scalingFactornumber
systemReferenceNumberstring
Reconcile with the system reference number

Use systemReferenceNumber as the reconciliation key. Store it with the settled amounts for your audit trail. Nium invalidates the wallet balance and transaction history caches after a successful transfer, so any balance view you re-fetch shows the new figures.

Clean up​

Call element.destroy() on route change, modal close, or component unmount. It removes the iFrame, detaches all listeners, and releases the SDK's internal state.

Mount each element once

Call element.mount(selector) once per instance. To mount again, create a new element.

How the component works​

Between mount and a settled transfer, the iFrame makes four service calls:

  1. Token exchange. It exchanges the PKCE authorization code for an access token through /api/niam-service/oauth2/token.
  2. Wallet resolution. With the access token, it loads the customer's wallet and per-currency balances through GET /api/wallet-service/api/v1/client/{clientId}/customer/{customerId}/wallet.
  3. FX quote. When the user selects a source and destination currency, it requests a live exchange rate from the Nium FX service. The rate includes markup and net rate. The component holds the returned quote for confirmation.
  4. Transfer. On confirmation, it posts to /api/fx-service/api/v1/client/{clientId}/customer/{customerId}/wallet/{walletHashId}/transfer and shows the settled summary.

The component checks the entered amount against the source-currency balance before the user can confirm a quote. It shows a loading state during the token exchange and wallet lookup.

Theming​

Pass a NiumTheme object in the theme option to control fonts, colors, input styles, and border radius. The Theme customization reference documents all 15 theme properties, a gating matrix, and four ready-to-use example themes.

Troubleshooting​

Common issues
  • No currencies in the dropdown. The customerHashId is incorrect, or the customer's wallet has fewer than two currencies. Verify the customerHashId and confirm the customer has an active multicurrency wallet with at least two currencies.
  • Rate not loading. The source and destination currencies are identical. The component requests a rate only when the two currencies differ.
  • Insufficient balance error. The conversion amount exceeds the available source-currency balance. Validate the amount against the wallet balance in your own UI before the user submits.
  • Component not rendering. The container element is missing at mount time, or an unhandled error occurred. Check the browser console for error events. Make sure the container exists before you call mount().
  • Incorrect role or scope error. The client isn't provisioned with the correct scope. Verify that your client has the mcy-wallet-move-funds scope. This is the confirmed role for this component.

For additional support, contact your Nium integration team.

Next steps​

LLM-ready documentation:: llms.txt and llms-full.txt
Was this page helpful?