252 lines
9.4 KiB
Markdown
252 lines
9.4 KiB
Markdown
---
|
|
title: Escrow Marketplace E2E Procedure
|
|
tags: [testing, e2e, escrow, marketplace, buyer, seller]
|
|
created: 2026-06-06
|
|
---
|
|
|
|
# Escrow Marketplace E2E Procedure
|
|
|
|
This procedure validates the marketplace flow with one buyer and at least two
|
|
sellers. Use it for live dev validation after payment, marketplace, delivery,
|
|
or scanner changes.
|
|
|
|
## Preconditions
|
|
|
|
- Dev API is reachable: `GET https://dev.amn.gg/api/version`.
|
|
- Backend, frontend, and scanner containers are healthy.
|
|
- Admin credentials are available through a secure local channel, not docs.
|
|
- BSC Testnet wallet has enough tBNB for gas and enough canonical tUSDT.
|
|
- Backend/scanner chain 97 registry points to `0x109F54Dab34426D5477986b0460aE5dFBA65f022`.
|
|
- Local wallet private key or mnemonic is stored only in ignored `.env`.
|
|
- Notification checks are enabled in the runner. See [[Notification Assertion Procedure]].
|
|
|
|
## Actors
|
|
|
|
| Actor | Count | Role |
|
|
|---|---:|---|
|
|
| Buyer | 1 | Creates request, accepts offer, funds payment, confirms delivery. |
|
|
| Sellers | 2 minimum, 3 preferred | Submit competing offers and delivery evidence. |
|
|
| Admin | 1 | Creates test users and can inspect/repair state. |
|
|
|
|
## High-Level Procedure
|
|
|
|
1. Generate a run id.
|
|
2. Admin creates one buyer and at least two sellers.
|
|
3. Assert initial notification baselines for buyer and sellers.
|
|
4. Buyer creates purchase request with a min/max USDT budget.
|
|
5. Assert purchase-request notifications for expected sellers.
|
|
6. Sellers submit bids inside the budget range.
|
|
7. After each seller bid, assert offer notifications for the buyer.
|
|
8. Randomize or vary:
|
|
- bid amount,
|
|
- delivery timing,
|
|
- seller note,
|
|
- delivery method.
|
|
9. Buyer selects a bid.
|
|
10. Assert offer-accepted notification for selected seller and offer-rejected/updated notifications for non-selected sellers when implemented.
|
|
11. Backend creates scanner payment intent.
|
|
12. Assert payment-pending or payment-started notification where implemented; if missing, record as notification coverage gap.
|
|
13. Buyer pays with BSC Testnet tUSDT.
|
|
14. Scanner confirms the payment.
|
|
15. Assert payment-confirmed notifications for buyer and selected seller.
|
|
16. Seller marks delivery.
|
|
17. Assert delivery notification for buyer.
|
|
18. Buyer confirms delivery.
|
|
19. Assert delivery-confirmed notification for selected seller and buyer status notification if implemented.
|
|
20. Record current block: flow pauses before automated release policy.
|
|
|
|
## Expected State Transitions
|
|
|
|
| Step | Purchase request expectation | Payment expectation |
|
|
|---|---|---|
|
|
| Request created | request visible to sellers | no payment |
|
|
| Offers submitted | `received_offers` or equivalent offer-ready state | no payment |
|
|
| Offer accepted | selected offer stored | payment intent can be created |
|
|
| Payment sent | payment/check pending or processing | scanner sees chain/token/destination/amount |
|
|
| Scanner confirms | request can proceed to delivery path | status paid/confirmed/completed depending endpoint |
|
|
| Seller delivers | `delivery` | escrow remains held |
|
|
| Buyer confirms | `delivered`, `deliveryConfirmed=true` | release policy not automatic yet |
|
|
|
|
## Notification Assertions After Every Step
|
|
|
|
Notification verification is mandatory after every state-changing step. A step
|
|
is not complete until the test runner has either:
|
|
|
|
1. observed the expected notification for every recipient; or
|
|
2. recorded a known coverage gap with route/action, expected recipient, and linked issue/backlog item.
|
|
|
|
Use [[Notification Assertion Procedure]] for the exact API/socket checks.
|
|
|
|
| Step | Expected recipients | Required notification assertion |
|
|
|---|---|---|
|
|
| Baseline after user creation | buyer, every seller | Capture unread count and latest notification id for each actor before business mutations. |
|
|
| Buyer creates request | eligible sellers | Sellers receive a request/new-opportunity notification, or the gap is recorded. |
|
|
| Seller submits bid | buyer | Buyer receives a new-offer notification with `relatedId` or action URL pointing to the request/offer. |
|
|
| Buyer selects bid | selected seller; non-selected sellers if rejection notices are implemented | Selected seller receives acceptance notification. Non-selected sellers receive rejection/update notification where supported. |
|
|
| Payment intent created | buyer | Buyer receives payment-started/pending notification where supported. Missing `pending_payment` coverage is a known notification gap and must be recorded. |
|
|
| Scanner confirms payment | buyer, selected seller | Buyer and seller receive payment-confirmed/funded notification. |
|
|
| Seller marks delivery | buyer | Buyer receives delivery/proof submitted notification. |
|
|
| Buyer confirms delivery | selected seller; buyer if status-change notices are implemented | Seller receives delivery-confirmed notification. |
|
|
| Dispute raised, when added | buyer, seller, admin/mediator | All parties receive dispute-created/hold notification. |
|
|
| Release/refund, when added | buyer, seller, admin | Funds movement notification is persisted and pushed. |
|
|
|
|
Minimum notification evidence per assertion:
|
|
|
|
| Evidence | Source |
|
|
|---|---|
|
|
| unread count before and after | `GET /api/notifications/unread-count` |
|
|
| latest notification payload | `GET /api/notifications?limit=5` |
|
|
| recipient id/email | authenticated actor profile or test user record |
|
|
| notification category/type/title/actionUrl | notification payload |
|
|
| socket event, if runner supports it | `new-notification` on `user-<userId>` |
|
|
| elapsed time from action to notification visibility | runner timestamp |
|
|
|
|
## Buyer Request Template
|
|
|
|
Use unique values so live data can be filtered later:
|
|
|
|
```json
|
|
{
|
|
"title": "Scanner BSC Testnet E2E <runId> R<round>",
|
|
"description": "Automated scanner payment test round <round>",
|
|
"productType": "physical_product",
|
|
"productLink": "https://example.test/e2e/<runId>/<round>",
|
|
"quantity": 1,
|
|
"budget": {
|
|
"min": 0.18,
|
|
"max": 0.48,
|
|
"currency": "USDT"
|
|
},
|
|
"urgency": "medium"
|
|
}
|
|
```
|
|
|
|
## Seller Bid Rules
|
|
|
|
For each round:
|
|
|
|
- create at least two bids;
|
|
- prefer three bids so ranking/selection is clearer;
|
|
- keep all bids within buyer min/max budget;
|
|
- vary delivery timing, for example 1 day, 4 days, 7 days;
|
|
- pick a deterministic winner rule for automation, such as lowest price.
|
|
|
|
Example bid set:
|
|
|
|
| Seller | Amount | Delivery |
|
|
|---|---:|---|
|
|
| seller1 | `0.31 USDT` | `7 days` |
|
|
| seller2 | `0.28 USDT` | `5 days` |
|
|
| seller3 | `0.26 USDT` | `4 days` |
|
|
|
|
## Delivery Proof
|
|
|
|
Seller delivery should include structured proof where the API supports it:
|
|
|
|
```json
|
|
{
|
|
"proof": {
|
|
"type": "e2e",
|
|
"runId": "<runId>",
|
|
"round": 1,
|
|
"note": "Seller delivery proof for automated dev test"
|
|
}
|
|
}
|
|
```
|
|
|
|
Buyer confirmation may use similar metadata:
|
|
|
|
```json
|
|
{
|
|
"proof": {
|
|
"type": "e2e-confirmation",
|
|
"runId": "<runId>",
|
|
"round": 1
|
|
}
|
|
}
|
|
```
|
|
|
|
## Assertions
|
|
|
|
Minimum assertions per round:
|
|
|
|
| Assertion | Required |
|
|
|---|---|
|
|
| Buyer login succeeds | yes |
|
|
| Seller logins succeed | yes |
|
|
| Request id is created | yes |
|
|
| At least two offer ids are created | yes |
|
|
| Selected offer id matches accepted seller | yes |
|
|
| Payment id is created | yes |
|
|
| Payment chain id is `97` | yes |
|
|
| Payment token is canonical tUSDT | yes |
|
|
| On-chain tx hash exists | yes |
|
|
| Scanner check returns paid/confirmed | yes |
|
|
| Seller delivery returns HTTP 200 | yes |
|
|
| Buyer confirm delivery returns HTTP 200 | yes |
|
|
| Final request status is `delivered` | yes |
|
|
| Notification assertion executed after each state-changing step | yes |
|
|
| Notification gaps are recorded with expected recipient and route/action | yes |
|
|
|
|
## Reference Execution - 2026-06-06
|
|
|
|
Run id:
|
|
|
|
```text
|
|
20260606043238
|
|
```
|
|
|
|
Generated users:
|
|
|
|
| Actor | Email |
|
|
|---|---|
|
|
| Buyer | `amn-e2e-20260606043238-buyer@example.test` |
|
|
| Seller 1 | `amn-e2e-20260606043238-seller1@example.test` |
|
|
| Seller 2 | `amn-e2e-20260606043238-seller2@example.test` |
|
|
| Seller 3 | `amn-e2e-20260606043238-seller3@example.test` |
|
|
|
|
Round 1:
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| purchaseRequestId | `732e9de8-9631-484e-a5ac-bb657ca55020` |
|
|
| paymentId | `f7f02ba4-9154-4408-984b-d3481d1ec5fa` |
|
|
| selectedOfferId | `263b30f0-7ee6-4e63-9d0a-af2d7624fdde` |
|
|
| selected seller | `seller3` |
|
|
| amount | `0.26 USDT` |
|
|
| token | `0x109F54Dab34426D5477986b0460aE5dFBA65f022` |
|
|
| txHash | `0x7a5c2785161df3367374574d8e1af00c548131c8a44c3fa06b592966920e3edc` |
|
|
| scanner result | paid |
|
|
| final request status | `delivered` |
|
|
|
|
Round 2:
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| purchaseRequestId | `da34d9bc-2b2d-4dc3-98f0-aa1a07a55ebb` |
|
|
| paymentId | `2e8582eb-3ac3-4793-b10f-ea721b6466d4` |
|
|
| selectedOfferId | `36e3a912-2121-4f07-87e6-4c73b1adf224` |
|
|
| selected seller | `seller2` |
|
|
| amount | `0.32 USDT` |
|
|
| token | `0x109F54Dab34426D5477986b0460aE5dFBA65f022` |
|
|
| txHash | `0x861a1197d7d345609f5a46b1a3723a29877ba9929bd1e7b21f7060381a1b14d0` |
|
|
| scanner result | paid |
|
|
| final request status | `delivered` |
|
|
|
|
Important finding from this run:
|
|
|
|
- Payment confirmation succeeded after correcting the chain 97 token registry to the actual tUSDT contract.
|
|
- Buyer delivery confirmation initially failed with HTTP 403 because user ids were compared across stores directly. Backend `2.8.117` fixed the id comparison; both confirmations then returned HTTP 200.
|
|
|
|
## Current Product Boundary
|
|
|
|
The procedure currently stops at `delivered`.
|
|
|
|
Release policy is not complete:
|
|
|
|
- physical-product grace period is not implemented;
|
|
- gift-card/digital immediate release is not implemented;
|
|
- dispute-to-release/refund automation is not complete.
|
|
|
|
Use [[Testing Expansion Backlog]] before extending this scenario into fund release.
|