mpp-test-sdk 1.1.1 → 1.1.2

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,9 +4,9 @@
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 **Solana devnet**. Auto-creates wallets, airdrops SOL, handles HTTP 402 MPP payments zero setup required.
7
+ Test pay-per-request APIs on **Solana** - devnet, testnet, or mainnet. Auto-creates wallets, airdrops SOL, handles HTTP 402 MPP payments. Zero setup required.
8
8
 
9
- **[mpptestkit.com](https://mpptestkit.com)** · [GitHub](https://github.com/mpptestkit/mpp-test-sdk) · [X](https://x.com/mpptestkit)
9
+ **[mpptestkit.com](https://mpptestkit.com)** · [Playground](https://mpptestkit.com/playground) · [Docs](https://mpptestkit.com/docs) · [GitHub](https://github.com/mpptestkit/mpp-test-sdk) · [X](https://x.com/mpptestkit)
10
10
 
11
11
  ---
12
12
 
@@ -16,7 +16,7 @@ Test pay-per-request APIs on **Solana devnet**. Auto-creates wallets, airdrops S
16
16
  npm i mpp-test-sdk
17
17
  ```
18
18
 
19
- Requires Node.js 22+.
19
+ Requires Node.js 18+.
20
20
 
21
21
  ---
22
22
 
@@ -25,9 +25,16 @@ 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
+ // One line. No wallet setup. No config.
29
29
  const res = await mppFetch("https://your-api.com/api/data");
30
30
  const data = await res.json();
31
+
32
+ // What happened automatically:
33
+ // 1. SDK generated a Solana keypair
34
+ // 2. Airdropped 2 SOL from the devnet faucet
35
+ // 3. Server returned 402 Payment Required
36
+ // 4. SDK sent 0.001 SOL on Solana (~800ms finality)
37
+ // 5. Retried with Payment-Receipt header → 200 OK
31
38
  ```
32
39
 
33
40
  Or with a dedicated client instance:
@@ -36,13 +43,14 @@ Or with a dedicated client instance:
36
43
  import { createTestClient } from "mpp-test-sdk";
37
44
 
38
45
  const client = await createTestClient({
46
+ network: "devnet",
39
47
  onStep: (step) => console.log(step.type, step.message),
40
48
  });
41
49
 
42
50
  const res = await client.fetch("https://your-api.com/api/data");
43
51
  ```
44
52
 
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.
53
+ Call `mppFetch.reset()` to discard the shared client and generate a fresh wallet on the next request.
46
54
 
47
55
  ---
48
56
 
@@ -53,19 +61,19 @@ import express from "express";
53
61
  import { createTestServer } from "mpp-test-sdk";
54
62
 
55
63
  const app = express();
64
+ const mpp = createTestServer(); // auto-generates server wallet
56
65
 
57
- // No config needed — auto-generates a server wallet
58
- const mpp = createTestServer();
59
-
60
- // Free — no middleware
66
+ // Free - no middleware
61
67
  app.get("/api/ping", (req, res) => res.json({ ok: true }));
62
68
 
63
- // Paid one line (0.001 SOL)
64
- app.get("/api/data", mpp.charge({ amount: "0.001" }), (req, res) => {
65
- res.json({ data: "premium content" });
66
- });
69
+ // Paid - one line (0.001 SOL)
70
+ app.get("/api/data",
71
+ mpp.charge({ amount: "0.001" }),
72
+ (req, res) => res.json({ data: "premium content" })
73
+ );
67
74
 
68
75
  app.listen(3001);
76
+ console.log("Payments go to:", mpp.recipientAddress);
69
77
  ```
70
78
 
71
79
  ---
@@ -74,9 +82,7 @@ app.listen(3001);
74
82
 
75
83
  ### `mppFetch(url, init?)`
76
84
 
77
- Drop-in replacement for `fetch`. Uses a shared client lazily created on first call.
78
-
79
- Call `mppFetch.reset()` to discard the shared client and generate a new wallet on the next request.
85
+ Drop-in replacement for `fetch`. Lazily creates a shared client on first call and reuses it across requests.
80
86
 
81
87
  ### `createTestClient(config?)`
82
88
 
@@ -84,36 +90,58 @@ Creates a client with its own isolated Solana wallet.
84
90
 
85
91
  | Option | Type | Default | Description |
86
92
  |---|---|---|---|
87
- | `secretKey` | `Uint8Array` | auto-generated | Reuse a pre-funded Solana keypair |
88
- | `onStep` | `(step: PaymentStep) => void` | | Lifecycle event callback |
93
+ | `network` | `"devnet" \| "testnet" \| "mainnet"` | `"devnet"` | Solana network to use |
94
+ | `secretKey` | `Uint8Array \| number[]` | auto-generated | Reuse a pre-funded keypair (required on mainnet) |
95
+ | `onStep` | `(step: PaymentStep) => void` | - | Lifecycle event callback |
89
96
  | `timeout` | `number` | `30000` | Full flow timeout in ms |
90
- | `rpcUrl` | `string` | devnet RPC | Solana RPC endpoint |
91
97
 
92
- Returns `Promise<TestClient>` with `{ address, method, fetch }`.
98
+ Returns `Promise<TestClient>`:
99
+
100
+ ```ts
101
+ interface TestClient {
102
+ address: string; // Solana public key (base58)
103
+ network: SolanaNetwork;
104
+ fetch: (url: string, init?: RequestInit) => Promise<Response>;
105
+ }
106
+ ```
93
107
 
94
- **Throws:** `MppFaucetError` if the Solana devnet airdrop fails.
108
+ **Throws:**
109
+ - `MppFaucetError` - devnet/testnet airdrop failed
110
+ - `MppNetworkError` - mainnet used without a `secretKey`
95
111
 
96
112
  ### `createTestServer(config?)`
97
113
 
98
- Creates Express middleware that enforces MPP payment on any route.
114
+ Creates Express middleware that enforces payment on any route.
99
115
 
100
116
  | Option | Type | Default | Description |
101
117
  |---|---|---|---|
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 |
118
+ | `network` | `"devnet" \| "testnet" \| "mainnet"` | `"devnet"` | Solana network to verify payments on |
119
+ | `secretKey` | `Uint8Array \| number[]` | auto-generated | Server wallet keypair |
120
+
121
+ **Properties:**
122
+
123
+ | Property | Description |
124
+ |---|---|
125
+ | `mpp.recipientAddress` | Server wallet public key - payments land here |
126
+ | `mpp.network` | Active network |
127
+
128
+ ### `mpp.charge(opts)`
106
129
 
107
- Returns `MppServer` with `.charge({ amount })` middleware.
130
+ Express `RequestHandler`. Place before your route handler.
131
+
132
+ | Option | Type | Description |
133
+ |---|---|---|
134
+ | `amount` | `string` | Amount in SOL, e.g. `"0.001"` |
108
135
 
109
136
  ### `PaymentStep` events
110
137
 
111
138
  | `step.type` | When |
112
139
  |---|---|
113
140
  | `"wallet-created"` | Solana keypair generated |
114
- | `"funded"` | Devnet airdrop confirmed |
115
- | `"request"` | Outgoing HTTP request |
116
- | `"payment"` | SOL transfer submitted or confirmed |
141
+ | `"funded"` | Faucet airdrop confirmed (devnet/testnet) |
142
+ | `"request"` | Outgoing HTTP request fired |
143
+ | `"payment"` | SOL transaction submitted and confirmed |
144
+ | `"retry"` | Request retried with Payment-Receipt header |
117
145
  | `"success"` | Final 200 response received |
118
146
  | `"error"` | Flow failed |
119
147
 
@@ -122,58 +150,79 @@ Returns `MppServer` with `.charge({ amount })` middleware.
122
150
  ## Error Handling
123
151
 
124
152
  ```ts
125
- import { MppFaucetError, MppPaymentError, MppTimeoutError } from "mpp-test-sdk";
153
+ import {
154
+ MppError,
155
+ MppFaucetError,
156
+ MppPaymentError,
157
+ MppTimeoutError,
158
+ MppNetworkError,
159
+ } from "mpp-test-sdk";
126
160
 
127
161
  try {
128
- const res = await client.fetch("https://api.example.com/data");
162
+ const res = await mppFetch("https://api.example.com/data");
129
163
  } catch (err) {
130
- if (err instanceof MppFaucetError) {
131
- // Devnet airdrop failed (rate limited) — err.address
164
+ if (err instanceof MppNetworkError) {
165
+ // Mainnet used without secretKey
166
+ } else if (err instanceof MppFaucetError) {
167
+ // Devnet/testnet airdrop failed - err.address
132
168
  } else if (err instanceof MppPaymentError) {
133
- // Server rejected payment err.status, err.url
169
+ // Server rejected payment - err.status, err.url
134
170
  } else if (err instanceof MppTimeoutError) {
135
- // Flow timed out err.url, err.timeoutMs
171
+ // Flow timed out - err.url, err.timeoutMs
136
172
  }
137
173
  }
138
174
  ```
139
175
 
140
- **Tip:** Pass a pre-funded `secretKey` to `createTestClient` to skip the airdrop step.
176
+ **Tip:** Pass a pre-funded `secretKey` to skip faucet calls entirely - useful in CI or when devnet is rate-limiting.
141
177
 
142
178
  ---
143
179
 
144
180
  ## Protocol
145
181
 
146
- The SDK implements **MPP (Machine Payments Protocol)** on Solana. The wire format is plain HTTP headers:
182
+ The SDK implements **MPP (Machine Payments Protocol)** on Solana. Plain HTTP headers, no custom transport:
147
183
 
148
184
  ```
149
- # Server → Client (402)
150
- Payment-Request: solana; amount="0.001"; recipient="<base58>"; network="devnet"
185
+ # Server → Client (402 Payment Required)
186
+ Payment-Request: solana; amount="0.001"; recipient="9WzDX..."; network="devnet"
151
187
 
152
- # Client → Server (retry)
153
- Payment-Receipt: solana; signature="<base58_sig>"; network="devnet"; amount="0.001"
188
+ # Client → Server (retry with proof)
189
+ Payment-Receipt: solana; signature="3xKm7..."; network="devnet"
154
190
  ```
155
191
 
192
+ On-chain verification confirms: transaction exists, recipient matches, SOL delta ≥ required amount.
193
+
156
194
  ---
157
195
 
158
- ## Network
196
+ ## Networks
159
197
 
160
- | | Value |
161
- |---|---|
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()` |
198
+ | | devnet | testnet | mainnet |
199
+ |---|---|---|---|
200
+ | Faucet | Auto (2 SOL) | Auto (2 SOL) | Bring your own |
201
+ | Cost | Free | Free | Real SOL |
202
+ | Use for | Local dev, CI | Pre-production | Production |
203
+
204
+ ```ts
205
+ // Devnet (default)
206
+ const client = await createTestClient({ network: "devnet" });
207
+
208
+ // Mainnet - bring your own funded keypair
209
+ const client = await createTestClient({
210
+ network: "mainnet",
211
+ secretKey: Uint8Array.from(JSON.parse(process.env.SOLANA_SECRET_KEY!)),
212
+ });
213
+ ```
167
214
 
168
215
  ---
169
216
 
170
217
  ## Troubleshooting
171
218
 
172
- **`MppFaucetError`** Devnet airdrop is rate limited. Wait 30–60 seconds and retry, or pass a pre-funded `secretKey` to skip the faucet.
219
+ **`MppFaucetError`** - Devnet airdrop is rate-limited. Wait 30–60 seconds and retry, or pass a pre-funded `secretKey` to skip the faucet.
220
+
221
+ **`MppNetworkError`** - You passed `network: "mainnet"` without a `secretKey`. Mainnet has no faucet - provide a funded keypair.
173
222
 
174
- **`MppTimeoutError`** Increase `timeout` in `createTestClient`. Solana devnet confirmations typically take 1–5 seconds.
223
+ **`MppTimeoutError`** - Increase `timeout` in `createTestClient`. Solana devnet confirmations typically take 1–3 seconds.
175
224
 
176
- **402 not handled** Ensure the server has `createTestServer()` middleware in place before the route handler.
225
+ **402 not handled** - Ensure `mpp.charge()` middleware is placed before the route handler on the server.
177
226
 
178
227
  ---
179
228
 
package/dist/index.d.mts CHANGED
@@ -10,15 +10,15 @@ interface PaymentStep {
10
10
  interface TestClientConfig {
11
11
  /**
12
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`.
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
16
  */
17
17
  network?: SolanaNetwork;
18
18
  /**
19
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.
20
+ * - On `devnet`/`testnet`: optional - wallet is auto-funded via airdrop.
21
+ * - On `mainnet`: **required** - no airdrop available.
22
22
  */
23
23
  secretKey?: Uint8Array;
24
24
  /** Lifecycle event callback for observing the payment flow. */
@@ -46,13 +46,13 @@ interface TestClient {
46
46
  *
47
47
  * @example
48
48
  * ```ts
49
- * // devnet (default) zero config
49
+ * // devnet (default) - zero config
50
50
  * const client = await createTestClient();
51
51
  *
52
52
  * // testnet
53
53
  * const client = await createTestClient({ network: "testnet" });
54
54
  *
55
- * // mainnet must provide pre-funded wallet
55
+ * // mainnet - must provide pre-funded wallet
56
56
  * const client = await createTestClient({
57
57
  * network: "mainnet",
58
58
  * secretKey: loadKeypairFromFile("./wallet.json").secretKey,
@@ -108,9 +108,9 @@ interface MppServer {
108
108
  interface TestServerConfig {
109
109
  /**
110
110
  * Solana network to connect to.
111
- * - `"devnet"` (default) Solana devnet.
112
- * - `"testnet"` Solana testnet.
113
- * - `"mainnet"` Solana mainnet (real SOL).
111
+ * - `"devnet"` (default) - Solana devnet.
112
+ * - `"testnet"` - Solana testnet.
113
+ * - `"mainnet"` - Solana mainnet (real SOL).
114
114
  */
115
115
  network?: SolanaNetwork;
116
116
  /** Server wallet keypair secret key. Auto-generated if omitted. */
@@ -127,7 +127,7 @@ interface TestServerConfig {
127
127
  * Create a Solana MPP-enabled Express server.
128
128
  *
129
129
  * Handles the HTTP 402 payment flow and verifies SOL transfers on-chain.
130
- * No config needed auto-generates a server wallet.
130
+ * No config needed - auto-generates a server wallet.
131
131
  *
132
132
  * @example
133
133
  * ```ts
package/dist/index.d.ts CHANGED
@@ -10,15 +10,15 @@ interface PaymentStep {
10
10
  interface TestClientConfig {
11
11
  /**
12
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`.
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
16
  */
17
17
  network?: SolanaNetwork;
18
18
  /**
19
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.
20
+ * - On `devnet`/`testnet`: optional - wallet is auto-funded via airdrop.
21
+ * - On `mainnet`: **required** - no airdrop available.
22
22
  */
23
23
  secretKey?: Uint8Array;
24
24
  /** Lifecycle event callback for observing the payment flow. */
@@ -46,13 +46,13 @@ interface TestClient {
46
46
  *
47
47
  * @example
48
48
  * ```ts
49
- * // devnet (default) zero config
49
+ * // devnet (default) - zero config
50
50
  * const client = await createTestClient();
51
51
  *
52
52
  * // testnet
53
53
  * const client = await createTestClient({ network: "testnet" });
54
54
  *
55
- * // mainnet must provide pre-funded wallet
55
+ * // mainnet - must provide pre-funded wallet
56
56
  * const client = await createTestClient({
57
57
  * network: "mainnet",
58
58
  * secretKey: loadKeypairFromFile("./wallet.json").secretKey,
@@ -108,9 +108,9 @@ interface MppServer {
108
108
  interface TestServerConfig {
109
109
  /**
110
110
  * Solana network to connect to.
111
- * - `"devnet"` (default) Solana devnet.
112
- * - `"testnet"` Solana testnet.
113
- * - `"mainnet"` Solana mainnet (real SOL).
111
+ * - `"devnet"` (default) - Solana devnet.
112
+ * - `"testnet"` - Solana testnet.
113
+ * - `"mainnet"` - Solana mainnet (real SOL).
114
114
  */
115
115
  network?: SolanaNetwork;
116
116
  /** Server wallet keypair secret key. Auto-generated if omitted. */
@@ -127,7 +127,7 @@ interface TestServerConfig {
127
127
  * Create a Solana MPP-enabled Express server.
128
128
  *
129
129
  * Handles the HTTP 402 payment flow and verifies SOL transfers on-chain.
130
- * No config needed auto-generates a server wallet.
130
+ * No config needed - auto-generates a server wallet.
131
131
  *
132
132
  * @example
133
133
  * ```ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mpp-test-sdk",
3
- "version": "1.1.1",
4
- "description": "Test pay-per-request APIs on Solana devnet. Auto-creates wallets, airdrops SOL, handles 402 MPP payments zero setup required.",
3
+ "version": "1.1.2",
4
+ "description": "Test pay-per-request APIs on Solana devnet. Auto-creates wallets, airdrops SOL, handles 402 MPP payments - zero setup required.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",