> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# MPP 概述

> 使用 Machine Payments Protocol 在 Monad 上发送和接收支付

[`@monad-crypto/mpp`](https://www.npmjs.com/package/@monad-crypto/mpp) 包为 [Machine Payments Protocol](https://mpp.dev)(MPP)实现了 Monad 支付。它通过 Monad 上的 ERC-20 代币转账实现一次性支付处理。

本指南涵盖 Monad 专用的 `@monad-crypto/mpp` 包。有关 MPP 通用概念,请参阅 [MPPX 文档](https://mpp.sh/docs)。

## 安装

安装该包及其对等依赖:

<Tabs>
  <Tab title="npm">
    ```bash theme={null}
    npm install @monad-crypto/mpp mppx viem
    ```
  </Tab>

  <Tab title="pnpm">
    ```bash theme={null}
    pnpm add @monad-crypto/mpp mppx viem
    ```
  </Tab>

  <Tab title="yarn">
    ```bash theme={null}
    yarn add @monad-crypto/mpp mppx viem
    ```
  </Tab>

  <Tab title="bun">
    ```bash theme={null}
    bun add @monad-crypto/mpp mppx viem
    ```
  </Tab>
</Tabs>

## 服务端

服务端定义所需的支付并验证客户端提交的凭证。从服务端入口导入 `monad` 并传入 `Mppx.create`。

```ts title="server.ts" theme={null}
import { monad } from "@monad-crypto/mpp/server";
import { Mppx } from "mppx";
import { privateKeyToAccount } from "viem/accounts";

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

const mppx = Mppx.create({
  methods: [
    monad({
      account,
      recipient: account.address,
    }),
  ],
});
```

### 保护端点

使用 `mppx.charge()` 作为中间件,在返回响应之前要求支付。

```ts title="server.ts" theme={null}
import { Hono } from "hono";

const app = new Hono();

app.get("/premium", mppx.charge(), async (ctx) => {
  return ctx.json({ message: "Premium content" });
});

export default app;
```

当客户端请求 `/premium` 但未提供有效的支付凭证时,服务器将返回 `402 Payment Required` 状态码及描述支付要求的 challenge。客户端随后提交凭证(交易哈希或已签名的授权)以完成支付。

### 测试网

默认情况下,该包连接到 Monad 主网(chain ID `143`)。要使用测试网,请设置 `testnet: true`。

```ts theme={null}
monad({
  account,
  recipient: account.address,
  testnet: true,
})
```

## 客户端

客户端处理钱包交互和凭证创建。从客户端入口导入 `monad`。

在使用本地私钥时,客户端默认使用 **pull 模式** —— 签署一个 ERC-3009 授权而不广播交易。

```ts title="client.ts" theme={null}
import { monad } from "@monad-crypto/mpp/client";
import { Mppx } from "mppx/client";
import { privateKeyToAccount } from "viem/accounts";

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

const mppx = Mppx.create({
  methods: [monad({ account })],
});

// 发起付费请求
const response = await fetch("http://localhost:3000/premium");
const data = await response.json();
console.log(data);
```

### Push 与 Pull 模式

|             | Push                    | Pull                              |
| ----------- | ----------------------- | --------------------------------- |
| **谁支付 gas** | 客户端                     | 服务端                               |
| **交易**      | 客户端广播 ERC-20 `transfer` | 服务端调用 `transferWithAuthorization` |
| **凭证**      | 交易哈希                    | 已签名的 ERC-3009 授权                  |
| **默认适用于**   | JSON-RPC 账户(浏览器钱包)      | 本地账户(私钥)                          |
| **权衡**      | 客户端需要 gas 代币            | 服务端需要 gas 代币                      |

### 覆盖模式

使用 `mode` 选项显式设置支付模式,无论账户类型如何。

```ts theme={null}
monad({
  account,
  mode: "push", // 始终广播交易
})

monad({
  account,
  mode: "pull", // 始终签署授权
})
```

### Monkey patch

客户端 `Mppx.create()` 函数会 [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch) Web `fetch` API,以便在收到 `402 Payment Required` HTTP 响应时使用配置的支付方式。

您也可以直接使用 `mppx.fetch`。

```ts title="client.ts" theme={null}
import { monad } from "@monad-crypto/mpp/client";
import { Mppx } from "mppx/client";
import { privateKeyToAccount } from "viem/accounts";

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

const mppx = Mppx.create({
  methods: [monad({ account })],
  polyfill: false,
});

const response = await mppx.fetch("http://localhost:3000/premium");
const data = await response.json();
console.log(data);
```

## 链接

* NPM 包:[@monad-crypto/mpp](https://www.npmjs.com/package/@monad-crypto/mpp)
* GitHub 仓库:[monad-crypto/monad-ts](https://github.com/monad-crypto/monad-ts)
