docs: sync from backend 896f17f - persist webhook confirmations
This commit is contained in:
@@ -6,12 +6,12 @@ aliases: [Payment Record, Escrow, IPayment]
|
||||
|
||||
# Payment
|
||||
|
||||
> **Last updated:** 2026-05-31 — added AMN scanner provider, oracle quote mirror, and Postgres `payment_quotes` linkage.
|
||||
> **Last updated:** 2026-05-31 — added AMN scanner provider, oracle quote mirror, Postgres `payment_quotes` linkage, and webhook confirmation persistence.
|
||||
|
||||
Records every monetary movement in the marketplace: buyer pay-ins, seller payouts, and refunds. The current model is centered on Request Network pay-in, in-house checkout metadata, on-chain transaction verification, escrow state, and provider request IDs. The `provider` and `direction` discriminators let one collection hold incoming buyer payments, outgoing seller releases, refunds, and legacy/other provider records.
|
||||
|
||||
> [!warning] Runtime store
|
||||
> The `Payment` document is still created, read, and updated through Mongoose on normal request paths. Backend `2.6.80` can persist oracle quotes to Postgres `payment_quotes`, but that is conditional on `ORACLE_QUOTING_ENABLED=true` and does not make the whole payment domain PG-authoritative. See [[Postgres Runtime Cutover Status]].
|
||||
> The `Payment` document is still created, read, and updated through Mongoose on normal request paths. Backend `2.6.81` can persist oracle quotes to Postgres `payment_quotes`, but that is conditional on `ORACLE_QUOTING_ENABLED=true` and does not make the whole payment domain PG-authoritative. See [[Postgres Runtime Cutover Status]].
|
||||
|
||||
> [!note] Source
|
||||
> `backend/src/models/Payment.ts:3` — schema definition
|
||||
@@ -52,7 +52,7 @@ Records every monetary movement in the marketplace: buyer pay-ins, seller payout
|
||||
| `blockchain.sender` | String | no | — | — | — | Source address. |
|
||||
| `blockchain.receiver` | String | no | — | — | — | Destination address. |
|
||||
| `blockchain.confirmedAt` | Date | no | — | — | — | When tx confirmed. |
|
||||
| `blockchain.confirmations` | Number | no | `0` | — | — | Confirmation count. |
|
||||
| `blockchain.confirmations` | Number | no | `0` | — | — | Confirmation count persisted from transaction-safety verifier evidence, provider payload `confirmations`, or the configured per-chain threshold fallback when a webhook already reports `confirmed`/`completed`. |
|
||||
| `status` | String | no | `pending` | enum: `pending` / `processing` / `confirmed` / `completed` / `failed` / `cancelled` / `refunded` | yes (compound) | Lifecycle status. ⚠️ `confirmed` vs `completed`: only `confirmed` is counted as a successful payment in stats. See status note below. |
|
||||
| `escrowState` | String | no | — | enum: `funded` / `releasable` / `released` / `refunded` / `releasing` / `failed` / `cancelled` / `partial` | — | Escrow lifecycle. Note the intermediate states `releasable` (delivery confirmed, ready to pay out) and `releasing` (payout in flight) between `funded` and `released`. |
|
||||
| `providerPaymentId` | String | no | — | — | yes (sparse) | External provider id for idempotency. |
|
||||
|
||||
@@ -5,7 +5,7 @@ tags: [api, payment, reference, request-network, escrow]
|
||||
|
||||
# Payment API
|
||||
|
||||
> **Last updated:** 2026-05-31 — Postgres integration promotion, oracle quote persistence, AMN scanner rail-switch fix, and partial gasless permit endpoints.
|
||||
> **Last updated:** 2026-05-31 — Postgres integration promotion, oracle quote persistence, AMN scanner rail-switch fix, webhook confirmation persistence, and partial gasless permit endpoints.
|
||||
|
||||
The payment surface is split across provider-neutral payment routers, Request Network checkout/webhook routes, derived-destination custody routes, and admin safety routes:
|
||||
|
||||
@@ -23,7 +23,7 @@ The payment surface is split across provider-neutral payment routers, Request Ne
|
||||
Core model: [[Payment]]. Coordination logic to avoid race conditions when multiple sources update the same payment is in `paymentCoordinator.ts`.
|
||||
|
||||
> [!warning] Persistence status
|
||||
> Payment APIs still create/read/update Mongo `Payment` documents on backend `2.6.79`. The Postgres branch adds schemas, repos, migrations, and optional quote persistence, but it is not a full payment-domain cutover. `/api/payment/request-network/intents` can write `payment_quotes` only when `ORACLE_QUOTING_ENABLED=true`; the payment record itself remains Mongo-backed unless future service wiring changes that boundary.
|
||||
> Payment APIs still create/read/update Mongo `Payment` documents on backend `2.6.81`. The Postgres branch adds schemas, repos, migrations, and optional quote persistence, but it is not a full payment-domain cutover. `/api/payment/request-network/intents` can write `payment_quotes` only when `ORACLE_QUOTING_ENABLED=true`; the payment record itself remains Mongo-backed unless future service wiring changes that boundary.
|
||||
|
||||
## Configuration / health
|
||||
|
||||
@@ -208,6 +208,7 @@ Core model: [[Payment]]. Coordination logic to avoid race conditions when multip
|
||||
**Description:** Request Network posts settlement updates here. The route verifies `x-request-network-signature` over the raw body, deduplicates delivery IDs, evaluates the Transaction Safety Provider, and coordinates the payment/ledger update.
|
||||
**Auth required:** No (signature-protected)
|
||||
**Response:** `200` when processed or duplicate; `202` when accepted but safety checks are pending; `401` for invalid signature.
|
||||
**Side effects:** For confirmed/completed events, `blockchain.confirmations` is stored from safety verifier evidence, provider payload `confirmations`, or the configured per-chain threshold fallback before the payment/ledger update is emitted.
|
||||
|
||||
> [!note] RN payout/release/refund routes
|
||||
> `POST /api/payment/request-network/:paymentId/payout/initiate`, `POST /api/payment/request-network/:paymentId/payout/confirm`, `POST /api/payment/request-network/:paymentId/release/confirm`, and `POST /api/payment/request-network/:paymentId/refund/confirm` are registered in `requestNetworkRoutes.ts` but are stub-level implementations. They accept the request and return a 200 but do not yet drive the ledger-gated release/refund orchestration. Use `POST /api/payment/:id/release` and `POST /api/payment/:id/refund` for actual escrow releases.
|
||||
@@ -220,9 +221,9 @@ AMN Pay Scanner is a custom in-house blockchain scanner that replaces the hosted
|
||||
|
||||
**Description:** AMN Pay Scanner posts settlement confirmations here. The route verifies a `webhookSecret`-based HMAC signature, then runs the Transaction Safety Provider and `PaymentCoordinator` pipeline identical to the RN webhook path.
|
||||
**Auth required:** No (signature-protected via `AMN_SCANNER_WEBHOOK_SECRET`)
|
||||
**Request body:** `{ intentId, status, transactionHash?, chainId?, ... }` — scanner-specific envelope
|
||||
**Request body:** `{ intentId, status, txHash?, transactionHash?, chainId?, confirmations?, ... }` — scanner-specific envelope. Current scanner payloads usually use `txHash`; `confirmations` may be omitted once the scanner has already waited for the configured threshold.
|
||||
**Response:** `200` processed; `401` bad signature; `400` missing `intentId` or unknown format; `404` payment not found.
|
||||
**Side effects:** Same as the RN webhook — updates [[Payment]], advances [[PurchaseRequest]], accepts/rejects offers, emits socket events when safety checks pass.
|
||||
**Side effects:** Same as the RN webhook — updates [[Payment]], advances [[PurchaseRequest]], accepts/rejects offers, emits socket events when safety checks pass. Backend `2.6.81+` treats scanner `status: "confirmed"` as a settlement status for Transaction Safety Provider evaluation and confirmation persistence; if neither verifier evidence nor payload `confirmations` exists, it stores the configured chain threshold so the dashboard does not show a paid scanner transaction with `0` confirmations.
|
||||
|
||||
> [!note] Provider value
|
||||
> Payments created via the AMN Pay Scanner have `provider: 'amn.scanner'` in the database. This is distinct from `request.network` and `shkeeper`.
|
||||
|
||||
@@ -6,6 +6,8 @@ created: 2026-05-30
|
||||
|
||||
# Payment Flow — AMN Pay Scanner (In-House)
|
||||
|
||||
> **Last updated:** 2026-05-31 — documented backend `2.6.81` confirmation persistence for scanner `confirmed` webhooks.
|
||||
|
||||
End-to-end payment flow using the in-house AMN Pay Scanner, replacing the Request Network integration. The scanner is a separate microservice; the backend talks to it over an internal HTTP API.
|
||||
|
||||
See also: [Scanner Architecture](../01%20-%20Architecture/Scanner%20Architecture.md), [Scanner API](../03%20-%20API%20Reference/Scanner%20API.md)
|
||||
@@ -57,7 +59,7 @@ Authorization: Bearer <SCANNER_API_KEY>
|
||||
"tokenAddress": "0x55d398326f99059ff775485246999027b3197955",
|
||||
"destination": "0xSellerWalletAddress",
|
||||
"amount": "10000000000000000000",
|
||||
"callbackUrl": "https://api.amn.gg/api/payment/scanner-callback",
|
||||
"callbackUrl": "https://api.amn.gg/api/payment/amn-scanner/webhook",
|
||||
"callbackSecret": "<per-intent HMAC secret stored in payment doc>",
|
||||
"confirmations": 12
|
||||
}
|
||||
@@ -116,13 +118,14 @@ The scanner POSTs to `callbackUrl` with:
|
||||
"amount": "10000000000000000000",
|
||||
"token": "0x55d...",
|
||||
"chainId": 56,
|
||||
"confirmations": 12,
|
||||
"status": "confirmed"
|
||||
}
|
||||
```
|
||||
|
||||
Header `X-AMN-Signature` = `HMAC-SHA256(body, callbackSecret)`.
|
||||
|
||||
The backend verifies the signature, matches the intentId to a Payment record, and marks it paid.
|
||||
The backend verifies the signature, matches the `intentId` to a Payment record, and marks it paid. Backend `2.6.81+` treats scanner `status: "confirmed"` as final enough to run Transaction Safety Provider checks and persist `blockchain.confirmations`. The stored confirmation count comes from verifier evidence first, then the webhook payload, then the configured per-chain threshold fallback when the scanner has already waited for enough blocks but did not send a raw count.
|
||||
|
||||
### Step 6 — Backend acknowledges
|
||||
|
||||
|
||||
@@ -11,6 +11,18 @@ entries on top. Maintained by agents per the rule in `../AGENTS.md`.
|
||||
|
||||
---
|
||||
|
||||
### 2026-05-31 — backend@896f17f, frontend@fd8e797 — persist webhook confirmations for scanner payments
|
||||
|
||||
**Commits:** backend `896f17f`, frontend `fd8e797` (backend `2.6.81`, frontend `2.7.21`)
|
||||
**Touched:**
|
||||
- Backend: `src/routes/amnScannerWebhookRoutes.ts`, `src/services/payment/requestNetwork/requestNetworkRoutes.ts`, `src/services/payment/safety/transactionSafetyProvider.ts`, `__tests__/transaction-safety-provider.test.ts`, `package.json`, `package-lock.json`
|
||||
- Frontend: `package.json`, `package-lock.json` version bump only.
|
||||
**Why:** `dev.amn.gg` showed a confirmed AMN scanner payment with `blockchain.confirmations = 0`. Scanner webhooks report `status: "confirmed"`, but transaction safety only evaluated `"completed"` statuses, so no verifier evidence was produced. The webhook routes now persist confirmations from safety evidence, scanner/RN payloads, or the chain confirmation threshold fallback when the provider already says confirmed/completed.
|
||||
**Verification:** Backend `npm test -- --runTestsByPath __tests__/transaction-safety-provider.test.ts`; backend `npm run typecheck`; backend `git diff --check`; frontend `npx tsc --noEmit --ignoreDeprecations 6.0`; frontend `git diff --check`. Could not inspect the actual `dev.amn.gg` payment row because SSH to `193.180.213.68` rejected the available key.
|
||||
**Linked docs updated:** [[Payment]], [[Payment API]], [[Payment Flow - Scanner]]
|
||||
|
||||
---
|
||||
|
||||
### 2026-05-31 — backend@cab0719, frontend@ec2f765 — align request budget validation after Postgres migration
|
||||
|
||||
**Commits:** backend `cab0719`, frontend `ec2f765` (backend `2.6.80`, frontend `2.7.20`)
|
||||
|
||||
Reference in New Issue
Block a user