mpp-test-sdk 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Node.js](https://img.shields.io/node/v/mpp-test-sdk)](https://nodejs.org)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-zinc.svg)](LICENSE)
6
6
 
7
- Test pay-per-request APIs on Tempo testnet. Auto-creates wallets, funds from faucet, handles 402 payments — zero setup required.
7
+ Test pay-per-request APIs on **Solana devnet**. Auto-creates wallets, airdrops SOL, handles HTTP 402 MPP payments — zero setup required.
8
8
 
9
9
  **[mpptestkit.com](https://mpptestkit.com)** · [GitHub](https://github.com/mpptestkit/mpp-test-sdk) · [X](https://x.com/mpptestkit)
10
10
 
@@ -25,6 +25,7 @@ Requires Node.js 22+.
25
25
  ```ts
26
26
  import { mppFetch } from "mpp-test-sdk";
27
27
 
28
+ // Auto-creates Solana wallet, airdrops SOL, handles 402
28
29
  const res = await mppFetch("https://your-api.com/api/data");
29
30
  const data = await res.json();
30
31
  ```
@@ -41,7 +42,7 @@ const client = await createTestClient({
41
42
  const res = await client.fetch("https://your-api.com/api/data");
42
43
  ```
43
44
 
44
- The SDK handles the full flow: wallet generation, testnet faucet funding, 402 detection, on-chain payment, and automatic retry with payment proof.
45
+ The SDK handles the full flow: Solana keypair generation, devnet SOL airdrop, 402 detection, on-chain SOL transfer, and automatic retry with payment proof.
45
46
 
46
47
  ---
47
48
 
@@ -52,13 +53,15 @@ import express from "express";
52
53
  import { createTestServer } from "mpp-test-sdk";
53
54
 
54
55
  const app = express();
55
- const mpp = createTestServer({ secretKey: process.env.MPP_SECRET_KEY });
56
+
57
+ // No config needed — auto-generates a server wallet
58
+ const mpp = createTestServer();
56
59
 
57
60
  // Free — no middleware
58
61
  app.get("/api/ping", (req, res) => res.json({ ok: true }));
59
62
 
60
- // Paid — one line
61
- app.get("/api/data", mpp.charge({ amount: "0.01" }), (req, res) => {
63
+ // Paid — one line (0.001 SOL)
64
+ app.get("/api/data", mpp.charge({ amount: "0.001" }), (req, res) => {
62
65
  res.json({ data: "premium content" });
63
66
  });
64
67
 
@@ -77,41 +80,40 @@ Call `mppFetch.reset()` to discard the shared client and generate a new wallet o
77
80
 
78
81
  ### `createTestClient(config?)`
79
82
 
80
- Creates a client with its own isolated wallet.
83
+ Creates a client with its own isolated Solana wallet.
81
84
 
82
85
  | Option | Type | Default | Description |
83
86
  |---|---|---|---|
84
- | `privateKey` | `` `0x${string}` `` | auto-generated | Reuse a pre-funded wallet |
87
+ | `secretKey` | `Uint8Array` | auto-generated | Reuse a pre-funded Solana keypair |
85
88
  | `onStep` | `(step: PaymentStep) => void` | — | Lifecycle event callback |
86
89
  | `timeout` | `number` | `30000` | Full flow timeout in ms |
87
- | `maxRetries` | `number` | `1` | Max retry attempts |
90
+ | `rpcUrl` | `string` | devnet RPC | Solana RPC endpoint |
88
91
 
89
92
  Returns `Promise<TestClient>` with `{ address, method, fetch }`.
90
93
 
91
- **Throws:** `MppFaucetError` if the testnet faucet is unreachable.
94
+ **Throws:** `MppFaucetError` if the Solana devnet airdrop fails.
92
95
 
93
- ### `createTestServer(config)`
96
+ ### `createTestServer(config?)`
94
97
 
95
- Creates Express middleware that enforces payment on any route.
98
+ Creates Express middleware that enforces MPP payment on any route.
96
99
 
97
100
  | Option | Type | Default | Description |
98
101
  |---|---|---|---|
99
- | `secretKey` | `string` | **required** | MPP secret key for payment verification |
100
- | `privateKey` | `` `0x${string}` `` | auto-generated | Server wallet private key |
101
- | `currency` | `` `0x${string}` `` | PathUSD | ERC-20 token address to accept |
102
+ | `secretKey` | `Uint8Array` | auto-generated | Server wallet keypair |
103
+ | `recipientAddress` | `string` | derived from keypair | Override recipient base58 address |
104
+ | `rpcUrl` | `string` | devnet RPC | Solana RPC for verification |
105
+ | `network` | `"devnet" \| "mainnet-beta"` | `"devnet"` | Network label in headers |
102
106
 
103
107
  Returns `MppServer` with `.charge({ amount })` middleware.
104
108
 
105
- **Throws:** `Error` synchronously if `secretKey` is missing.
106
-
107
109
  ### `PaymentStep` events
108
110
 
109
111
  | `step.type` | When |
110
112
  |---|---|
111
- | `"wallet-created"` | New ephemeral wallet generated |
112
- | `"funded"` | Faucet funding confirmed |
113
+ | `"wallet-created"` | Solana keypair generated |
114
+ | `"funded"` | Devnet airdrop confirmed |
113
115
  | `"request"` | Outgoing HTTP request |
114
- | `"payment"` | On-chain payment submitted |
116
+ | `"payment"` | SOL transfer submitted or confirmed |
115
117
  | `"success"` | Final 200 response received |
116
118
  | `"error"` | Flow failed |
117
119
 
@@ -126,40 +128,52 @@ try {
126
128
  const res = await client.fetch("https://api.example.com/data");
127
129
  } catch (err) {
128
130
  if (err instanceof MppFaucetError) {
129
- // Testnet faucet unreachable — err.address
131
+ // Devnet airdrop failed (rate limited) — err.address
130
132
  } else if (err instanceof MppPaymentError) {
131
- // Payment rejected — err.status, err.url
133
+ // Server rejected payment — err.status, err.url
132
134
  } else if (err instanceof MppTimeoutError) {
133
135
  // Flow timed out — err.url, err.timeoutMs
134
136
  }
135
137
  }
136
138
  ```
137
139
 
138
- **Tip:** Pass a pre-funded `privateKey` to `createTestClient` during development to skip faucet calls.
140
+ **Tip:** Pass a pre-funded `secretKey` to `createTestClient` to skip the airdrop step.
139
141
 
140
142
  ---
141
143
 
142
- ## Network
144
+ ## Protocol
145
+
146
+ The SDK implements **MPP (Machine Payments Protocol)** on Solana. The wire format is plain HTTP headers:
147
+
148
+ ```
149
+ # Server → Client (402)
150
+ Payment-Request: solana; amount="0.001"; recipient="<base58>"; network="devnet"
143
151
 
144
- All payments use **PathUSD** test tokens on **Tempo Moderato Testnet** (chain ID 42431). Real on-chain transactions, zero financial risk.
152
+ # Client Server (retry)
153
+ Payment-Receipt: solana; signature="<base58_sig>"; network="devnet"; amount="0.001"
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Network
145
159
 
146
160
  | | Value |
147
161
  |---|---|
148
- | Chain ID | `42431` |
149
- | RPC | `https://rpc.testnet.tempo.xyz` |
150
- | Explorer | `https://explorer.testnet.tempo.xyz` |
151
- | PathUSD | `0x20c0000000000000000000000000000000000000` |
152
- | Faucet | Automatic via SDK |
162
+ | Network | Solana Devnet |
163
+ | Currency | SOL (test) |
164
+ | RPC | `https://api.devnet.solana.com` |
165
+ | Explorer | `https://explorer.solana.com/?cluster=devnet` |
166
+ | Faucet | Automatic via `connection.requestAirdrop()` |
153
167
 
154
168
  ---
155
169
 
156
170
  ## Troubleshooting
157
171
 
158
- **`MppFaucetError`** — Faucet has rate limits. Wait a few seconds and retry, or pass a pre-funded `privateKey` to skip faucet calls.
172
+ **`MppFaucetError`** — Devnet airdrop is rate limited. Wait 30–60 seconds and retry, or pass a pre-funded `secretKey` to skip the faucet.
159
173
 
160
- **`MppTimeoutError`** — Increase `timeout` in `createTestClient`. On-chain confirmations typically take 2–5 seconds.
174
+ **`MppTimeoutError`** — Increase `timeout` in `createTestClient`. Solana devnet confirmations typically take 1–5 seconds.
161
175
 
162
- **402 not handled** — Ensure `createTestServer` is called with a valid `secretKey` and the middleware is placed before the route handler.
176
+ **402 not handled** — Ensure the server has `createTestServer()` middleware in place before the route handler.
163
177
 
164
178
  ---
165
179
 
package/dist/index.d.mts CHANGED
@@ -1,62 +1,86 @@
1
1
  import { RequestHandler } from 'express';
2
2
 
3
+ /** Solana network to connect to. */
4
+ type SolanaNetwork = "devnet" | "testnet" | "mainnet";
3
5
  interface PaymentStep {
4
- type: "wallet-created" | "funded" | "request" | "payment" | "success" | "error";
6
+ type: "wallet-created" | "funded" | "request" | "payment" | "retry" | "success" | "error";
5
7
  message: string;
6
8
  data?: Record<string, unknown>;
7
9
  }
8
10
  interface TestClientConfig {
9
- /** Use a specific wallet. If omitted, a new wallet is auto-generated. */
10
- privateKey?: `0x${string}`;
11
+ /**
12
+ * Solana network to connect to.
13
+ * - `"devnet"` (default) — Free SOL airdrop, fast confirmation.
14
+ * - `"testnet"` — Solana's testnet. Also has free airdrop.
15
+ * - `"mainnet"` — Real SOL. Requires a pre-funded `secretKey`.
16
+ */
17
+ network?: SolanaNetwork;
18
+ /**
19
+ * Pre-funded Solana keypair secret key (32 or 64 bytes).
20
+ * - On `devnet`/`testnet`: optional — wallet is auto-funded via airdrop.
21
+ * - On `mainnet`: **required** — no airdrop available.
22
+ */
23
+ secretKey?: Uint8Array;
11
24
  /** Lifecycle event callback for observing the payment flow. */
12
25
  onStep?: (step: PaymentStep) => void;
13
- /** Request timeout in milliseconds. Default: 30000 (30s). */
26
+ /** Full flow timeout in ms (wallet + payment + retry). Default: 30000. */
14
27
  timeout?: number;
15
- /** Maximum retry attempts for transient failures. Default: 1 (single 402 retry). */
16
- maxRetries?: number;
28
+ /** Override the Solana RPC endpoint. Takes precedence over `network`. */
29
+ rpcUrl?: string;
17
30
  }
18
31
  interface TestClient {
19
- /** The wallet address. */
32
+ /** Solana wallet address (base58 public key). */
20
33
  address: string;
21
- /** The payment method being used. */
22
- method: "tempo";
23
- /** Fetch a URL with automatic 402 payment handling. */
34
+ /** Network this client is connected to. */
35
+ network: SolanaNetwork;
36
+ /** Payment method. */
37
+ method: "solana";
38
+ /** Fetch a URL with automatic 402 MPP payment handling. */
24
39
  fetch: (url: string, init?: RequestInit) => Promise<Response>;
25
40
  }
26
41
  /**
27
- * Create an MPP test client.
42
+ * Create a Solana MPP test client.
28
43
  *
29
- * Auto-generates a wallet, funds it from the Tempo testnet faucet,
30
- * and handles 402 payments automatically.
44
+ * Automatically creates a Solana wallet, funds it (via airdrop on devnet/testnet),
45
+ * and handles HTTP 402 MPP payments with automatic retry.
31
46
  *
32
47
  * @example
33
48
  * ```ts
34
- * import { createTestClient } from "mpp-test-sdk";
35
- *
49
+ * // devnet (default) zero config
36
50
  * const client = await createTestClient();
37
- * const res = await client.fetch("http://localhost:3001/api/ping/paid");
38
- * const data = await res.json();
51
+ *
52
+ * // testnet
53
+ * const client = await createTestClient({ network: "testnet" });
54
+ *
55
+ * // mainnet — must provide pre-funded wallet
56
+ * const client = await createTestClient({
57
+ * network: "mainnet",
58
+ * secretKey: loadKeypairFromFile("./wallet.json").secretKey,
59
+ * });
60
+ *
61
+ * const res = await client.fetch("http://localhost:3001/api/data");
39
62
  * ```
40
63
  *
41
- * @throws {MppFaucetError} When the testnet faucet is unreachable or returns an error.
64
+ * @throws {MppNetworkError} When `mainnet` is specified without a `secretKey`.
65
+ * @throws {MppFaucetError} When the devnet/testnet airdrop fails after retries.
42
66
  */
43
67
  declare function createTestClient(config?: TestClientConfig): Promise<TestClient>;
44
68
  /**
45
- * One-shot fetch with automatic wallet creation, funding, and 402 payment.
69
+ * Drop-in replacement for `fetch` with automatic Solana MPP payment.
46
70
  *
47
- * Uses a shared client instance across calls (lazy-initialized on first call).
48
- * Call `mppFetch.reset()` to discard the shared instance.
71
+ * Uses a shared client instance lazily created on first call (devnet by default).
72
+ * Call `mppFetch.reset()` to discard the shared instance and generate a new wallet.
49
73
  *
50
74
  * @example
51
75
  * ```ts
52
76
  * import { mppFetch } from "mpp-test-sdk";
53
77
  *
54
- * const res = await mppFetch("http://localhost:3001/api/ping/paid");
78
+ * const res = await mppFetch("http://localhost:3001/api/data");
55
79
  * const data = await res.json();
56
80
  * ```
57
81
  *
58
- * @throws {MppFaucetError} When the testnet faucet is unreachable.
59
- * @throws {MppTimeoutError} When the request times out.
82
+ * @throws {MppFaucetError} When the devnet airdrop fails after retries.
83
+ * @throws {MppTimeoutError} When the full flow exceeds the timeout.
60
84
  */
61
85
  declare function mppFetch(url: string, init?: RequestInit): Promise<Response>;
62
86
  declare namespace mppFetch {
@@ -64,23 +88,46 @@ declare namespace mppFetch {
64
88
  }
65
89
 
66
90
  interface ChargeOptions {
67
- /** Amount to charge in PathUSD (e.g. "0.01"). */
91
+ /** Amount to charge in SOL (e.g. "0.001"). */
68
92
  amount: string;
69
93
  }
70
94
  interface MppServer {
71
- /** Express middleware that charges the specified amount before passing through. */
95
+ /**
96
+ * Express middleware that requires SOL payment before passing to the route handler.
97
+ *
98
+ * - No receipt → 402 with `Payment-Request` header.
99
+ * - Valid receipt + on-chain confirmation → calls `next()`.
100
+ * - Invalid or insufficient payment → 403.
101
+ */
72
102
  charge: (opts: ChargeOptions) => RequestHandler;
103
+ /** The Solana address where payments are sent. */
104
+ recipientAddress: string;
105
+ /** Network this server is configured for. */
106
+ network: SolanaNetwork;
73
107
  }
74
108
  interface TestServerConfig {
75
- /** Your MPP secret key. Required. */
76
- secretKey: string;
77
- /** Optional private key for the server wallet. Auto-generated if omitted. */
78
- privateKey?: `0x${string}`;
79
- /** Optional currency token address. Defaults to PathUSD on Tempo testnet. */
80
- currency?: `0x${string}`;
109
+ /**
110
+ * Solana network to connect to.
111
+ * - `"devnet"` (default) Solana devnet.
112
+ * - `"testnet"` — Solana testnet.
113
+ * - `"mainnet"` Solana mainnet (real SOL).
114
+ */
115
+ network?: SolanaNetwork;
116
+ /** Server wallet keypair secret key. Auto-generated if omitted. */
117
+ secretKey?: Uint8Array;
118
+ /**
119
+ * Override the recipient Solana address (base58).
120
+ * Defaults to the server keypair's public key.
121
+ */
122
+ recipientAddress?: string;
123
+ /** Override the Solana RPC endpoint. Takes precedence over `network`. */
124
+ rpcUrl?: string;
81
125
  }
82
126
  /**
83
- * Create an MPP-enabled Express middleware.
127
+ * Create a Solana MPP-enabled Express server.
128
+ *
129
+ * Handles the HTTP 402 payment flow and verifies SOL transfers on-chain.
130
+ * No config needed — auto-generates a server wallet.
84
131
  *
85
132
  * @example
86
133
  * ```ts
@@ -88,11 +135,15 @@ interface TestServerConfig {
88
135
  * import { createTestServer } from "mpp-test-sdk";
89
136
  *
90
137
  * const app = express();
91
- * const mpp = createTestServer({ secretKey: "sk_test_..." });
92
- * app.get("/api/paid", mpp.charge({ amount: "0.01" }), (req, res) => res.json({ ok: true }));
138
+ * const mpp = createTestServer(); // or createTestServer({ network: "mainnet" })
139
+ *
140
+ * // Charge 0.001 SOL per request
141
+ * app.get("/api/data", mpp.charge({ amount: "0.001" }), (req, res) => {
142
+ * res.json({ data: "premium content" });
143
+ * });
93
144
  * ```
94
145
  */
95
- declare function createTestServer(config: TestServerConfig): MppServer;
146
+ declare function createTestServer(config?: TestServerConfig): MppServer;
96
147
 
97
148
  declare class MppError extends Error {
98
149
  constructor(message: string);
@@ -111,5 +162,9 @@ declare class MppTimeoutError extends MppError {
111
162
  readonly timeoutMs: number;
112
163
  constructor(url: string, timeoutMs: number);
113
164
  }
165
+ declare class MppNetworkError extends MppError {
166
+ readonly network: string;
167
+ constructor(network: string, message?: string);
168
+ }
114
169
 
115
- export { type ChargeOptions, MppError, MppFaucetError, MppPaymentError, type MppServer, MppTimeoutError, type PaymentStep, type TestClient, type TestClientConfig, type TestServerConfig, createTestClient, createTestServer, mppFetch };
170
+ export { type ChargeOptions, MppError, MppFaucetError, MppNetworkError, MppPaymentError, type MppServer, MppTimeoutError, type PaymentStep, type SolanaNetwork, type TestClient, type TestClientConfig, type TestServerConfig, createTestClient, createTestServer, mppFetch };
package/dist/index.d.ts CHANGED
@@ -1,62 +1,86 @@
1
1
  import { RequestHandler } from 'express';
2
2
 
3
+ /** Solana network to connect to. */
4
+ type SolanaNetwork = "devnet" | "testnet" | "mainnet";
3
5
  interface PaymentStep {
4
- type: "wallet-created" | "funded" | "request" | "payment" | "success" | "error";
6
+ type: "wallet-created" | "funded" | "request" | "payment" | "retry" | "success" | "error";
5
7
  message: string;
6
8
  data?: Record<string, unknown>;
7
9
  }
8
10
  interface TestClientConfig {
9
- /** Use a specific wallet. If omitted, a new wallet is auto-generated. */
10
- privateKey?: `0x${string}`;
11
+ /**
12
+ * Solana network to connect to.
13
+ * - `"devnet"` (default) — Free SOL airdrop, fast confirmation.
14
+ * - `"testnet"` — Solana's testnet. Also has free airdrop.
15
+ * - `"mainnet"` — Real SOL. Requires a pre-funded `secretKey`.
16
+ */
17
+ network?: SolanaNetwork;
18
+ /**
19
+ * Pre-funded Solana keypair secret key (32 or 64 bytes).
20
+ * - On `devnet`/`testnet`: optional — wallet is auto-funded via airdrop.
21
+ * - On `mainnet`: **required** — no airdrop available.
22
+ */
23
+ secretKey?: Uint8Array;
11
24
  /** Lifecycle event callback for observing the payment flow. */
12
25
  onStep?: (step: PaymentStep) => void;
13
- /** Request timeout in milliseconds. Default: 30000 (30s). */
26
+ /** Full flow timeout in ms (wallet + payment + retry). Default: 30000. */
14
27
  timeout?: number;
15
- /** Maximum retry attempts for transient failures. Default: 1 (single 402 retry). */
16
- maxRetries?: number;
28
+ /** Override the Solana RPC endpoint. Takes precedence over `network`. */
29
+ rpcUrl?: string;
17
30
  }
18
31
  interface TestClient {
19
- /** The wallet address. */
32
+ /** Solana wallet address (base58 public key). */
20
33
  address: string;
21
- /** The payment method being used. */
22
- method: "tempo";
23
- /** Fetch a URL with automatic 402 payment handling. */
34
+ /** Network this client is connected to. */
35
+ network: SolanaNetwork;
36
+ /** Payment method. */
37
+ method: "solana";
38
+ /** Fetch a URL with automatic 402 MPP payment handling. */
24
39
  fetch: (url: string, init?: RequestInit) => Promise<Response>;
25
40
  }
26
41
  /**
27
- * Create an MPP test client.
42
+ * Create a Solana MPP test client.
28
43
  *
29
- * Auto-generates a wallet, funds it from the Tempo testnet faucet,
30
- * and handles 402 payments automatically.
44
+ * Automatically creates a Solana wallet, funds it (via airdrop on devnet/testnet),
45
+ * and handles HTTP 402 MPP payments with automatic retry.
31
46
  *
32
47
  * @example
33
48
  * ```ts
34
- * import { createTestClient } from "mpp-test-sdk";
35
- *
49
+ * // devnet (default) zero config
36
50
  * const client = await createTestClient();
37
- * const res = await client.fetch("http://localhost:3001/api/ping/paid");
38
- * const data = await res.json();
51
+ *
52
+ * // testnet
53
+ * const client = await createTestClient({ network: "testnet" });
54
+ *
55
+ * // mainnet — must provide pre-funded wallet
56
+ * const client = await createTestClient({
57
+ * network: "mainnet",
58
+ * secretKey: loadKeypairFromFile("./wallet.json").secretKey,
59
+ * });
60
+ *
61
+ * const res = await client.fetch("http://localhost:3001/api/data");
39
62
  * ```
40
63
  *
41
- * @throws {MppFaucetError} When the testnet faucet is unreachable or returns an error.
64
+ * @throws {MppNetworkError} When `mainnet` is specified without a `secretKey`.
65
+ * @throws {MppFaucetError} When the devnet/testnet airdrop fails after retries.
42
66
  */
43
67
  declare function createTestClient(config?: TestClientConfig): Promise<TestClient>;
44
68
  /**
45
- * One-shot fetch with automatic wallet creation, funding, and 402 payment.
69
+ * Drop-in replacement for `fetch` with automatic Solana MPP payment.
46
70
  *
47
- * Uses a shared client instance across calls (lazy-initialized on first call).
48
- * Call `mppFetch.reset()` to discard the shared instance.
71
+ * Uses a shared client instance lazily created on first call (devnet by default).
72
+ * Call `mppFetch.reset()` to discard the shared instance and generate a new wallet.
49
73
  *
50
74
  * @example
51
75
  * ```ts
52
76
  * import { mppFetch } from "mpp-test-sdk";
53
77
  *
54
- * const res = await mppFetch("http://localhost:3001/api/ping/paid");
78
+ * const res = await mppFetch("http://localhost:3001/api/data");
55
79
  * const data = await res.json();
56
80
  * ```
57
81
  *
58
- * @throws {MppFaucetError} When the testnet faucet is unreachable.
59
- * @throws {MppTimeoutError} When the request times out.
82
+ * @throws {MppFaucetError} When the devnet airdrop fails after retries.
83
+ * @throws {MppTimeoutError} When the full flow exceeds the timeout.
60
84
  */
61
85
  declare function mppFetch(url: string, init?: RequestInit): Promise<Response>;
62
86
  declare namespace mppFetch {
@@ -64,23 +88,46 @@ declare namespace mppFetch {
64
88
  }
65
89
 
66
90
  interface ChargeOptions {
67
- /** Amount to charge in PathUSD (e.g. "0.01"). */
91
+ /** Amount to charge in SOL (e.g. "0.001"). */
68
92
  amount: string;
69
93
  }
70
94
  interface MppServer {
71
- /** Express middleware that charges the specified amount before passing through. */
95
+ /**
96
+ * Express middleware that requires SOL payment before passing to the route handler.
97
+ *
98
+ * - No receipt → 402 with `Payment-Request` header.
99
+ * - Valid receipt + on-chain confirmation → calls `next()`.
100
+ * - Invalid or insufficient payment → 403.
101
+ */
72
102
  charge: (opts: ChargeOptions) => RequestHandler;
103
+ /** The Solana address where payments are sent. */
104
+ recipientAddress: string;
105
+ /** Network this server is configured for. */
106
+ network: SolanaNetwork;
73
107
  }
74
108
  interface TestServerConfig {
75
- /** Your MPP secret key. Required. */
76
- secretKey: string;
77
- /** Optional private key for the server wallet. Auto-generated if omitted. */
78
- privateKey?: `0x${string}`;
79
- /** Optional currency token address. Defaults to PathUSD on Tempo testnet. */
80
- currency?: `0x${string}`;
109
+ /**
110
+ * Solana network to connect to.
111
+ * - `"devnet"` (default) Solana devnet.
112
+ * - `"testnet"` — Solana testnet.
113
+ * - `"mainnet"` Solana mainnet (real SOL).
114
+ */
115
+ network?: SolanaNetwork;
116
+ /** Server wallet keypair secret key. Auto-generated if omitted. */
117
+ secretKey?: Uint8Array;
118
+ /**
119
+ * Override the recipient Solana address (base58).
120
+ * Defaults to the server keypair's public key.
121
+ */
122
+ recipientAddress?: string;
123
+ /** Override the Solana RPC endpoint. Takes precedence over `network`. */
124
+ rpcUrl?: string;
81
125
  }
82
126
  /**
83
- * Create an MPP-enabled Express middleware.
127
+ * Create a Solana MPP-enabled Express server.
128
+ *
129
+ * Handles the HTTP 402 payment flow and verifies SOL transfers on-chain.
130
+ * No config needed — auto-generates a server wallet.
84
131
  *
85
132
  * @example
86
133
  * ```ts
@@ -88,11 +135,15 @@ interface TestServerConfig {
88
135
  * import { createTestServer } from "mpp-test-sdk";
89
136
  *
90
137
  * const app = express();
91
- * const mpp = createTestServer({ secretKey: "sk_test_..." });
92
- * app.get("/api/paid", mpp.charge({ amount: "0.01" }), (req, res) => res.json({ ok: true }));
138
+ * const mpp = createTestServer(); // or createTestServer({ network: "mainnet" })
139
+ *
140
+ * // Charge 0.001 SOL per request
141
+ * app.get("/api/data", mpp.charge({ amount: "0.001" }), (req, res) => {
142
+ * res.json({ data: "premium content" });
143
+ * });
93
144
  * ```
94
145
  */
95
- declare function createTestServer(config: TestServerConfig): MppServer;
146
+ declare function createTestServer(config?: TestServerConfig): MppServer;
96
147
 
97
148
  declare class MppError extends Error {
98
149
  constructor(message: string);
@@ -111,5 +162,9 @@ declare class MppTimeoutError extends MppError {
111
162
  readonly timeoutMs: number;
112
163
  constructor(url: string, timeoutMs: number);
113
164
  }
165
+ declare class MppNetworkError extends MppError {
166
+ readonly network: string;
167
+ constructor(network: string, message?: string);
168
+ }
114
169
 
115
- export { type ChargeOptions, MppError, MppFaucetError, MppPaymentError, type MppServer, MppTimeoutError, type PaymentStep, type TestClient, type TestClientConfig, type TestServerConfig, createTestClient, createTestServer, mppFetch };
170
+ export { type ChargeOptions, MppError, MppFaucetError, MppNetworkError, MppPaymentError, type MppServer, MppTimeoutError, type PaymentStep, type SolanaNetwork, type TestClient, type TestClientConfig, type TestServerConfig, createTestClient, createTestServer, mppFetch };