@odatano/x402 0.1.0 → 0.3.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/.github/workflows/test.yaml +49 -0
- package/CHANGELOG.md +57 -0
- package/README.md +29 -281
- package/cds-plugin.js +2 -0
- package/db/x402-grants.cds +49 -0
- package/db/x402-receipts.cds +44 -0
- package/package.json +11 -4
- package/srv/bridge.d.ts +9 -12
- package/srv/bridge.js +10 -13
- package/srv/cds-augment.d.ts +17 -0
- package/srv/client/axios.d.ts +38 -0
- package/srv/client/axios.js +107 -0
- package/srv/client/envelope.d.ts +33 -0
- package/srv/client/envelope.js +52 -0
- package/srv/client/errors.d.ts +107 -0
- package/srv/client/errors.js +144 -0
- package/srv/client/fetch.d.ts +30 -0
- package/srv/client/fetch.js +141 -0
- package/srv/client/pay-handlers.d.ts +41 -0
- package/srv/client/pay-handlers.js +47 -0
- package/srv/client/types.d.ts +56 -0
- package/srv/client/types.js +10 -0
- package/srv/core/asset.d.ts +1 -1
- package/srv/core/decode.d.ts +2 -2
- package/srv/core/decode.js +5 -5
- package/srv/core/errors.js +3 -3
- package/srv/core/network.d.ts +1 -1
- package/srv/core/network.js +1 -1
- package/srv/core/requirements.d.ts +37 -5
- package/srv/core/requirements.js +43 -4
- package/srv/core/types.d.ts +68 -6
- package/srv/core/types.js +3 -3
- package/srv/core/validate.d.ts +31 -7
- package/srv/core/validate.js +84 -9
- package/srv/facilitator/adapter.d.ts +69 -0
- package/srv/facilitator/adapter.js +52 -0
- package/srv/facilitator/http.d.ts +43 -0
- package/srv/facilitator/http.js +99 -0
- package/srv/facilitator/nonce.d.ts +4 -4
- package/srv/facilitator/nonce.js +4 -4
- package/srv/facilitator/server.d.ts +68 -0
- package/srv/facilitator/server.js +167 -0
- package/srv/facilitator/settle.d.ts +2 -2
- package/srv/facilitator/settle.js +4 -4
- package/srv/facilitator/verify.d.ts +5 -5
- package/srv/facilitator/verify.js +19 -5
- package/srv/helpers/build-unsigned-tx.d.ts +5 -5
- package/srv/helpers/build-unsigned-tx.js +3 -3
- package/srv/helpers/verify-confirmed.d.ts +1 -1
- package/srv/helpers/verify-confirmed.js +1 -1
- package/srv/index.d.ts +11 -2
- package/srv/index.js +23 -3
- package/srv/middleware/cap.d.ts +53 -8
- package/srv/middleware/cap.js +87 -43
- package/srv/middleware/express.d.ts +22 -9
- package/srv/middleware/express.js +21 -21
- package/srv/middleware/grants.d.ts +64 -0
- package/srv/middleware/grants.js +113 -0
- package/srv/middleware/pricing.d.ts +41 -0
- package/srv/middleware/pricing.js +78 -0
- package/srv/middleware/receipts.d.ts +38 -0
- package/srv/middleware/receipts.js +68 -0
- package/srv/plugin.d.ts +2 -2
- package/srv/plugin.js +2 -2
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CAP-backed persistence for accepted x402 payments.
|
|
4
|
+
*
|
|
5
|
+
* Called from `gateService` when its `receipts` option is set. One INSERT
|
|
6
|
+
* per accepted payment; runs AFTER settle confirms and BEFORE the 200
|
|
7
|
+
* response is served to the buyer. Best-effort: any INSERT failure is
|
|
8
|
+
* logged and SWALLOWED, the canonical record is on chain and we never
|
|
9
|
+
* want a flaky DB to deny a paying buyer their response.
|
|
10
|
+
*
|
|
11
|
+
* Entity shape: see `db/x402-receipts.cds`. The schema is shipped in the
|
|
12
|
+
* plugin's `db/`; CAP auto-discovers it when `@odatano/x402` is in
|
|
13
|
+
* node_modules. Consumers wanting a custom shape can pass
|
|
14
|
+
* `receipts: { entity: 'my.namespace.MyTable' }`, the table needs to
|
|
15
|
+
* carry the columns we INSERT below.
|
|
16
|
+
*
|
|
17
|
+
* Idempotency: txHash carries `@assert.unique`. A duplicate INSERT
|
|
18
|
+
* (e.g. settle returning twice for the same buyer) hits a unique-key
|
|
19
|
+
* violation and we log + continue. Buyers' UX is unaffected.
|
|
20
|
+
*/
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.DEFAULT_RECEIPTS_ENTITY = void 0;
|
|
26
|
+
exports.persistReceipt = persistReceipt;
|
|
27
|
+
exports.resolveReceiptsEntity = resolveReceiptsEntity;
|
|
28
|
+
const cds_1 = __importDefault(require("@sap/cds"));
|
|
29
|
+
const log = cds_1.default.log('x402');
|
|
30
|
+
/** Canonical entity name shipped by the plugin. */
|
|
31
|
+
exports.DEFAULT_RECEIPTS_ENTITY = 'odatano.x402.X402Receipts';
|
|
32
|
+
/**
|
|
33
|
+
* Insert one receipt for an accepted payment. Returns a promise that
|
|
34
|
+
* always resolves (never throws), errors are logged.
|
|
35
|
+
*
|
|
36
|
+
* The `route` argument is the resource URL the buyer paid for, the same
|
|
37
|
+
* value embedded in `accepts[0].resource.url`. We pass it explicitly
|
|
38
|
+
* rather than re-deriving it inside this module so the persisted route
|
|
39
|
+
* matches what the 402 advertised, even when the consumer set a custom
|
|
40
|
+
* `resourceUrl` builder.
|
|
41
|
+
*/
|
|
42
|
+
async function persistReceipt(entityName, claim, route) {
|
|
43
|
+
try {
|
|
44
|
+
await INSERT.into(entityName).entries({
|
|
45
|
+
ID: cds_1.default.utils.uuid(),
|
|
46
|
+
txHash: claim.txHash,
|
|
47
|
+
payerAddr: claim.payerAddr ?? null,
|
|
48
|
+
payTo: claim.payTo,
|
|
49
|
+
asset: claim.asset,
|
|
50
|
+
amount: claim.amountUnits,
|
|
51
|
+
network: claim.network,
|
|
52
|
+
route,
|
|
53
|
+
nonceRef: claim.nonceRef,
|
|
54
|
+
at: new Date().toISOString(),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
log.warn(`x402 receipts INSERT into ${entityName} failed (non-fatal):`, err?.message ?? err);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Resolve the entity name from the `receipts` option. */
|
|
62
|
+
function resolveReceiptsEntity(receipts) {
|
|
63
|
+
if (!receipts)
|
|
64
|
+
return null;
|
|
65
|
+
if (receipts === true)
|
|
66
|
+
return exports.DEFAULT_RECEIPTS_ENTITY;
|
|
67
|
+
return receipts.entity ?? exports.DEFAULT_RECEIPTS_ENTITY;
|
|
68
|
+
}
|
package/srv/plugin.d.ts
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* CAP plugin registration for `@odatano/x402`.
|
|
3
3
|
*
|
|
4
4
|
* Unlike `@odatano/core`, this plugin doesn't auto-serve any CDS
|
|
5
|
-
* entities
|
|
5
|
+
* entities, x402 is a library, not a service. We use the
|
|
6
6
|
* `cds.on('served')` hook only to initialise the bridge (warm up the
|
|
7
7
|
* @odatano/core connection) and the `cds.on('shutdown')` hook to clean
|
|
8
8
|
* up. Consumers wire middleware / gateService themselves inside their
|
|
9
9
|
* own service init().
|
|
10
10
|
*
|
|
11
|
-
* NEVER throws on init failure
|
|
11
|
+
* NEVER throws on init failure, the plugin must not crash the host
|
|
12
12
|
* CAP application. Errors are logged; calls into the bridge later
|
|
13
13
|
* will fail with `BRIDGE_UNAVAILABLE`.
|
|
14
14
|
*/
|
package/srv/plugin.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
* CAP plugin registration for `@odatano/x402`.
|
|
4
4
|
*
|
|
5
5
|
* Unlike `@odatano/core`, this plugin doesn't auto-serve any CDS
|
|
6
|
-
* entities
|
|
6
|
+
* entities, x402 is a library, not a service. We use the
|
|
7
7
|
* `cds.on('served')` hook only to initialise the bridge (warm up the
|
|
8
8
|
* @odatano/core connection) and the `cds.on('shutdown')` hook to clean
|
|
9
9
|
* up. Consumers wire middleware / gateService themselves inside their
|
|
10
10
|
* own service init().
|
|
11
11
|
*
|
|
12
|
-
* NEVER throws on init failure
|
|
12
|
+
* NEVER throws on init failure, the plugin must not crash the host
|
|
13
13
|
* CAP application. Errors are logged; calls into the bridge later
|
|
14
14
|
* will fail with `BRIDGE_UNAVAILABLE`.
|
|
15
15
|
*/
|