@contextvm/sdk 0.12.5 → 0.13.1
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/dist/esm/core/constants.d.ts +2 -0
- package/dist/esm/core/constants.d.ts.map +1 -1
- package/dist/esm/core/constants.js +2 -0
- package/dist/esm/core/constants.js.map +1 -1
- package/dist/esm/payments/authorization-store.d.ts +55 -0
- package/dist/esm/payments/authorization-store.d.ts.map +1 -0
- package/dist/esm/payments/authorization-store.js +115 -0
- package/dist/esm/payments/authorization-store.js.map +1 -0
- package/dist/esm/payments/canonical-identity.d.ts +20 -0
- package/dist/esm/payments/canonical-identity.d.ts.map +1 -0
- package/dist/esm/payments/canonical-identity.js +59 -0
- package/dist/esm/payments/canonical-identity.js.map +1 -0
- package/dist/esm/payments/client-payments.d.ts +43 -0
- package/dist/esm/payments/client-payments.d.ts.map +1 -1
- package/dist/esm/payments/client-payments.js +248 -28
- package/dist/esm/payments/client-payments.js.map +1 -1
- package/dist/esm/payments/constants.d.ts +12 -0
- package/dist/esm/payments/constants.d.ts.map +1 -1
- package/dist/esm/payments/constants.js +12 -0
- package/dist/esm/payments/constants.js.map +1 -1
- package/dist/esm/payments/server-explicit-gating.d.ts +13 -0
- package/dist/esm/payments/server-explicit-gating.d.ts.map +1 -0
- package/dist/esm/payments/server-explicit-gating.js +189 -0
- package/dist/esm/payments/server-explicit-gating.js.map +1 -0
- package/dist/esm/payments/server-payments-utils.d.ts +39 -0
- package/dist/esm/payments/server-payments-utils.d.ts.map +1 -0
- package/dist/esm/payments/server-payments-utils.js +117 -0
- package/dist/esm/payments/server-payments-utils.js.map +1 -0
- package/dist/esm/payments/server-payments.d.ts +10 -1
- package/dist/esm/payments/server-payments.d.ts.map +1 -1
- package/dist/esm/payments/server-payments.js +74 -150
- package/dist/esm/payments/server-payments.js.map +1 -1
- package/dist/esm/payments/server-transport-payments.d.ts +6 -0
- package/dist/esm/payments/server-transport-payments.d.ts.map +1 -1
- package/dist/esm/payments/server-transport-payments.js +46 -3
- package/dist/esm/payments/server-transport-payments.js.map +1 -1
- package/dist/esm/payments/types.d.ts +75 -9
- package/dist/esm/payments/types.d.ts.map +1 -1
- package/dist/esm/payments/types.js.map +1 -1
- package/dist/esm/relay/applesauce-relay-pool.d.ts +11 -9
- package/dist/esm/relay/applesauce-relay-pool.d.ts.map +1 -1
- package/dist/esm/relay/applesauce-relay-pool.js +21 -82
- package/dist/esm/relay/applesauce-relay-pool.js.map +1 -1
- package/dist/esm/transport/capability-negotiator.d.ts +17 -2
- package/dist/esm/transport/capability-negotiator.d.ts.map +1 -1
- package/dist/esm/transport/capability-negotiator.js +27 -2
- package/dist/esm/transport/capability-negotiator.js.map +1 -1
- package/dist/esm/transport/middleware.d.ts +8 -0
- package/dist/esm/transport/middleware.d.ts.map +1 -1
- package/dist/esm/transport/nostr-client/inbound-coordinator.d.ts +1 -1
- package/dist/esm/transport/nostr-client/inbound-coordinator.d.ts.map +1 -1
- package/dist/esm/transport/nostr-client/inbound-coordinator.js +16 -1
- package/dist/esm/transport/nostr-client/inbound-coordinator.js.map +1 -1
- package/dist/esm/transport/nostr-client/outbound-sender.d.ts.map +1 -1
- package/dist/esm/transport/nostr-client/outbound-sender.js +2 -2
- package/dist/esm/transport/nostr-client/outbound-sender.js.map +1 -1
- package/dist/esm/transport/nostr-client/server-metadata-store.d.ts +4 -0
- package/dist/esm/transport/nostr-client/server-metadata-store.d.ts.map +1 -1
- package/dist/esm/transport/nostr-client/server-metadata-store.js +7 -0
- package/dist/esm/transport/nostr-client/server-metadata-store.js.map +1 -1
- package/dist/esm/transport/nostr-client-transport.d.ts +9 -0
- package/dist/esm/transport/nostr-client-transport.d.ts.map +1 -1
- package/dist/esm/transport/nostr-client-transport.js +19 -3
- package/dist/esm/transport/nostr-client-transport.js.map +1 -1
- package/dist/esm/transport/nostr-server/inbound-coordinator.d.ts +3 -0
- package/dist/esm/transport/nostr-server/inbound-coordinator.d.ts.map +1 -1
- package/dist/esm/transport/nostr-server/inbound-coordinator.js +58 -3
- package/dist/esm/transport/nostr-server/inbound-coordinator.js.map +1 -1
- package/dist/esm/transport/nostr-server/outbound-response-router.d.ts +7 -0
- package/dist/esm/transport/nostr-server/outbound-response-router.d.ts.map +1 -1
- package/dist/esm/transport/nostr-server/outbound-response-router.js +43 -1
- package/dist/esm/transport/nostr-server/outbound-response-router.js.map +1 -1
- package/dist/esm/transport/nostr-server/session-store.d.ts +7 -0
- package/dist/esm/transport/nostr-server/session-store.d.ts.map +1 -1
- package/dist/esm/transport/nostr-server/session-store.js.map +1 -1
- package/dist/esm/transport/nostr-server-transport.d.ts +16 -1
- package/dist/esm/transport/nostr-server-transport.d.ts.map +1 -1
- package/dist/esm/transport/nostr-server-transport.js +18 -0
- package/dist/esm/transport/nostr-server-transport.js.map +1 -1
- package/package.json +2 -2
|
@@ -99,6 +99,8 @@ export declare const NOSTR_TAGS: {
|
|
|
99
99
|
* Support CEP-41 open-ended stream transfer via notifications/progress framing.
|
|
100
100
|
*/
|
|
101
101
|
readonly SUPPORT_OPEN_STREAM: "support_open_stream";
|
|
102
|
+
/** CEP-8 payment interaction negotiation tag. */
|
|
103
|
+
readonly PAYMENT_INTERACTION: "payment_interaction";
|
|
102
104
|
};
|
|
103
105
|
export declare const DEFAULT_LRU_SIZE = 5000;
|
|
104
106
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/core/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC;;;GAGG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC;;GAEG;AACH,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AAEjD;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AAEvC;;GAEG;AACH,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAE9C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,wJAO/B,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,UAAU;;;IAGrB;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/core/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC;;;GAGG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC;;GAEG;AACH,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AAEjD;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AAEvC;;GAEG;AACH,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAE9C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,wJAO/B,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,UAAU;;;IAGrB;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH,iDAAiD;;CAEzC,CAAC;AAEX,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAEzC,eAAO,MAAM,mBAAmB,EAAE,mBAKxB,CAAC;AAEX,eAAO,MAAM,iBAAiB,eAAe,CAAC;AAC9C,eAAO,MAAM,gCAAgC,8BAA8B,CAAC;AAE5E;;GAEG;AACH,eAAO,MAAM,4BAA4B,+BAA+B,CAAC"}
|
|
@@ -105,6 +105,8 @@ export const NOSTR_TAGS = {
|
|
|
105
105
|
* Support CEP-41 open-ended stream transfer via notifications/progress framing.
|
|
106
106
|
*/
|
|
107
107
|
SUPPORT_OPEN_STREAM: 'support_open_stream',
|
|
108
|
+
/** CEP-8 payment interaction negotiation tag. */
|
|
109
|
+
PAYMENT_INTERACTION: 'payment_interaction',
|
|
108
110
|
};
|
|
109
111
|
export const DEFAULT_LRU_SIZE = 5000;
|
|
110
112
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/core/constants.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAEzC;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAEnC;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAEzC;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEvC;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,sBAAsB;IACtB,wBAAwB;IACxB,eAAe;IACf,2BAA2B;IAC3B,kBAAkB;IAClB,uBAAuB;CACf,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,MAAM,EAAE,GAAG;IACX,KAAK,EAAE,GAAG;IACV;;OAEG;IACH,QAAQ,EAAE,GAAG;IACb;;OAEG;IACH,UAAU,EAAE,KAAK;IACjB;;OAEG;IACH,IAAI,EAAE,MAAM;IACZ;;OAEG;IACH,OAAO,EAAE,SAAS;IAClB;;OAEG;IACH,OAAO,EAAE,SAAS;IAClB;;OAEG;IACH,KAAK,EAAE,OAAO;IACd;;OAEG;IACH,kBAAkB,EAAE,oBAAoB;IAExC;;OAEG;IACH,4BAA4B,EAAE,8BAA8B;IAE5D;;OAEG;IACH,0BAA0B,EAAE,4BAA4B;IAExD;;OAEG;IACH,mBAAmB,EAAE,qBAAqB;CAClC,CAAC;AAEX,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAM,CAAC;AAEzC,MAAM,CAAC,MAAM,mBAAmB,GAAwB;IACtD,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,gBAAgB;IAC3B,iBAAiB,EAAE,0BAA0B;IAC7C,OAAO,EAAE,cAAc;CACf,CAAC;AAEX,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAAC;AAC9C,MAAM,CAAC,MAAM,gCAAgC,GAAG,2BAA2B,CAAC;AAE5E;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/core/constants.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAEzC;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAEnC;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAEzC;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEvC;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,sBAAsB;IACtB,wBAAwB;IACxB,eAAe;IACf,2BAA2B;IAC3B,kBAAkB;IAClB,uBAAuB;CACf,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,MAAM,EAAE,GAAG;IACX,KAAK,EAAE,GAAG;IACV;;OAEG;IACH,QAAQ,EAAE,GAAG;IACb;;OAEG;IACH,UAAU,EAAE,KAAK;IACjB;;OAEG;IACH,IAAI,EAAE,MAAM;IACZ;;OAEG;IACH,OAAO,EAAE,SAAS;IAClB;;OAEG;IACH,OAAO,EAAE,SAAS;IAClB;;OAEG;IACH,KAAK,EAAE,OAAO;IACd;;OAEG;IACH,kBAAkB,EAAE,oBAAoB;IAExC;;OAEG;IACH,4BAA4B,EAAE,8BAA8B;IAE5D;;OAEG;IACH,0BAA0B,EAAE,4BAA4B;IAExD;;OAEG;IACH,mBAAmB,EAAE,qBAAqB;IAE1C,iDAAiD;IACjD,mBAAmB,EAAE,qBAAqB;CAClC,CAAC;AAEX,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAM,CAAC;AAEzC,MAAM,CAAC,MAAM,mBAAmB,GAAwB;IACtD,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,gBAAgB;IAC3B,iBAAiB,EAAE,0BAA0B;IAC7C,OAAO,EAAE,cAAc;CACf,CAAC;AAEX,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAAC;AAC9C,MAAM,CAAC,MAAM,gCAAgC,GAAG,2BAA2B,CAAC;AAE5E;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { CanonicalInvocationIdentity } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A bounded, TTL-aware store for explicit gating authorizations.
|
|
4
|
+
* It manages both the pending state (waiting for payment verification)
|
|
5
|
+
* and the granted state (paid and ready to consume).
|
|
6
|
+
*
|
|
7
|
+
* NOTE: The atomicity provided by `trySetPending` relies on in-memory maps,
|
|
8
|
+
* meaning it is strictly single-process. For multi-process horizontal scaling,
|
|
9
|
+
* implementers should use a distributed lock (e.g. Redis Redlock) keyed by
|
|
10
|
+
* the canonical invocation identity to prevent duplicate payments.
|
|
11
|
+
*/
|
|
12
|
+
export declare class AuthorizationStore {
|
|
13
|
+
private readonly authorizations;
|
|
14
|
+
private readonly pending;
|
|
15
|
+
private readonly logger;
|
|
16
|
+
constructor(opts?: {
|
|
17
|
+
maxEntries?: number;
|
|
18
|
+
});
|
|
19
|
+
private getKey;
|
|
20
|
+
/**
|
|
21
|
+
* Records a paid authorization. Each grant authorizes exactly one future
|
|
22
|
+
* execution (CEP-8: "each successful payment SHOULD authorize one future
|
|
23
|
+
* execution unless server policy explicitly grants a different number").
|
|
24
|
+
*/
|
|
25
|
+
grant(identity: CanonicalInvocationIdentity, ttlMs: number): void;
|
|
26
|
+
/**
|
|
27
|
+
* Atomically claims the single execution authorization.
|
|
28
|
+
* Returns true if claimed, false if none available or expired.
|
|
29
|
+
*/
|
|
30
|
+
claim(identity: CanonicalInvocationIdentity): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Atomically checks whether a payment is already pending for this identity
|
|
33
|
+
* and, if not, marks it as pending. Returns `true` if this call transitioned
|
|
34
|
+
* the identity to pending (caller should emit -32042). Returns `false` if
|
|
35
|
+
* already pending (caller should emit -32043).
|
|
36
|
+
*
|
|
37
|
+
* This atomic check-and-set prevents concurrent requests from both receiving
|
|
38
|
+
* -32042 and triggering duplicate payment flows.
|
|
39
|
+
* NOTE: This is single-process only. Distributed setups must use an external lock.
|
|
40
|
+
*/
|
|
41
|
+
trySetPending(identity: CanonicalInvocationIdentity, ttlMs: number): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Updates the TTL of an already pending authorization. No-op if not pending.
|
|
44
|
+
*
|
|
45
|
+
* @param identity The canonical invocation identity.
|
|
46
|
+
* @param ttlMs The new TTL in milliseconds to apply from now.
|
|
47
|
+
* @returns void
|
|
48
|
+
*/
|
|
49
|
+
updatePendingTtl(identity: CanonicalInvocationIdentity, ttlMs: number): void;
|
|
50
|
+
/** Gets the remaining TTL in milliseconds for a pending authorization, or 0 if not pending. */
|
|
51
|
+
getPendingRemainingMs(identity: CanonicalInvocationIdentity): number;
|
|
52
|
+
/** Clears pending state (e.g. on verification failure or expiry). */
|
|
53
|
+
clearPending(identity: CanonicalInvocationIdentity): void;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=authorization-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-store.d.ts","sourceRoot":"","sources":["../../../src/payments/authorization-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAU9D;;;;;;;;;GASG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA8B;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;gBAElD,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;IAM1C,OAAO,CAAC,MAAM;IAId;;;;OAIG;IACI,KAAK,CAAC,QAAQ,EAAE,2BAA2B,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAYxE;;;OAGG;IACI,KAAK,CAAC,QAAQ,EAAE,2BAA2B,GAAG,OAAO;IAmB5D;;;;;;;;;OASG;IACI,aAAa,CAClB,QAAQ,EAAE,2BAA2B,EACrC,KAAK,EAAE,MAAM,GACZ,OAAO;IAoBV;;;;;;OAMG;IACI,gBAAgB,CACrB,QAAQ,EAAE,2BAA2B,EACrC,KAAK,EAAE,MAAM,GACZ,IAAI;IASP,+FAA+F;IACxF,qBAAqB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM;IAQ3E,qEAAqE;IAC9D,YAAY,CAAC,QAAQ,EAAE,2BAA2B,GAAG,IAAI;CAKjE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { LruCache } from '../core/utils/lru-cache.js';
|
|
2
|
+
import { createLogger } from '../core/utils/logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* A bounded, TTL-aware store for explicit gating authorizations.
|
|
5
|
+
* It manages both the pending state (waiting for payment verification)
|
|
6
|
+
* and the granted state (paid and ready to consume).
|
|
7
|
+
*
|
|
8
|
+
* NOTE: The atomicity provided by `trySetPending` relies on in-memory maps,
|
|
9
|
+
* meaning it is strictly single-process. For multi-process horizontal scaling,
|
|
10
|
+
* implementers should use a distributed lock (e.g. Redis Redlock) keyed by
|
|
11
|
+
* the canonical invocation identity to prevent duplicate payments.
|
|
12
|
+
*/
|
|
13
|
+
export class AuthorizationStore {
|
|
14
|
+
constructor(opts) {
|
|
15
|
+
var _a;
|
|
16
|
+
this.logger = createLogger('authorization-store');
|
|
17
|
+
const maxEntries = (_a = opts === null || opts === void 0 ? void 0 : opts.maxEntries) !== null && _a !== void 0 ? _a : 5000;
|
|
18
|
+
this.authorizations = new LruCache(maxEntries);
|
|
19
|
+
this.pending = new LruCache(maxEntries);
|
|
20
|
+
}
|
|
21
|
+
getKey(identity) {
|
|
22
|
+
return `${identity.clientPubkey}:${identity.invocationHash}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Records a paid authorization. Each grant authorizes exactly one future
|
|
26
|
+
* execution (CEP-8: "each successful payment SHOULD authorize one future
|
|
27
|
+
* execution unless server policy explicitly grants a different number").
|
|
28
|
+
*/
|
|
29
|
+
grant(identity, ttlMs) {
|
|
30
|
+
const key = this.getKey(identity);
|
|
31
|
+
const expiresAtMs = Date.now() + ttlMs;
|
|
32
|
+
this.authorizations.set(key, { key, expiresAtMs });
|
|
33
|
+
// Once granted, it's no longer pending
|
|
34
|
+
this.pending.delete(key);
|
|
35
|
+
this.logger.debug('authorization granted', { key, ttlMs });
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Atomically claims the single execution authorization.
|
|
39
|
+
* Returns true if claimed, false if none available or expired.
|
|
40
|
+
*/
|
|
41
|
+
claim(identity) {
|
|
42
|
+
const key = this.getKey(identity);
|
|
43
|
+
const auth = this.authorizations.get(key);
|
|
44
|
+
if (!auth) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (Date.now() > auth.expiresAtMs) {
|
|
48
|
+
this.authorizations.delete(key);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
// Single-use: consume the authorization atomically.
|
|
52
|
+
this.authorizations.delete(key);
|
|
53
|
+
this.logger.debug('authorization claimed', { key });
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Atomically checks whether a payment is already pending for this identity
|
|
58
|
+
* and, if not, marks it as pending. Returns `true` if this call transitioned
|
|
59
|
+
* the identity to pending (caller should emit -32042). Returns `false` if
|
|
60
|
+
* already pending (caller should emit -32043).
|
|
61
|
+
*
|
|
62
|
+
* This atomic check-and-set prevents concurrent requests from both receiving
|
|
63
|
+
* -32042 and triggering duplicate payment flows.
|
|
64
|
+
* NOTE: This is single-process only. Distributed setups must use an external lock.
|
|
65
|
+
*/
|
|
66
|
+
trySetPending(identity, ttlMs) {
|
|
67
|
+
const key = this.getKey(identity);
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
const existingExpiry = this.pending.get(key);
|
|
70
|
+
if (existingExpiry !== undefined) {
|
|
71
|
+
if (now > existingExpiry) {
|
|
72
|
+
// Expired pending state, we can overwrite it
|
|
73
|
+
this.pending.delete(key);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// Already pending and active
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
this.pending.set(key, now + ttlMs);
|
|
81
|
+
this.logger.debug('authorization marked pending', { key, ttlMs });
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Updates the TTL of an already pending authorization. No-op if not pending.
|
|
86
|
+
*
|
|
87
|
+
* @param identity The canonical invocation identity.
|
|
88
|
+
* @param ttlMs The new TTL in milliseconds to apply from now.
|
|
89
|
+
* @returns void
|
|
90
|
+
*/
|
|
91
|
+
updatePendingTtl(identity, ttlMs) {
|
|
92
|
+
const key = this.getKey(identity);
|
|
93
|
+
const existingExpiry = this.pending.get(key);
|
|
94
|
+
if (existingExpiry !== undefined && Date.now() <= existingExpiry) {
|
|
95
|
+
this.pending.set(key, Date.now() + ttlMs);
|
|
96
|
+
this.logger.debug('authorization pending TTL updated', { key, ttlMs });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** Gets the remaining TTL in milliseconds for a pending authorization, or 0 if not pending. */
|
|
100
|
+
getPendingRemainingMs(identity) {
|
|
101
|
+
const key = this.getKey(identity);
|
|
102
|
+
const expiry = this.pending.get(key);
|
|
103
|
+
if (expiry === undefined)
|
|
104
|
+
return 0;
|
|
105
|
+
const remaining = expiry - Date.now();
|
|
106
|
+
return remaining > 0 ? remaining : 0;
|
|
107
|
+
}
|
|
108
|
+
/** Clears pending state (e.g. on verification failure or expiry). */
|
|
109
|
+
clearPending(identity) {
|
|
110
|
+
const key = this.getKey(identity);
|
|
111
|
+
this.pending.delete(key);
|
|
112
|
+
this.logger.debug('authorization pending state cleared', { key });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=authorization-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-store.js","sourceRoot":"","sources":["../../../src/payments/authorization-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CanonicalInvocationIdentity } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Computes a deterministic SHA-256 hash of an invocation's `method` and
|
|
4
|
+
* semantic `params` (RFC 8785 JCS, key-order independent). `params._meta`
|
|
5
|
+
* (MCP's reserved per-request extension namespace: progressToken, stream, ...)
|
|
6
|
+
* is excluded so retries/re-invocations match a paid authorization regardless
|
|
7
|
+
* of per-request transport metadata. The full `params` (incl. `_meta`) are
|
|
8
|
+
* still forwarded to the handler at execution time.
|
|
9
|
+
*/
|
|
10
|
+
export declare function computeCanonicalInvocationHash(method: string, params: unknown): string;
|
|
11
|
+
/**
|
|
12
|
+
* Computes the canonical invocation identity for explicit-gating authorization matching.
|
|
13
|
+
*
|
|
14
|
+
* @param clientPubkey - The client's public key
|
|
15
|
+
* @param method - The JSON-RPC method
|
|
16
|
+
* @param params - The JSON-RPC parameters
|
|
17
|
+
* @returns The computed identity
|
|
18
|
+
*/
|
|
19
|
+
export declare function computeCanonicalInvocationIdentity(clientPubkey: string, method: string, params: unknown): CanonicalInvocationIdentity;
|
|
20
|
+
//# sourceMappingURL=canonical-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-identity.d.ts","sourceRoot":"","sources":["../../../src/payments/canonical-identity.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAE9D;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,GACd,MAAM,CAoCR;AAED;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,CAChD,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,GACd,2BAA2B,CAK7B"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import canonicalizePackage from 'canonicalize';
|
|
2
|
+
const canonicalize = canonicalizePackage;
|
|
3
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
4
|
+
import { bytesToHex } from '@noble/hashes/utils.js';
|
|
5
|
+
/**
|
|
6
|
+
* Computes a deterministic SHA-256 hash of an invocation's `method` and
|
|
7
|
+
* semantic `params` (RFC 8785 JCS, key-order independent). `params._meta`
|
|
8
|
+
* (MCP's reserved per-request extension namespace: progressToken, stream, ...)
|
|
9
|
+
* is excluded so retries/re-invocations match a paid authorization regardless
|
|
10
|
+
* of per-request transport metadata. The full `params` (incl. `_meta`) are
|
|
11
|
+
* still forwarded to the handler at execution time.
|
|
12
|
+
*/
|
|
13
|
+
export function computeCanonicalInvocationHash(method, params) {
|
|
14
|
+
// Only object params carry a reserved `_meta`; arrays/primitives pass through.
|
|
15
|
+
let semanticParams = params;
|
|
16
|
+
if (params && typeof params === 'object' && !Array.isArray(params)) {
|
|
17
|
+
const { _meta: _omit, ...rest } = params;
|
|
18
|
+
semanticParams = rest;
|
|
19
|
+
}
|
|
20
|
+
const payload = { method, params: semanticParams };
|
|
21
|
+
let canonicalString;
|
|
22
|
+
try {
|
|
23
|
+
// Pre-validate that all values are strictly JSON-serializable.
|
|
24
|
+
// canonicalize() might ignore functions/symbols or throw stack overflows,
|
|
25
|
+
// so we use JSON.stringify as a strict validator first.
|
|
26
|
+
JSON.stringify(payload, (_key, value) => {
|
|
27
|
+
if (typeof value === 'function' ||
|
|
28
|
+
typeof value === 'symbol' ||
|
|
29
|
+
typeof value === 'bigint') {
|
|
30
|
+
throw new Error('Invalid type');
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
});
|
|
34
|
+
canonicalString = canonicalize(payload);
|
|
35
|
+
}
|
|
36
|
+
catch (_a) {
|
|
37
|
+
canonicalString = undefined;
|
|
38
|
+
}
|
|
39
|
+
if (canonicalString === undefined) {
|
|
40
|
+
throw new Error(`Failed to canonicalize invocation payload for method '${method}'. ` +
|
|
41
|
+
'Ensure params contain only JSON-serializable values (no circular references, functions, symbols, or BigInt).');
|
|
42
|
+
}
|
|
43
|
+
return bytesToHex(sha256(new TextEncoder().encode(canonicalString)));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Computes the canonical invocation identity for explicit-gating authorization matching.
|
|
47
|
+
*
|
|
48
|
+
* @param clientPubkey - The client's public key
|
|
49
|
+
* @param method - The JSON-RPC method
|
|
50
|
+
* @param params - The JSON-RPC parameters
|
|
51
|
+
* @returns The computed identity
|
|
52
|
+
*/
|
|
53
|
+
export function computeCanonicalInvocationIdentity(clientPubkey, method, params) {
|
|
54
|
+
return {
|
|
55
|
+
clientPubkey,
|
|
56
|
+
invocationHash: computeCanonicalInvocationHash(method, params),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=canonical-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-identity.js","sourceRoot":"","sources":["../../../src/payments/canonical-identity.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,MAAM,cAAc,CAAC;AAE/C,MAAM,YAAY,GAAG,mBAAgD,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD;;;;;;;GAOG;AACH,MAAM,UAAU,8BAA8B,CAC5C,MAAc,EACd,MAAe;IAEf,+EAA+E;IAC/E,IAAI,cAAc,GAAG,MAAM,CAAC;IAC5B,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,MAAiC,CAAC;QACpE,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;IACD,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACnD,IAAI,eAAmC,CAAC;IACxC,IAAI,CAAC;QACH,+DAA+D;QAC/D,0EAA0E;QAC1E,wDAAwD;QACxD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YACtC,IACE,OAAO,KAAK,KAAK,UAAU;gBAC3B,OAAO,KAAK,KAAK,QAAQ;gBACzB,OAAO,KAAK,KAAK,QAAQ,EACzB,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;YAClC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;QACH,eAAe,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IAAC,WAAM,CAAC;QACP,eAAe,GAAG,SAAS,CAAC;IAC9B,CAAC;IAED,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,yDAAyD,MAAM,KAAK;YAClE,8GAA8G,CACjH,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kCAAkC,CAChD,YAAoB,EACpB,MAAc,EACd,MAAe;IAEf,OAAO;QACL,YAAY;QACZ,cAAc,EAAE,8BAA8B,CAAC,MAAM,EAAE,MAAM,CAAC;KAC/D,CAAC;AACJ,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Transport } from '@contextvm/mcp-sdk/shared/transport';
|
|
2
|
+
import { type JSONRPCRequest } from '@contextvm/mcp-sdk/types.js';
|
|
2
3
|
import { PaymentHandler, PaymentHandlerRequest } from './types.js';
|
|
3
4
|
import type { OriginalRequestContext } from '../transport/nostr-client/correlation-store.js';
|
|
5
|
+
import type { PaymentInteractionMode, PaymentOption } from './types.js';
|
|
4
6
|
export interface ClientPaymentsOptions {
|
|
5
7
|
handlers: readonly PaymentHandler[];
|
|
6
8
|
/**
|
|
@@ -30,6 +32,47 @@ export interface ClientPaymentsOptions {
|
|
|
30
32
|
* triggered the payment.
|
|
31
33
|
*/
|
|
32
34
|
paymentPolicy?: (req: PaymentHandlerRequest, originalRequestContext?: OriginalRequestContext) => boolean | Promise<boolean>;
|
|
35
|
+
/** Requested payment interaction mode. @default 'transparent' */
|
|
36
|
+
paymentInteraction?: PaymentInteractionMode;
|
|
37
|
+
/**
|
|
38
|
+
* Maximum number of -32043 (Payment Pending) retries before giving up.
|
|
39
|
+
*
|
|
40
|
+
* With retry_after=2 and 1.5× exponential backoff capped at 10s, the default
|
|
41
|
+
* of 10 retries gives ~45s of cumulative wait — enough for typical verification
|
|
42
|
+
* flows. Increase for slow payment processors (e.g. on-chain confirmation).
|
|
43
|
+
* @default 10
|
|
44
|
+
*/
|
|
45
|
+
maxPendingRetries?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Handler for explicit-gating -32042 errors.
|
|
48
|
+
* Called when a priced invocation returns Payment Required.
|
|
49
|
+
* The handler should pay one option and signal completion.
|
|
50
|
+
*
|
|
51
|
+
* **Error handling contract**:
|
|
52
|
+
* - If the promise resolves with `{ paid: true }`, the wrapper auto-retries the
|
|
53
|
+
* original request with the same `method` and `params`.
|
|
54
|
+
* - If the promise resolves with `{ paid: false, reason }`, the wrapper synthesizes
|
|
55
|
+
* a JSON-RPC error to the caller with code `-32042` and `data: { reason }`.
|
|
56
|
+
* Use `reason: 'user_cancelled'` for user-initiated cancellations.
|
|
57
|
+
* - If the promise **rejects**, the wrapper MUST NOT silently fall back.
|
|
58
|
+
* It synthesizes a JSON-RPC error with code `-32042` and
|
|
59
|
+
* `data: { reason: error.message, type: 'payment_handler_error' }`.
|
|
60
|
+
* - Transient payment-provider failures should reject with an Error whose
|
|
61
|
+
* `message` contains the provider error details.
|
|
62
|
+
*
|
|
63
|
+
* **Verify-timeout window**: if the server's verification times out or fails
|
|
64
|
+
* after the client paid, its pending state is cleared and the client's retry
|
|
65
|
+
* receives a fresh `-32042` with a new invoice (CEP-8-compliant). The wrapper
|
|
66
|
+
* does not dedup across distinct `pay_req` values.
|
|
67
|
+
*/
|
|
68
|
+
onPaymentRequired?: (params: {
|
|
69
|
+
options: PaymentOption[];
|
|
70
|
+
instructions?: string;
|
|
71
|
+
originalRequest: JSONRPCRequest;
|
|
72
|
+
}) => Promise<{
|
|
73
|
+
paid: boolean;
|
|
74
|
+
reason?: string;
|
|
75
|
+
}>;
|
|
33
76
|
}
|
|
34
77
|
/**
|
|
35
78
|
* Wraps a transport to automatically handle CEP-8 payment requests.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-payments.d.ts","sourceRoot":"","sources":["../../../src/payments/client-payments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"client-payments.d.ts","sourceRoot":"","sources":["../../../src/payments/client-payments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAML,KAAK,cAAc,EAEpB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,cAAc,EAGd,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,KAAK,EACV,sBAAsB,EACtB,aAAa,EAGd,MAAM,YAAY,CAAC;AAYpB,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IACpC;;;;;;;OAOG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,CACd,GAAG,EAAE,qBAAqB,EAC1B,sBAAsB,CAAC,EAAE,sBAAsB,KAC5C,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhC,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,sBAAsB,CAAC;IAE5C;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE;QAC3B,OAAO,EAAE,aAAa,EAAE,CAAC;QACzB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,cAAc,CAAC;KACjC,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AA6DD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,qBAAqB,GAC7B,SAAS,CAqpBX"}
|