Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
"ignore": [],
"privatePackages": {
"version": false,
"tag": false
}
}
5 changes: 5 additions & 0 deletions .github/workflows/publish_npm_coinbase_x402.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ jobs:
contents: read
id-token: write
steps:
- name: Refuse to publish a retired package
run: |
echo "::error::@sei-js x402 packages are retired. Sei is supported natively upstream via @x402/*. See MIGRATION.md."
exit 1

- uses: actions/checkout@v4

- name: Setup pnpm
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/publish_npm_x402.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ jobs:
contents: read
id-token: write
steps:
- name: Refuse to publish a retired package
run: |
echo "::error::@sei-js x402 packages are retired. Sei is supported natively upstream via @x402/*. See MIGRATION.md."
exit 1

- uses: actions/checkout@v4

- name: Setup pnpm
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/publish_npm_x402_axios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ jobs:
contents: read
id-token: write
steps:
- name: Refuse to publish a retired package
run: |
echo "::error::@sei-js x402 packages are retired. Sei is supported natively upstream via @x402/*. See MIGRATION.md."
exit 1

- uses: actions/checkout@v4

- name: Setup pnpm
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/publish_npm_x402_express.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ jobs:
contents: read
id-token: write
steps:
- name: Refuse to publish a retired package
run: |
echo "::error::@sei-js x402 packages are retired. Sei is supported natively upstream via @x402/*. See MIGRATION.md."
exit 1

- uses: actions/checkout@v4

- name: Setup pnpm
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/publish_npm_x402_fetch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ jobs:
contents: read
id-token: write
steps:
- name: Refuse to publish a retired package
run: |
echo "::error::@sei-js x402 packages are retired. Sei is supported natively upstream via @x402/*. See MIGRATION.md."
exit 1

- uses: actions/checkout@v4

- name: Setup pnpm
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/publish_npm_x402_hono.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ jobs:
contents: read
id-token: write
steps:
- name: Refuse to publish a retired package
run: |
echo "::error::@sei-js x402 packages are retired. Sei is supported natively upstream via @x402/*. See MIGRATION.md."
exit 1

- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/publish_npm_x402_next.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ jobs:
contents: read
id-token: write
steps:
- name: Refuse to publish a retired package
run: |
echo "::error::@sei-js x402 packages are retired. Sei is supported natively upstream via @x402/*. See MIGRATION.md."
exit 1

- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
name: Release @sei-js packages

on:
push:
branches:
- main
paths:
- "typescript/**"
workflow_dispatch:

concurrency: ${{ github.workflow }}-${{ github.ref }}

Expand All @@ -18,6 +14,11 @@ jobs:
pull-requests: write
id-token: write
steps:
- name: Refuse to release a retired package set
run: |
echo "::error::@sei-js x402 packages are retired. Sei is supported natively upstream via @x402/*. See MIGRATION.md."
exit 1

- name: Checkout Repo
uses: actions/checkout@v4
with:
Expand Down
260 changes: 260 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
# Migrating off `@sei-js/*` x402 packages

The `@sei-js/*` x402 packages are **deprecated and no longer maintained**. Sei is now
supported natively in the upstream [x402](https://github.com/x402-foundation/x402) SDK,
so this fork no longer has a reason to exist.

Migrate to the upstream v2 `@x402/*` packages.

## Read this first: the Sei mainnet USDC changed

This fork defaults Sei mainnet (chain 1329) to an IBC-bridged USDC that **does not
implement EIP-3009**. Since EIP-3009 `transferWithAuthorization` is what the `exact`
scheme relies on to settle, payments against that asset cannot settle.

Upstream uses native USDC, which does implement EIP-3009:

| Network | Chain | This fork (broken) | Upstream (use this) |
| --- | --- | --- | --- |
| Sei mainnet | 1329 | `0x3894085Ef7Ff0f0aeDf52E2A2704928d1Ec074F1` | `0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392` |
| Sei testnet | 1328 | `0xeAcd10aaA6f362a94823df6BBC3C536841870772` | `0x4fCF1784B31630811181f670Aea7A7bEF803eaED` |

Both upstream contracts report symbol `USDC`, EIP-712 version `2`, and 6 decimals. If you
hardcoded either fork address anywhere, replace it. If you relied on the default asset,
upgrading picks up the correct one automatically.

## Package mapping

| Deprecated | Replacement |
| --- | --- |
| `@sei-js/x402` | `@x402/core` + `@x402/evm` |
| `@sei-js/x402-fetch` | `@x402/fetch` |
| `@sei-js/x402-axios` | `@x402/axios` |
| `@sei-js/x402-express` | `@x402/express` |
| `@sei-js/x402-hono` | `@x402/hono` |
| `@sei-js/x402-next` | `@x402/next` |
| `@sei-js/coinbase-x402` | `@coinbase/x402` |

The `@sei-js/*` packages tracked x402 v1. The `@x402/*` packages are v2, so this is a
protocol upgrade rather than a rename, and the API changed. The sections below cover
every breaking change you will hit.

## Network identifiers are now CAIP-2

v1 used bare network names. v2 uses CAIP-2 identifiers everywhere a network is named.

| v1 | v2 |
| --- | --- |
| `"sei"` | `"eip155:1329"` |
| `"sei-testnet"` | `"eip155:1328"` |

v2 also accepts wildcards such as `"eip155:*"` when registering a scheme for all EVM
chains.

## Clients

### fetch

Before:

```typescript
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { sei } from "viem/chains";
import { wrapFetchWithPayment } from "@sei-js/x402-fetch";

const account = privateKeyToAccount("0xYourPrivateKey");
const client = createWalletClient({ account, transport: http(), chain: sei });

const fetchWithPay = wrapFetchWithPayment(fetch, client);
```

After:

```typescript
import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";

const account = privateKeyToAccount("0xYourPrivateKey");

const fetchWithPay = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:1329", client: new ExactEvmScheme(account) }],
});
```

Note that v2 takes a viem `Account` rather than a `WalletClient`, so the chain is no
longer configured on the wallet. It comes from the `network` you register.

The `maxValue` parameter is gone. Spend limits are now configured on the client instead
of being passed positionally.

### axios

Before:

```typescript
import axios from "axios";
import { withPaymentInterceptor } from "@sei-js/x402-axios";

const api = withPaymentInterceptor(axios.create(), client);
```

After:

```typescript
import axios from "axios";
import { wrapAxiosWithPaymentFromConfig } from "@x402/axios";
import { ExactEvmScheme } from "@x402/evm";

const api = wrapAxiosWithPaymentFromConfig(axios.create(), {
schemes: [{ network: "eip155:1329", client: new ExactEvmScheme(account) }],
});
```

## Servers

v1 took `payTo` as the first argument and read `price` and `network` per route. v2 takes a
pre-built `x402ResourceServer` and moves the payment terms into an `accepts` block, which
is what lets a single route offer multiple schemes or networks.

### express

Before:

```typescript
import express from "express";
import { paymentMiddleware } from "@sei-js/x402-express";

const app = express();

app.use(
paymentMiddleware("0xYourAddress", {
"/protected": { price: "$0.10", network: "sei" },
}),
);
```

After:

```typescript
import express from "express";
import { paymentMiddleware, x402ResourceServer } from "@x402/express";
import { ExactEvmScheme } from "@x402/evm/exact/server";
import { HTTPFacilitatorClient } from "@x402/core/server";

const app = express();

const facilitatorClient = new HTTPFacilitatorClient({ url: "https://x402.org/facilitator" });
const resourceServer = new x402ResourceServer(facilitatorClient).register(
"eip155:1329",
new ExactEvmScheme(),
);

app.use(
paymentMiddleware(
{
"GET /protected": {
accepts: {
scheme: "exact",
price: "$0.10",
network: "eip155:1329",
payTo: "0xYourAddress",
},
description: "Access to premium content",
},
},
resourceServer,
),
);
```

Two things to watch for. Route keys now include the HTTP verb (`"GET /protected"` rather
than `"/protected"`), and `payTo` moved from the first positional argument into each
route's `accepts` block, so different routes can pay out to different addresses.

Import `ExactEvmScheme` from `@x402/evm/exact/server` on the server side, and from
`@x402/evm` on the client side.

### hono

Identical shape to express, importing `paymentMiddleware` and `x402ResourceServer` from
`@x402/hono`.

### next

v2 renames the entry point from `paymentMiddleware` to `paymentProxy`, and the
conventional file moves from `middleware.ts` to `proxy.ts`.

Before, in `middleware.ts`:

```typescript
import { paymentMiddleware } from "@sei-js/x402-next";

export const middleware = paymentMiddleware("0xYourAddress", {
"/protected": { price: "$0.01", network: "sei" },
});

export const config = { matcher: ["/protected/:path*"] };
```

After, in `proxy.ts`:

```typescript
import { paymentProxy, x402ResourceServer } from "@x402/next";
import { HTTPFacilitatorClient } from "@x402/core/server";
import { ExactEvmScheme } from "@x402/evm/exact/server";

const facilitatorClient = new HTTPFacilitatorClient({ url: "https://x402.org/facilitator" });
const resourceServer = new x402ResourceServer(facilitatorClient).register(
"eip155:1329",
new ExactEvmScheme(),
);

export const proxy = paymentProxy(
{
"/protected": {
accepts: {
scheme: "exact",
price: "$0.01",
network: "eip155:1329",
payTo: "0xYourAddress",
},
description: "Access to protected content",
},
},
resourceServer,
);

export const config = { matcher: ["/protected/:path*"] };
```

## Coinbase facilitator

`@sei-js/coinbase-x402` was a scope rename of `@coinbase/x402` with no Sei-specific
changes, so switch the import back. The exported API is unchanged: `facilitator` and
`createFacilitatorConfig(apiKeyId, apiKeySecret)`, still reading `CDP_API_KEY_ID` and
`CDP_API_KEY_SECRET` from the environment.

Its `FacilitatorConfig` output plugs directly into v2's facilitator client:

```typescript
import { facilitator } from "@coinbase/x402";
import { HTTPFacilitatorClient } from "@x402/core/server";

const facilitatorClient = new HTTPFacilitatorClient(facilitator);
```

## Wallet and client helpers

The fork exported Sei-specific viem helpers from `@sei-js/x402` (`createClientSei`,
`createSignerSei`, `createClientSeiTestnet`, `createSignerSeiTestnet`). These have no v2
equivalent and are not needed: construct a viem account with `privateKeyToAccount` and let
the registered `network` determine the chain.

## Further reading

- [Upstream repository](https://github.com/x402-foundation/x402)
- [Network and token support](https://github.com/x402-foundation/x402/blob/main/docs/core-concepts/network-and-token-support.mdx)
- [PR #3227](https://github.com/x402-foundation/x402/pull/3227), which added the Sei
default stablecoins upstream
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# x402 payments protocol

> [!CAUTION]
> **This fork is deprecated and unmaintained.** The `@sei-js/*` x402 packages published from
> this repository are retired. Sei is now supported natively in the upstream
> [x402 SDK](https://github.com/x402-foundation/x402), so use the `@x402/*` packages instead.
>
> **Existing users should migrate: see [MIGRATION.md](./MIGRATION.md).**
>
> Beyond being unmaintained, these packages default Sei mainnet to an IBC-bridged USDC that
> does not implement EIP-3009. Because the `exact` scheme settles via
> `transferWithAuthorization`, payments cannot settle against that asset. Upstream uses
> native USDC, which does implement EIP-3009.

> "1 line of code to accept digital dollars. No fee, 2 second settlement, $0.001 minimum payment."

```typescript
Expand Down
Loading
Loading