# m2m.monster

> Non-custodial settlement for agent-to-agent payments over x402 with the m2m-split scheme on Solana. Agents sign locally; m2m.monster holds no agents' keys or funds and never signs or pays payment transactions; payers pay their own gas.

- Network: `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` (solana-devnet)
- API: https://sandbox.m2m.monster/v1 · OpenAPI: https://sandbox.m2m.monster/v1/openapi.json · Errors: https://sandbox.m2m.monster/v1/errors
- MCP (streamable HTTP): https://sandbox.m2m.monster/mcp
- x402 scheme: `m2m-split` (x402 v2)

## Fee

`fee = min(max(0.25% × amount, $0.001), $0.5)`

- Borne by the payee: it receives the amount minus the fee.
- Paid in USDC (`4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU`) to the treasury `DeQ2ZniNv2BiK746guCUz8tcxJ1HvmLW1e7EjjTiMFMj`, inside the same transaction.
- Minimum payment $0.001. Fees round up to 0.000001 USDC.
- Quotes are valid for 30 seconds and show fee_gross, discount and fee_net.
- The payer pays its own gas and needs USDC for the fee even when paying in another token.

## Tokens (exact mint addresses)

- USDC: `4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU`

## Pay a seller that answers 402 (TypeScript)

```ts
import { createApiClient, createPaymentFetch } from "@m2m-monster/sdk";
import { createKeyPairSignerFromBytes, createSolanaRpc } from "@solana/kit";

const signer = await createKeyPairSignerFromBytes(yourSecretKeyBytes); // stays local
const api = createApiClient("https://sandbox.m2m.monster");
const pay = createPaymentFetch({
  rpc: createSolanaRpc(YOUR_RPC_URL),
  signer,
  serviceAddress: await api.serviceAddress(),
});
const res = await pay("https://seller.example/resource"); // 402 -> pay -> 200
```

## Get paid (TypeScript)

```ts
import { createApiClient, createPaywall } from "@m2m-monster/sdk";
import { createSolanaRpc } from "@solana/kit";

const paywall = createPaywall({
  api: createApiClient("https://sandbox.m2m.monster", { apiKey: YOUR_API_KEY }), // apiKey optional
  rpc: createSolanaRpc(YOUR_RPC_URL),
  network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
  payee: YOUR_WALLET,
});
// In any fetch-style handler:
return paywall.handle(request, { mint: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU", amount: "100000" }, { description: "..." }, () =>
  Response.json({ result: "..." }),
);
```

The payee's token account and the treasury USDC account must exist before paying; payments never create accounts.

## Try it on Devnet

`GET https://sandbox.m2m.monster/demo` answers 402 with an m2m-split quote for 0.01 Devnet USDC (fee 0.001 USDC). Pay it with Devnet funds:

```ts
const res = await pay("https://sandbox.m2m.monster/demo"); // createPaymentFetch from above, Devnet RPC and keys
console.log(res.status, await res.json()); // 200 and the receipt in PAYMENT-RESPONSE
```

## Quote with curl

```sh
curl -X POST https://sandbox.m2m.monster/v1/quotes \
  -H 'content-type: application/json' \
  -H 'idempotency-key: 6f1c2e8a-quote-1' \
  -d '{"network":"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1","mint":"4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU","amount":"100000","payee":"YOUR_WALLET"}'
```

## MCP

```json
{ "mcpServers": { "m2m-monster": { "url": "https://sandbox.m2m.monster/mcp" } } }
```

Tools: `get_pricing`, `quote_payment`, `build_payment`, `verify_payment`, `submit_payment`, `verify_receipt`, `build_refund`, `register_agent`, `get_referral_status`, `get_status`. Tools that move funds return unsigned transactions; sign them locally.

## Referrals

Register with `referred_by` (optional registration, challenge signed with your key). Referred agents get 25% off their fees for 90 days; referrers earn 10% of the fees their referred agents pay, as non-cash credits on their own fees (combined discounts at most 50% of each fee, credits expire after 12 months).

## Error codes

- `INVALID_REQUEST`
- `PAYMENT_BELOW_MINIMUM`
- `RECEIVER_TOKEN_ACCOUNT_MISSING`
- `SIMULATION_FAILED`
- `QUOTE_EXPIRED`
- `QUOTE_INVALID`
- `RATE_LIMITED`
- `MINT_NOT_ALLOWED`
- `FEE_BALANCE_INSUFFICIENT_USDC`
- `PAYMENT_TRANSACTION_INVALID`
- `TRANSACTION_FAILED`
- `RECEIPT_INVALID`
- `NOT_FOUND`
- `UNAUTHORIZED`
- `CHALLENGE_INVALID`
- `IDEMPOTENCY_KEY_REUSED`
- `INTERNAL_ERROR`
