> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://mpp.dev/api/mcp` to find what you need.

# Elysia \[Payment middleware for Elysia]

## Choose a signing account

### Direct

Create a server-only wallet.ts module, then import account wherever an example creates a local signing account.

```ts
import { privateKeyToAccount } from 'viem/accounts'

export const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)
```

### Privy

Create an EVM wallet in Privy, fund it with the required currency on this page's network, and keep PRIVY\_APP\_SECRET server-side.

```bash
pnpm add @privy-io/node
```

Create a server-only privy.ts module, then import its account wherever an example configures account or feePayer.

```ts
import { PrivyClient } from '@privy-io/node'
import { createViemAccount } from '@privy-io/node/viem'

const privy = new PrivyClient({
  appId: process.env.PRIVY_APP_ID!,
  appSecret: process.env.PRIVY_APP_SECRET!,
})

export const account = createViemAccount(privy, {
  address: process.env.PRIVY_WALLET_ADDRESS as `0x${string}`,
  walletId: process.env.PRIVY_WALLET_ID!,
})
```

createViemAccount delegates signatures to the Privy wallet, so it replaces any local viem account in the examples on this page.

Native [Elysia](https://elysiajs.com) middleware that gates routes behind payment intents.

## Install

:::code-group
```bash [npm]
$ npm install mppx elysia
```

```bash [pnpm]
$ pnpm add mppx elysia
```

```bash [bun]
$ bun add mppx elysia
```
:::

## Usage

Import `Mppx` and `tempo` from `mppx/elysia` to create an Elysia-aware payment handler. Each intent (for example, `charge`) returns an Elysia `beforeHandle` hook you can use with `.guard()` to scope payment to specific routes.

```ts [server.ts]
import { Elysia } from 'elysia'
import { Mppx, tempo } from 'mppx/elysia'

const mppx = Mppx.create({ methods: [tempo.charge()] })

const app = new Elysia()
  .guard(
    { beforeHandle: mppx.charge({ amount: '1' }) },
    (app) => app.get('/premium', () => ({ data: 'paid content' })),
  )
```

### Global application

Use `.onBeforeHandle()` to apply payment to all routes.

```ts [server.ts]
import { Elysia } from 'elysia'
import { Mppx, tempo } from 'mppx/elysia'

const mppx = Mppx.create({ methods: [tempo.charge()] }) // [!code hl]

const app = new Elysia()
  .onBeforeHandle(mppx.charge({ amount: '1' })) // [!code hl]
  .get('/premium', () => ({ data: 'paid content' }))
  .get('/another', () => ({ data: 'also paid' }))
```

### Session payments

Use `mppx.session()` with `tempo.session()` to gate routes behind current v2 Sessions.

```ts [server.ts]
import { Store } from 'mppx'
import { Elysia } from 'elysia'
import { Mppx, tempo } from 'mppx/elysia'
import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount('0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef')

const mppx = Mppx.create({
  methods: [
    tempo.session({
      account,
      chainId: 4217,
      currency: '0x20c0000000000000000000000000000000000000', // pathUSD on Tempo
      store: Store.memory(),
    }),
  ],
})

const app = new Elysia()
  .guard(
    { beforeHandle: mppx.session({ amount: '1', unitType: 'token' }) },
    (app) => app.get('/content', () => ({ data: 'session content' })),
  )
```

## x402-compatible clients

Elysia apps can serve MPP and x402 clients from the same endpoint when you register [`evm.charge`](/payment-methods/evm/charge) with `x402.facilitator`.

```ts [server.ts]
import { Elysia } from 'elysia'
import { Mppx, evm } from 'mppx/elysia'

const mppx = Mppx.create({
  methods: [
    evm.charge({
      currency: evm.assets.baseSepolia.USDC,
      recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
      x402: {
        facilitator: 'https://x402.org/facilitator',
      },
    }),
  ],
  secretKey: process.env.MPP_SECRET_KEY ?? 'local-dev-secret',
})

const app = new Elysia().guard(
  {
    beforeHandle: mppx.evm.charge({
      amount: '0.01',
      description: 'Premium API access',
    }),
  },
  (app) => app.get('/paid', () => ({ data: 'paid content' })),
)
```

See [build a client for MPP and x402](/guides/use-mpp-with-x402#build-a-client-for-mpp-and-x402) for the client setup.
