@t402/core 2.5.0 → 2.6.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/cjs/client/index.js +41 -4
- package/dist/cjs/client/index.js.map +1 -1
- package/dist/cjs/facilitator/index.js.map +1 -1
- package/dist/cjs/http/index.d.ts +331 -2
- package/dist/cjs/http/index.js +309 -8
- package/dist/cjs/http/index.js.map +1 -1
- package/dist/cjs/index.d.ts +23 -1
- package/dist/cjs/index.js +38 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/server/index.d.ts +1 -1
- package/dist/cjs/server/index.js +55 -4
- package/dist/cjs/server/index.js.map +1 -1
- package/dist/cjs/{t402HTTPResourceServer-B-aOi0BZ.d.ts → t402HTTPResourceServer-BIEvnbwL.d.ts} +9 -4
- package/dist/esm/{chunk-7RHSIMQL.mjs → chunk-4DIIUML6.mjs} +278 -10
- package/dist/esm/chunk-4DIIUML6.mjs.map +1 -0
- package/dist/esm/chunk-YM7W5RG3.mjs +44 -0
- package/dist/esm/chunk-YM7W5RG3.mjs.map +1 -0
- package/dist/esm/client/index.mjs +2 -2
- package/dist/esm/facilitator/index.mjs +1 -1
- package/dist/esm/http/index.d.mts +331 -2
- package/dist/esm/http/index.mjs +6 -2
- package/dist/esm/index.d.mts +23 -1
- package/dist/esm/index.mjs +3 -1
- package/dist/esm/server/index.d.mts +1 -1
- package/dist/esm/server/index.mjs +2 -2
- package/dist/esm/{t402HTTPResourceServer-CstWZOsH.d.mts → t402HTTPResourceServer-Jmmvy9kc.d.mts} +9 -4
- package/package.json +26 -10
- package/dist/esm/chunk-3VTYR43U.mjs +0 -7
- package/dist/esm/chunk-3VTYR43U.mjs.map +0 -1
- package/dist/esm/chunk-7RHSIMQL.mjs.map +0 -1
package/dist/cjs/http/index.js
CHANGED
|
@@ -23,7 +23,9 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
23
23
|
var http_exports = {};
|
|
24
24
|
__export(http_exports, {
|
|
25
25
|
HTTPFacilitatorClient: () => HTTPFacilitatorClient,
|
|
26
|
+
IntentClient: () => IntentClient,
|
|
26
27
|
RouteConfigurationError: () => RouteConfigurationError,
|
|
28
|
+
StreamingClient: () => StreamingClient,
|
|
27
29
|
decodePaymentRequiredHeader: () => decodePaymentRequiredHeader,
|
|
28
30
|
decodePaymentResponseHeader: () => decodePaymentResponseHeader,
|
|
29
31
|
decodePaymentSignatureHeader: () => decodePaymentSignatureHeader,
|
|
@@ -115,6 +117,38 @@ function safeBase64Decode(data) {
|
|
|
115
117
|
return Buffer.from(data, "base64").toString("utf-8");
|
|
116
118
|
}
|
|
117
119
|
|
|
120
|
+
// src/errors.ts
|
|
121
|
+
var T402PaymentError = class _T402PaymentError extends Error {
|
|
122
|
+
constructor(message, options) {
|
|
123
|
+
super(message);
|
|
124
|
+
__publicField(this, "cause");
|
|
125
|
+
__publicField(this, "phase");
|
|
126
|
+
__publicField(this, "retryable");
|
|
127
|
+
__publicField(this, "code");
|
|
128
|
+
this.name = "T402PaymentError";
|
|
129
|
+
this.cause = options?.cause;
|
|
130
|
+
this.phase = options?.phase ?? "unknown";
|
|
131
|
+
this.retryable = options?.retryable ?? false;
|
|
132
|
+
this.code = options?.code;
|
|
133
|
+
if (Error.captureStackTrace) {
|
|
134
|
+
Error.captureStackTrace(this, _T402PaymentError);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
isRetryable() {
|
|
138
|
+
return this.retryable;
|
|
139
|
+
}
|
|
140
|
+
toJSON() {
|
|
141
|
+
return {
|
|
142
|
+
name: this.name,
|
|
143
|
+
message: this.message,
|
|
144
|
+
phase: this.phase,
|
|
145
|
+
retryable: this.retryable,
|
|
146
|
+
code: this.code,
|
|
147
|
+
cause: this.cause?.message
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
118
152
|
// src/index.ts
|
|
119
153
|
var t402Version = 2;
|
|
120
154
|
|
|
@@ -627,7 +661,11 @@ var HTTPFacilitatorClient = class {
|
|
|
627
661
|
});
|
|
628
662
|
if (!response.ok) {
|
|
629
663
|
const errorText = await response.text().catch(() => response.statusText);
|
|
630
|
-
throw new
|
|
664
|
+
throw new T402PaymentError(`Facilitator verify failed (${response.status}): ${errorText}`, {
|
|
665
|
+
phase: "verification",
|
|
666
|
+
code: response.status,
|
|
667
|
+
retryable: response.status >= 500 || response.status === 429
|
|
668
|
+
});
|
|
631
669
|
}
|
|
632
670
|
return await response.json();
|
|
633
671
|
}
|
|
@@ -636,12 +674,16 @@ var HTTPFacilitatorClient = class {
|
|
|
636
674
|
*
|
|
637
675
|
* @param paymentPayload - The payment to settle
|
|
638
676
|
* @param paymentRequirements - The requirements for settlement
|
|
677
|
+
* @param options - Optional settings including idempotency key
|
|
639
678
|
* @returns Settlement response
|
|
640
679
|
*/
|
|
641
|
-
async settle(paymentPayload, paymentRequirements) {
|
|
680
|
+
async settle(paymentPayload, paymentRequirements, options) {
|
|
642
681
|
let headers = {
|
|
643
682
|
"Content-Type": "application/json"
|
|
644
683
|
};
|
|
684
|
+
if (options?.idempotencyKey) {
|
|
685
|
+
headers["Idempotency-Key"] = options.idempotencyKey;
|
|
686
|
+
}
|
|
645
687
|
if (this._createAuthHeaders) {
|
|
646
688
|
const authHeaders = await this.createAuthHeaders("settle");
|
|
647
689
|
headers = { ...headers, ...authHeaders.headers };
|
|
@@ -657,7 +699,11 @@ var HTTPFacilitatorClient = class {
|
|
|
657
699
|
});
|
|
658
700
|
if (!response.ok) {
|
|
659
701
|
const errorText = await response.text().catch(() => response.statusText);
|
|
660
|
-
throw new
|
|
702
|
+
throw new T402PaymentError(`Facilitator settle failed (${response.status}): ${errorText}`, {
|
|
703
|
+
phase: "settlement",
|
|
704
|
+
code: response.status,
|
|
705
|
+
retryable: response.status >= 500 || response.status === 429
|
|
706
|
+
});
|
|
661
707
|
}
|
|
662
708
|
return await response.json();
|
|
663
709
|
}
|
|
@@ -680,7 +726,14 @@ var HTTPFacilitatorClient = class {
|
|
|
680
726
|
});
|
|
681
727
|
if (!response.ok) {
|
|
682
728
|
const errorText = await response.text().catch(() => response.statusText);
|
|
683
|
-
throw new
|
|
729
|
+
throw new T402PaymentError(
|
|
730
|
+
`Facilitator getSupported failed (${response.status}): ${errorText}`,
|
|
731
|
+
{
|
|
732
|
+
phase: "unknown",
|
|
733
|
+
code: response.status,
|
|
734
|
+
retryable: response.status >= 500 || response.status === 429
|
|
735
|
+
}
|
|
736
|
+
);
|
|
684
737
|
}
|
|
685
738
|
return await response.json();
|
|
686
739
|
}
|
|
@@ -742,8 +795,9 @@ var t402HTTPClient = class {
|
|
|
742
795
|
"X-PAYMENT": encodePaymentSignatureHeader(paymentPayload)
|
|
743
796
|
};
|
|
744
797
|
default:
|
|
745
|
-
throw new
|
|
746
|
-
`Unsupported t402 version: ${paymentPayload.t402Version}
|
|
798
|
+
throw new T402PaymentError(
|
|
799
|
+
`Unsupported t402 version: ${paymentPayload.t402Version}`,
|
|
800
|
+
{ phase: "submission" }
|
|
747
801
|
);
|
|
748
802
|
}
|
|
749
803
|
}
|
|
@@ -762,7 +816,9 @@ var t402HTTPClient = class {
|
|
|
762
816
|
if (body && body instanceof Object && "t402Version" in body && body.t402Version === 1) {
|
|
763
817
|
return body;
|
|
764
818
|
}
|
|
765
|
-
throw new
|
|
819
|
+
throw new T402PaymentError("Invalid payment required response", {
|
|
820
|
+
phase: "submission"
|
|
821
|
+
});
|
|
766
822
|
}
|
|
767
823
|
/**
|
|
768
824
|
* Extracts payment settlement response from HTTP headers.
|
|
@@ -779,7 +835,9 @@ var t402HTTPClient = class {
|
|
|
779
835
|
if (xPaymentResponse) {
|
|
780
836
|
return decodePaymentResponseHeader(xPaymentResponse);
|
|
781
837
|
}
|
|
782
|
-
throw new
|
|
838
|
+
throw new T402PaymentError("Payment response header not found", {
|
|
839
|
+
phase: "settlement"
|
|
840
|
+
});
|
|
783
841
|
}
|
|
784
842
|
/**
|
|
785
843
|
* Creates a payment payload for the given payment requirements.
|
|
@@ -793,6 +851,247 @@ var t402HTTPClient = class {
|
|
|
793
851
|
}
|
|
794
852
|
};
|
|
795
853
|
|
|
854
|
+
// src/http/streamingClient.ts
|
|
855
|
+
var DEFAULT_FACILITATOR_URL2 = "https://facilitator.t402.io";
|
|
856
|
+
var StreamingClient = class {
|
|
857
|
+
constructor(config) {
|
|
858
|
+
__publicField(this, "url");
|
|
859
|
+
__publicField(this, "apiKey");
|
|
860
|
+
__publicField(this, "requesterAddress");
|
|
861
|
+
this.url = config?.url || DEFAULT_FACILITATOR_URL2;
|
|
862
|
+
this.apiKey = config?.apiKey;
|
|
863
|
+
this.requesterAddress = config?.requesterAddress;
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Open a new payment stream
|
|
867
|
+
*/
|
|
868
|
+
async openStream(params) {
|
|
869
|
+
return this.post("/v1/stream/open", params);
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Update a stream with a new cumulative amount
|
|
873
|
+
*/
|
|
874
|
+
async updateStream(params) {
|
|
875
|
+
return this.post("/v1/stream/update", params);
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Close a stream and settle the final amount
|
|
879
|
+
*/
|
|
880
|
+
async closeStream(params) {
|
|
881
|
+
return this.post("/v1/stream/close", params);
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* Get stream details by ID
|
|
885
|
+
*/
|
|
886
|
+
async getStream(id, options) {
|
|
887
|
+
const params = new URLSearchParams();
|
|
888
|
+
if (options?.includeUpdates) params.set("include_updates", "true");
|
|
889
|
+
if (options?.includeStats) params.set("include_stats", "true");
|
|
890
|
+
const query = params.toString();
|
|
891
|
+
const path = `/v1/stream/${encodeURIComponent(id)}${query ? `?${query}` : ""}`;
|
|
892
|
+
return this.get(path);
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* Pause an active stream
|
|
896
|
+
*/
|
|
897
|
+
async pauseStream(id) {
|
|
898
|
+
return this.post(`/v1/stream/${encodeURIComponent(id)}/pause`, {});
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Resume a paused stream
|
|
902
|
+
*/
|
|
903
|
+
async resumeStream(id) {
|
|
904
|
+
return this.post(`/v1/stream/${encodeURIComponent(id)}/resume`, {});
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* List streams with optional filters
|
|
908
|
+
*/
|
|
909
|
+
async listStreams(filters) {
|
|
910
|
+
const params = new URLSearchParams();
|
|
911
|
+
if (filters?.network) params.set("network", filters.network);
|
|
912
|
+
if (filters?.payer) params.set("payer", filters.payer);
|
|
913
|
+
if (filters?.payee) params.set("payee", filters.payee);
|
|
914
|
+
if (filters?.status) {
|
|
915
|
+
for (const s of filters.status) params.append("status", s);
|
|
916
|
+
}
|
|
917
|
+
if (filters?.limit !== void 0) params.set("limit", String(filters.limit));
|
|
918
|
+
if (filters?.offset !== void 0) params.set("offset", String(filters.offset));
|
|
919
|
+
if (filters?.orderBy) params.set("orderBy", filters.orderBy);
|
|
920
|
+
if (filters?.orderDesc) params.set("orderDesc", "true");
|
|
921
|
+
const query = params.toString();
|
|
922
|
+
return this.get(`/v1/stream${query ? `?${query}` : ""}`);
|
|
923
|
+
}
|
|
924
|
+
// ============================================================================
|
|
925
|
+
// Internal HTTP helpers
|
|
926
|
+
// ============================================================================
|
|
927
|
+
buildHeaders() {
|
|
928
|
+
const headers = {
|
|
929
|
+
"Content-Type": "application/json"
|
|
930
|
+
};
|
|
931
|
+
if (this.apiKey) {
|
|
932
|
+
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
933
|
+
}
|
|
934
|
+
if (this.requesterAddress) {
|
|
935
|
+
headers["X-Requester-Address"] = this.requesterAddress;
|
|
936
|
+
}
|
|
937
|
+
return headers;
|
|
938
|
+
}
|
|
939
|
+
async post(path, body) {
|
|
940
|
+
const response = await fetch(`${this.url}${path}`, {
|
|
941
|
+
method: "POST",
|
|
942
|
+
headers: this.buildHeaders(),
|
|
943
|
+
body: JSON.stringify(body)
|
|
944
|
+
});
|
|
945
|
+
if (!response.ok) {
|
|
946
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
947
|
+
throw new T402PaymentError(`Streaming API ${path} failed (${response.status}): ${errorText}`, {
|
|
948
|
+
phase: "unknown",
|
|
949
|
+
code: response.status,
|
|
950
|
+
retryable: response.status >= 500 || response.status === 429
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
return await response.json();
|
|
954
|
+
}
|
|
955
|
+
async get(path) {
|
|
956
|
+
const response = await fetch(`${this.url}${path}`, {
|
|
957
|
+
method: "GET",
|
|
958
|
+
headers: this.buildHeaders()
|
|
959
|
+
});
|
|
960
|
+
if (!response.ok) {
|
|
961
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
962
|
+
throw new T402PaymentError(`Streaming API ${path} failed (${response.status}): ${errorText}`, {
|
|
963
|
+
phase: "unknown",
|
|
964
|
+
code: response.status,
|
|
965
|
+
retryable: response.status >= 500 || response.status === 429
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
return await response.json();
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
// src/http/intentClient.ts
|
|
973
|
+
var DEFAULT_FACILITATOR_URL3 = "https://facilitator.t402.io";
|
|
974
|
+
var IntentClient = class {
|
|
975
|
+
constructor(config) {
|
|
976
|
+
__publicField(this, "url");
|
|
977
|
+
__publicField(this, "apiKey");
|
|
978
|
+
this.url = config?.url || DEFAULT_FACILITATOR_URL3;
|
|
979
|
+
this.apiKey = config?.apiKey;
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Create a new payment intent and get available routes
|
|
983
|
+
*/
|
|
984
|
+
async createIntent(params) {
|
|
985
|
+
return this.post("/v1/intent", params);
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* Get intent details by ID
|
|
989
|
+
*/
|
|
990
|
+
async getIntent(id) {
|
|
991
|
+
return this.get(`/v1/intent/${encodeURIComponent(id)}`);
|
|
992
|
+
}
|
|
993
|
+
/**
|
|
994
|
+
* Select a route for an intent
|
|
995
|
+
*/
|
|
996
|
+
async selectRoute(id, params) {
|
|
997
|
+
return this.post(
|
|
998
|
+
`/v1/intent/${encodeURIComponent(id)}/route`,
|
|
999
|
+
params
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Execute an intent with a signed authorization
|
|
1004
|
+
*/
|
|
1005
|
+
async executeIntent(id, params) {
|
|
1006
|
+
return this.post(
|
|
1007
|
+
`/v1/intent/${encodeURIComponent(id)}/execute`,
|
|
1008
|
+
params
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Cancel a pending intent
|
|
1013
|
+
*/
|
|
1014
|
+
async cancelIntent(id, params) {
|
|
1015
|
+
return this.post(
|
|
1016
|
+
`/v1/intent/${encodeURIComponent(id)}/cancel`,
|
|
1017
|
+
params ?? {}
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Refresh available routes for an intent
|
|
1022
|
+
*/
|
|
1023
|
+
async refreshRoutes(id) {
|
|
1024
|
+
return this.post(
|
|
1025
|
+
`/v1/intent/${encodeURIComponent(id)}/refresh`,
|
|
1026
|
+
{}
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* List intents with optional filters
|
|
1031
|
+
*/
|
|
1032
|
+
async listIntents(filters) {
|
|
1033
|
+
const params = new URLSearchParams();
|
|
1034
|
+
if (filters?.payer) params.set("payer", filters.payer);
|
|
1035
|
+
if (filters?.payee) params.set("payee", filters.payee);
|
|
1036
|
+
if (filters?.status) {
|
|
1037
|
+
for (const s of filters.status) params.append("status", s);
|
|
1038
|
+
}
|
|
1039
|
+
if (filters?.limit !== void 0) params.set("limit", String(filters.limit));
|
|
1040
|
+
if (filters?.offset !== void 0) params.set("offset", String(filters.offset));
|
|
1041
|
+
const query = params.toString();
|
|
1042
|
+
return this.get(`/v1/intent${query ? `?${query}` : ""}`);
|
|
1043
|
+
}
|
|
1044
|
+
/**
|
|
1045
|
+
* Get intent statistics (counts by status)
|
|
1046
|
+
*/
|
|
1047
|
+
async getIntentStats() {
|
|
1048
|
+
return this.get("/v1/intent/stats");
|
|
1049
|
+
}
|
|
1050
|
+
// ============================================================================
|
|
1051
|
+
// Internal HTTP helpers
|
|
1052
|
+
// ============================================================================
|
|
1053
|
+
buildHeaders() {
|
|
1054
|
+
const headers = {
|
|
1055
|
+
"Content-Type": "application/json"
|
|
1056
|
+
};
|
|
1057
|
+
if (this.apiKey) {
|
|
1058
|
+
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
1059
|
+
}
|
|
1060
|
+
return headers;
|
|
1061
|
+
}
|
|
1062
|
+
async post(path, body) {
|
|
1063
|
+
const response = await fetch(`${this.url}${path}`, {
|
|
1064
|
+
method: "POST",
|
|
1065
|
+
headers: this.buildHeaders(),
|
|
1066
|
+
body: JSON.stringify(body)
|
|
1067
|
+
});
|
|
1068
|
+
if (!response.ok) {
|
|
1069
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
1070
|
+
throw new T402PaymentError(`Intent API ${path} failed (${response.status}): ${errorText}`, {
|
|
1071
|
+
phase: "unknown",
|
|
1072
|
+
code: response.status,
|
|
1073
|
+
retryable: response.status >= 500 || response.status === 429
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
return await response.json();
|
|
1077
|
+
}
|
|
1078
|
+
async get(path) {
|
|
1079
|
+
const response = await fetch(`${this.url}${path}`, {
|
|
1080
|
+
method: "GET",
|
|
1081
|
+
headers: this.buildHeaders()
|
|
1082
|
+
});
|
|
1083
|
+
if (!response.ok) {
|
|
1084
|
+
const errorText = await response.text().catch(() => response.statusText);
|
|
1085
|
+
throw new T402PaymentError(`Intent API ${path} failed (${response.status}): ${errorText}`, {
|
|
1086
|
+
phase: "unknown",
|
|
1087
|
+
code: response.status,
|
|
1088
|
+
retryable: response.status >= 500 || response.status === 429
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
return await response.json();
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
|
|
796
1095
|
// src/http/index.ts
|
|
797
1096
|
function encodePaymentSignatureHeader(paymentPayload) {
|
|
798
1097
|
return safeBase64Encode(JSON.stringify(paymentPayload));
|
|
@@ -830,7 +1129,9 @@ function decodePaymentResponseHeader(paymentResponseHeader) {
|
|
|
830
1129
|
// Annotate the CommonJS export names for ESM import in node:
|
|
831
1130
|
0 && (module.exports = {
|
|
832
1131
|
HTTPFacilitatorClient,
|
|
1132
|
+
IntentClient,
|
|
833
1133
|
RouteConfigurationError,
|
|
1134
|
+
StreamingClient,
|
|
834
1135
|
decodePaymentRequiredHeader,
|
|
835
1136
|
decodePaymentResponseHeader,
|
|
836
1137
|
decodePaymentSignatureHeader,
|