Jupiterswap: embedded swaps with Jupiter Plugin
Jupiterswap integrations can place Jupiter's Solana swap interface inside a web app through Jupiter Plugin. The component supplies token selection, quotes, wallet connection, and swap-status screens. It supports inline, floating, and modal layouts, including passthrough from an existing wallet provider. The documented Plugin integration uses Ultra Swap, whose API is no longer actively maintained and has been superseded by Swap V2. Connecting a wallet alone does not authorize a trade.
In this guide
Bottom line: Wallet passthrough shares the host app's connection with Jupiter Plugin, while the wallet's signing function remains necessary for swap execution.
How do you embed Jupiter swaps in an existing app?
Jupiter Plugin supplies a browser-based swap component that you load and initialize in your application, using either the window-object integration or the npm package.
Loading the component
Script-loaded applications
The script-based approach exposes window.Jupiter.init(). Initialization belongs after the loader becomes available and, for integrated mode, after the target element exists. Plain HTML can initialize through the page's load event. The host application supplies configuration while Plugin supplies the swap interface.
Module-based applications
The @jup-ag/plugin package exposes an init function for module-based builds. Its integration includes the package stylesheet and requires maintaining its dependencies. This approach fits an application's build process; the script-based approach loads the component through the browser.
React integrations initialize after mounting, when the rendered container exists. Next.js integrations also need a client-side execution boundary because Plugin uses the browser's window and document objects. Calling initialization during server rendering cannot mount a browser interface.
Loader readiness and container readiness are separate dependencies. A rendered target element does not establish that the Plugin script has finished loading.
Inline, floating, and modal layouts
Integrated mode places the swap form inside a designated page element, widget mode provides floating access, and modal mode displays the form in an overlay.
For an inline form, integratedTargetId identifies the existing container. A floating widget uses widgetStyle to control its corner position and size. Modal presentation suits an app that opens swaps on demand. These settings control placement; they do not define a different token exchange or remove wallet authorization.
Container styles and classes adjust the form's surrounding layout. Theme variables control colors, and the branding configuration accepts an app name and logo. Preserve readable amounts and visible warnings when matching the host design. Responsive widths also need room for token selection and the wallet prompt, rather than only the initial form.
Wallet passthrough and transaction authorization
Wallet passthrough lets Plugin share the connection that an application already manages, provided the host supplies its wallet context and synchronizes changes with the component.
Set enableWalletPassthrough when the host owns wallet connection. The passthroughWalletContextState supplies that context, and syncProps() updates it when connection state changes. The onRequestConnectWallet callback can invoke the application's own connection flow. This keeps the embedded form aligned with the wallet that the host uses.
An application without an existing provider can use Plugin's built-in connection through Unified Wallet Kit and Wallet Standard support. Both arrangements need a connected wallet with the signing functions that execution requires. Supplying a public address alone does not supply a transaction-signing function.
Jupiter Plugin calls the connected wallet's signTransaction function before submitting a swap.
The host's connection callback opens its wallet-selection flow; transaction signing uses the separate method supplied in the wallet context. Passthrough needs both pieces when the application manages connection itself.
Token presets, field locks, and amount modes
Form presets choose what the swap interface initially displays, while field locks restrict what users can change; neither setting establishes that a requested swap has available liquidity.
initialInputMint and initialOutputMint identify the starting tokens by mint address. fixedMint locks the matching side of the form, so it must correspond to the configured input or output mint. Setting an initial token alone leaves its selector editable. Similarly, initialAmount prefills an amount, while fixedAmount prevents amount edits.
The swapMode setting distinguishes input-driven and output-driven requests. ExactIn fixes the input amount; ExactOut requests a specified output amount. ExactInOrOut allows either amount-entry direction. A usable quote remains necessary for the selected request. Locking a field does not guarantee execution, create liquidity, or establish that a swap fulfills a separate payment obligation.
Referral configuration and fee collection
Plugin accepts a referral account and referral fee through formProps, with fee collection depending on the referral accounts required by its underlying Ultra integration.
The referralFee setting uses basis points, each representing one hundredth of a percentage point. Its documented Ultra configuration permits referral fees from 50 to 255 bps. Jupiter takes 20% of the collected integrator fee. Ultra chooses the token mint in which it collects the fee, and the corresponding referral token account must already exist. If that account is missing, an order can remain executable without the integrator's fee. An accepted quote therefore does not establish that the application will collect its configured charge.
Inspect the order's feeMint and feeBps when evaluating that setup. Token selection in the form and token selection for fee collection describe different roles. Ultra's integrator-fee setup excludes JupiterZ quotes, so enabling a fee can change which quotes are available.
The boundary between Plugin and the swap API
The documented Plugin integration delegates transaction sending, wallet balances, and token information to Ultra, while Jupiter has superseded the standalone Ultra Swap API with Swap V2. The API maintenance notice applies to Ultra; it does not establish that Plugin has stopped operating. An app using the widget must distinguish its component version from a separately integrated API. Changing a direct API integration does not, by itself, update an embedded Plugin build.
From component loading to a reported swap result
A mounted swap form establishes that the interface is available; the execution response establishes whether the submitted swap succeeded, so an app should handle those states separately.
For an app embedding a form with a specified input amount, the component and its service have different responsibilities. Plugin handles the interface and wallet-signing request. Ultra supplies the order and processes the signed submission. Their relationship lets the host present swaps without treating every interface event as a completed exchange.
| Stage | Component or service behavior | Required condition or observable result |
|---|---|---|
| Load Plugin | Make the browser component available. | The loader or module must be ready. |
| Mount the form | Initialize the selected display mode. | Integrated mode needs an existing target element. |
| Connect the wallet | Use built-in connection or host passthrough. | The wallet must expose the required signing function. |
| Obtain an order | Request a quote for the selected tokens and amount. | Execution needs a usable order with transaction data. |
| Request a signature | Ask the wallet to sign the supplied transaction. | Wallet authorization must succeed before submission. |
| Submit the signed transaction | Send it with the associated request identifier. | A submission alone does not establish success. |
| Report the execution result | Expose success or error information to the host. | Use the returned execution status and result. |
| Completion | The success payload identifies the transaction and executed amounts. | Use execution data when displaying the completed exchange. |
These are conceptual stages, not a requirement for a separate transaction at each row. An existing wallet connection can precede form initialization. The signature still precedes submission, and the execution response still determines the reported result.
onFormUpdate reports edits to the form, while onSuccess supplies the transaction identifier and swap result. The result's inputAmount and outputAmount contain reported executed quantities in token base units. Apply each mint's decimals when displaying them. The associated quoteResponseMeta retains quote information, which has a different role from those execution amounts.
Quick answers
Do I need an API key or a private RPC endpoint for Jupiter Plugin?
The documented drop-in Plugin integration requires neither an API key nor an app-managed RPC endpoint. Its Ultra integration supplies transaction sending, wallet balances, and token information. That requirement applies to the embedded component, not every separate Jupiter API or additional feature that a host app might build.
How can I prevent token search from collapsing the inline swap form?
Give the integrated swap container an explicit height through containerStyles. This addresses the layout collapse associated with opening token search. Choose the height for the host layout and keep the width responsive. A height that fits the initial form still needs enough room for its expanded interaction states; no single pixel height suits every application.
Does initialAmount use whole tokens or the token's smallest units?
For Plugin's input-amount initialization, initialAmount uses the input token's smallest units as a string. The component converts that value into the displayed amount using the input mint's decimals. Sending an already formatted decimal amount would apply the wrong scale. Match the preset to the configured input mint, particularly when changing that mint between integrations.
Can autoConnect approve a swap automatically?
The autoConnect option concerns wallet reconnection on later visits and does not authorize swap transactions. Plugin passes this option to its built-in wallet provider. In passthrough mode, the host manages connection behavior instead. A connected wallet still needs to supply the transaction-signing function used by the swap flow, and reconnection does not establish execution success.
Is TypeScript required to embed swaps in a plain HTML site?
Plain HTML embedding can use JavaScript without TypeScript. The browser loads the Plugin script, and the page initializes the component once the script and required container are ready. Type declarations help applications that use TypeScript describe the interface; they are not a prerequisite for a plain HTML integration. The npm package is an alternative installation method.
Where can I preview Plugin settings before adding them to my app?
The Plugin Playground previews display modes, form settings, branding, and color configuration. It also generates integration snippets for the selected settings. An app using wallet passthrough still supplies its own wallet context. The preview shows the chosen presentation, while script loading and connection synchronization belong to the application that embeds the component.
Which information does onSwapError return to the host app?
The onSwapError callback exposes an error field and associated quoteResponseMeta. The error field is optional, and quoteResponseMeta can be null, so the host must handle missing details. Use any available error information to explain the failure state without treating quote data as a successful execution result. The success callback provides a different payload.
Will closing the modal remove the Plugin instance?
The close method hides the existing Plugin container without unmounting its interface. The resume method makes that container visible again. Reinitializing through init replaces the previous instance, so reopening and reinitializing have different effects on the component. Hiding the interface does not cancel a swap that has already been submitted.
Last updated -