moltspay 2.0.0 → 2.4.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.example +23 -0
- package/CHANGELOG.md +551 -0
- package/README.md +466 -8
- package/dist/cdp/index.js.map +1 -1
- package/dist/cdp/index.mjs.map +1 -1
- package/dist/chains/index.d.mts +69 -4
- package/dist/chains/index.d.ts +69 -4
- package/dist/chains/index.js +45 -1
- package/dist/chains/index.js.map +1 -1
- package/dist/chains/index.mjs +39 -1
- package/dist/chains/index.mjs.map +1 -1
- package/dist/cli/index.js +5444 -2126
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +5457 -2133
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/index.d.mts +307 -1
- package/dist/client/index.d.ts +307 -1
- package/dist/client/index.js +639 -34
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +656 -52
- package/dist/client/index.mjs.map +1 -1
- package/dist/client/web/index.mjs.map +1 -1
- package/dist/facilitators/index.d.mts +512 -10
- package/dist/facilitators/index.d.ts +512 -10
- package/dist/facilitators/index.js +925 -13
- package/dist/facilitators/index.js.map +1 -1
- package/dist/facilitators/index.mjs +906 -12
- package/dist/facilitators/index.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2843 -551
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2849 -558
- package/dist/index.mjs.map +1 -1
- package/dist/mcp/index.js +635 -32
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/index.mjs +660 -57
- package/dist/mcp/index.mjs.map +1 -1
- package/dist/server/index.d.mts +252 -11
- package/dist/server/index.d.ts +252 -11
- package/dist/server/index.js +2049 -261
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +2049 -261
- package/dist/server/index.mjs.map +1 -1
- package/dist/verify/index.js.map +1 -1
- package/dist/verify/index.mjs.map +1 -1
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +14 -2
- package/schemas/moltspay.services.schema.json +127 -16
package/.env.example
CHANGED
|
@@ -74,3 +74,26 @@ CDP_API_KEY_SECRET=
|
|
|
74
74
|
# Private key for paying BNB Chain transaction fees
|
|
75
75
|
# Required for server-side settlement on BNB chains (bsc, opbnb)
|
|
76
76
|
# BNB_SERVER_PRIVATE_KEY=
|
|
77
|
+
|
|
78
|
+
# ===========================================
|
|
79
|
+
# Public Base URL (2.4.0+)
|
|
80
|
+
# ===========================================
|
|
81
|
+
# Absolute base URL this server is reached at, INCLUDING any deployment path
|
|
82
|
+
# prefix (e.g. behind a reverse proxy at /t/my-service). When set, service
|
|
83
|
+
# discovery emits absolute endpoints / 402 resource URLs so a discovering agent
|
|
84
|
+
# lands on the right backend instead of the domain root. Leave unset for
|
|
85
|
+
# local / no-prefix deployments (falls back to relative paths).
|
|
86
|
+
# PUBLIC_BASE_URL=https://your.host/your/prefix
|
|
87
|
+
|
|
88
|
+
# ===========================================
|
|
89
|
+
# Fiat & Balance Rails (Alipay / WeChat / custodial balance)
|
|
90
|
+
# ===========================================
|
|
91
|
+
# These rails are NOT configured here — their merchant credentials and pricing
|
|
92
|
+
# live in your moltspay.services.json manifest (provider.alipay / provider.wechat
|
|
93
|
+
# / provider.balance + per-service blocks), referenced by ID and key-file path.
|
|
94
|
+
# See the rail docs:
|
|
95
|
+
# Alipay: https://github.com/Yaqing2023/moltspay/blob/v2.4.0/docs/ALIPAY-RAIL.md
|
|
96
|
+
# WeChat: https://github.com/Yaqing2023/moltspay/blob/v2.4.0/docs/WECHAT-RAIL-DESIGN.md
|
|
97
|
+
# Balance: https://github.com/Yaqing2023/moltspay/blob/v2.4.0/docs/WECHAT-BALANCE-PASSWORDLESS-DESIGN.md
|
|
98
|
+
# Balance spend authentication is the manifest knob provider.balance.auth_mode
|
|
99
|
+
# (off | shadow | enforce); see "Balance Authentication (2.4.0)" in the README.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [2.4.0] - 2026-07-14
|
|
4
|
+
|
|
5
|
+
**The balance rail grows a user.** 2.2/2.3 made payments password-free but left the buyer as a bare string: anyone who knew a `buyer_id` could spend that balance (bearer semantics), and the same person writing it two ways (`real01` / `test-buyer-001`) split into two accounts. This release gives the balance rail a real identity — anchored to the WeChat payer's `openid` at top-up, and authorized by a per-request signature at spend — closing both holes. It also fixes the server's self-description (a discovering agent was being sent to the wrong URL and told the wrong price), and ships `moltspay transfer`.
|
|
6
|
+
|
|
7
|
+
**No breaking changes**, but the balance rail's new authentication is **staged, not on by default**: `provider.balance.auth_mode` defaults to `off`, and existing unsigned clients keep working until an operator moves to `shadow` → `enforce`.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- **Balance identity — WeChat `openid` as the anchor.** On a WeChat-funded top-up, the server extracts `payer.openid` from the (signature-verified) order query and records it on the account (`buyers.wechat_openid`). Accounts are anchored to the person who actually paid, not to whatever string the caller self-reported, which removes the account-splitting class of bug at the source. Binding is observational and never overwrites: a conflicting openid is reported, not silently rebound. Exposed via `GET /balance`.
|
|
11
|
+
- **Balance authentication — per-request signatures.** Each deduction now carries an EIP-191 signature over a canonical message (`buildDeductMessage`: domain `moltspay-balance-auth:v1` / `balance-deduct` / `buyer_id` / `request_id` / `service` / `timestamp`). The server (`verifyDeductAuth`) recovers the signer address, TOFU-binds it to the account on first use (`buyers.signer_address`), and verifies it thereafter. Amount is deliberately *not* signed — the service id determines the price server-side, while `request_id` + a ±5-minute `timestamp` window bound replay.
|
|
12
|
+
- **`provider.balance.auth_mode`: `off` | `shadow` | `enforce`** — `off` skips the check (default, backward-compatible); `shadow` verifies and logs what it *would* deny without blocking (use this to confirm every real client is signing before you tighten); `enforce` rejects unsigned/invalid requests with 401. Rollback is a config flip + restart.
|
|
13
|
+
- **Signing key** — the client signs with its EVM wallet, or, for balance-only clients with no crypto wallet, a per-configDir identity key auto-created at `<configDir>/balance-identity.key` (0600). `MoltsPayClient.getBalanceSignerAddress()` exposes the address.
|
|
14
|
+
- **`moltspay balance whoami [server]` / `moltspay balance bind <server>`** — show the local signer address (and, against a server, the account's bound signer/openid), and bind the signer to an account explicitly. Top-up also carries the signer address through the WeChat `attach` passthrough, so identity is established at funding time rather than only on first spend.
|
|
15
|
+
- **Recoverable top-up for chat agents** — `moltspay balance topup-order` creates a WeChat pack order, emits the QR, and **exits immediately** instead of blocking on the scan; `balance topup-confirm <out_trade_no>` confirms and credits it later, `topup-status` / `topup-list` inspect pending orders. The blocking `topup-pack` assumes a terminal that can wait; a turn-based agent (Discord/飞书) cannot, and used to strand or re-issue orders. The order persists across turns, and confirming is idempotent on `out_trade_no` — the agent must reconfirm the *same* order rather than minting a new one.
|
|
16
|
+
- **`moltspay transfer <to> <amount>`** — transfer USDC/USDT to any address, so CLI/skill users can move funds out (e.g. to an exchange deposit address) without exporting the private key into a third-party wallet. Options: `--token USDC|USDT` (default USDC), `--chain base|polygon|bnb|base_sepolia|bnb_testnet|tempo_moderato` (default base), `--yes` (skip the confirmation prompt for scripts/agents), `--json`. A thin wrapper over `Wallet.transfer()`; see `docs/SEND-COMMAND-DESIGN.md`.
|
|
17
|
+
- **EVM only** — Solana is a separate keypair/transfer path and is rejected with a clear message.
|
|
18
|
+
- **Not gasless** — unlike x402 `pay`, a plain transfer needs native gas (ETH/BNB/POL); the command preflights the token balance and native gas and fails early if short.
|
|
19
|
+
- **Safety** — checksum-validates the destination, previews From/To/Network before sending (interactive unless `--yes`/`--json`), never prints the private key, and reminds the caller that the send network must match the receiver's deposit network.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **Service discovery sent agents to the wrong URL.** The discovery payload advertised its own `endpoints` as root-relative paths (`/services`, `/execute`), which resolve against the *domain* root and drop any deployment path prefix — an agent following `moltspay.com/t/moltspay-server`'s own discovery ended up at `moltspay.com/services` (a different backend) instead of `moltspay.com/t/moltspay-server/services`. The server is now prefix-aware: set `PUBLIC_BASE_URL` and `endpoints`, 404 hints, and the 402 `resource.url` are emitted as absolute URLs. Unset, it falls back to relative paths, so local/no-prefix deployments are unchanged.
|
|
23
|
+
- **Base URL returned a bare 404.** `GET /` was not routed and fell through to `{"error":"Not found"}`, so the most natural first request an agent makes told it nothing. The root path now serves the discovery payload, and the 404 body carries a `discovery` pointer.
|
|
24
|
+
- **Discovery under-reported payment options and hid CNY pricing.** Each service advertised only `price: 0.01 / currency: USDC`, so an agent reading discovery concluded the service took USDC only — even though the 402 challenge correctly offered Alipay, WeChat, and balance in CNY. Services now carry a structured `pricing` array covering every enabled rail (e.g. `[{rail: crypto, USDC, 0.01}, {rail: alipay, CNY, 1.00}, {rail: wechat, CNY, 0.07}, {rail: balance, CNY, 0.07}]`) and `acceptedCurrencies` is the union across rails. The top-level `price`/`currency` are unchanged for backward compatibility.
|
|
25
|
+
- **Balance identity key could fail to persist** when `configDir` did not exist yet — the directory is now created before the key is written.
|
|
26
|
+
- **Discovery and the 402 body advertised a crypto rail the server does not offer.** Both described the crypto rail from the service's list price alone, ignoring whether the provider actually has crypto chains configured — on a fiat/balance-only server, discovery still promised `crypto USDC` and the 402 body still said "Service requires $0.1 USDC" while `accepts[]` contained no crypto entry. An agent reads those fields to pick a rail (one tried `--rail crypto` first, failed, and fell back to a rail it should not have been on). `describeServicePricing` now emits crypto pricing only when `getProviderChains()` is non-empty (the same source that drives the crypto `accepts[]`), and the 402 `message`/`acceptedCurrencies` are derived from the rails actually offered instead of the hardcoded USDC list price. Same class as the endpoint/pricing discovery fixes above.
|
|
27
|
+
- **The top-level `price`/`currency` still quoted USDC on a server that cannot settle it.** The legacy back-compat `price: 0.1, currency: USDC` was reported even with no crypto chains configured, and an LLM agent quoted it back to the user as a payment option ("加密货币 $0.10 USDC" on a balance-only server). When crypto is not on offer, the top-level price now headlines the first rail that is (e.g. `1 CNY` for balance); crypto-enabled servers are unaffected, as the crypto entry still wins.
|
|
28
|
+
|
|
29
|
+
### Security
|
|
30
|
+
- **Closes the bearer-`buyer_id` hole flagged in 2.2/2.3.** With `auth_mode: enforce`, knowing a `buyer_id` is no longer sufficient to spend that balance; the caller must hold the bound signing key. This brings the balance rail to parity with the Alipay rail's per-request `payment_proof`.
|
|
31
|
+
- **Trust model — one agent key spends for all its users.** The shipped model is *agent-custodial*: a single agent key is bound to every account it tops up (`signer_address` is one-to-many). Accounts stay separated by openid, but **whoever holds the agent's key can spend every bound user's balance** — protect `<configDir>/balance-identity.key` accordingly. Per-user key isolation is a future upgrade, not what this release does.
|
|
32
|
+
- **WeChat response verification is the foundation of the openid anchor.** `openid` is only trustworthy if the order-query response is verified against the WeChat platform certificate — configure `provider.wechat.platform_public_key_path` (present ⇒ every response is verified, and a verification failure throws). Without it, responses are unverified and the identity anchor is not trustworthy.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
- The CLI's 2682-line `index.ts` was split into per-group modules (`cli/commands/*` + `shared.ts`). No command surface changed.
|
|
36
|
+
|
|
37
|
+
### Migration from 2.1.0
|
|
38
|
+
This release ships everything accumulated in the unreleased 2.2.0/2.3.0 sections below (custodial balance rail, WeChat-funded password-free payments) plus the above. No code changes are required to upgrade; the balance rail and its authentication are both opt-in via configuration.
|
|
39
|
+
|
|
40
|
+
To adopt balance authentication on an existing deployment, stage it: set `auth_mode: "shadow"`, upgrade clients, watch the logs until nothing is reported as would-deny, then set `auth_mode: "enforce"`. Legacy accounts with no openid (created before this release) TOFU-bind their signer on the first signed request.
|
|
41
|
+
|
|
42
|
+
## [2.3.0] - Unreleased
|
|
43
|
+
|
|
44
|
+
**Scan once, then password-free.** Fuses the WeChat Native rail (2.1.0) and the custodial balance rail (2.2.0) into one flow: WeChat becomes a **balance funding source** (the buyer scans once to load a top-up pack) and the balance rail does the spending (subsequent purchases deduct server-side, no scan, no password). WeChat has no autonomous payer product, so "password-free" lives entirely on the balance-deduction side; the first purchase against an empty balance still requires one scan, but it buys a pack, not a single item.
|
|
45
|
+
|
|
46
|
+
**No breaking changes.** The per-transaction WeChat rail and the manual balance top-up endpoint keep working; the fused flow is opt-in via config + client behavior. Design: [`docs/WECHAT-BALANCE-PASSWORDLESS-DESIGN.md`](https://github.com/Yaqing2023/moltspay/blob/v2.4.0/docs/WECHAT-BALANCE-PASSWORDLESS-DESIGN.md) (supersedes the now-deprecated `WECHAT-RAIL-DESIGN.md` / `BALANCE-RAIL-DESIGN.md`).
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
- **WeChat-funded balance top-up** — `POST /balance/topup/order` mints a buyer-bound WeChat Native order for a configured top-up pack and returns `{ code_url, out_trade_no, pack, expires_at }`. Buyer binding rides in the WeChat `attach` passthrough (`{ buyer_id, nonce }`), so an anonymous Native order credits the correct balance.
|
|
50
|
+
- **Automatic crediting** — the server confirms a top-up by **polling the WeChat order query** (`trade_state === SUCCESS`), credits the gateway-verified `payer_total`, and is idempotent on `wechat:<out_trade_no>`. Replaces the manual `balance topup --out-trade-no --amount` step. (The async `POST /wechat/notify` webhook — apiv3 AES-256-GCM decrypt + platform-cert verify — is **not implemented**; polling is the only confirmation path today. Callback-primary crediting remains planned.)
|
|
51
|
+
- **Fixed top-up packs** — `provider.balance.topup_packs` / `default_pack` / `auto_topup_max`. The client auto-tops-up with `default_pack` (bounded by `auto_topup_max`) when a 402 finds an insufficient balance, then auto-retries the original request.
|
|
52
|
+
- **CNY ledger** — `provider.balance.currency: "CNY"`. The ledger minor unit (`*_sat`) is fen for CNY, so WeChat `payer_total` credits 1:1 with no FX. A new `ledger_meta` row records the ledger currency and the rail refuses to start on a currency mismatch (guards against re-interpreting a USD ledger as CNY).
|
|
53
|
+
- **Client password-free orchestration** — `pay()` goes balance-first, surfaces a pack QR only when funds are short, and auto-retries after crediting; new `onTopupRequired` / `onTopupCredited` hooks. CLI: `moltspay balance topup --pack <amt>`; `moltspay pay` completes password-free when funded.
|
|
54
|
+
|
|
55
|
+
### Security
|
|
56
|
+
- **Structural amount integrity** — top-ups credit only the gateway-verified `payer_total` (callback decrypt+verify, or order-query `SUCCESS`); a client-declared amount never reaches the ledger. This makes the amount-spoofing class impossible by construction, generalizing the earlier `handleBalanceTopup` fix.
|
|
57
|
+
- **Bearer `buyer_id` caveat** — password-free means a pre-funded balance sits behind a bearer identifier; signed buyer tokens (Phase 3) are recommended before wide rollout, and `auto_topup_max` bounds how much a compromised client can pull from the user's WeChat.
|
|
58
|
+
|
|
59
|
+
## [2.2.0] - Unreleased
|
|
60
|
+
|
|
61
|
+
Third payment mode: a **custodial balance rail (password-free payments / 免密支付)**, alongside per-transaction crypto signing and the Alipay/WeChat scan-to-pay fiat rails. A buyer tops up once and subsequent purchases are deducted server-side — no signature, no QR, no password per transaction.
|
|
62
|
+
|
|
63
|
+
**No breaking changes.** Every existing rail behaves identically; the balance rail is strictly opt-in via configuration. Enabling it requires **Node.js >= 22.5** (the ledger uses the built-in `node:sqlite` — zero new dependencies); servers that don't enable it keep the package's `node >= 18` floor.
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
- **Custodial balance rail** — a new `BalanceFacilitator` (scheme/network `balance`) backed by a SQLite ledger (`src/facilitators/balance/ledger.ts`).
|
|
67
|
+
- Amounts are integer cents; check-and-deduct runs in a single `BEGIN IMMEDIATE` transaction, so a balance can never go negative under concurrency.
|
|
68
|
+
- Triple idempotency, each enforced by a unique index: deducts replay on the client's `request_id`, top-ups replay on the external settlement reference (`tx_hash` / trade number), refunds replay per deduct. No retry path can double-charge, double-credit, or double-refund.
|
|
69
|
+
- Server-side hard limits per buyer: per-transaction (default `5.00`) and daily (default `10.00`), configurable.
|
|
70
|
+
- `createPaymentRequirements` is **pure** — a 402 challenge mints nothing, so the order-per-challenge class of bug is structurally impossible on this rail.
|
|
71
|
+
- **HTTP server integration** — opt-in via `provider.balance` (`db_path`, optional `currency` / `single_limit` / `daily_limit`) and per-service `services[].balance` (`price`, defaults to the service's USD price). 402 responses append a `balance` `accepts[]` entry.
|
|
72
|
+
- `/execute` dispatch order is **inverted** relative to the QR rails: atomic deduct **before** the skill runs, automatic refund if the skill fails. (QR rails: verify paid → run → confirm.)
|
|
73
|
+
- Balance management endpoints: `GET /balance`, `POST /balance/topup`, `POST /balance/refund`, `GET /balance/transactions`.
|
|
74
|
+
- **Top-ups reuse the existing rails** — `POST /balance/topup` verifies the reported settlement per rail and credits the ledger: `crypto` verifies the `tx_hash` on-chain (receipt + USDC/USDT transfer to the provider wallet + amount); `wechat` queries the order by `out_trade_no` (must be `SUCCESS`); `alipay` is operator-trusted in this MVP (AI-Pay verification requires the buyer-side `payment_proof`) — protect the endpoint accordingly. All rails are idempotent on the external reference.
|
|
75
|
+
- **Buyer identity** — an opaque `buyer_id` with bearer semantics, carried in the X-Payment payload together with a client-generated `request_id` UUID. Channel runtimes map their own session ids to `buyer_id` at the application layer.
|
|
76
|
+
- **SDK client APIs** — `pay(..., { rail: 'balance', buyerId })`, `getBuyerBalance()`, `topupBalance()`, `listBalanceTransactions()`, `setBuyerId()` (persisted in `config.json`). No EVM wallet required.
|
|
77
|
+
- **CLI** — `moltspay balance query|topup|transactions|set-buyer` and `moltspay pay --rail balance`.
|
|
78
|
+
- **Docs** — `docs/BALANCE-RAIL-DESIGN.md` (design + SDK integration).
|
|
79
|
+
|
|
80
|
+
### Fixed
|
|
81
|
+
- **WeChat 402 double-charge** — every 402 emit used to place a fresh Native order, so a client that received two challenges could surface two live QRs and a buyer could pay both (confirmed ¥0.07×2 real double charge, 2026-07-02). The server now caches the unpaid order per service id and reuses it for every 402 within the order's `time_expire` window (refreshing 30s before expiry so served QRs always have usable life); the entry is dropped the moment the order verifies as paid (Native is one-code-one-payment), concurrent 402 builds share one in-flight order create, and build failures are never cached. In-memory by design: a server restart at worst leaves one extra *unpaid* order to expire server-side — never a double charge.
|
|
82
|
+
|
|
83
|
+
### Migration from 2.1.0
|
|
84
|
+
1. No code changes required — fully backward compatible.
|
|
85
|
+
2. Optional: add `provider.balance` + `services[].balance` to your services JSON to enable password-free payments (requires Node >= 22.5 on the server).
|
|
86
|
+
3. Buyers top up once (`moltspay balance topup`), then pay with `moltspay pay --rail balance` — no per-transaction signing or scanning.
|
|
87
|
+
|
|
88
|
+
## [2.1.0] - 2026-06-27
|
|
89
|
+
|
|
90
|
+
Second **fiat rail: WeChat Pay v3 Native (微信支付 / 扫码付)**, settling in CNY alongside USDC and Alipay.
|
|
91
|
+
|
|
92
|
+
**No breaking changes.** Every existing rail (crypto + Alipay) behaves identically; WeChat is strictly opt-in via configuration. Upgrading from 2.0.x requires no code changes.
|
|
93
|
+
|
|
94
|
+
Unlike Alipay AI Pay, WeChat has no autonomous payer product, so this rail is **SDK-managed scan-to-pay with server-side verify/settle**: the server issues a payer-agnostic Native `code_url` (no `openid`), the SDK client persists the payment session and polls, anyone scans to pay, and the server confirms by polling the order. One code, one payment.
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
- **WeChat Pay fiat rail** — a new `WechatFacilitator` settling CNY over the x402 protocol.
|
|
98
|
+
- New `wechat` chain / `wechatpay-native` scheme; **SHA256-RSA** request signing (`WECHATPAY2-SHA256-RSA2048`), optional response-signature verification against the WeChat platform certificate.
|
|
99
|
+
- `createPaymentRequirements` places a Native order (`POST /v3/pay/transactions/native`) and returns a `code_url`; `verify` queries the order (`trade_state === SUCCESS`); `settle` is an idempotent confirm; `healthCheck` validates keys + gateway reachability.
|
|
100
|
+
- Amount is converted yuan → fen (`cnyToFen`) for the WeChat API; the manifest uses yuan decimal strings.
|
|
101
|
+
- **WeChat crypto helpers** — `wechatV3Sign` / `buildAuthorizationToken` / `wechatV3VerifyResponse` (`src/facilitators/wechat/sign.ts`) and the `wechatV3Call` v3 JSON gateway client (`src/facilitators/wechat/api.ts`).
|
|
102
|
+
- **HTTP server integration** — opt-in via `provider.wechat` (`mchid`, `appid`, `serial_no`, `private_key_path`, `notify_url`, optional `platform_public_key_path` / `apiv3_key`) and per-service `services[].wechat` (`price_cny`, `description`). 402 responses append a `wechatpay-native` `accepts[]` entry carrying `code_url` + `out_trade_no`; `/execute` dispatches the rail to verify → run skill → fire-and-forget settle.
|
|
103
|
+
- **Recoverable WeChat buyer sessions** — `WechatClient` persists `payment_session_id`, `out_trade_no`, QR payload, original request body, service context, status, and result under `<configDir>/wechat-sessions`. Sessions can be recovered by session id or `out_trade_no`, polled, fulfilled idempotently, cancelled, and listed.
|
|
104
|
+
- **WeChat SDK orchestration APIs** — `MoltsPayClient.startWechatPayment()`, `getWechatPaymentStatus()`, `fulfillWechatPayment()`, `cancelWechatPayment()`, and `listWechatPaymentSessions()`. `startWechatPayment()` supports `autoPoll`, `onWechatPaymentCompleted`, and `onWechatPaymentFailed` so channel runtimes can let the SDK client own payment polling and asynchronous fulfillment.
|
|
105
|
+
- **WeChat CLI session commands** — `moltspay wechat start/status/fulfill/cancel/list` for non-blocking QR issuance and operational recovery. `moltspay pay --rail wechat` remains the blocking terminal wrapper, now built on the same persisted session flow.
|
|
106
|
+
- **Scenario-A demo** — `examples/wechat-native-pay.ts` (issue code → `qrcode-terminal` → poll → settle); mock by default, `WECHAT_REAL=1` hits the live gateway.
|
|
107
|
+
- **Docs** — `docs/WECHAT-RAIL-DESIGN.md` (design + scenario A) and `docs/WECHAT-RAIL-PLAN.md` (dev plan).
|
|
108
|
+
|
|
109
|
+
### Fixed
|
|
110
|
+
- **Fiat rails no longer produce a spurious crypto `accepts[]` entry** — `getProviderChains` now excludes `alipay`/`wechat` from EVM chain iteration (they were defaulting to a base/USDC entry when listed in `provider.chains`). Affects Alipay too.
|
|
111
|
+
|
|
112
|
+
### Migration from 2.0.x
|
|
113
|
+
1. No code changes required — fully backward compatible.
|
|
114
|
+
2. Optional: add `provider.wechat` + `services[].wechat` to your services JSON to enable WeChat payments.
|
|
115
|
+
3. For terminal use, `moltspay pay --rail wechat` still blocks until paid/timeout.
|
|
116
|
+
4. For chat/channel integrations, use `startWechatPayment()` or `moltspay wechat start` so the SDK client persists the session before the QR is shown, then recover with `status` / `fulfill` by `payment_session_id` or `out_trade_no`.
|
|
117
|
+
|
|
118
|
+
## [2.0.0] - 2026-06-20
|
|
119
|
+
|
|
120
|
+
First-class **fiat payments via Alipay (支付宝 AI 收)**. This is the milestone release that takes MoltsPay beyond crypto-only settlement.
|
|
121
|
+
|
|
122
|
+
**No breaking changes to the existing crypto rails.** The Node CLI, the x402 wire protocol, and every chain that worked in 1.6.0 behave identically. The major version bump marks the fiat milestone, not an incompatible API. Upgrading from 1.6.0 requires no code changes; Alipay is strictly opt-in via configuration. (npm 1.7.0 was never published — 2.0.0 supersedes it.)
|
|
123
|
+
|
|
124
|
+
### Added
|
|
125
|
+
- **Alipay fiat payment rail** — a new `AlipayFacilitator` settling Chinese Yuan (CNY) over the x402 protocol.
|
|
126
|
+
- New `alipay` chain / `alipay-aipay` scheme, RSA2 signature verification, health-check + settlement APIs.
|
|
127
|
+
- Opt-in via `provider.alipay` and per-service `services[].alipay` in your services JSON (`seller_id`, `app_id`, key paths, `service_id`, `price_cny`, `goods_name`, …). See `docs/ALIPAY-RAIL.md`.
|
|
128
|
+
- Equivalent env vars: `ALIPAY_SELLER_ID`, `ALIPAY_APP_ID`, `ALIPAY_SELLER_NAME`, `ALIPAY_PRIVATE_KEY_PATH`, `ALIPAY_PUBLIC_KEY_PATH`, `ALIPAY_GATEWAY_URL`.
|
|
129
|
+
- **Dual-emit HTTP 402 middleware** — services advertise both the x402 `X-Payment-Required` challenge and the legacy alipay-bot `Payment-Needed` header in one response, so existing clients keep working.
|
|
130
|
+
- **Client-side Alipay pay flow** — CLI wrapper around `alipay-bot` with an 8-step `pay402` state machine; consumes `Payment-Proof` on `/execute`.
|
|
131
|
+
- **Key-encoding utilities** — `toPem()` (bare Base64 → PEM), `decodeBase64UrlWithPadFix()` (Base64URL with padding repair), `rsa2Sign()` / `rsa2Verify()`.
|
|
132
|
+
- **Auto-provision of the `alipay-bot` CLI on install** — `postinstall` downloads it from Alipay's official CDN (it is not on npm and is UNLICENSED, so it is never redistributed by us). Best-effort: a provisioning failure prints an actionable notice but never fails `npm install`. Opt out with `MOLTSPAY_SKIP_CLI_INSTALL=1`; provision manually with `npx -y @alipay/agent-payment install-cli`.
|
|
133
|
+
- **Alipay verification scripts** — `verify:alipay:offline` (offline E2E) and `verify:alipay:http` (402 dual-emit).
|
|
134
|
+
|
|
135
|
+
### Fixed
|
|
136
|
+
- **Paid resource never leaks into the log stream**, and the 402 challenge headers are hardened. The deliverable is returned via the resource-URL HTTP body only — never stdout/logs.
|
|
137
|
+
- **`Payment-Proof` header now consumed and validated** on `/execute`; corrected `UNPAID` status parsing for Alipay transactions.
|
|
138
|
+
- **Settled-trade report recognition** for `alipay-bot` 0.3.15 (Shape C).
|
|
139
|
+
- **`scripts/postinstall.js` is now shipped in the published tarball** (was missing from the `files` whitelist, so auto-provision never ran on a clean install).
|
|
140
|
+
|
|
141
|
+
### Performance
|
|
142
|
+
- **Cross-flow `check-wallet` cache** — wallet authorization status is cached across payments (it doesn't change once authorized), removing a ~23s spawn from the pre-QR window of every payment after the first.
|
|
143
|
+
- **Overlapping status polls** — `pollUntil` launches overlapping `402-query-payment-status` spawns on a fixed cadence instead of serially; first to observe `paid` wins and aborts the rest. Cuts post-payment detection lag from ~50–60s to ~(cadence + 1 spawn). Tunables: `maxInflight` / `launchIntervalMs` (or `MOLTSPAY_ALIPAY_POLL_MAX_INFLIGHT` / `MOLTSPAY_ALIPAY_POLL_LAUNCH_MS`); set `maxInflight=1` for strict sequential polling. Concurrent polls are read-only verifies — no double-charge or double-delivery.
|
|
144
|
+
- **Skip-cache the payment-intent handshake** and the vendor perf request to shave fixed latency off the buyer-pay path.
|
|
145
|
+
|
|
146
|
+
### Migration from 1.6.0
|
|
147
|
+
1. No code changes required — fully backward compatible.
|
|
148
|
+
2. Optional: add `provider.alipay` + `services[].alipay` to your services JSON to enable fiat payments.
|
|
149
|
+
3. Optional: update clients to handle the `alipay-aipay` scheme.
|
|
150
|
+
|
|
151
|
+
## [1.6.0] - 2026-04-24
|
|
152
|
+
|
|
153
|
+
First-class browser support. Node CLI behavior and the x402 wire protocol are unchanged; everything here is additive.
|
|
154
|
+
|
|
155
|
+
### Added
|
|
156
|
+
- **Web Client (`moltspay/web`)** — `MoltsPayWebClient` + signer adapters for browser use. No private key ever in browser memory; signing is delegated to an injected wallet.
|
|
157
|
+
- `eip1193Signer(window.ethereum)` for MetaMask / Rainbow / Frame / any EIP-1193 provider.
|
|
158
|
+
- `solanaSigner(walletAdapter)` for Phantom / Solflare / Backpack / any `@solana/wallet-adapter` wallet.
|
|
159
|
+
- `composeSigners(evm, svm)` to route by chain from a single client instance.
|
|
160
|
+
- `SpendingLedger` — opt-in `localStorage`-backed per-browser spend limits.
|
|
161
|
+
- `new ./web` subpath export, browser-only bundle (40 KB gzipped, no Node-only APIs).
|
|
162
|
+
- Error classes `NeedsApprovalError` / `UnsupportedChainError` / `PaymentRejectedError` / `InsufficientBalanceError` / `SpendingLimitExceededError` / `ServerError` / `MoltsPayError` each with a stable `code` field.
|
|
163
|
+
- **`solanaRpc` option on `MoltsPayWebClient`** — per-chain RPC URL override so customers can point Solana traffic at Helius / QuickNode / Alchemy etc. The public `api.mainnet-beta.solana.com` endpoint returns 403 to browser requests, so this is required in practice for Solana mainnet.
|
|
164
|
+
- **Tempo permit settlement path** — server's `TempoFacilitator` now advertises `scheme: "permit"` in the 402 response and accepts EIP-2612 permit payloads, enabling browser payment on Tempo Moderato without a chain switch. Node CLI callers still default to MPP on Tempo; no CLI opt-in changes.
|
|
165
|
+
- **`MoltsPayServer` `cors` option** — CORS is required for browser clients. Default (`*`) preserves 1.5.x behavior; set to a string, string-array, or `false` to tighten. Default response already advertises `Access-Control-Expose-Headers: X-Payment-Required, X-Payment-Response, WWW-Authenticate, Payment-Receipt` so browsers can read the 402 challenge.
|
|
166
|
+
- **React + Vite demo** at `examples/web/` — reference integration showing MetaMask + Phantom + `composeSigners`.
|
|
167
|
+
|
|
168
|
+
### Fixed
|
|
169
|
+
- **EIP-712 `signTypedData` now calls `ensureChainId`** before signing. Previously MetaMask threw `The Provider is not connected to the requested chain` for any EIP-3009 or permit sign whose `domain.chainId` differed from the wallet's active chain.
|
|
170
|
+
- **Browser wallet disambiguation** in the demo's `detectProvider` now excludes Coinbase Wallet by its proxy-specific keys (`providerMap`, `overrideIsMetaMask`, `selectedProvider`, `qrUrl`). Coinbase Wallet spoofs `isMetaMask: true` via `overrideIsMetaMask`, so naive `providers[0]` or `isMetaMask` filtering mis-picked Coinbase when both wallets were installed.
|
|
171
|
+
- **Server `validatePayment` and `/proxy` now accept `scheme: "permit"`** in addition to `scheme: "exact"`. Previously two hardcoded checks rejected permit payloads before the facilitator router could see them, breaking Tempo browser payments.
|
|
172
|
+
- **EVM settle failure after skill execution now returns HTTP 402** with `{error, message, facilitator}` instead of a false-positive `HTTP 200 {success: true, payment: {status: "pending"}}`. Customers were seeing "Paid" in the UI while no settlement had occurred on-chain. Pay-for-success providers using this path lose the skill cost on settle failure but no longer silently claim success.
|
|
173
|
+
- **Tempo EIP-712 domain name casing** corrected: `pathUSD` → `PathUSD`, `alphaUSD` → `AlphaUSD` etc. — token-per-token fixtures now match what the on-chain TIP-20 contracts expose via `name()`.
|
|
174
|
+
|
|
175
|
+
### Known Limitations
|
|
176
|
+
Phase 8 browser QA exercised 3 of 8 chains end-to-end in production-equivalent conditions (`base`, `base_sepolia`, `solana_devnet` — all passed with real on-chain settlements). The other 5 chains have code paths covered only by unit tests or by partial integration runs:
|
|
177
|
+
|
|
178
|
+
- **`bnb` and `bnb_testnet`** — Web Client's `approveBnb` + EIP-712 `PaymentIntent` flow has not been verified end-to-end in a browser. BNB's `requiresApproval: true` code path is structurally distinct from the one-signature flows other chains use. First BNB customer is the de-facto verification.
|
|
179
|
+
- **`solana:mainnet`** — `solanaRpc` override is covered by 3 unit tests but has not been verified in-browser against a real Helius/QuickNode endpoint.
|
|
180
|
+
- **`polygon`** — client-side EIP-3009 signature construction verified via CDP verify, but no successful on-chain settlement run in QA (tester wallet had 0 USDC on Polygon). Code path is identical to `base` which did pass.
|
|
181
|
+
- **`tempo_moderato`** — permit signature + on-chain allowance update verified; the subsequent `transferFrom` step did not run in QA due to tester wallet having 0 pathUSD.
|
|
182
|
+
|
|
183
|
+
See `docs/WEB-CLIENT-DESIGN.md` §Phase 8 for full QA matrix and 1.6.1 follow-up plan.
|
|
184
|
+
|
|
185
|
+
## [Unreleased]
|
|
186
|
+
|
|
187
|
+
### Added
|
|
188
|
+
- **Solana Chain Support** - Full Solana mainnet and devnet integration
|
|
189
|
+
- New `SolanaFacilitator` for SPL token transfers
|
|
190
|
+
- Separate ed25519 wallet stored at `~/.moltspay/wallet-solana.json`
|
|
191
|
+
- `npx moltspay faucet --chain solana_devnet` for free testnet USDC
|
|
192
|
+
- Official Circle USDC SPL token support
|
|
193
|
+
- Cost: ~$0.001 SOL per transaction
|
|
194
|
+
|
|
195
|
+
- **BNB Chain Support** - BNB Smart Chain mainnet and testnet
|
|
196
|
+
- New `BNBFacilitator` with EIP-712 intent signing
|
|
197
|
+
- Gas-sponsored model (server pays ~$0.0001 per tx)
|
|
198
|
+
- `npx moltspay faucet --chain bnb_testnet` gives USDC + tBNB for gas
|
|
199
|
+
- Pay-for-success: payment only settles if service succeeds
|
|
200
|
+
- Note: BNB uses 18 decimals (not 6 like Base/Polygon)
|
|
201
|
+
|
|
202
|
+
- **Tempo Chain Support** - Tempo Moderato testnet with MPP protocol
|
|
203
|
+
- New `TempoFacilitator` for native gas-free transfers
|
|
204
|
+
- TIP-20 tokens: pathUSD (USDC), alphaUSD (USDT)
|
|
205
|
+
- `npx moltspay faucet --chain tempo_moderato` for free testnet tokens
|
|
206
|
+
- MPP (Machine Payments Protocol) support alongside x402
|
|
207
|
+
|
|
208
|
+
- **Testnet Faucet** - `npx moltspay faucet` to get free testnet USDC
|
|
209
|
+
- Base Sepolia: 1 USDC per request, once per 24 hours
|
|
210
|
+
- Solana Devnet: 1 USDC per request
|
|
211
|
+
- BNB Testnet: 1 USDC + 0.001 tBNB (for gas)
|
|
212
|
+
- Tempo Moderato: 1 pathUSD per request
|
|
213
|
+
|
|
214
|
+
### Fixed
|
|
215
|
+
- **EIP-712 Domain Name** - Fixed signature verification failures on Base Sepolia
|
|
216
|
+
- Server now returns correct token domain per network in `extra` field
|
|
217
|
+
- Base mainnet USDC uses domain name `"USD Coin"`
|
|
218
|
+
- Base Sepolia USDC uses domain name `"USDC"` (different contract!)
|
|
219
|
+
- Client now uses server's `extra` field for signing instead of hardcoded values
|
|
220
|
+
- Added `base_sepolia` to supported chains in CLI
|
|
221
|
+
|
|
222
|
+
## [0.9.5] - 2026-03-04
|
|
223
|
+
|
|
224
|
+
### Added
|
|
225
|
+
- **Skill Execution Timeout** - Prevents hung skills from blocking requests forever
|
|
226
|
+
- Configurable via `SKILL_TIMEOUT_SECONDS` env var (default: 1200 = 20 minutes)
|
|
227
|
+
- Applies to both `/execute` and `/proxy` endpoints
|
|
228
|
+
- If skill times out, payment is NOT settled (client keeps money)
|
|
229
|
+
|
|
230
|
+
### Example
|
|
231
|
+
```env
|
|
232
|
+
# In ~/.moltspay/.env
|
|
233
|
+
SKILL_TIMEOUT_SECONDS=1200 # 20 minutes
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## [0.9.3] - 2026-02-23
|
|
237
|
+
|
|
238
|
+
### Fixed
|
|
239
|
+
- Include buyer wallet address (`from`) in `/proxy` response
|
|
240
|
+
|
|
241
|
+
## [0.9.2] - 2026-02-21
|
|
242
|
+
|
|
243
|
+
### Added
|
|
244
|
+
- **Proxy Execute Mode** - `/proxy` endpoint now supports skill execution with pay-on-success
|
|
245
|
+
- Pass `execute: true` + `service` + `params` to execute a skill after payment verification
|
|
246
|
+
- Skill executes BEFORE settlement - if skill fails, payment is NOT settled (client keeps money)
|
|
247
|
+
- Perfect for platform integrations (e.g., moltspay.com marketplace)
|
|
248
|
+
- IP whitelist for `/proxy` endpoint (`PROXY_ALLOWED_IPS` env var)
|
|
249
|
+
|
|
250
|
+
### Changed
|
|
251
|
+
- `/proxy` with `execute: true` now follows pay-on-success model:
|
|
252
|
+
1. Verify payment signature
|
|
253
|
+
2. Execute skill
|
|
254
|
+
3. If success -> settle payment, return result
|
|
255
|
+
4. If fail -> don't settle, return error
|
|
256
|
+
- Improved logging for proxy execute flow
|
|
257
|
+
|
|
258
|
+
### Fixed
|
|
259
|
+
- Proxy execute now properly passes params to skill handler
|
|
260
|
+
|
|
261
|
+
### Example Usage
|
|
262
|
+
```bash
|
|
263
|
+
# Platform calls /proxy with execute mode
|
|
264
|
+
curl -X POST https://server.com/proxy \
|
|
265
|
+
-H "Content-Type: application/json" \
|
|
266
|
+
-H "X-Payment: <payment-header>" \
|
|
267
|
+
-d '{
|
|
268
|
+
"wallet": "0x...",
|
|
269
|
+
"amount": 0.99,
|
|
270
|
+
"execute": true,
|
|
271
|
+
"service": "text-to-video",
|
|
272
|
+
"params": {"prompt": "a cat dancing"}
|
|
273
|
+
}'
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## [0.9.1] - 2026-02-20
|
|
277
|
+
|
|
278
|
+
### Added
|
|
279
|
+
- Facilitator selection via environment variables:
|
|
280
|
+
- `FACILITATOR_PRIMARY` - Primary facilitator (default: cdp)
|
|
281
|
+
- `FACILITATOR_FALLBACK` - Comma-separated fallback list
|
|
282
|
+
- `FACILITATOR_STRATEGY` - Selection strategy (failover/cheapest/fastest/random/roundrobin)
|
|
283
|
+
- Updated `.env.example` with all facilitator config options
|
|
284
|
+
- Placeholder sections for upcoming ChaosChain and Questflow facilitators
|
|
285
|
+
|
|
286
|
+
### Fixed
|
|
287
|
+
- Users no longer need to modify code to configure facilitators
|
|
288
|
+
|
|
289
|
+
## [0.9.0] - 2026-02-20
|
|
290
|
+
|
|
291
|
+
### Added
|
|
292
|
+
- **Facilitator Abstraction Layer** (Phase 1 of v0.9.0)
|
|
293
|
+
- `Facilitator` interface for pluggable payment facilitators
|
|
294
|
+
- `CDPFacilitator` class (extracted from server logic)
|
|
295
|
+
- `FacilitatorRegistry` with selection strategies (failover, cheapest, fastest, random, roundrobin)
|
|
296
|
+
- New `/health` endpoint showing facilitator status
|
|
297
|
+
- Exports: `moltspay/facilitators` subpath for direct access
|
|
298
|
+
- Server now accepts `facilitators` config option
|
|
299
|
+
|
|
300
|
+
### Changed
|
|
301
|
+
- Server refactored to use `FacilitatorRegistry` instead of hardcoded CDP logic
|
|
302
|
+
- `/services` endpoint now includes facilitator configuration in response
|
|
303
|
+
|
|
304
|
+
### Fixed
|
|
305
|
+
- Server now loads `.env` file before reading `USE_MAINNET` (was ignoring env file)
|
|
306
|
+
|
|
307
|
+
### Migration
|
|
308
|
+
- Fully backward compatible - default behavior unchanged
|
|
309
|
+
- New facilitator config is opt-in:
|
|
310
|
+
```typescript
|
|
311
|
+
const server = new MoltsPayServer('./services.json', {
|
|
312
|
+
facilitators: {
|
|
313
|
+
primary: 'cdp',
|
|
314
|
+
fallback: ['chaoschain'], // Coming soon
|
|
315
|
+
strategy: 'failover'
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## [0.8.15] - 2026-02-19
|
|
321
|
+
|
|
322
|
+
### Changed
|
|
323
|
+
- Entry point discovery now reads `package.json` `main` field
|
|
324
|
+
- Falls back to `index.js` if no `main` specified
|
|
325
|
+
- Providers no longer need to name their entry point `index.js`
|
|
326
|
+
|
|
327
|
+
## [0.8.14] - 2026-02-19
|
|
328
|
+
|
|
329
|
+
### Added
|
|
330
|
+
- JSON Schema for `moltspay.services.json` validation
|
|
331
|
+
- `npx moltspay validate <path>` command to validate manifests
|
|
332
|
+
- Schema available at `schemas/moltspay.services.schema.json`
|
|
333
|
+
|
|
334
|
+
## [0.8.13] - 2026-02-19
|
|
335
|
+
|
|
336
|
+
### Changed
|
|
337
|
+
- Skill-based architecture: providers add only `moltspay.services.json`
|
|
338
|
+
- `function` field points to existing exports in skill's entry point
|
|
339
|
+
- Server auto-discovers entry point from skill's `package.json`
|
|
340
|
+
- No wrapper code needed - existing skill code stays untouched
|
|
341
|
+
|
|
342
|
+
### Fixed
|
|
343
|
+
- Various x402 flow improvements
|
|
344
|
+
|
|
345
|
+
## [0.5.4] - 2026-02-17
|
|
346
|
+
|
|
347
|
+
### Added
|
|
348
|
+
- Internal module improvements
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## [0.4.4] - 2026-02-16
|
|
353
|
+
|
|
354
|
+
### Fixed
|
|
355
|
+
- Fixed imports: use `import { createX402Client } from 'moltspay'` (main export)
|
|
356
|
+
- Removed broken subpath exports (`/x402`, `/cdp`) that didn't exist in build
|
|
357
|
+
|
|
358
|
+
## [0.4.3] - 2026-02-16
|
|
359
|
+
|
|
360
|
+
### Fixed
|
|
361
|
+
- Corrected x402 endpoint URL to `https://juai8.com/zen7/v1/video/generate`
|
|
362
|
+
|
|
363
|
+
## [0.4.2] - 2026-02-16
|
|
364
|
+
|
|
365
|
+
### Changed
|
|
366
|
+
- **Docs overhaul:** Clarified that local wallet + x402 = NO GAS needed for client agents
|
|
367
|
+
- Moved CDP wallet to "optional/advanced" section (not recommended for most users)
|
|
368
|
+
- Added clear explanation of EIP-3009 signature flow (client signs, facilitator pays gas)
|
|
369
|
+
|
|
370
|
+
### Fixed
|
|
371
|
+
- Updated x402 example URLs to use actual endpoint: `https://juai8.com/x402pay`
|
|
372
|
+
|
|
373
|
+
## [0.4.1] - 2026-02-16
|
|
374
|
+
|
|
375
|
+
### Fixed
|
|
376
|
+
- Updated x402 example URLs to use actual endpoint: `https://juai8.com/x402pay`
|
|
377
|
+
|
|
378
|
+
## [0.4.0] - 2026-02-16
|
|
379
|
+
|
|
380
|
+
### Added
|
|
381
|
+
|
|
382
|
+
#### x402 Protocol Support
|
|
383
|
+
- `createX402Client()` - Create HTTP client with automatic x402 payment handling
|
|
384
|
+
- `x402Fetch()` - One-shot function for paid HTTP requests
|
|
385
|
+
- `isX402Available()` - Check if x402 packages are installed
|
|
386
|
+
- Automatic 402 Payment Required response handling
|
|
387
|
+
- Integration with official `@x402/fetch` and `@x402/evm` packages
|
|
388
|
+
|
|
389
|
+
#### CDP (Coinbase Developer Platform) Wallet
|
|
390
|
+
- `initCDPWallet()` - Initialize CDP-hosted wallet
|
|
391
|
+
- `CDPWallet` class - Manage CDP wallet operations
|
|
392
|
+
- `npx moltspay init --cdp` - CLI command for CDP wallet creation
|
|
393
|
+
- No gas needed for wallet creation
|
|
394
|
+
- viem account compatibility for x402 integration
|
|
395
|
+
|
|
396
|
+
#### CLI Enhancements
|
|
397
|
+
- `moltspay init` now supports `--cdp` flag for CDP wallet
|
|
398
|
+
- `moltspay init` shows clear next steps after initialization
|
|
399
|
+
|
|
400
|
+
### Changed
|
|
401
|
+
- x402 packages moved to peerDependencies (optional)
|
|
402
|
+
- CDP SDK added as optional peerDependency
|
|
403
|
+
- Package exports updated to include `/x402` and `/cdp` subpaths
|
|
404
|
+
|
|
405
|
+
## [0.3.0] - 2026-02-15
|
|
406
|
+
|
|
407
|
+
### Added
|
|
408
|
+
- AgentWallet with auto-initialization
|
|
409
|
+
- Direct transfer support (wallet.transfer())
|
|
410
|
+
- Service payment helper (wallet.payService())
|
|
411
|
+
|
|
412
|
+
## [0.2.1] - 2026-02-15
|
|
413
|
+
|
|
414
|
+
### Changed
|
|
415
|
+
- Converted all content to English (templates, receipts, guides, comments)
|
|
416
|
+
- Status markers now use `[status:xxx]` format instead of Chinese
|
|
417
|
+
|
|
418
|
+
## [0.2.0] - 2026-02-15
|
|
419
|
+
|
|
420
|
+
### Added - Agent-to-Agent Payment Flow
|
|
421
|
+
|
|
422
|
+
Complete implementation of all features required for Agent-to-Agent conversational payment flow.
|
|
423
|
+
|
|
424
|
+
#### P0: Core Features
|
|
425
|
+
|
|
426
|
+
**createWallet()** - Create wallet for buyer Agent
|
|
427
|
+
```typescript
|
|
428
|
+
import { createWallet, loadWallet } from 'moltspay';
|
|
429
|
+
|
|
430
|
+
// Create new wallet (auto-stored to ~/.moltspay/wallet.json)
|
|
431
|
+
const result = createWallet();
|
|
432
|
+
console.log('Wallet address:', result.address);
|
|
433
|
+
|
|
434
|
+
// Encrypted storage
|
|
435
|
+
const result = createWallet({ password: 'secure123' });
|
|
436
|
+
|
|
437
|
+
// Load existing wallet
|
|
438
|
+
const wallet = loadWallet({ password: 'secure123' });
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**PermitWallet** - Pay using Boss's Permit authorization
|
|
442
|
+
```typescript
|
|
443
|
+
import { PermitWallet } from 'moltspay';
|
|
444
|
+
|
|
445
|
+
const wallet = new PermitWallet({ chain: 'base' });
|
|
446
|
+
|
|
447
|
+
// Pay using Boss-signed Permit
|
|
448
|
+
const result = await wallet.transferWithPermit({
|
|
449
|
+
to: '0xSELLER...',
|
|
450
|
+
amount: 3.99,
|
|
451
|
+
permit: {
|
|
452
|
+
owner: '0xBOSS...',
|
|
453
|
+
spender: wallet.address,
|
|
454
|
+
value: '10000000',
|
|
455
|
+
deadline: 1234567890,
|
|
456
|
+
v: 27,
|
|
457
|
+
r: '0x...',
|
|
458
|
+
s: '0x...'
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
#### P1: Receipt Generation
|
|
464
|
+
|
|
465
|
+
**generateReceipt()** - Generate transaction receipt
|
|
466
|
+
```typescript
|
|
467
|
+
import { generateReceipt, formatReceiptText } from 'moltspay';
|
|
468
|
+
|
|
469
|
+
const receipt = generateReceipt({
|
|
470
|
+
orderId: 'vo_abc123',
|
|
471
|
+
service: 'Video generation 5s 720p',
|
|
472
|
+
amount: 3.99,
|
|
473
|
+
chain: 'base',
|
|
474
|
+
txHash: '0x...',
|
|
475
|
+
payerAddress: '0xBUYER...',
|
|
476
|
+
recipientAddress: '0xSELLER...',
|
|
477
|
+
delivery: {
|
|
478
|
+
url: 'https://...',
|
|
479
|
+
fileHash: 'sha256:...'
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
// Format as plain text (for Feishu/WhatsApp)
|
|
484
|
+
console.log(formatReceiptText(receipt));
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
#### P2: Conversation Templates
|
|
488
|
+
|
|
489
|
+
**SellerTemplates / BuyerTemplates** - Standardized dialogue templates
|
|
490
|
+
```typescript
|
|
491
|
+
import { SellerTemplates, BuyerTemplates, parseStatusMarker } from 'moltspay';
|
|
492
|
+
|
|
493
|
+
// Seller templates
|
|
494
|
+
SellerTemplates.askPaymentCapability();
|
|
495
|
+
SellerTemplates.guideInstall();
|
|
496
|
+
SellerTemplates.quote({ service: 'Video gen', price: 3.99, recipientAddress: '0x...' });
|
|
497
|
+
|
|
498
|
+
// Buyer templates
|
|
499
|
+
BuyerTemplates.requestService('video generation');
|
|
500
|
+
BuyerTemplates.walletCreated('0x...');
|
|
501
|
+
BuyerTemplates.paymentSent('0xtx...', 3.99);
|
|
502
|
+
|
|
503
|
+
// Parse status markers
|
|
504
|
+
const status = parseStatusMarker('[status:payment_sent tx=0xabc amount=3.99 USDC]');
|
|
505
|
+
// { type: 'payment_sent', data: { txHash: '0xabc', amount: '3.99' } }
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### New Exports
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
// Wallet creation
|
|
512
|
+
export { createWallet, loadWallet, getWalletAddress, walletExists } from 'moltspay';
|
|
513
|
+
|
|
514
|
+
// Permit wallet
|
|
515
|
+
export { PermitWallet, formatPermitRequest } from 'moltspay';
|
|
516
|
+
|
|
517
|
+
// Receipt
|
|
518
|
+
export { generateReceipt, generateReceiptFromInvoice, formatReceiptMessage, formatReceiptText, formatReceiptJson } from 'moltspay';
|
|
519
|
+
|
|
520
|
+
// Conversation templates
|
|
521
|
+
export { SellerTemplates, BuyerTemplates, StatusMarkers, parseStatusMarker } from 'moltspay';
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## [0.1.3] - 2026-02-10
|
|
527
|
+
|
|
528
|
+
### Added
|
|
529
|
+
- OrderManager for order management
|
|
530
|
+
- Payment guide message generation
|
|
531
|
+
|
|
532
|
+
## [0.1.2] - 2026-02-08
|
|
533
|
+
|
|
534
|
+
### Added
|
|
535
|
+
- SecureWallet (limits/whitelist/audit)
|
|
536
|
+
- AuditLog for immutable audit logging
|
|
537
|
+
|
|
538
|
+
## [0.1.1] - 2026-02-06
|
|
539
|
+
|
|
540
|
+
### Added
|
|
541
|
+
- PaymentAgent core class
|
|
542
|
+
- Invoice generation
|
|
543
|
+
- On-chain payment verification
|
|
544
|
+
- Multi-chain support (Base, Polygon, Ethereum)
|
|
545
|
+
|
|
546
|
+
## [0.1.0] - 2026-02-05
|
|
547
|
+
|
|
548
|
+
### Added
|
|
549
|
+
- Initial release
|
|
550
|
+
- Basic Wallet class
|
|
551
|
+
- EIP-2612 Permit support
|