Skip to content

@openrampkit/svelte ​

A thin Svelte wrapper over <openramp-modal>. It works with Svelte 5 (runes) and Svelte 4. Peer dependency: svelte ^4 || ^5.

The package is plain TypeScript: stores, actions and context helpers. It has no .svelte files, so you do not need a special build step. It is safe for server rendering (SvelteKit). @openrampkit/web (and Lit) loads only in the browser, in actions and in click handlers.

ts
import {
  createOpenRamp, setOpenRamp, getOpenRamp, depositButton, withdrawButton, openRampEmbedded, depositControllerStore,
  lightTheme, darkTheme, autoTheme,
} from '@openrampkit/svelte'
ReactSvelte
OpenRampProvidersetOpenRamp(config) in a parent component
useOpenRamp()getOpenRamp(), or the value from createOpenRamp()
DepositButton, WithdrawButtonuse:depositButton, use:withdrawButton on your own element
DepositButton.CustomYour markup with ramp.beginDeposit and $isOpen
OpenRampEmbeddeduse:openRampEmbedded
useDepositControllerdepositControllerStore(controller)

createOpenRamp(config) ​

Makes the modal state for your app. You can call it in a module or in a component. Nothing loads until you open the modal.

ts
// lib/ramp.ts
import { createOpenRamp, lightTheme } from '@openrampkit/svelte'

export const ramp = createOpenRamp({ baseUrl: '/api/openramp', theme: lightTheme(), onEvent: track })

The config is the same as the OpenRampProvider props in React: baseUrl (required), wallet, theme, appearance, messages, locale, providerRenderers and onEvent.

It returns an OpenRamp:

MemberTypeDescription
beginDeposit({ clientSecret, onEvent? })Promise<PublicSession>Opens the modal. Resolves when the deposit completes. Rejects (with an OpenRampError) when the modal closes first. Rejects on the server.
beginWithdraw({ clientSecret, onEvent? })Promise<PublicSession>The same for a withdraw session (created with direction: 'withdraw').
close()() => voidCloses the modal
isOpenReadable<boolean>A store. Use $isOpen in a component.
configReadable<OpenRampConfig>A store with the current config
update(config)(partial) => voidMerges new config values. Theme, appearance and locale changes go to an open modal.

Only one modal is open at a time. When you open a new modal, the previous modal closes.

You can make an OpenRamp in a shared module, also on a SvelteKit server. On the server, isOpen stays false and beginDeposit rejects, so no state goes from one user to another.

setOpenRamp(config) and getOpenRamp() ​

Share one OpenRamp with child components through the Svelte context. Call both functions during component initialization.

svelte
<!-- +layout.svelte -->
<script>
  import { setOpenRamp, lightTheme } from '@openrampkit/svelte'
  let { children } = $props()
  setOpenRamp({ baseUrl: '/api/openramp', theme: lightTheme() })
</script>

{@render children()}

setOpenRamp accepts a config or an existing OpenRamp. When it makes the OpenRamp, the modal closes when the component is destroyed. getOpenRamp() throws when no parent called setOpenRamp().

To keep the theme live with runes, call update in an effect:

svelte
<script>
  import { setOpenRamp, lightTheme, darkTheme } from '@openrampkit/svelte'
  const ramp = setOpenRamp({ baseUrl: '/api/openramp' })
  let dark = $state(false)
  $effect(() => ramp.update({ theme: dark ? darkTheme() : lightTheme() }))
</script>

use:depositButton and use:withdrawButton ​

Actions for your own button. On click, the action opens the modal. The action disables the element while the modal is open (only for elements with a disabled property, such as <button>).

svelte
<script>
  import { getOpenRamp, depositButton, withdrawButton } from '@openrampkit/svelte'
  const ramp = getOpenRamp()
  const isOpen = ramp.isOpen
</script>

<button use:depositButton={{ ramp, getClientSecret, onComplete: refreshBalance, onError: showError }}>
  {$isOpen ? 'Opening' : 'Deposit'}
</button>

<button use:withdrawButton={{ ramp, getClientSecret: getWithdrawSecret }}>Withdraw</button>
ParameterTypeDescription
rampOpenRampRequired. From createOpenRamp(), setOpenRamp() or getOpenRamp().
getClientSecretstring | () => Promise<string>Required. A secret, or a function that fetches one on click.
onComplete(session: PublicSession) => voidThe deposit or withdrawal completed
onError(error: OpenRampError) => voidThe modal closed before completion (code CLOSED, or the step's error)
onEvent(e: ClientEvent) => voidBrowser events for this session (in addition to the ramp's)
disabledbooleanKeep the element disabled

For fully custom markup, call the ramp yourself:

svelte
<a href="#top-up" onclick={() => ramp.beginDeposit({ clientSecret: getClientSecret }).then(refreshBalance, () => {})}>
  {$isOpen ? 'Opened' : 'Add funds'}
</a>

use:openRampEmbedded ​

Renders the modal inline, without an overlay. It follows the direction of the session, so it works for deposit and withdraw sessions.

Put the action on <openramp-modal>. Then the server also renders the element. You can also put it on any container. Then the action adds an <openramp-modal> inside the container.

svelte
<openramp-modal
  style="max-width: 420px"
  use:openRampEmbedded={{ ramp, clientSecret, onComplete: () => goto('/done') }}
></openramp-modal>
ParameterTypeDescription
clientSecretstring | () => Promise<string>Required
rampOpenRampDefault values for baseUrl, wallet, theme, appearance, messages, locale and onEvent. The action follows ramp.update().
baseUrlstringRequired when there is no ramp
wallet, theme, appearance, messages, localeDefault: the ramp's values
onEvent(e) => voidCalled after the ramp's onEvent
onComplete(session) => voidThe deposit or withdrawal completed
onClose(session?) => voidThe user pressed Close or Done on a result or error screen
onController(controller) => voidReceives the controller when it exists

It makes one controller for each client secret. A new string secret, baseUrl or wallet starts a new session. A new function does not. To start again with a function, wrap the element in {#key}.

depositControllerStore(controller) ​

A store with the Snapshot of a DepositController. Use it for a fully custom UI, or next to use:openRampEmbedded with onController.

svelte
<script>
  import { depositControllerStore } from '@openrampkit/svelte'
  let { controller } = $props()
  const snap = $derived(depositControllerStore(controller))
</script>

<p>{$snap?.screen}</p>

The value is undefined when controller is undefined or null.

Re-exports ​

Themes: lightTheme, darkTheme, autoTheme (from @openrampkit/web/theme, no Lit). Types: Theme, ThemeOptions, ThemeColors, Appearance, RadiusScale, DepositController, WithdrawController, RampController, Snapshot, PublicSession, OpenRampError, ClientEvent, WalletAdapter, OpenRamp, OpenRampConfig, BeginDepositOptions, BeginWithdrawOptions, ButtonActionParams, EmbeddedActionParams, ActionReturn, Readable.

Flow options ​

beginDeposit() and beginWithdraw() take flow and autoClose, and the embedded component takes them as props. They work as in openDeposit: flow sets the first tab, a method to open at once, the amount, presets, default tokens and a withdraw balance, and autoClose closes the modal when the payment completes.

MIT licensed