across-pay-mpp 1.0.0
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/.env +3 -0
- package/.env.example +5 -0
- package/.herenow/state.json +7 -0
- package/PRD.md +236 -0
- package/PROGRESS-UPDATE.md +214 -0
- package/README.md +35 -0
- package/SESSION-LOG.md +122 -0
- package/STEP2-DEMO-PLAN.md +357 -0
- package/TEST-RESULTS.md +477 -0
- package/across-mpp-bridge/.herenow/state.json +7 -0
- package/across-mpp-bridge/SKILL.md +118 -0
- package/across-mpp-bridge/index.html +427 -0
- package/firecrawl-response.json +23 -0
- package/package.json +29 -0
- package/src/buyer/across.ts +152 -0
- package/src/buyer/balance.ts +106 -0
- package/src/buyer/tempo-wallet.ts +42 -0
- package/src/buyer/tempo-with-across.ts +327 -0
- package/src/demo/external.ts +280 -0
- package/src/demo/local.ts +202 -0
- package/src/dev/client.ts +30 -0
- package/src/dev/preflight.ts +133 -0
- package/src/dev/server.ts +97 -0
- package/src/dev/swap-for-gas.ts +50 -0
- package/src/index.ts +2 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# MPP Step 2 Demo Plan
|
|
2
|
+
|
|
3
|
+
**Status:** Agreed plan
|
|
4
|
+
**Date locked:** March 31, 2026
|
|
5
|
+
**Audience:** Stripe-facing MPP demo only
|
|
6
|
+
**Goal:** Prove that agents can avoid per-request bridging by paying locally on Arbitrum, while the merchant still settles treasury to Tempo via hourly batching.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Locked Decisions
|
|
11
|
+
|
|
12
|
+
- Keep the `MPP` Step 2 demo code **separate** from `x402`.
|
|
13
|
+
- Buyer starts with funds on **Arbitrum**.
|
|
14
|
+
- Merchant's preferred settlement chain is **Tempo**.
|
|
15
|
+
- Token can be **USDC** or **USDC.e**, whichever is simplest in the implementation.
|
|
16
|
+
- Receiver is **predeployed** before the demo.
|
|
17
|
+
- Verifier is **run by us**.
|
|
18
|
+
- Each paid request is **$0.02**.
|
|
19
|
+
- Demo shows **3 successful payments**.
|
|
20
|
+
- Merchant serves after **each** successful payment.
|
|
21
|
+
- After payment 3, the demo shows a live **manual trigger of the hourly sweep**.
|
|
22
|
+
- Step 1 comparison is explained **verbally**, not shown as a second live path.
|
|
23
|
+
- Buyer UX should still feel like an **MPP flow**, even though the buyer is Step 2-aware under the hood.
|
|
24
|
+
- Buyer retry should send **`reference + txHash`** back to the merchant.
|
|
25
|
+
- Do **not** retrofit the existing `src/dev/server.ts`; build a **new Step 2 server**.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Demo Story
|
|
30
|
+
|
|
31
|
+
This is the exact story we are telling:
|
|
32
|
+
|
|
33
|
+
1. Merchant wants final settlement on **Tempo**.
|
|
34
|
+
2. Agent only has funds on **Arbitrum**.
|
|
35
|
+
3. Merchant returns an MPP-facing 402 challenge.
|
|
36
|
+
4. Buyer derives the merchant's deterministic Arbitrum receiver and proves it exists.
|
|
37
|
+
5. Buyer pays the receiver locally on Arbitrum.
|
|
38
|
+
6. Merchant verifies the Arbitrum payment and serves immediately.
|
|
39
|
+
7. This happens three times.
|
|
40
|
+
8. After the third payment, the operator triggers the scheduled hourly sweep.
|
|
41
|
+
9. Accumulated funds move from the Arbitrum receiver to the merchant's Tempo settlement address.
|
|
42
|
+
|
|
43
|
+
**Headline:** the user got three successful paid responses without three separate bridge operations.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## What "MPP Step 2" Means
|
|
48
|
+
|
|
49
|
+
This is **not** the current Step 1 flow in `tempo-with-across.ts`.
|
|
50
|
+
|
|
51
|
+
Step 1 today:
|
|
52
|
+
|
|
53
|
+
- buyer gets Tempo challenge
|
|
54
|
+
- if buyer lacks Tempo funds, Across bridges to the buyer on Tempo
|
|
55
|
+
- buyer completes a normal Tempo payment
|
|
56
|
+
|
|
57
|
+
Step 2 for this demo:
|
|
58
|
+
|
|
59
|
+
- buyer gets an MPP-facing challenge
|
|
60
|
+
- buyer checks whether the merchant has a deployed receiver on **Arbitrum**
|
|
61
|
+
- if yes, buyer pays that receiver locally on Arbitrum
|
|
62
|
+
- merchant verifies the local payment and serves
|
|
63
|
+
- treasury moves to Tempo later on an hourly schedule
|
|
64
|
+
|
|
65
|
+
That is why this demo needs a separate server and a separate buyer path.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Current Code We Keep As Reference
|
|
70
|
+
|
|
71
|
+
- Buyer Step 1 wrapper: `src/buyer/tempo-with-across.ts`
|
|
72
|
+
- Current local MPP seller: `src/dev/server.ts`
|
|
73
|
+
- Current demo entrypoints: `src/demo/local.ts`, `src/demo/external.ts`
|
|
74
|
+
|
|
75
|
+
We should **not** try to mutate those into Step 2. They remain the Step 1 baseline.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## New Modules To Add
|
|
80
|
+
|
|
81
|
+
Create a new `src/step2/` area for the demo-specific code.
|
|
82
|
+
|
|
83
|
+
### 1. Merchant server
|
|
84
|
+
|
|
85
|
+
`src/step2/server.ts`
|
|
86
|
+
|
|
87
|
+
Responsibilities:
|
|
88
|
+
|
|
89
|
+
- issue the MPP-facing 402 challenge
|
|
90
|
+
- create a unique `reference` per challenge
|
|
91
|
+
- store challenge state
|
|
92
|
+
- accept retry requests containing `reference + txHash`
|
|
93
|
+
- call the verifier
|
|
94
|
+
- serve the paid response after successful verification
|
|
95
|
+
- expose a manual "run hourly sweep now" action for the demo
|
|
96
|
+
|
|
97
|
+
### 2. Challenge store
|
|
98
|
+
|
|
99
|
+
`src/step2/challenges.ts`
|
|
100
|
+
|
|
101
|
+
Responsibilities:
|
|
102
|
+
|
|
103
|
+
- create challenge records
|
|
104
|
+
- store:
|
|
105
|
+
- `reference`
|
|
106
|
+
- `amount`
|
|
107
|
+
- `payer` if known
|
|
108
|
+
- `createdAt`
|
|
109
|
+
- `expiresAt`
|
|
110
|
+
- `consumedAt`
|
|
111
|
+
- `txHash`
|
|
112
|
+
- verification status
|
|
113
|
+
- mark one-time consumption after serving
|
|
114
|
+
|
|
115
|
+
For the demo, in-memory storage is acceptable.
|
|
116
|
+
|
|
117
|
+
### 3. Verifier service
|
|
118
|
+
|
|
119
|
+
`src/step2/verifier.ts`
|
|
120
|
+
|
|
121
|
+
Responsibilities:
|
|
122
|
+
|
|
123
|
+
- read Arbitrum transaction receipts
|
|
124
|
+
- decode `PaymentReceived`
|
|
125
|
+
- confirm:
|
|
126
|
+
- event emitter is the expected receiver
|
|
127
|
+
- `reference` matches
|
|
128
|
+
- amount matches
|
|
129
|
+
- token matches
|
|
130
|
+
- confirmations threshold is met
|
|
131
|
+
- return a compact decision to the merchant server
|
|
132
|
+
|
|
133
|
+
Recommended demo default:
|
|
134
|
+
|
|
135
|
+
- `CONFIRMATIONS_REQUIRED=1`
|
|
136
|
+
- keep it configurable
|
|
137
|
+
|
|
138
|
+
### 4. Buyer Step 2 path
|
|
139
|
+
|
|
140
|
+
`src/step2/buyer.ts`
|
|
141
|
+
|
|
142
|
+
Responsibilities:
|
|
143
|
+
|
|
144
|
+
- request the protected resource
|
|
145
|
+
- parse the MPP-facing challenge
|
|
146
|
+
- derive the deterministic Arbitrum receiver from merchant identity
|
|
147
|
+
- check `eth_getCode(receiver)` on Arbitrum
|
|
148
|
+
- log clearly that the buyer discovered the correct receiver
|
|
149
|
+
- pay the receiver locally
|
|
150
|
+
- retry the original request with `reference + txHash`
|
|
151
|
+
|
|
152
|
+
Important:
|
|
153
|
+
|
|
154
|
+
- this is a **custom Step 2-aware buyer**
|
|
155
|
+
- the audience should still experience it as an MPP flow
|
|
156
|
+
|
|
157
|
+
### 5. Receiver address derivation helper
|
|
158
|
+
|
|
159
|
+
`src/step2/receiver.ts`
|
|
160
|
+
|
|
161
|
+
Responsibilities:
|
|
162
|
+
|
|
163
|
+
- compute deterministic receiver address
|
|
164
|
+
- share the same derivation logic between buyer, merchant server, and verifier
|
|
165
|
+
|
|
166
|
+
### 6. Sweep trigger
|
|
167
|
+
|
|
168
|
+
`src/step2/sweep.ts`
|
|
169
|
+
|
|
170
|
+
Responsibilities:
|
|
171
|
+
|
|
172
|
+
- run the manual demo sweep
|
|
173
|
+
- log that this represents the scheduled hourly sweep policy
|
|
174
|
+
- show source balance, destination chain, and completion
|
|
175
|
+
|
|
176
|
+
### 7. Demo runner
|
|
177
|
+
|
|
178
|
+
`src/step2/demo.ts`
|
|
179
|
+
|
|
180
|
+
Responsibilities:
|
|
181
|
+
|
|
182
|
+
- execute the three-payment script
|
|
183
|
+
- show:
|
|
184
|
+
- payment 1 verified
|
|
185
|
+
- payment 2 verified
|
|
186
|
+
- payment 3 verified
|
|
187
|
+
- receiver balance accumulated to `$0.06`
|
|
188
|
+
- hourly sweep triggered
|
|
189
|
+
- Tempo settlement observed
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## HTTP Contract For The Demo
|
|
194
|
+
|
|
195
|
+
### First request
|
|
196
|
+
|
|
197
|
+
`GET /api/premium`
|
|
198
|
+
|
|
199
|
+
Expected result:
|
|
200
|
+
|
|
201
|
+
- merchant returns `402`
|
|
202
|
+
- challenge includes enough identity for the buyer to derive the receiver
|
|
203
|
+
|
|
204
|
+
### Retry after local payment
|
|
205
|
+
|
|
206
|
+
`GET /api/premium`
|
|
207
|
+
|
|
208
|
+
Headers:
|
|
209
|
+
|
|
210
|
+
- `X-Step2-Reference: <reference>`
|
|
211
|
+
- `X-Step2-Tx-Hash: <txHash>`
|
|
212
|
+
|
|
213
|
+
Merchant flow:
|
|
214
|
+
|
|
215
|
+
- load challenge by `reference`
|
|
216
|
+
- call verifier with `reference + txHash`
|
|
217
|
+
- if verified and not consumed, serve content
|
|
218
|
+
|
|
219
|
+
The buyer should make this obvious in logs:
|
|
220
|
+
|
|
221
|
+
- `Derived receiver`
|
|
222
|
+
- `Receiver deployed: yes`
|
|
223
|
+
- `Paid locally on Arbitrum`
|
|
224
|
+
- `Retrying with reference + txHash`
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Event Contract
|
|
229
|
+
|
|
230
|
+
The receiver needs one event:
|
|
231
|
+
|
|
232
|
+
```solidity
|
|
233
|
+
event PaymentReceived(
|
|
234
|
+
address indexed payer,
|
|
235
|
+
address indexed token,
|
|
236
|
+
uint256 amount,
|
|
237
|
+
bytes32 indexed reference
|
|
238
|
+
);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
That is enough for the verifier to bind the Arbitrum payment to the original merchant challenge.
|
|
242
|
+
|
|
243
|
+
If we want easier demo logging, add a non-indexed string or bytes field later, but the default should stay compact.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Demo UX Requirements
|
|
248
|
+
|
|
249
|
+
Minimal but explicit.
|
|
250
|
+
|
|
251
|
+
The demo must show:
|
|
252
|
+
|
|
253
|
+
1. Buyer got a payment challenge.
|
|
254
|
+
2. Buyer derived the correct Arbitrum receiver.
|
|
255
|
+
3. Buyer found deployed code at that address.
|
|
256
|
+
4. Buyer paid locally on Arbitrum.
|
|
257
|
+
5. Merchant served immediately after verification.
|
|
258
|
+
6. Three payments accumulated on the receiver.
|
|
259
|
+
7. One live "hourly sweep" moved the balance to Tempo.
|
|
260
|
+
|
|
261
|
+
We do **not** need a polished dashboard.
|
|
262
|
+
We do need logs or a minimal operator view that makes the batching story visually obvious.
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Operator View
|
|
267
|
+
|
|
268
|
+
Minimal output is enough.
|
|
269
|
+
|
|
270
|
+
Show these fields:
|
|
271
|
+
|
|
272
|
+
- `reference`
|
|
273
|
+
- `payment count`
|
|
274
|
+
- `receiver address`
|
|
275
|
+
- `receiver balance`
|
|
276
|
+
- `last verified tx`
|
|
277
|
+
- `sweep status`
|
|
278
|
+
- `Tempo settlement tx`
|
|
279
|
+
|
|
280
|
+
A single terminal + one minimal status page is enough.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Sweep Policy
|
|
285
|
+
|
|
286
|
+
Real policy:
|
|
287
|
+
|
|
288
|
+
- sweep **every hour**
|
|
289
|
+
|
|
290
|
+
Demo behavior:
|
|
291
|
+
|
|
292
|
+
- after payment 3, manually trigger the "hourly sweep now" action
|
|
293
|
+
|
|
294
|
+
What we say out loud:
|
|
295
|
+
|
|
296
|
+
- "In production, this runs on the hourly policy."
|
|
297
|
+
- "For the demo, we're forcing the scheduled action to happen now."
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Success Criteria
|
|
302
|
+
|
|
303
|
+
The demo succeeds if all of the following are true:
|
|
304
|
+
|
|
305
|
+
1. Buyer makes **3** paid requests from Arbitrum.
|
|
306
|
+
2. Merchant serves after each one.
|
|
307
|
+
3. Buyer never bridges three separate payments to Tempo.
|
|
308
|
+
4. Receiver balance visibly accumulates to roughly **$0.06** before sweep.
|
|
309
|
+
5. One sweep moves the accumulated balance to Tempo.
|
|
310
|
+
6. The audience can plainly see that Step 2 replaced per-request bridging with hourly batching.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Non-Goals
|
|
315
|
+
|
|
316
|
+
- shared code with x402
|
|
317
|
+
- retrofitting the current Step 1 demo surface
|
|
318
|
+
- undeployed counterfactual receive
|
|
319
|
+
- automatic scheduler infrastructure
|
|
320
|
+
- polished production dashboard
|
|
321
|
+
- live Step 1 comparison path in the same demo
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## Build Order
|
|
326
|
+
|
|
327
|
+
### Phase 1
|
|
328
|
+
|
|
329
|
+
- receiver address derivation helper
|
|
330
|
+
- challenge store
|
|
331
|
+
- merchant Step 2 server shell
|
|
332
|
+
|
|
333
|
+
### Phase 2
|
|
334
|
+
|
|
335
|
+
- verifier service
|
|
336
|
+
- buyer Step 2 path
|
|
337
|
+
- retry contract with `reference + txHash`
|
|
338
|
+
|
|
339
|
+
### Phase 3
|
|
340
|
+
|
|
341
|
+
- manual sweep action
|
|
342
|
+
- minimal operator view / logs
|
|
343
|
+
- scripted three-payment demo runner
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Open Implementation Details
|
|
348
|
+
|
|
349
|
+
These do **not** block the architecture, but they need to be decided during build:
|
|
350
|
+
|
|
351
|
+
- exact receiver contract ABI
|
|
352
|
+
- exact `reference` type (`bytes32` vs string encoded to bytes32)
|
|
353
|
+
- whether Tempo settlement target is plain `USDC` or `USDC.e`
|
|
354
|
+
- exact verifier response schema
|
|
355
|
+
- whether the status view is terminal-only or terminal + tiny web page
|
|
356
|
+
|
|
357
|
+
None of those change the agreed demo story.
|