# Funding

:::warning\[Beta]
This feature is experimental and may change as we iterate.
:::

For concepts (sessions, statuses, refunds) and the underlying HTTP API see [Funding](/docs/configuration/funding) and the [REST reference](/docs/configuration/funding/headless). This page covers the `openfort.funding` namespace in `@openfort/openfort-js`.

## Using the SDK

`@openfort/openfort-js` exposes funding under `openfort.funding` — usable from any JavaScript runtime (browser or server) with your publishable key.

When the source route is known upfront, funding is **one call plus a wait** — pass `paymentMethod` at creation and the session comes back with the deposit address. The SDK remembers each session's `clientSecret`, so follow-up calls don't need to thread it.

```ts
import { Openfort } from '@openfort/openfort-js'

const openfort = new Openfort({
  baseConfiguration: { publishableKey: process.env.OPENFORT_PUBLISHABLE_KEY! },
})

// Required before accessing openfort.funding (like auth / embeddedWallet / user)
// — see https://www.openfort.io/docs/products/embedded-wallet/javascript/use-openfort
await openfort.waitForInitialization()

// One call: create the session AND mint the deposit address.
// Destination: USDC on Base. Source: USDC on Polygon.
const session = await openfort.funding.sessions.create({
  target: {
    chain: 'eip155:8453',
    currency: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
    address: '0xUserWalletAddress',
  },
  paymentMethod: {
    type: 'evm',
    source: { chain: 'eip155:137', currency: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', amount: '10000000' },
  },
})

console.log(session.status)                          // "waiting_payment"
console.log(session.paymentMethod?.receiverAddress)  // address the user sends to
console.log(session.paymentMethod?.addressUri)       // EIP-681 / Solana Pay URI for a QR

// Wait for settlement (polls until succeeded | bounced | expired).
const settled = await openfort.funding.sessions.wait(session.id, { pollMs: 4000, timeoutMs: 600000 })
console.log(settled.status) // "succeeded"
```

`wait` accepts `{ clientSecret?, pollMs?, timeoutMs? }` — `pollMs` (default `4000`) is the poll interval and `timeoutMs` (default `1800000`, 30 min) is how long to wait before giving up; `clientSecret` is filled from the remembered session when omitted.

Prefer the two-step flow when the user picks the source later — `sessions.create({ target })` then `sessions.setPaymentMethod(session.id, { paymentMethod })`; the SDK fills in the remembered `clientSecret` (pass it explicitly for sessions created elsewhere).

:::note
A `@openfort/openfort-node` server namespace is planned; until then, server-side integrations call the [REST endpoints](/docs/configuration/funding/headless#rest-endpoints) directly.
:::

## Payment method types

`setPaymentMethod` (or the inline `paymentMethod` on `create`) takes one of three source types:

:::code-group

```ts [EVM]
{ type: 'evm', source: { chain: 'eip155:137', currency: '0x3c49…3359', amount: '10000000' } }
```

```ts [Solana]
{ type: 'solana', source: { chain: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', currency: 'EPjF…Dt1v', amount: '10000000' } }
```

```ts [Exchange (CEX)]
{ type: 'cex', cex: 'binance', source: { chain: 'eip155:8453', currency: '0x8335…2913', amount: '10000000' } }
```

:::

* **`evm` / `solana`** — self-custody transfers. The response carries `receiverAddress`, `addressUri` (for a QR), and wallet `deeplinks`.
* **`cex`** — a guided withdrawal from a centralized exchange. The response adds a `cex` object (`network`, `minWithdrawal`, `requiresMemo`) and no deeplinks (exchanges don't expose withdrawal links); the user withdraws to `receiverAddress` themselves.

All three are typed in the SDK (`openfort.funding`) and accepted by the REST endpoint.

:::tip\[Show fees and the minimum before the user sends]
Once a payment method is set, `session.paymentMethod.fees` (an array of `{ kind, amount, currency }` where `kind` is `gas` | `relayerGas` | `relayerService` | `app`) and `session.paymentMethod.minAmount` (in base units, or `null` for no floor) carry the cost and minimum for the route. Surface both so the user sees what it costs and the smallest amount they can send before they transfer.
:::

## Next steps

* Read the full HTTP API, session options, and response fields in the [REST reference](/docs/configuration/funding/headless).
* Build a Deposit UI in React with the [`useFunding` hook](/docs/products/embedded-wallet/react/wallet/funding) or the [wallet modal](/docs/products/embedded-wallet/react/ui/configuration#funding).
* React to settlement with [Webhooks](/docs/configuration/webhooks#funding-events).
