@hashgraphonline/standards-sdk 0.1.137 → 0.1.138-feat-hcs-21-package-std.canary.4376298.35
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/hcs-21/base-client.d.ts +33 -0
- package/dist/cjs/hcs-21/base-client.d.ts.map +1 -0
- package/dist/cjs/hcs-21/browser.d.ts +20 -0
- package/dist/cjs/hcs-21/browser.d.ts.map +1 -0
- package/dist/cjs/hcs-21/errors.d.ts +6 -0
- package/dist/cjs/hcs-21/errors.d.ts.map +1 -0
- package/dist/cjs/hcs-21/index.d.ts +7 -0
- package/dist/cjs/hcs-21/index.d.ts.map +1 -0
- package/dist/cjs/hcs-21/sdk.d.ts +48 -0
- package/dist/cjs/hcs-21/sdk.d.ts.map +1 -0
- package/dist/cjs/hcs-21/tx.d.ts +20 -0
- package/dist/cjs/hcs-21/tx.d.ts.map +1 -0
- package/dist/cjs/hcs-21/types.d.ts +89 -0
- package/dist/cjs/hcs-21/types.d.ts.map +1 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/services/registry-broker/client.d.ts.map +1 -1
- package/dist/cjs/services/types.d.ts +1 -1
- package/dist/cjs/services/types.d.ts.map +1 -1
- package/dist/cjs/standards-sdk.cjs +2 -2
- package/dist/cjs/standards-sdk.cjs.map +1 -1
- package/dist/es/hcs-21/base-client.d.ts +33 -0
- package/dist/es/hcs-21/base-client.d.ts.map +1 -0
- package/dist/es/hcs-21/browser.d.ts +20 -0
- package/dist/es/hcs-21/browser.d.ts.map +1 -0
- package/dist/es/hcs-21/errors.d.ts +6 -0
- package/dist/es/hcs-21/errors.d.ts.map +1 -0
- package/dist/es/hcs-21/index.d.ts +7 -0
- package/dist/es/hcs-21/index.d.ts.map +1 -0
- package/dist/es/hcs-21/sdk.d.ts +48 -0
- package/dist/es/hcs-21/sdk.d.ts.map +1 -0
- package/dist/es/hcs-21/tx.d.ts +20 -0
- package/dist/es/hcs-21/tx.d.ts.map +1 -0
- package/dist/es/hcs-21/types.d.ts +89 -0
- package/dist/es/hcs-21/types.d.ts.map +1 -0
- package/dist/es/index.d.ts +1 -0
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/services/registry-broker/client.d.ts.map +1 -1
- package/dist/es/services/types.d.ts +1 -1
- package/dist/es/services/types.d.ts.map +1 -1
- package/dist/es/standards-sdk.es.js +67 -48
- package/dist/es/standards-sdk.es.js.map +1 -1
- package/dist/es/standards-sdk.es10.js +2 -2
- package/dist/es/standards-sdk.es100.js +231 -28
- package/dist/es/standards-sdk.es100.js.map +1 -1
- package/dist/es/standards-sdk.es101.js +109 -18
- package/dist/es/standards-sdk.es101.js.map +1 -1
- package/dist/es/standards-sdk.es102.js +32 -158
- package/dist/es/standards-sdk.es102.js.map +1 -1
- package/dist/es/standards-sdk.es103.js +80 -204
- package/dist/es/standards-sdk.es103.js.map +1 -1
- package/dist/es/standards-sdk.es104.js +21 -780
- package/dist/es/standards-sdk.es104.js.map +1 -1
- package/dist/es/standards-sdk.es105.js +140 -11
- package/dist/es/standards-sdk.es105.js.map +1 -1
- package/dist/es/standards-sdk.es106.js +29 -567
- package/dist/es/standards-sdk.es106.js.map +1 -1
- package/dist/es/standards-sdk.es107.js +17 -597
- package/dist/es/standards-sdk.es107.js.map +1 -1
- package/dist/es/standards-sdk.es108.js +159 -12
- package/dist/es/standards-sdk.es108.js.map +1 -1
- package/dist/es/standards-sdk.es109.js +208 -2
- package/dist/es/standards-sdk.es109.js.map +1 -1
- package/dist/es/standards-sdk.es110.js +774 -67
- package/dist/es/standards-sdk.es110.js.map +1 -1
- package/dist/es/standards-sdk.es111.js +11 -37
- package/dist/es/standards-sdk.es111.js.map +1 -1
- package/dist/es/standards-sdk.es112.js +567 -2
- package/dist/es/standards-sdk.es112.js.map +1 -1
- package/dist/es/standards-sdk.es113.js +576 -197
- package/dist/es/standards-sdk.es113.js.map +1 -1
- package/dist/es/standards-sdk.es114.js +12 -1139
- package/dist/es/standards-sdk.es114.js.map +1 -1
- package/dist/es/standards-sdk.es115.js +2 -306
- package/dist/es/standards-sdk.es115.js.map +1 -1
- package/dist/es/standards-sdk.es116.js +79 -418
- package/dist/es/standards-sdk.es116.js.map +1 -1
- package/dist/es/standards-sdk.es117.js +35 -351
- package/dist/es/standards-sdk.es117.js.map +1 -1
- package/dist/es/standards-sdk.es118.js +2 -761
- package/dist/es/standards-sdk.es118.js.map +1 -1
- package/dist/es/standards-sdk.es119.js +204 -185
- package/dist/es/standards-sdk.es119.js.map +1 -1
- package/dist/es/standards-sdk.es12.js +1 -1
- package/dist/es/standards-sdk.es120.js +1055 -1482
- package/dist/es/standards-sdk.es120.js.map +1 -1
- package/dist/es/standards-sdk.es121.js +265 -2024
- package/dist/es/standards-sdk.es121.js.map +1 -1
- package/dist/es/standards-sdk.es122.js +420 -50
- package/dist/es/standards-sdk.es122.js.map +1 -1
- package/dist/es/standards-sdk.es123.js +350 -82
- package/dist/es/standards-sdk.es123.js.map +1 -1
- package/dist/es/standards-sdk.es124.js +741 -139
- package/dist/es/standards-sdk.es124.js.map +1 -1
- package/dist/es/standards-sdk.es125.js +204 -7
- package/dist/es/standards-sdk.es125.js.map +1 -1
- package/dist/es/standards-sdk.es126.js +1533 -52
- package/dist/es/standards-sdk.es126.js.map +1 -1
- package/dist/es/standards-sdk.es127.js +2077 -59
- package/dist/es/standards-sdk.es127.js.map +1 -1
- package/dist/es/standards-sdk.es128.js +52 -28
- package/dist/es/standards-sdk.es128.js.map +1 -1
- package/dist/es/standards-sdk.es129.js +80 -131
- package/dist/es/standards-sdk.es129.js.map +1 -1
- package/dist/es/standards-sdk.es13.js +1 -1
- package/dist/es/standards-sdk.es130.js +152 -35
- package/dist/es/standards-sdk.es130.js.map +1 -1
- package/dist/es/standards-sdk.es131.js +7 -17
- package/dist/es/standards-sdk.es131.js.map +1 -1
- package/dist/es/standards-sdk.es132.js +53 -12241
- package/dist/es/standards-sdk.es132.js.map +1 -1
- package/dist/es/standards-sdk.es133.js +65 -694
- package/dist/es/standards-sdk.es133.js.map +1 -1
- package/dist/es/standards-sdk.es134.js +28 -172
- package/dist/es/standards-sdk.es134.js.map +1 -1
- package/dist/es/standards-sdk.es135.js +115 -299
- package/dist/es/standards-sdk.es135.js.map +1 -1
- package/dist/es/standards-sdk.es136.js +36 -340
- package/dist/es/standards-sdk.es136.js.map +1 -1
- package/dist/es/standards-sdk.es137.js +694 -453
- package/dist/es/standards-sdk.es137.js.map +1 -1
- package/dist/es/standards-sdk.es138.js +12210 -267
- package/dist/es/standards-sdk.es138.js.map +1 -1
- package/dist/es/standards-sdk.es139.js +15 -74
- package/dist/es/standards-sdk.es139.js.map +1 -1
- package/dist/es/standards-sdk.es14.js +1 -1
- package/dist/es/standards-sdk.es141.js +1 -1
- package/dist/es/standards-sdk.es142.js +175 -0
- package/dist/es/standards-sdk.es142.js.map +1 -0
- package/dist/es/standards-sdk.es143.js +325 -0
- package/dist/es/standards-sdk.es143.js.map +1 -0
- package/dist/es/standards-sdk.es144.js +349 -0
- package/dist/es/standards-sdk.es144.js.map +1 -0
- package/dist/es/standards-sdk.es145.js +456 -0
- package/dist/es/standards-sdk.es145.js.map +1 -0
- package/dist/es/standards-sdk.es146.js +334 -0
- package/dist/es/standards-sdk.es146.js.map +1 -0
- package/dist/es/standards-sdk.es147.js +79 -0
- package/dist/es/standards-sdk.es147.js.map +1 -0
- package/dist/es/standards-sdk.es15.js +1 -1
- package/dist/es/standards-sdk.es16.js +1 -1
- package/dist/es/standards-sdk.es17.js +5 -5
- package/dist/es/standards-sdk.es19.js +12 -12
- package/dist/es/standards-sdk.es20.js +9 -9
- package/dist/es/standards-sdk.es21.js +1 -1
- package/dist/es/standards-sdk.es22.js +1 -1
- package/dist/es/standards-sdk.es23.js +1 -1
- package/dist/es/standards-sdk.es24.js +1 -1
- package/dist/es/standards-sdk.es25.js +1 -1
- package/dist/es/standards-sdk.es26.js +1 -1
- package/dist/es/standards-sdk.es27.js +1 -1
- package/dist/es/standards-sdk.es28.js +12 -12
- package/dist/es/standards-sdk.es3.js +2 -2
- package/dist/es/standards-sdk.es31.js +2 -2
- package/dist/es/standards-sdk.es32.js +4 -4
- package/dist/es/standards-sdk.es33.js +1 -1
- package/dist/es/standards-sdk.es36.js +6 -6
- package/dist/es/standards-sdk.es37.js +4 -4
- package/dist/es/standards-sdk.es38.js +2 -2
- package/dist/es/standards-sdk.es39.js +2 -2
- package/dist/es/standards-sdk.es40.js +1 -1
- package/dist/es/standards-sdk.es41.js +1 -1
- package/dist/es/standards-sdk.es42.js +2 -2
- package/dist/es/standards-sdk.es47.js +1 -1
- package/dist/es/standards-sdk.es5.js +2 -2
- package/dist/es/standards-sdk.es52.js +1 -1
- package/dist/es/standards-sdk.es54.js +1 -1
- package/dist/es/standards-sdk.es57.js +1 -1
- package/dist/es/standards-sdk.es6.js +2 -2
- package/dist/es/standards-sdk.es61.js +7 -7
- package/dist/es/standards-sdk.es65.js +2 -2
- package/dist/es/standards-sdk.es66.js +3 -3
- package/dist/es/standards-sdk.es69.js +2 -2
- package/dist/es/standards-sdk.es7.js +2 -2
- package/dist/es/standards-sdk.es70.js +3 -3
- package/dist/es/standards-sdk.es71.js +2 -2
- package/dist/es/standards-sdk.es72.js +1 -1
- package/dist/es/standards-sdk.es75.js +2 -2
- package/dist/es/standards-sdk.es77.js +2 -2
- package/dist/es/standards-sdk.es78.js +4 -4
- package/dist/es/standards-sdk.es79.js +1 -1
- package/dist/es/standards-sdk.es8.js +1 -1
- package/dist/es/standards-sdk.es80.js +41 -27
- package/dist/es/standards-sdk.es80.js.map +1 -1
- package/dist/es/standards-sdk.es81.js +6 -78
- package/dist/es/standards-sdk.es81.js.map +1 -1
- package/dist/es/standards-sdk.es82.js +27 -64
- package/dist/es/standards-sdk.es82.js.map +1 -1
- package/dist/es/standards-sdk.es83.js +69 -23
- package/dist/es/standards-sdk.es83.js.map +1 -1
- package/dist/es/standards-sdk.es84.js +165 -23
- package/dist/es/standards-sdk.es84.js.map +1 -1
- package/dist/es/standards-sdk.es85.js +31 -166
- package/dist/es/standards-sdk.es85.js.map +1 -1
- package/dist/es/standards-sdk.es86.js +24 -127
- package/dist/es/standards-sdk.es86.js.map +1 -1
- package/dist/es/standards-sdk.es87.js +65 -142
- package/dist/es/standards-sdk.es87.js.map +1 -1
- package/dist/es/standards-sdk.es88.js +52 -127
- package/dist/es/standards-sdk.es88.js.map +1 -1
- package/dist/es/standards-sdk.es89.js +26 -41
- package/dist/es/standards-sdk.es89.js.map +1 -1
- package/dist/es/standards-sdk.es90.js +23 -261
- package/dist/es/standards-sdk.es90.js.map +1 -1
- package/dist/es/standards-sdk.es91.js +162 -93
- package/dist/es/standards-sdk.es91.js.map +1 -1
- package/dist/es/standards-sdk.es92.js +112 -83
- package/dist/es/standards-sdk.es92.js.map +1 -1
- package/dist/es/standards-sdk.es93.js +156 -28
- package/dist/es/standards-sdk.es93.js.map +1 -1
- package/dist/es/standards-sdk.es94.js +133 -225
- package/dist/es/standards-sdk.es94.js.map +1 -1
- package/dist/es/standards-sdk.es95.js +40 -108
- package/dist/es/standards-sdk.es95.js.map +1 -1
- package/dist/es/standards-sdk.es96.js +253 -24
- package/dist/es/standards-sdk.es96.js.map +1 -1
- package/dist/es/standards-sdk.es97.js +96 -80
- package/dist/es/standards-sdk.es97.js.map +1 -1
- package/dist/es/standards-sdk.es98.js +91 -21
- package/dist/es/standards-sdk.es98.js.map +1 -1
- package/dist/es/standards-sdk.es99.js +28 -141
- package/dist/es/standards-sdk.es99.js.map +1 -1
- package/package.json +62 -59
|
@@ -1,2068 +1,309 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import { createSigner } from "x402/types";
|
|
11
|
-
import { searchResponseSchema, statsResponseSchema, registriesResponseSchema, additionalRegistryCatalogResponseSchema, popularResponseSchema, resolveResponseSchema, registerAgentResponseSchema, registrationQuoteResponseSchema, registrationProgressResponseSchema, creditPurchaseResponseSchema, x402MinimumsResponseSchema, x402CreditPurchaseResponseSchema, ledgerChallengeResponseSchema, ledgerVerifyResponseSchema, protocolsResponseSchema, detectProtocolResponseSchema, registrySearchByNamespaceSchema, vectorSearchResponseSchema, adapterDetailsResponseSchema, websocketStatsResponseSchema, metricsSummaryResponseSchema, uaidValidationResponseSchema, uaidConnectionStatusSchema, dashboardStatsResponseSchema, adaptersResponseSchema, searchFacetsResponseSchema, createSessionResponseSchema, chatHistorySnapshotResponseSchema, chatHistoryCompactionResponseSchema, sessionEncryptionStatusResponseSchema, encryptionHandshakeResponseSchema, registerEncryptionKeyResponseSchema, sendMessageResponseSchema } from "./standards-sdk.es133.js";
|
|
12
|
-
import { ZodError } from "zod";
|
|
13
|
-
import { createPrivateKeySigner } from "./standards-sdk.es122.js";
|
|
14
|
-
const getFs = () => {
|
|
15
|
-
if (typeof require !== "function") {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
try {
|
|
19
|
-
const fsModule = require("node:fs");
|
|
20
|
-
if (fsModule && typeof fsModule.existsSync === "function" && typeof fsModule.readFileSync === "function" && typeof fsModule.writeFileSync === "function" && typeof fsModule.appendFileSync === "function") {
|
|
21
|
-
return fsModule;
|
|
22
|
-
}
|
|
23
|
-
} catch {
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
};
|
|
27
|
-
const DEFAULT_USER_AGENT = "@hashgraphonline/standards-sdk/registry-broker-client";
|
|
28
|
-
const DEFAULT_PROGRESS_INTERVAL_MS = 1500;
|
|
29
|
-
const DEFAULT_PROGRESS_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
30
|
-
const createAbortError = () => typeof DOMException === "function" ? new DOMException("Aborted", "AbortError") : new Error("The operation was aborted");
|
|
31
|
-
const normaliseHeaderName = (name) => name.trim().toLowerCase();
|
|
32
|
-
const isBrowserRuntime = () => typeof window !== "undefined" && typeof window.fetch === "function";
|
|
33
|
-
const DEFAULT_BASE_URL = "https://registry.hashgraphonline.com/api/v1";
|
|
34
|
-
const JSON_CONTENT_TYPE = /application\/json/i;
|
|
35
|
-
const DEFAULT_HISTORY_TOP_UP_HBAR = 0.25;
|
|
36
|
-
const MINIMUM_REGISTRATION_AUTO_TOP_UP_CREDITS = 1;
|
|
37
|
-
const toJsonValue = (value) => {
|
|
38
|
-
if (value === null) {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
if (value instanceof Date) {
|
|
42
|
-
return value.toISOString();
|
|
43
|
-
}
|
|
44
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
45
|
-
return value;
|
|
46
|
-
}
|
|
47
|
-
if (Array.isArray(value)) {
|
|
48
|
-
return value.map((item) => item === void 0 ? null : toJsonValue(item));
|
|
49
|
-
}
|
|
50
|
-
if (typeof value === "object") {
|
|
51
|
-
const result = {};
|
|
52
|
-
Object.entries(value).forEach(
|
|
53
|
-
([key, entryValue]) => {
|
|
54
|
-
if (entryValue !== void 0) {
|
|
55
|
-
result[key] = toJsonValue(entryValue);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
);
|
|
59
|
-
return result;
|
|
60
|
-
}
|
|
61
|
-
throw new TypeError("Only JSON-compatible values are supported");
|
|
62
|
-
};
|
|
63
|
-
const isJsonObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
64
|
-
const toJsonObject = (value) => {
|
|
65
|
-
const normalised = toJsonValue(value);
|
|
66
|
-
if (isJsonObject(normalised)) {
|
|
67
|
-
return normalised;
|
|
68
|
-
}
|
|
69
|
-
throw new TypeError("Expected JSON object value");
|
|
70
|
-
};
|
|
71
|
-
const serialiseAuthConfig = (auth) => {
|
|
72
|
-
const authPayload = {};
|
|
73
|
-
if (auth.type) {
|
|
74
|
-
authPayload.type = auth.type;
|
|
75
|
-
}
|
|
76
|
-
if (auth.token) {
|
|
77
|
-
authPayload.token = auth.token;
|
|
78
|
-
}
|
|
79
|
-
if (auth.username) {
|
|
80
|
-
authPayload.username = auth.username;
|
|
81
|
-
}
|
|
82
|
-
if (auth.password) {
|
|
83
|
-
authPayload.password = auth.password;
|
|
84
|
-
}
|
|
85
|
-
if (auth.headerName) {
|
|
86
|
-
authPayload.headerName = auth.headerName;
|
|
87
|
-
}
|
|
88
|
-
if (auth.headerValue) {
|
|
89
|
-
authPayload.headerValue = auth.headerValue;
|
|
90
|
-
}
|
|
91
|
-
if (auth.headers) {
|
|
92
|
-
authPayload.headers = { ...auth.headers };
|
|
93
|
-
}
|
|
94
|
-
return authPayload;
|
|
95
|
-
};
|
|
96
|
-
const serialiseAgentRegistrationRequest = (payload) => {
|
|
97
|
-
const body = {
|
|
98
|
-
profile: toJsonObject(payload.profile)
|
|
99
|
-
};
|
|
100
|
-
if (payload.endpoint !== void 0) {
|
|
101
|
-
body.endpoint = payload.endpoint;
|
|
102
|
-
}
|
|
103
|
-
if (payload.protocol !== void 0) {
|
|
104
|
-
body.protocol = payload.protocol;
|
|
105
|
-
}
|
|
106
|
-
if (payload.communicationProtocol !== void 0) {
|
|
107
|
-
body.communicationProtocol = payload.communicationProtocol;
|
|
108
|
-
}
|
|
109
|
-
if (payload.registry !== void 0) {
|
|
110
|
-
body.registry = payload.registry;
|
|
111
|
-
}
|
|
112
|
-
if (payload.additionalRegistries !== void 0) {
|
|
113
|
-
body.additionalRegistries = payload.additionalRegistries;
|
|
114
|
-
}
|
|
115
|
-
if (payload.metadata !== void 0) {
|
|
116
|
-
body.metadata = toJsonObject(payload.metadata);
|
|
117
|
-
}
|
|
118
|
-
return body;
|
|
119
|
-
};
|
|
120
|
-
const normalizeHexPrivateKey = (value) => {
|
|
121
|
-
const trimmed = value.trim();
|
|
122
|
-
if (!trimmed) {
|
|
123
|
-
throw new Error("evmPrivateKey is required");
|
|
124
|
-
}
|
|
125
|
-
return trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
|
|
126
|
-
};
|
|
127
|
-
class RegistryBrokerError extends Error {
|
|
128
|
-
constructor(message, details) {
|
|
129
|
-
super(message);
|
|
130
|
-
this.status = details.status;
|
|
131
|
-
this.statusText = details.statusText;
|
|
132
|
-
this.body = details.body;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
class RegistryBrokerParseError extends Error {
|
|
136
|
-
constructor(message, cause, rawValue) {
|
|
137
|
-
super(message);
|
|
138
|
-
this.cause = cause;
|
|
139
|
-
this.rawValue = rawValue;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
function normaliseBaseUrl(input) {
|
|
143
|
-
const trimmed = input?.trim();
|
|
144
|
-
const baseCandidate = trimmed && trimmed.length > 0 ? trimmed : DEFAULT_BASE_URL;
|
|
145
|
-
const withoutTrailing = baseCandidate.replace(/\/+$/, "");
|
|
146
|
-
if (/\/api\/v\d+$/i.test(withoutTrailing)) {
|
|
147
|
-
return withoutTrailing;
|
|
148
|
-
}
|
|
149
|
-
if (/\/api$/i.test(withoutTrailing)) {
|
|
150
|
-
return `${withoutTrailing}/v1`;
|
|
151
|
-
}
|
|
152
|
-
return `${withoutTrailing}/api/v1`;
|
|
153
|
-
}
|
|
154
|
-
function buildSearchQuery(params) {
|
|
155
|
-
const query = new URLSearchParams();
|
|
156
|
-
const appendList = (key, values) => {
|
|
157
|
-
if (!values) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
values.forEach((value) => {
|
|
161
|
-
if (typeof value === "string") {
|
|
162
|
-
const trimmed = value.trim();
|
|
163
|
-
if (trimmed.length > 0) {
|
|
164
|
-
query.append(key, trimmed);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
};
|
|
169
|
-
if (params.q) {
|
|
170
|
-
const trimmed = params.q.trim();
|
|
171
|
-
if (trimmed.length > 0) {
|
|
172
|
-
query.set("q", trimmed);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
if (typeof params.page === "number") {
|
|
176
|
-
query.set("page", params.page.toString());
|
|
177
|
-
}
|
|
178
|
-
if (typeof params.limit === "number") {
|
|
179
|
-
query.set("limit", params.limit.toString());
|
|
180
|
-
}
|
|
181
|
-
if (params.registry) {
|
|
182
|
-
const trimmed = params.registry.trim();
|
|
183
|
-
if (trimmed.length > 0) {
|
|
184
|
-
query.set("registry", trimmed);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
appendList("registries", params.registries);
|
|
188
|
-
if (typeof params.minTrust === "number") {
|
|
189
|
-
query.set("minTrust", params.minTrust.toString());
|
|
190
|
-
}
|
|
191
|
-
appendList("capabilities", params.capabilities);
|
|
192
|
-
appendList("protocols", params.protocols);
|
|
193
|
-
appendList("adapters", params.adapters);
|
|
194
|
-
if (params.metadata) {
|
|
195
|
-
Object.entries(params.metadata).forEach(([key, values]) => {
|
|
196
|
-
if (!key || !Array.isArray(values) || values.length === 0) {
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
const trimmedKey = key.trim();
|
|
200
|
-
if (trimmedKey.length === 0) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
values.forEach((value) => {
|
|
204
|
-
if (value === void 0 || value === null) {
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
query.append(`metadata.${trimmedKey}`, String(value));
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
if (params.type) {
|
|
212
|
-
const trimmedType = params.type.trim();
|
|
213
|
-
if (trimmedType.length > 0 && trimmedType.toLowerCase() !== "all") {
|
|
214
|
-
query.set("type", trimmedType);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
if (params.verified === true) {
|
|
218
|
-
query.set("verified", "true");
|
|
219
|
-
}
|
|
220
|
-
if (params.online === true) {
|
|
221
|
-
query.set("online", "true");
|
|
222
|
-
}
|
|
223
|
-
if (params.sortBy) {
|
|
224
|
-
const trimmedSort = params.sortBy.trim();
|
|
225
|
-
if (trimmedSort.length > 0) {
|
|
226
|
-
query.set("sortBy", trimmedSort);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
if (params.sortOrder) {
|
|
230
|
-
const lowered = params.sortOrder.toLowerCase();
|
|
231
|
-
if (lowered === "asc" || lowered === "desc") {
|
|
232
|
-
query.set("sortOrder", lowered);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
const queryString = query.toString();
|
|
236
|
-
return queryString.length > 0 ? `?${queryString}` : "";
|
|
237
|
-
}
|
|
238
|
-
class RegistryBrokerClient {
|
|
239
|
-
constructor(options = {}) {
|
|
240
|
-
this.conversationContexts = /* @__PURE__ */ new Map();
|
|
241
|
-
this.request = async (path2, config) => {
|
|
242
|
-
const headers = new Headers();
|
|
243
|
-
Object.entries(this.defaultHeaders).forEach(([key, value]) => {
|
|
244
|
-
headers.set(key, value);
|
|
245
|
-
});
|
|
246
|
-
if (config.headers) {
|
|
247
|
-
Object.entries(config.headers).forEach(([key, value]) => {
|
|
248
|
-
headers.set(key, value);
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
if (!headers.has("accept")) {
|
|
252
|
-
headers.set("accept", "application/json");
|
|
253
|
-
}
|
|
254
|
-
if (!headers.has("user-agent") && !isBrowserRuntime()) {
|
|
255
|
-
headers.set("user-agent", DEFAULT_USER_AGENT);
|
|
256
|
-
}
|
|
257
|
-
const init = {
|
|
258
|
-
method: config.method ?? "GET",
|
|
259
|
-
headers
|
|
260
|
-
};
|
|
261
|
-
if (config.body !== void 0) {
|
|
262
|
-
init.body = JSON.stringify(config.body);
|
|
263
|
-
if (!headers.has("content-type")) {
|
|
264
|
-
headers.set("content-type", "application/json");
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
const response = await this.fetchImpl(this.buildUrl(path2), init);
|
|
268
|
-
if (response.ok) {
|
|
269
|
-
return response;
|
|
270
|
-
}
|
|
271
|
-
const errorBody = await this.extractErrorBody(response);
|
|
272
|
-
throw new RegistryBrokerError("Registry broker request failed", {
|
|
273
|
-
status: response.status,
|
|
274
|
-
statusText: response.statusText,
|
|
275
|
-
body: errorBody
|
|
276
|
-
});
|
|
277
|
-
};
|
|
278
|
-
this.baseUrl = normaliseBaseUrl(options.baseUrl);
|
|
279
|
-
const fetchCandidate = options.fetchImplementation ?? globalThis.fetch;
|
|
280
|
-
if (!fetchCandidate) {
|
|
281
|
-
throw new Error(
|
|
282
|
-
"A fetch implementation is required for RegistryBrokerClient"
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
this.fetchImpl = fetchCandidate;
|
|
286
|
-
this.defaultHeaders = {};
|
|
287
|
-
if (options.defaultHeaders) {
|
|
288
|
-
Object.entries(options.defaultHeaders).forEach(([name, value]) => {
|
|
289
|
-
if (typeof value === "string") {
|
|
290
|
-
this.setDefaultHeader(name, value);
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
if (options.apiKey && options.apiKey.trim().length > 0) {
|
|
295
|
-
this.setApiKey(options.apiKey);
|
|
296
|
-
}
|
|
297
|
-
if (options.ledgerApiKey && options.ledgerApiKey.trim().length > 0) {
|
|
298
|
-
this.setLedgerApiKey(options.ledgerApiKey);
|
|
299
|
-
}
|
|
300
|
-
this.registrationAutoTopUp = options.registrationAutoTopUp;
|
|
301
|
-
this.historyAutoTopUp = options.historyAutoTopUp;
|
|
302
|
-
this.encryptedChatManager = new EncryptedChatManager(this);
|
|
303
|
-
this.encryptionOptions = options.encryption;
|
|
304
|
-
this.encryptionBootstrapPromise = this.bootstrapEncryptionOptions(
|
|
305
|
-
options.encryption
|
|
306
|
-
);
|
|
307
|
-
this.chat = {
|
|
308
|
-
start: (options2) => this.startChat(options2),
|
|
309
|
-
createSession: (payload) => this.createSession(payload),
|
|
310
|
-
sendMessage: (payload) => this.sendMessage(payload),
|
|
311
|
-
endSession: (sessionId) => this.endSession(sessionId),
|
|
312
|
-
getHistory: (sessionId, options2) => this.fetchHistorySnapshot(sessionId, options2),
|
|
313
|
-
compactHistory: (payload) => this.compactHistory(payload),
|
|
314
|
-
getEncryptionStatus: (sessionId) => this.fetchEncryptionStatus(sessionId),
|
|
315
|
-
submitEncryptionHandshake: (sessionId, payload) => this.postEncryptionHandshake(sessionId, payload),
|
|
316
|
-
startConversation: (opts) => this.startConversation(opts),
|
|
317
|
-
acceptConversation: (opts) => this.acceptConversation(opts)
|
|
318
|
-
};
|
|
319
|
-
this.encryption = {
|
|
320
|
-
registerKey: (payload) => this.registerEncryptionKey(payload),
|
|
321
|
-
generateEphemeralKeyPair: () => this.createEphemeralKeyPair(),
|
|
322
|
-
deriveSharedSecret: (options2) => this.deriveSharedSecret(options2),
|
|
323
|
-
encryptCipherEnvelope: (options2) => this.buildCipherEnvelope(options2),
|
|
324
|
-
decryptCipherEnvelope: (options2) => this.openCipherEnvelope(options2),
|
|
325
|
-
ensureAgentKey: (options2) => this.ensureAgentEncryptionKey(options2)
|
|
326
|
-
};
|
|
327
|
-
this.chat.createEncryptedSession = (options2) => this.encryptedChatManager.startSession(options2);
|
|
328
|
-
this.chat.acceptEncryptedSession = (options2) => this.encryptedChatManager.acceptSession(options2);
|
|
329
|
-
}
|
|
330
|
-
static async initializeAgent(options) {
|
|
331
|
-
const { uaid, ensureEncryptionKey = true, ...clientOptions } = options;
|
|
332
|
-
const client = new RegistryBrokerClient(clientOptions);
|
|
333
|
-
let encryption = null;
|
|
334
|
-
if (ensureEncryptionKey) {
|
|
335
|
-
const ensureOptions = typeof ensureEncryptionKey === "object" ? ensureEncryptionKey : { generateIfMissing: true };
|
|
336
|
-
encryption = await client.encryption.ensureAgentKey({
|
|
337
|
-
uaid,
|
|
338
|
-
...ensureOptions
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
return { client, encryption };
|
|
342
|
-
}
|
|
343
|
-
setApiKey(apiKey) {
|
|
344
|
-
this.setDefaultHeader("x-api-key", apiKey);
|
|
345
|
-
}
|
|
346
|
-
setLedgerApiKey(apiKey) {
|
|
347
|
-
this.setDefaultHeader("x-ledger-api-key", apiKey);
|
|
348
|
-
}
|
|
349
|
-
setDefaultHeader(name, value) {
|
|
350
|
-
if (!name || name.trim().length === 0) {
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
const headerName = normaliseHeaderName(name);
|
|
354
|
-
if (!value || value.trim().length === 0) {
|
|
355
|
-
delete this.defaultHeaders[headerName];
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
this.defaultHeaders[headerName] = value.trim();
|
|
359
|
-
}
|
|
360
|
-
getDefaultHeaders() {
|
|
361
|
-
return { ...this.defaultHeaders };
|
|
362
|
-
}
|
|
363
|
-
async encryptionReady() {
|
|
364
|
-
if (!this.encryptionBootstrapPromise) {
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
await this.encryptionBootstrapPromise;
|
|
368
|
-
}
|
|
369
|
-
async search(params = {}) {
|
|
370
|
-
const query = buildSearchQuery(params);
|
|
371
|
-
const raw = await this.requestJson(`/search${query}`, {
|
|
372
|
-
method: "GET"
|
|
373
|
-
});
|
|
374
|
-
return this.parseWithSchema(raw, searchResponseSchema, "search response");
|
|
375
|
-
}
|
|
376
|
-
async stats() {
|
|
377
|
-
const raw = await this.requestJson("/stats", { method: "GET" });
|
|
378
|
-
return this.parseWithSchema(raw, statsResponseSchema, "stats response");
|
|
379
|
-
}
|
|
380
|
-
async registries() {
|
|
381
|
-
const raw = await this.requestJson("/registries", {
|
|
382
|
-
method: "GET"
|
|
383
|
-
});
|
|
384
|
-
return this.parseWithSchema(
|
|
385
|
-
raw,
|
|
386
|
-
registriesResponseSchema,
|
|
387
|
-
"registries response"
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
async getAdditionalRegistries() {
|
|
391
|
-
const raw = await this.requestJson(
|
|
392
|
-
"/register/additional-registries",
|
|
393
|
-
{
|
|
394
|
-
method: "GET"
|
|
395
|
-
}
|
|
396
|
-
);
|
|
397
|
-
return this.parseWithSchema(
|
|
398
|
-
raw,
|
|
399
|
-
additionalRegistryCatalogResponseSchema,
|
|
400
|
-
"additional registry catalog response"
|
|
401
|
-
);
|
|
402
|
-
}
|
|
403
|
-
bootstrapEncryptionOptions(options) {
|
|
404
|
-
if (!options?.autoRegister || options.autoRegister.enabled === false) {
|
|
405
|
-
return null;
|
|
406
|
-
}
|
|
407
|
-
return this.autoRegisterEncryptionKey(options.autoRegister).then(
|
|
408
|
-
() => void 0
|
|
409
|
-
);
|
|
410
|
-
}
|
|
411
|
-
async autoRegisterEncryptionKey(config) {
|
|
412
|
-
const identity = this.normalizeAutoRegisterIdentity(config);
|
|
413
|
-
if (!identity) {
|
|
414
|
-
throw new Error(
|
|
415
|
-
"Auto-registration requires uaid, ledgerAccountId, or email"
|
|
416
|
-
);
|
|
417
|
-
}
|
|
418
|
-
const material = await this.resolveAutoRegisterKeyMaterial(config);
|
|
419
|
-
if (!material) {
|
|
420
|
-
throw new Error(
|
|
421
|
-
"Unable to resolve encryption public key for auto-registration"
|
|
422
|
-
);
|
|
423
|
-
}
|
|
424
|
-
await this.registerEncryptionKey({
|
|
425
|
-
keyType: config.keyType ?? "secp256k1",
|
|
426
|
-
publicKey: material.publicKey,
|
|
427
|
-
...identity
|
|
428
|
-
});
|
|
429
|
-
return material;
|
|
430
|
-
}
|
|
431
|
-
normalizeAutoRegisterIdentity(config) {
|
|
432
|
-
const identity = {};
|
|
433
|
-
if (config.uaid) {
|
|
434
|
-
identity.uaid = config.uaid;
|
|
435
|
-
}
|
|
436
|
-
if (config.ledgerAccountId) {
|
|
437
|
-
identity.ledgerAccountId = config.ledgerAccountId;
|
|
438
|
-
if (config.ledgerNetwork) {
|
|
439
|
-
identity.ledgerNetwork = config.ledgerNetwork;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
if (config.email) {
|
|
443
|
-
identity.email = config.email;
|
|
444
|
-
}
|
|
445
|
-
if (identity.uaid || identity.ledgerAccountId || identity.email) {
|
|
446
|
-
return identity;
|
|
447
|
-
}
|
|
448
|
-
return null;
|
|
449
|
-
}
|
|
450
|
-
async resolveAutoRegisterKeyMaterial(config) {
|
|
451
|
-
if (config.publicKey?.trim()) {
|
|
452
|
-
return { publicKey: config.publicKey.trim() };
|
|
453
|
-
}
|
|
454
|
-
let privateKey = config.privateKey?.trim();
|
|
455
|
-
const envVar = config.envVar ?? "RB_ENCRYPTION_PRIVATE_KEY";
|
|
456
|
-
if (!privateKey && envVar && process?.env?.[envVar]?.trim()) {
|
|
457
|
-
privateKey = process.env[envVar]?.trim();
|
|
458
|
-
}
|
|
459
|
-
if (!privateKey && config.generateIfMissing) {
|
|
460
|
-
const pair = await this.generateEncryptionKeyPair({
|
|
461
|
-
keyType: config.keyType ?? "secp256k1",
|
|
462
|
-
envVar,
|
|
463
|
-
envPath: config.envPath,
|
|
464
|
-
overwrite: config.overwriteEnv
|
|
465
|
-
});
|
|
466
|
-
if (envVar) {
|
|
467
|
-
process.env[envVar] = pair.privateKey;
|
|
468
|
-
}
|
|
469
|
-
return { publicKey: pair.publicKey, privateKey: pair.privateKey };
|
|
470
|
-
}
|
|
471
|
-
if (privateKey) {
|
|
472
|
-
const publicKey = this.derivePublicKeyFromPrivateKey(privateKey);
|
|
473
|
-
return { publicKey, privateKey };
|
|
474
|
-
}
|
|
475
|
-
return null;
|
|
476
|
-
}
|
|
477
|
-
derivePublicKeyFromPrivateKey(privateKey) {
|
|
478
|
-
const normalized = this.hexToBuffer(privateKey);
|
|
479
|
-
const publicKey = secp256k1.getPublicKey(normalized, true);
|
|
480
|
-
return Buffer.from(publicKey).toString("hex");
|
|
481
|
-
}
|
|
482
|
-
ensureAgentEncryptionKey(options) {
|
|
483
|
-
return this.autoRegisterEncryptionKey({
|
|
484
|
-
...options,
|
|
485
|
-
uaid: options.uaid,
|
|
486
|
-
enabled: true
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
async popularSearches() {
|
|
490
|
-
const raw = await this.requestJson("/popular", {
|
|
491
|
-
method: "GET"
|
|
492
|
-
});
|
|
493
|
-
return this.parseWithSchema(
|
|
494
|
-
raw,
|
|
495
|
-
popularResponseSchema,
|
|
496
|
-
"popular searches response"
|
|
497
|
-
);
|
|
498
|
-
}
|
|
499
|
-
async resolveUaid(uaid) {
|
|
500
|
-
const raw = await this.requestJson(
|
|
501
|
-
`/resolve/${encodeURIComponent(uaid)}`,
|
|
502
|
-
{
|
|
503
|
-
method: "GET"
|
|
504
|
-
}
|
|
505
|
-
);
|
|
506
|
-
return this.parseWithSchema(
|
|
507
|
-
raw,
|
|
508
|
-
resolveResponseSchema,
|
|
509
|
-
"resolve UAID response"
|
|
510
|
-
);
|
|
511
|
-
}
|
|
512
|
-
async performRegisterAgent(payload) {
|
|
513
|
-
const raw = await this.requestJson("/register", {
|
|
514
|
-
method: "POST",
|
|
515
|
-
body: serialiseAgentRegistrationRequest(payload),
|
|
516
|
-
headers: { "content-type": "application/json" }
|
|
517
|
-
});
|
|
518
|
-
return this.parseWithSchema(
|
|
519
|
-
raw,
|
|
520
|
-
registerAgentResponseSchema,
|
|
521
|
-
"register agent response"
|
|
522
|
-
);
|
|
523
|
-
}
|
|
524
|
-
async registerAgent(payload, options) {
|
|
525
|
-
const autoTopUp = options?.autoTopUp ?? this.registrationAutoTopUp;
|
|
526
|
-
if (!autoTopUp) {
|
|
527
|
-
return this.performRegisterAgent(payload);
|
|
528
|
-
}
|
|
529
|
-
await this.ensureCreditsForRegistration(payload, autoTopUp);
|
|
530
|
-
let retried = false;
|
|
531
|
-
while (true) {
|
|
532
|
-
try {
|
|
533
|
-
return await this.performRegisterAgent(payload);
|
|
534
|
-
} catch (error) {
|
|
535
|
-
const shortfall = this.extractInsufficientCreditsDetails(error);
|
|
536
|
-
if (shortfall && !retried) {
|
|
537
|
-
await this.ensureCreditsForRegistration(payload, autoTopUp);
|
|
538
|
-
retried = true;
|
|
539
|
-
continue;
|
|
540
|
-
}
|
|
541
|
-
throw error;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
async getRegistrationQuote(payload) {
|
|
546
|
-
const raw = await this.requestJson("/register/quote", {
|
|
547
|
-
method: "POST",
|
|
548
|
-
body: serialiseAgentRegistrationRequest(payload),
|
|
549
|
-
headers: { "content-type": "application/json" }
|
|
550
|
-
});
|
|
551
|
-
return this.parseWithSchema(
|
|
552
|
-
raw,
|
|
553
|
-
registrationQuoteResponseSchema,
|
|
554
|
-
"registration quote response"
|
|
555
|
-
);
|
|
556
|
-
}
|
|
557
|
-
async updateAgent(uaid, payload) {
|
|
558
|
-
const raw = await this.requestJson(
|
|
559
|
-
`/register/${encodeURIComponent(uaid)}`,
|
|
560
|
-
{
|
|
561
|
-
method: "PUT",
|
|
562
|
-
body: serialiseAgentRegistrationRequest(payload),
|
|
563
|
-
headers: { "content-type": "application/json" }
|
|
564
|
-
}
|
|
565
|
-
);
|
|
566
|
-
return this.parseWithSchema(
|
|
567
|
-
raw,
|
|
568
|
-
registerAgentResponseSchema,
|
|
569
|
-
"update agent response"
|
|
570
|
-
);
|
|
571
|
-
}
|
|
572
|
-
async getRegistrationProgress(attemptId) {
|
|
573
|
-
const normalisedAttemptId = attemptId.trim();
|
|
574
|
-
if (!normalisedAttemptId) {
|
|
575
|
-
throw new Error("attemptId is required");
|
|
576
|
-
}
|
|
1
|
+
import { proto } from "@hashgraph/proto";
|
|
2
|
+
import { hasTransactionType, parseKey } from "./standards-sdk.es147.js";
|
|
3
|
+
import { AccountId, Long, ScheduleId } from "@hashgraph/sdk";
|
|
4
|
+
class ScheduleParser {
|
|
5
|
+
/**
|
|
6
|
+
* Parse Schedule Service transaction using unified dual-branch approach
|
|
7
|
+
* This handles both regular transactions and signed transaction variants
|
|
8
|
+
*/
|
|
9
|
+
static parseScheduleTransaction(transaction, originalBytes) {
|
|
577
10
|
try {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
async waitForRegistrationCompletion(attemptId, options = {}) {
|
|
596
|
-
const normalisedAttemptId = attemptId.trim();
|
|
597
|
-
if (!normalisedAttemptId) {
|
|
598
|
-
throw new Error("attemptId is required");
|
|
599
|
-
}
|
|
600
|
-
const interval = Math.max(
|
|
601
|
-
250,
|
|
602
|
-
options.intervalMs ?? DEFAULT_PROGRESS_INTERVAL_MS
|
|
603
|
-
);
|
|
604
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_PROGRESS_TIMEOUT_MS;
|
|
605
|
-
const throwOnFailure = options.throwOnFailure ?? true;
|
|
606
|
-
const signal = options.signal;
|
|
607
|
-
const startedAt = Date.now();
|
|
608
|
-
while (true) {
|
|
609
|
-
if (signal?.aborted) {
|
|
610
|
-
throw createAbortError();
|
|
611
|
-
}
|
|
612
|
-
const progress = await this.getRegistrationProgress(normalisedAttemptId);
|
|
613
|
-
if (progress) {
|
|
614
|
-
options.onProgress?.(progress);
|
|
615
|
-
if (progress.status === "completed") {
|
|
616
|
-
return progress;
|
|
617
|
-
}
|
|
618
|
-
if (progress.status === "partial" || progress.status === "failed") {
|
|
619
|
-
if (throwOnFailure) {
|
|
620
|
-
throw new RegistryBrokerError(
|
|
621
|
-
"Registration did not complete successfully",
|
|
622
|
-
{
|
|
623
|
-
status: 409,
|
|
624
|
-
statusText: progress.status,
|
|
625
|
-
body: progress
|
|
11
|
+
if (originalBytes || transaction.toBytes) {
|
|
12
|
+
try {
|
|
13
|
+
const bytesToParse = originalBytes || transaction.toBytes();
|
|
14
|
+
const decoded = proto.TransactionList.decode(bytesToParse);
|
|
15
|
+
if (decoded.transactionList && decoded.transactionList.length > 0) {
|
|
16
|
+
const tx = decoded.transactionList[0];
|
|
17
|
+
let txBody = null;
|
|
18
|
+
if (tx.bodyBytes && tx.bodyBytes.length > 0) {
|
|
19
|
+
txBody = proto.TransactionBody.decode(tx.bodyBytes);
|
|
20
|
+
} else if (tx.signedTransactionBytes && tx.signedTransactionBytes.length > 0) {
|
|
21
|
+
const signedTx = proto.SignedTransaction.decode(
|
|
22
|
+
tx.signedTransactionBytes
|
|
23
|
+
);
|
|
24
|
+
if (signedTx.bodyBytes) {
|
|
25
|
+
txBody = proto.TransactionBody.decode(signedTx.bodyBytes);
|
|
626
26
|
}
|
|
627
|
-
|
|
27
|
+
}
|
|
28
|
+
if (txBody) {
|
|
29
|
+
const protoResult = this.parseFromProtobufTxBody(txBody);
|
|
30
|
+
if (protoResult.type && protoResult.type !== "UNKNOWN") {
|
|
31
|
+
return protoResult;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
628
34
|
}
|
|
629
|
-
|
|
35
|
+
} catch (protoError) {
|
|
630
36
|
}
|
|
631
37
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
async purchaseCreditsWithHbar(params) {
|
|
641
|
-
const body = {
|
|
642
|
-
accountId: params.accountId,
|
|
643
|
-
payerKey: params.privateKey,
|
|
644
|
-
hbarAmount: this.calculateHbarAmountParam(params.hbarAmount)
|
|
645
|
-
};
|
|
646
|
-
if (params.memo) {
|
|
647
|
-
body.memo = params.memo;
|
|
648
|
-
}
|
|
649
|
-
if (params.metadata) {
|
|
650
|
-
body.metadata = params.metadata;
|
|
651
|
-
}
|
|
652
|
-
const raw = await this.requestJson("/credits/purchase", {
|
|
653
|
-
method: "POST",
|
|
654
|
-
headers: { "content-type": "application/json" },
|
|
655
|
-
body
|
|
656
|
-
});
|
|
657
|
-
return this.parseWithSchema(
|
|
658
|
-
raw,
|
|
659
|
-
creditPurchaseResponseSchema,
|
|
660
|
-
"credit purchase response"
|
|
661
|
-
);
|
|
662
|
-
}
|
|
663
|
-
async getX402Minimums() {
|
|
664
|
-
const raw = await this.requestJson(
|
|
665
|
-
"/credits/purchase/x402/minimums",
|
|
666
|
-
{ method: "GET" }
|
|
667
|
-
);
|
|
668
|
-
return this.parseWithSchema(
|
|
669
|
-
raw,
|
|
670
|
-
x402MinimumsResponseSchema,
|
|
671
|
-
"x402 minimums response"
|
|
672
|
-
);
|
|
673
|
-
}
|
|
674
|
-
async purchaseCreditsWithX402(params) {
|
|
675
|
-
if (!Number.isFinite(params.credits) || params.credits <= 0) {
|
|
676
|
-
throw new Error("credits must be a positive number");
|
|
677
|
-
}
|
|
678
|
-
if (params.usdAmount !== void 0 && (!Number.isFinite(params.usdAmount) || params.usdAmount <= 0)) {
|
|
679
|
-
throw new Error("usdAmount must be a positive number when provided");
|
|
680
|
-
}
|
|
681
|
-
const body = {
|
|
682
|
-
accountId: params.accountId,
|
|
683
|
-
credits: params.credits
|
|
684
|
-
};
|
|
685
|
-
if (params.usdAmount !== void 0) {
|
|
686
|
-
body.usdAmount = params.usdAmount;
|
|
687
|
-
}
|
|
688
|
-
if (params.description) {
|
|
689
|
-
body.description = params.description;
|
|
690
|
-
}
|
|
691
|
-
if (params.metadata) {
|
|
692
|
-
body.metadata = params.metadata;
|
|
693
|
-
}
|
|
694
|
-
const axiosClient = axios.create({
|
|
695
|
-
baseURL: this.baseUrl,
|
|
696
|
-
headers: {
|
|
697
|
-
...this.getDefaultHeaders(),
|
|
698
|
-
"content-type": "application/json"
|
|
699
|
-
}
|
|
700
|
-
});
|
|
701
|
-
const paymentClient = withPaymentInterceptor(
|
|
702
|
-
axiosClient,
|
|
703
|
-
params.walletClient
|
|
704
|
-
);
|
|
705
|
-
const response = await paymentClient.post("/credits/purchase/x402", body);
|
|
706
|
-
const parsed = this.parseWithSchema(
|
|
707
|
-
response.data,
|
|
708
|
-
x402CreditPurchaseResponseSchema,
|
|
709
|
-
"x402 credit purchase response"
|
|
710
|
-
);
|
|
711
|
-
const paymentHeader = typeof response.headers["x-payment-response"] === "string" ? response.headers["x-payment-response"] : void 0;
|
|
712
|
-
const decodedPayment = paymentHeader !== void 0 ? decodeXPaymentResponse(paymentHeader) : void 0;
|
|
713
|
-
return {
|
|
714
|
-
...parsed,
|
|
715
|
-
paymentResponseHeader: paymentHeader,
|
|
716
|
-
paymentResponse: decodedPayment
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
async buyCreditsWithX402(params) {
|
|
720
|
-
const network = params.network ?? "base";
|
|
721
|
-
const normalizedKey = normalizeHexPrivateKey(params.evmPrivateKey);
|
|
722
|
-
const walletClient = await createSigner(network, normalizedKey);
|
|
723
|
-
return this.purchaseCreditsWithX402({
|
|
724
|
-
accountId: params.accountId,
|
|
725
|
-
credits: params.credits,
|
|
726
|
-
usdAmount: params.usdAmount,
|
|
727
|
-
description: params.description,
|
|
728
|
-
metadata: params.metadata,
|
|
729
|
-
walletClient
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
calculateHbarAmount(creditsToPurchase, creditsPerHbar) {
|
|
733
|
-
if (creditsPerHbar <= 0) {
|
|
734
|
-
throw new Error("creditsPerHbar must be positive");
|
|
735
|
-
}
|
|
736
|
-
if (creditsToPurchase <= 0) {
|
|
737
|
-
throw new Error("creditsToPurchase must be positive");
|
|
738
|
-
}
|
|
739
|
-
const rawHbar = creditsToPurchase / creditsPerHbar;
|
|
740
|
-
const tinybars = Math.ceil(rawHbar * 1e8);
|
|
741
|
-
return tinybars / 1e8;
|
|
742
|
-
}
|
|
743
|
-
resolveCreditsToPurchase(shortfallCredits) {
|
|
744
|
-
if (!Number.isFinite(shortfallCredits) || shortfallCredits <= 0) {
|
|
745
|
-
return 0;
|
|
746
|
-
}
|
|
747
|
-
return Math.max(
|
|
748
|
-
Math.ceil(shortfallCredits),
|
|
749
|
-
MINIMUM_REGISTRATION_AUTO_TOP_UP_CREDITS
|
|
750
|
-
);
|
|
751
|
-
}
|
|
752
|
-
calculateHbarAmountParam(hbarAmount) {
|
|
753
|
-
const tinybars = Math.ceil(hbarAmount * 1e8);
|
|
754
|
-
if (tinybars <= 0) {
|
|
755
|
-
throw new Error("Calculated purchase amount must be positive");
|
|
756
|
-
}
|
|
757
|
-
return tinybars / 1e8;
|
|
758
|
-
}
|
|
759
|
-
shouldAutoTopUpHistory(payload, error) {
|
|
760
|
-
if (!this.historyAutoTopUp || payload.historyTtlSeconds === void 0) {
|
|
761
|
-
return false;
|
|
762
|
-
}
|
|
763
|
-
if (!(error instanceof RegistryBrokerError)) {
|
|
764
|
-
return false;
|
|
765
|
-
}
|
|
766
|
-
if (error.status !== 402) {
|
|
767
|
-
return false;
|
|
768
|
-
}
|
|
769
|
-
const message = this.extractErrorMessage(error.body);
|
|
770
|
-
if (!message) {
|
|
771
|
-
return true;
|
|
772
|
-
}
|
|
773
|
-
const normalised = message.toLowerCase();
|
|
774
|
-
return normalised.includes("history") || normalised.includes("chat history");
|
|
775
|
-
}
|
|
776
|
-
extractErrorMessage(body) {
|
|
777
|
-
if (typeof body === "string") {
|
|
778
|
-
return body;
|
|
779
|
-
}
|
|
780
|
-
if (isJsonObject(body) && typeof body.error === "string") {
|
|
781
|
-
return body.error;
|
|
782
|
-
}
|
|
783
|
-
if (isJsonObject(body) && typeof body.message === "string") {
|
|
784
|
-
return body.message;
|
|
785
|
-
}
|
|
786
|
-
return void 0;
|
|
787
|
-
}
|
|
788
|
-
async executeHistoryAutoTopUp(reason) {
|
|
789
|
-
if (!this.historyAutoTopUp) {
|
|
790
|
-
return;
|
|
791
|
-
}
|
|
792
|
-
const hbarAmount = this.historyAutoTopUp.hbarAmount && this.historyAutoTopUp.hbarAmount > 0 ? this.historyAutoTopUp.hbarAmount : DEFAULT_HISTORY_TOP_UP_HBAR;
|
|
793
|
-
await this.purchaseCreditsWithHbar({
|
|
794
|
-
accountId: this.historyAutoTopUp.accountId,
|
|
795
|
-
privateKey: this.historyAutoTopUp.privateKey,
|
|
796
|
-
hbarAmount,
|
|
797
|
-
memo: this.historyAutoTopUp.memo ?? "registry-broker-client:chat-history-topup",
|
|
798
|
-
metadata: {
|
|
799
|
-
purpose: "chat-history",
|
|
800
|
-
reason
|
|
801
|
-
}
|
|
802
|
-
});
|
|
803
|
-
}
|
|
804
|
-
async ensureCreditsForRegistration(payload, autoTopUp) {
|
|
805
|
-
const details = autoTopUp ?? null;
|
|
806
|
-
if (!details) {
|
|
807
|
-
return;
|
|
808
|
-
}
|
|
809
|
-
if (!details.accountId || !details.accountId.trim()) {
|
|
810
|
-
throw new Error("autoTopUp.accountId is required");
|
|
811
|
-
}
|
|
812
|
-
if (!details.privateKey || !details.privateKey.trim()) {
|
|
813
|
-
throw new Error("autoTopUp.privateKey is required");
|
|
814
|
-
}
|
|
815
|
-
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
816
|
-
const quote = await this.getRegistrationQuote(payload);
|
|
817
|
-
const shortfall = quote.shortfallCredits ?? 0;
|
|
818
|
-
if (shortfall <= 0) {
|
|
819
|
-
return;
|
|
820
|
-
}
|
|
821
|
-
const creditsToPurchase = this.resolveCreditsToPurchase(shortfall);
|
|
822
|
-
if (creditsToPurchase <= 0) {
|
|
823
|
-
return;
|
|
824
|
-
}
|
|
825
|
-
const creditsPerHbar = quote.creditsPerHbar ?? null;
|
|
826
|
-
if (!creditsPerHbar || creditsPerHbar <= 0) {
|
|
827
|
-
throw new Error("Unable to determine credits per HBAR for auto top-up");
|
|
828
|
-
}
|
|
829
|
-
const hbarAmount = this.calculateHbarAmount(
|
|
830
|
-
creditsToPurchase,
|
|
831
|
-
creditsPerHbar
|
|
832
|
-
);
|
|
833
|
-
await this.purchaseCreditsWithHbar({
|
|
834
|
-
accountId: details.accountId.trim(),
|
|
835
|
-
privateKey: details.privateKey.trim(),
|
|
836
|
-
hbarAmount,
|
|
837
|
-
memo: details.memo ?? "Registry Broker auto top-up",
|
|
838
|
-
metadata: {
|
|
839
|
-
shortfallCredits: shortfall,
|
|
840
|
-
requiredCredits: quote.requiredCredits,
|
|
841
|
-
purchasedCredits: creditsToPurchase
|
|
842
|
-
}
|
|
843
|
-
});
|
|
844
|
-
}
|
|
845
|
-
const finalQuote = await this.getRegistrationQuote(payload);
|
|
846
|
-
if ((finalQuote.shortfallCredits ?? 0) > 0) {
|
|
847
|
-
throw new Error("Unable to purchase sufficient credits for registration");
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
extractInsufficientCreditsDetails(error) {
|
|
851
|
-
if (!(error instanceof RegistryBrokerError) || error.status !== 402) {
|
|
852
|
-
return null;
|
|
853
|
-
}
|
|
854
|
-
const body = error.body;
|
|
855
|
-
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
856
|
-
return null;
|
|
857
|
-
}
|
|
858
|
-
const maybeShortfall = body["shortfallCredits"];
|
|
859
|
-
if (typeof maybeShortfall !== "number" || maybeShortfall <= 0) {
|
|
860
|
-
return null;
|
|
861
|
-
}
|
|
862
|
-
return { shortfallCredits: maybeShortfall };
|
|
863
|
-
}
|
|
864
|
-
async createLedgerChallenge(payload) {
|
|
865
|
-
const resolvedNetwork = canonicalizeLedgerNetwork(payload.network);
|
|
866
|
-
const network = resolvedNetwork.kind === "hedera" ? resolvedNetwork.hederaNetwork ?? resolvedNetwork.canonical : resolvedNetwork.canonical;
|
|
867
|
-
const raw = await this.requestJson("/auth/ledger/challenge", {
|
|
868
|
-
method: "POST",
|
|
869
|
-
headers: { "content-type": "application/json" },
|
|
870
|
-
body: {
|
|
871
|
-
accountId: payload.accountId,
|
|
872
|
-
network
|
|
873
|
-
}
|
|
874
|
-
});
|
|
875
|
-
return this.parseWithSchema(
|
|
876
|
-
raw,
|
|
877
|
-
ledgerChallengeResponseSchema,
|
|
878
|
-
"ledger challenge response"
|
|
879
|
-
);
|
|
880
|
-
}
|
|
881
|
-
async verifyLedgerChallenge(payload) {
|
|
882
|
-
const resolvedNetwork = canonicalizeLedgerNetwork(payload.network);
|
|
883
|
-
const network = resolvedNetwork.kind === "hedera" ? resolvedNetwork.hederaNetwork ?? resolvedNetwork.canonical : resolvedNetwork.canonical;
|
|
884
|
-
const body = {
|
|
885
|
-
challengeId: payload.challengeId,
|
|
886
|
-
accountId: payload.accountId,
|
|
887
|
-
network,
|
|
888
|
-
signature: payload.signature
|
|
889
|
-
};
|
|
890
|
-
if (payload.signatureKind) {
|
|
891
|
-
body.signatureKind = payload.signatureKind;
|
|
892
|
-
}
|
|
893
|
-
if (payload.publicKey) {
|
|
894
|
-
body.publicKey = payload.publicKey;
|
|
895
|
-
}
|
|
896
|
-
if (typeof payload.expiresInMinutes === "number") {
|
|
897
|
-
body.expiresInMinutes = payload.expiresInMinutes;
|
|
38
|
+
return this.parseFromTransactionInternals(transaction);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
return {
|
|
41
|
+
type: "UNKNOWN",
|
|
42
|
+
humanReadableType: "Unknown Schedule Transaction"
|
|
43
|
+
};
|
|
898
44
|
}
|
|
899
|
-
const raw = await this.requestJson("/auth/ledger/verify", {
|
|
900
|
-
method: "POST",
|
|
901
|
-
headers: { "content-type": "application/json" },
|
|
902
|
-
body
|
|
903
|
-
});
|
|
904
|
-
const result = this.parseWithSchema(
|
|
905
|
-
raw,
|
|
906
|
-
ledgerVerifyResponseSchema,
|
|
907
|
-
"ledger verification response"
|
|
908
|
-
);
|
|
909
|
-
this.setLedgerApiKey(result.key);
|
|
910
|
-
return result;
|
|
911
|
-
}
|
|
912
|
-
async authenticateWithLedger(options) {
|
|
913
|
-
const challenge = await this.createLedgerChallenge({
|
|
914
|
-
accountId: options.accountId,
|
|
915
|
-
network: options.network
|
|
916
|
-
});
|
|
917
|
-
const signed = await this.resolveLedgerAuthSignature(
|
|
918
|
-
challenge.message,
|
|
919
|
-
options
|
|
920
|
-
);
|
|
921
|
-
const verification = await this.verifyLedgerChallenge({
|
|
922
|
-
challengeId: challenge.challengeId,
|
|
923
|
-
accountId: options.accountId,
|
|
924
|
-
network: options.network,
|
|
925
|
-
signature: signed.signature,
|
|
926
|
-
signatureKind: signed.signatureKind,
|
|
927
|
-
publicKey: signed.publicKey,
|
|
928
|
-
expiresInMinutes: options.expiresInMinutes
|
|
929
|
-
});
|
|
930
|
-
return verification;
|
|
931
45
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
if (!options.signer || typeof options.signer.sign !== "function") {
|
|
941
|
-
throw new Error(
|
|
942
|
-
"Ledger authentication requires a Hedera Signer or custom sign function."
|
|
46
|
+
/**
|
|
47
|
+
* Parse schedule transaction from protobuf TransactionBody
|
|
48
|
+
* Handles all schedule operations from decoded protobuf data
|
|
49
|
+
*/
|
|
50
|
+
static parseFromProtobufTxBody(txBody) {
|
|
51
|
+
if (txBody.scheduleCreate) {
|
|
52
|
+
const scheduleCreate = this.parseScheduleCreateFromProto(
|
|
53
|
+
txBody.scheduleCreate
|
|
943
54
|
);
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
if (
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
}
|
|
966
|
-
async authenticateWithLedgerCredentials(options) {
|
|
967
|
-
const {
|
|
968
|
-
accountId,
|
|
969
|
-
network,
|
|
970
|
-
signer,
|
|
971
|
-
sign,
|
|
972
|
-
hederaPrivateKey,
|
|
973
|
-
evmPrivateKey,
|
|
974
|
-
expiresInMinutes,
|
|
975
|
-
setAccountHeader = true,
|
|
976
|
-
label,
|
|
977
|
-
logger
|
|
978
|
-
} = options;
|
|
979
|
-
const resolvedNetwork = canonicalizeLedgerNetwork(network);
|
|
980
|
-
const labelSuffix = label ? ` for ${label}` : "";
|
|
981
|
-
const networkPayload = resolvedNetwork.canonical;
|
|
982
|
-
const authOptions = {
|
|
983
|
-
accountId,
|
|
984
|
-
network: networkPayload,
|
|
985
|
-
expiresInMinutes
|
|
986
|
-
};
|
|
987
|
-
if (sign) {
|
|
988
|
-
authOptions.sign = sign;
|
|
989
|
-
} else if (signer) {
|
|
990
|
-
authOptions.signer = signer;
|
|
991
|
-
} else if (hederaPrivateKey) {
|
|
992
|
-
if (resolvedNetwork.kind !== "hedera" || !resolvedNetwork.hederaNetwork) {
|
|
993
|
-
throw new Error(
|
|
994
|
-
"hederaPrivateKey can only be used with hedera:mainnet or hedera:testnet networks."
|
|
995
|
-
);
|
|
996
|
-
}
|
|
997
|
-
authOptions.signer = createPrivateKeySigner({
|
|
998
|
-
accountId,
|
|
999
|
-
privateKey: hederaPrivateKey,
|
|
1000
|
-
network: resolvedNetwork.hederaNetwork
|
|
1001
|
-
});
|
|
1002
|
-
} else if (evmPrivateKey) {
|
|
1003
|
-
if (resolvedNetwork.kind !== "evm") {
|
|
1004
|
-
throw new Error(
|
|
1005
|
-
"evmPrivateKey can only be used with CAIP-2 EVM networks (eip155:<chainId>)."
|
|
1006
|
-
);
|
|
1007
|
-
}
|
|
1008
|
-
const formattedKey = evmPrivateKey.startsWith("0x") ? evmPrivateKey : `0x${evmPrivateKey}`;
|
|
1009
|
-
const account = privateKeyToAccount(formattedKey);
|
|
1010
|
-
authOptions.sign = async (message) => ({
|
|
1011
|
-
signature: await account.signMessage({ message }),
|
|
1012
|
-
signatureKind: "evm",
|
|
1013
|
-
publicKey: account.publicKey
|
|
1014
|
-
});
|
|
1015
|
-
} else {
|
|
1016
|
-
throw new Error(
|
|
1017
|
-
"Provide a signer, sign function, hederaPrivateKey, or evmPrivateKey to authenticate with the ledger."
|
|
55
|
+
if (scheduleCreate) {
|
|
56
|
+
return {
|
|
57
|
+
type: "SCHEDULECREATE",
|
|
58
|
+
humanReadableType: "Schedule Create",
|
|
59
|
+
scheduleCreate
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (txBody.scheduleSign) {
|
|
64
|
+
const scheduleSign = this.parseScheduleSignFromProto(txBody.scheduleSign);
|
|
65
|
+
if (scheduleSign) {
|
|
66
|
+
return {
|
|
67
|
+
type: "SCHEDULESIGN",
|
|
68
|
+
humanReadableType: "Schedule Sign",
|
|
69
|
+
scheduleSign
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (txBody.scheduleDelete) {
|
|
74
|
+
const scheduleDelete = this.parseScheduleDeleteFromProto(
|
|
75
|
+
txBody.scheduleDelete
|
|
1018
76
|
);
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
this.setDefaultHeader("x-account-id", verification.accountId);
|
|
1026
|
-
}
|
|
1027
|
-
logger?.info?.(
|
|
1028
|
-
`Ledger authentication complete${labelSuffix}. Issued key prefix: ${verification.apiKey.prefix}…${verification.apiKey.lastFour}`
|
|
1029
|
-
);
|
|
1030
|
-
return verification;
|
|
1031
|
-
}
|
|
1032
|
-
async listProtocols() {
|
|
1033
|
-
const raw = await this.requestJson("/protocols", {
|
|
1034
|
-
method: "GET"
|
|
1035
|
-
});
|
|
1036
|
-
return this.parseWithSchema(
|
|
1037
|
-
raw,
|
|
1038
|
-
protocolsResponseSchema,
|
|
1039
|
-
"protocols response"
|
|
1040
|
-
);
|
|
1041
|
-
}
|
|
1042
|
-
async detectProtocol(message) {
|
|
1043
|
-
const raw = await this.requestJson("/detect-protocol", {
|
|
1044
|
-
method: "POST",
|
|
1045
|
-
body: { message },
|
|
1046
|
-
headers: { "content-type": "application/json" }
|
|
1047
|
-
});
|
|
1048
|
-
return this.parseWithSchema(
|
|
1049
|
-
raw,
|
|
1050
|
-
detectProtocolResponseSchema,
|
|
1051
|
-
"detect protocol response"
|
|
1052
|
-
);
|
|
1053
|
-
}
|
|
1054
|
-
async registrySearchByNamespace(registry, query) {
|
|
1055
|
-
const params = new URLSearchParams();
|
|
1056
|
-
if (query) {
|
|
1057
|
-
params.set("q", query);
|
|
1058
|
-
}
|
|
1059
|
-
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
1060
|
-
const raw = await this.requestJson(
|
|
1061
|
-
`/registries/${encodeURIComponent(registry)}/search${suffix}`,
|
|
1062
|
-
{
|
|
1063
|
-
method: "GET"
|
|
1064
|
-
}
|
|
1065
|
-
);
|
|
1066
|
-
return this.parseWithSchema(
|
|
1067
|
-
raw,
|
|
1068
|
-
registrySearchByNamespaceSchema,
|
|
1069
|
-
"registry search response"
|
|
1070
|
-
);
|
|
1071
|
-
}
|
|
1072
|
-
async vectorSearch(request) {
|
|
1073
|
-
const raw = await this.requestJson("/search", {
|
|
1074
|
-
method: "POST",
|
|
1075
|
-
body: request,
|
|
1076
|
-
headers: { "content-type": "application/json" }
|
|
1077
|
-
});
|
|
1078
|
-
return this.parseWithSchema(
|
|
1079
|
-
raw,
|
|
1080
|
-
vectorSearchResponseSchema,
|
|
1081
|
-
"vector search response"
|
|
1082
|
-
);
|
|
1083
|
-
}
|
|
1084
|
-
async adaptersDetailed() {
|
|
1085
|
-
const raw = await this.requestJson("/adapters/details", {
|
|
1086
|
-
method: "GET"
|
|
1087
|
-
});
|
|
1088
|
-
return this.parseWithSchema(
|
|
1089
|
-
raw,
|
|
1090
|
-
adapterDetailsResponseSchema,
|
|
1091
|
-
"adapter details response"
|
|
1092
|
-
);
|
|
1093
|
-
}
|
|
1094
|
-
async websocketStats() {
|
|
1095
|
-
const raw = await this.requestJson("/websocket/stats", {
|
|
1096
|
-
method: "GET"
|
|
1097
|
-
});
|
|
1098
|
-
return this.parseWithSchema(
|
|
1099
|
-
raw,
|
|
1100
|
-
websocketStatsResponseSchema,
|
|
1101
|
-
"websocket stats response"
|
|
1102
|
-
);
|
|
1103
|
-
}
|
|
1104
|
-
async metricsSummary() {
|
|
1105
|
-
const raw = await this.requestJson("/metrics", {
|
|
1106
|
-
method: "GET"
|
|
1107
|
-
});
|
|
1108
|
-
return this.parseWithSchema(
|
|
1109
|
-
raw,
|
|
1110
|
-
metricsSummaryResponseSchema,
|
|
1111
|
-
"metrics summary response"
|
|
1112
|
-
);
|
|
1113
|
-
}
|
|
1114
|
-
async validateUaid(uaid) {
|
|
1115
|
-
const raw = await this.requestJson(
|
|
1116
|
-
`/uaids/validate/${encodeURIComponent(uaid)}`,
|
|
1117
|
-
{
|
|
1118
|
-
method: "GET"
|
|
1119
|
-
}
|
|
1120
|
-
);
|
|
1121
|
-
return this.parseWithSchema(
|
|
1122
|
-
raw,
|
|
1123
|
-
uaidValidationResponseSchema,
|
|
1124
|
-
"UAID validation response"
|
|
1125
|
-
);
|
|
1126
|
-
}
|
|
1127
|
-
async getUaidConnectionStatus(uaid) {
|
|
1128
|
-
const raw = await this.requestJson(
|
|
1129
|
-
`/uaids/connections/${encodeURIComponent(uaid)}/status`,
|
|
1130
|
-
{
|
|
1131
|
-
method: "GET"
|
|
77
|
+
if (scheduleDelete) {
|
|
78
|
+
return {
|
|
79
|
+
type: "SCHEDULEDELETE",
|
|
80
|
+
humanReadableType: "Schedule Delete",
|
|
81
|
+
scheduleDelete
|
|
82
|
+
};
|
|
1132
83
|
}
|
|
1133
|
-
);
|
|
1134
|
-
return this.parseWithSchema(
|
|
1135
|
-
raw,
|
|
1136
|
-
uaidConnectionStatusSchema,
|
|
1137
|
-
"UAID connection status"
|
|
1138
|
-
);
|
|
1139
|
-
}
|
|
1140
|
-
async closeUaidConnection(uaid) {
|
|
1141
|
-
await this.request(`/uaids/connections/${encodeURIComponent(uaid)}`, {
|
|
1142
|
-
method: "DELETE"
|
|
1143
|
-
});
|
|
1144
|
-
}
|
|
1145
|
-
async dashboardStats() {
|
|
1146
|
-
const raw = await this.requestJson("/dashboard/stats", {
|
|
1147
|
-
method: "GET"
|
|
1148
|
-
});
|
|
1149
|
-
return this.parseWithSchema(
|
|
1150
|
-
raw,
|
|
1151
|
-
dashboardStatsResponseSchema,
|
|
1152
|
-
"dashboard stats response"
|
|
1153
|
-
);
|
|
1154
|
-
}
|
|
1155
|
-
async adapters() {
|
|
1156
|
-
const raw = await this.requestJson("/adapters", {
|
|
1157
|
-
method: "GET"
|
|
1158
|
-
});
|
|
1159
|
-
return this.parseWithSchema(
|
|
1160
|
-
raw,
|
|
1161
|
-
adaptersResponseSchema,
|
|
1162
|
-
"adapters response"
|
|
1163
|
-
);
|
|
1164
|
-
}
|
|
1165
|
-
async facets(adapter) {
|
|
1166
|
-
const params = new URLSearchParams();
|
|
1167
|
-
if (adapter) {
|
|
1168
|
-
params.set("adapter", adapter);
|
|
1169
84
|
}
|
|
1170
|
-
|
|
1171
|
-
const raw = await this.requestJson(`/search/facets${suffix}`, {
|
|
1172
|
-
method: "GET"
|
|
1173
|
-
});
|
|
1174
|
-
return this.parseWithSchema(
|
|
1175
|
-
raw,
|
|
1176
|
-
searchFacetsResponseSchema,
|
|
1177
|
-
"search facets response"
|
|
1178
|
-
);
|
|
85
|
+
return {};
|
|
1179
86
|
}
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
if ("agentUrl" in payload && payload.agentUrl) {
|
|
1186
|
-
body.agentUrl = payload.agentUrl;
|
|
1187
|
-
}
|
|
1188
|
-
if (payload.auth) {
|
|
1189
|
-
body.auth = serialiseAuthConfig(payload.auth);
|
|
1190
|
-
}
|
|
1191
|
-
if (payload.historyTtlSeconds !== void 0) {
|
|
1192
|
-
body.historyTtlSeconds = payload.historyTtlSeconds;
|
|
1193
|
-
}
|
|
1194
|
-
if (payload.encryptionRequested !== void 0) {
|
|
1195
|
-
body.encryptionRequested = payload.encryptionRequested;
|
|
1196
|
-
}
|
|
1197
|
-
if (payload.senderUaid) {
|
|
1198
|
-
body.senderUaid = payload.senderUaid;
|
|
1199
|
-
}
|
|
87
|
+
/**
|
|
88
|
+
* Extract schedule data from Transaction internal fields
|
|
89
|
+
* This handles cases where data is stored in Transaction object internals
|
|
90
|
+
*/
|
|
91
|
+
static parseFromTransactionInternals(transaction) {
|
|
1200
92
|
try {
|
|
1201
|
-
const
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
93
|
+
const tx = transaction;
|
|
94
|
+
if (hasTransactionType(transaction, "scheduleCreate")) {
|
|
95
|
+
const scheduleCreate = {
|
|
96
|
+
scheduledTransactionBody: Buffer.from(
|
|
97
|
+
tx._scheduledTransaction
|
|
98
|
+
).toString("base64"),
|
|
99
|
+
memo: tx._scheduleMemo,
|
|
100
|
+
adminKey: tx._adminKey ? parseKey(tx._adminKey) : void 0,
|
|
101
|
+
payerAccountId: tx._payerAccountId?.toString(),
|
|
102
|
+
expirationTime: tx._expirationTime?.toString(),
|
|
103
|
+
waitForExpiry: tx._waitForExpiry || false
|
|
104
|
+
};
|
|
105
|
+
return {
|
|
106
|
+
type: "SCHEDULECREATE",
|
|
107
|
+
humanReadableType: "Schedule Create",
|
|
108
|
+
scheduleCreate
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (hasTransactionType(transaction, "scheduleSign")) {
|
|
112
|
+
const scheduleSign = {
|
|
113
|
+
scheduleId: tx._scheduleId.toString()
|
|
114
|
+
};
|
|
115
|
+
return {
|
|
116
|
+
type: "SCHEDULESIGN",
|
|
117
|
+
humanReadableType: "Schedule Sign",
|
|
118
|
+
scheduleSign
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (hasTransactionType(transaction, "scheduleDelete")) {
|
|
122
|
+
const scheduleDelete = {
|
|
123
|
+
scheduleId: tx._scheduleId.toString()
|
|
124
|
+
};
|
|
125
|
+
return {
|
|
126
|
+
type: "SCHEDULEDELETE",
|
|
127
|
+
humanReadableType: "Schedule Delete",
|
|
128
|
+
scheduleDelete
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return {};
|
|
1211
132
|
} catch (error) {
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
}
|
|
1230
|
-
if (
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
133
|
+
return {};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Parse Schedule Create from protobuf data
|
|
138
|
+
*/
|
|
139
|
+
static parseScheduleCreateFromProto(body) {
|
|
140
|
+
if (!body) return void 0;
|
|
141
|
+
const data = {};
|
|
142
|
+
if (body.scheduledTransactionBody) {
|
|
143
|
+
const schedBytes = proto.SchedulableTransactionBody.encode(
|
|
144
|
+
proto.SchedulableTransactionBody.create(body.scheduledTransactionBody)
|
|
145
|
+
).finish();
|
|
146
|
+
data.scheduledTransactionBody = Buffer.from(schedBytes).toString("base64");
|
|
147
|
+
}
|
|
148
|
+
if (body.memo) {
|
|
149
|
+
data.memo = body.memo;
|
|
150
|
+
}
|
|
151
|
+
if (body.adminKey) {
|
|
152
|
+
data.adminKey = parseKey(body.adminKey);
|
|
153
|
+
}
|
|
154
|
+
if (body.payerAccountID) {
|
|
155
|
+
data.payerAccountId = new AccountId(
|
|
156
|
+
body.payerAccountID.shardNum ?? 0,
|
|
157
|
+
body.payerAccountID.realmNum ?? 0,
|
|
158
|
+
body.payerAccountID.accountNum ?? 0
|
|
159
|
+
).toString();
|
|
160
|
+
}
|
|
161
|
+
if (body.expirationTime?.seconds) {
|
|
162
|
+
data.expirationTime = `${Long.fromValue(
|
|
163
|
+
body.expirationTime.seconds
|
|
164
|
+
).toString()}.${body.expirationTime.nanos ?? 0}`;
|
|
165
|
+
}
|
|
166
|
+
if (body.waitForExpiry !== void 0) {
|
|
167
|
+
data.waitForExpiry = body.waitForExpiry;
|
|
168
|
+
}
|
|
169
|
+
return data;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Parse Schedule Sign from protobuf data
|
|
173
|
+
*/
|
|
174
|
+
static parseScheduleSignFromProto(body) {
|
|
175
|
+
if (!body) return void 0;
|
|
176
|
+
const data = {};
|
|
177
|
+
if (body.scheduleID) {
|
|
178
|
+
data.scheduleId = new ScheduleId(
|
|
179
|
+
body.scheduleID.shardNum ?? 0,
|
|
180
|
+
body.scheduleID.realmNum ?? 0,
|
|
181
|
+
body.scheduleID.scheduleNum ?? 0
|
|
182
|
+
).toString();
|
|
183
|
+
}
|
|
184
|
+
return data;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Parse Schedule Delete from protobuf data
|
|
188
|
+
*/
|
|
189
|
+
static parseScheduleDeleteFromProto(body) {
|
|
190
|
+
if (!body) return void 0;
|
|
191
|
+
const data = {};
|
|
192
|
+
if (body.scheduleID) {
|
|
193
|
+
data.scheduleId = new ScheduleId(
|
|
194
|
+
body.scheduleID.shardNum ?? 0,
|
|
195
|
+
body.scheduleID.realmNum ?? 0,
|
|
196
|
+
body.scheduleID.scheduleNum ?? 0
|
|
197
|
+
).toString();
|
|
198
|
+
}
|
|
199
|
+
return data;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Legacy method: Parse schedule create transaction
|
|
203
|
+
* @deprecated Use parseScheduleTransaction instead
|
|
204
|
+
*/
|
|
205
|
+
static parseScheduleCreate(transaction) {
|
|
1264
206
|
try {
|
|
1265
|
-
const
|
|
1266
|
-
|
|
1267
|
-
senderUaid: options.senderUaid,
|
|
1268
|
-
historyTtlSeconds: options.historyTtlSeconds,
|
|
1269
|
-
handshakeTimeoutMs: options.encryption?.handshakeTimeoutMs,
|
|
1270
|
-
pollIntervalMs: options.encryption?.pollIntervalMs,
|
|
1271
|
-
onSessionCreated: (sessionId) => {
|
|
1272
|
-
options.onSessionCreated?.(sessionId);
|
|
1273
|
-
},
|
|
1274
|
-
auth: options.auth
|
|
1275
|
-
});
|
|
1276
|
-
return handle;
|
|
207
|
+
const result = this.parseScheduleTransaction(transaction);
|
|
208
|
+
return result.scheduleCreate || null;
|
|
1277
209
|
} catch (error) {
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
throw error;
|
|
1281
|
-
}
|
|
1282
|
-
return this.createPlaintextConversationHandle(
|
|
1283
|
-
error.sessionId,
|
|
1284
|
-
error.summary ?? null,
|
|
1285
|
-
options.auth
|
|
1286
|
-
);
|
|
1287
|
-
}
|
|
1288
|
-
throw error;
|
|
210
|
+
console.warn("[ScheduleParser] Failed to parse schedule create:", error);
|
|
211
|
+
return null;
|
|
1289
212
|
}
|
|
1290
213
|
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
214
|
+
/**
|
|
215
|
+
* Legacy method: Parse schedule sign transaction
|
|
216
|
+
* @deprecated Use parseScheduleTransaction instead
|
|
217
|
+
*/
|
|
218
|
+
static parseScheduleSign(transaction) {
|
|
1296
219
|
try {
|
|
1297
|
-
const
|
|
1298
|
-
|
|
1299
|
-
responderUaid: options.responderUaid,
|
|
1300
|
-
handshakeTimeoutMs: options.encryption?.handshakeTimeoutMs,
|
|
1301
|
-
pollIntervalMs: options.encryption?.pollIntervalMs
|
|
1302
|
-
});
|
|
1303
|
-
return handle;
|
|
220
|
+
const result = this.parseScheduleTransaction(transaction);
|
|
221
|
+
return result.scheduleSign || null;
|
|
1304
222
|
} catch (error) {
|
|
1305
|
-
|
|
1306
|
-
return this.createPlaintextConversationHandle(options.sessionId, null);
|
|
1307
|
-
}
|
|
1308
|
-
throw error;
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
async fetchHistorySnapshot(sessionId, options) {
|
|
1312
|
-
if (!sessionId || sessionId.trim().length === 0) {
|
|
1313
|
-
throw new Error("sessionId is required to fetch chat history");
|
|
1314
|
-
}
|
|
1315
|
-
const raw = await this.requestJson(
|
|
1316
|
-
`/chat/session/${encodeURIComponent(sessionId)}/history`,
|
|
1317
|
-
{
|
|
1318
|
-
method: "GET"
|
|
1319
|
-
}
|
|
1320
|
-
);
|
|
1321
|
-
const snapshot = this.parseWithSchema(
|
|
1322
|
-
raw,
|
|
1323
|
-
chatHistorySnapshotResponseSchema,
|
|
1324
|
-
"chat history snapshot response"
|
|
1325
|
-
);
|
|
1326
|
-
return this.attachDecryptedHistory(sessionId, snapshot, options);
|
|
1327
|
-
}
|
|
1328
|
-
attachDecryptedHistory(sessionId, snapshot, options) {
|
|
1329
|
-
const shouldDecrypt = options?.decrypt !== void 0 ? options.decrypt : this.encryptionOptions?.autoDecryptHistory === true;
|
|
1330
|
-
if (!shouldDecrypt) {
|
|
1331
|
-
return snapshot;
|
|
1332
|
-
}
|
|
1333
|
-
const context = this.resolveDecryptionContext(sessionId, options);
|
|
1334
|
-
if (!context) {
|
|
1335
|
-
throw new Error(
|
|
1336
|
-
"Unable to decrypt chat history: encryption context unavailable"
|
|
1337
|
-
);
|
|
1338
|
-
}
|
|
1339
|
-
const decryptedHistory = snapshot.history.map((entry) => ({
|
|
1340
|
-
entry,
|
|
1341
|
-
plaintext: this.decryptHistoryEntryFromContext(sessionId, entry, context)
|
|
1342
|
-
}));
|
|
1343
|
-
return { ...snapshot, decryptedHistory };
|
|
1344
|
-
}
|
|
1345
|
-
registerConversationContext(context) {
|
|
1346
|
-
const normalized = {
|
|
1347
|
-
sessionId: context.sessionId,
|
|
1348
|
-
sharedSecret: Buffer.from(context.sharedSecret),
|
|
1349
|
-
identity: context.identity ? { ...context.identity } : void 0
|
|
1350
|
-
};
|
|
1351
|
-
const entries = this.conversationContexts.get(context.sessionId) ?? [];
|
|
1352
|
-
const existingIndex = entries.findIndex(
|
|
1353
|
-
(existing) => this.identitiesMatch(existing.identity, normalized.identity)
|
|
1354
|
-
);
|
|
1355
|
-
if (existingIndex >= 0) {
|
|
1356
|
-
entries[existingIndex] = normalized;
|
|
1357
|
-
} else {
|
|
1358
|
-
entries.push(normalized);
|
|
1359
|
-
}
|
|
1360
|
-
this.conversationContexts.set(context.sessionId, entries);
|
|
1361
|
-
}
|
|
1362
|
-
// Exposed for EncryptedChatManager to persist decryption context
|
|
1363
|
-
registerConversationContextForEncryption(context) {
|
|
1364
|
-
this.registerConversationContext(context);
|
|
1365
|
-
}
|
|
1366
|
-
resolveDecryptionContext(sessionId, options) {
|
|
1367
|
-
if (options?.sharedSecret) {
|
|
1368
|
-
return {
|
|
1369
|
-
sessionId,
|
|
1370
|
-
sharedSecret: this.normalizeSharedSecret(options.sharedSecret),
|
|
1371
|
-
identity: options.identity
|
|
1372
|
-
};
|
|
1373
|
-
}
|
|
1374
|
-
const contexts = this.conversationContexts.get(sessionId);
|
|
1375
|
-
if (!contexts || contexts.length === 0) {
|
|
223
|
+
console.warn("[ScheduleParser] Failed to parse schedule sign:", error);
|
|
1376
224
|
return null;
|
|
1377
225
|
}
|
|
1378
|
-
if (options?.identity) {
|
|
1379
|
-
const match = contexts.find(
|
|
1380
|
-
(context) => this.identitiesMatch(context.identity, options.identity)
|
|
1381
|
-
);
|
|
1382
|
-
if (match) {
|
|
1383
|
-
return match;
|
|
1384
|
-
}
|
|
1385
|
-
}
|
|
1386
|
-
return contexts[0];
|
|
1387
226
|
}
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
const secret = Buffer.from(context.sharedSecret);
|
|
227
|
+
/**
|
|
228
|
+
* Legacy method: Parse schedule delete transaction
|
|
229
|
+
* @deprecated Use parseScheduleTransaction instead
|
|
230
|
+
*/
|
|
231
|
+
static parseScheduleDelete(transaction) {
|
|
1394
232
|
try {
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
} catch (_error) {
|
|
233
|
+
const result = this.parseScheduleTransaction(transaction);
|
|
234
|
+
return result.scheduleDelete || null;
|
|
235
|
+
} catch (error) {
|
|
236
|
+
console.warn("[ScheduleParser] Failed to parse schedule delete:", error);
|
|
1400
237
|
return null;
|
|
1401
238
|
}
|
|
1402
239
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
if (!a || !b) {
|
|
1408
|
-
return false;
|
|
1409
|
-
}
|
|
1410
|
-
if (a.uaid && b.uaid && a.uaid.toLowerCase() === b.uaid.toLowerCase()) {
|
|
1411
|
-
return true;
|
|
1412
|
-
}
|
|
1413
|
-
if (a.ledgerAccountId && b.ledgerAccountId && a.ledgerAccountId.toLowerCase() === b.ledgerAccountId.toLowerCase()) {
|
|
1414
|
-
return true;
|
|
1415
|
-
}
|
|
1416
|
-
if (a.userId && b.userId && a.userId === b.userId) {
|
|
1417
|
-
return true;
|
|
1418
|
-
}
|
|
1419
|
-
if (a.email && b.email && a.email.toLowerCase() === b.email.toLowerCase()) {
|
|
1420
|
-
return true;
|
|
1421
|
-
}
|
|
1422
|
-
return false;
|
|
1423
|
-
}
|
|
1424
|
-
identityMatchesRecipient(recipient, identity) {
|
|
1425
|
-
if (identity.uaid && recipient.uaid?.toLowerCase() === identity.uaid.toLowerCase()) {
|
|
1426
|
-
return true;
|
|
1427
|
-
}
|
|
1428
|
-
if (identity.ledgerAccountId && recipient.ledgerAccountId?.toLowerCase() === identity.ledgerAccountId.toLowerCase()) {
|
|
1429
|
-
return true;
|
|
1430
|
-
}
|
|
1431
|
-
if (identity.userId && recipient.userId === identity.userId) {
|
|
1432
|
-
return true;
|
|
1433
|
-
}
|
|
1434
|
-
if (identity.email && recipient.email?.toLowerCase() === identity.email.toLowerCase()) {
|
|
1435
|
-
return true;
|
|
1436
|
-
}
|
|
1437
|
-
return false;
|
|
1438
|
-
}
|
|
1439
|
-
createPlaintextConversationHandle(sessionId, summary, defaultAuth) {
|
|
1440
|
-
return {
|
|
1441
|
-
sessionId,
|
|
1442
|
-
mode: "plaintext",
|
|
1443
|
-
summary: summary ?? null,
|
|
1444
|
-
send: async (options) => {
|
|
1445
|
-
const plaintext = options.plaintext;
|
|
1446
|
-
if (!plaintext || plaintext.trim().length === 0) {
|
|
1447
|
-
throw new Error("plaintext is required for chat messages");
|
|
1448
|
-
}
|
|
1449
|
-
const message = options.message ?? plaintext;
|
|
1450
|
-
return this.sendMessage({
|
|
1451
|
-
sessionId,
|
|
1452
|
-
message,
|
|
1453
|
-
streaming: options.streaming,
|
|
1454
|
-
auth: options.auth ?? defaultAuth
|
|
1455
|
-
});
|
|
1456
|
-
},
|
|
1457
|
-
decryptHistoryEntry: (entry) => entry.content
|
|
1458
|
-
};
|
|
1459
|
-
}
|
|
1460
|
-
async compactHistory(payload) {
|
|
1461
|
-
if (!payload.sessionId || payload.sessionId.trim().length === 0) {
|
|
1462
|
-
throw new Error("sessionId is required to compact chat history");
|
|
1463
|
-
}
|
|
1464
|
-
const body = {};
|
|
1465
|
-
if (typeof payload.preserveEntries === "number" && Number.isFinite(payload.preserveEntries) && payload.preserveEntries >= 0) {
|
|
1466
|
-
body.preserveEntries = Math.floor(payload.preserveEntries);
|
|
1467
|
-
}
|
|
1468
|
-
const raw = await this.requestJson(
|
|
1469
|
-
`/chat/session/${encodeURIComponent(payload.sessionId)}/compact`,
|
|
1470
|
-
{
|
|
1471
|
-
method: "POST",
|
|
1472
|
-
headers: { "content-type": "application/json" },
|
|
1473
|
-
body
|
|
1474
|
-
}
|
|
1475
|
-
);
|
|
1476
|
-
return this.parseWithSchema(
|
|
1477
|
-
raw,
|
|
1478
|
-
chatHistoryCompactionResponseSchema,
|
|
1479
|
-
"chat history compaction response"
|
|
1480
|
-
);
|
|
1481
|
-
}
|
|
1482
|
-
async fetchEncryptionStatus(sessionId) {
|
|
1483
|
-
if (!sessionId || sessionId.trim().length === 0) {
|
|
1484
|
-
throw new Error("sessionId is required for encryption status");
|
|
1485
|
-
}
|
|
1486
|
-
const raw = await this.requestJson(
|
|
1487
|
-
`/chat/session/${encodeURIComponent(sessionId)}/encryption`,
|
|
1488
|
-
{
|
|
1489
|
-
method: "GET"
|
|
1490
|
-
}
|
|
1491
|
-
);
|
|
1492
|
-
return this.parseWithSchema(
|
|
1493
|
-
raw,
|
|
1494
|
-
sessionEncryptionStatusResponseSchema,
|
|
1495
|
-
"session encryption status response"
|
|
1496
|
-
);
|
|
1497
|
-
}
|
|
1498
|
-
async postEncryptionHandshake(sessionId, payload) {
|
|
1499
|
-
if (!sessionId || sessionId.trim().length === 0) {
|
|
1500
|
-
throw new Error("sessionId is required for encryption handshake");
|
|
1501
|
-
}
|
|
1502
|
-
const raw = await this.requestJson(
|
|
1503
|
-
`/chat/session/${encodeURIComponent(sessionId)}/encryption-handshake`,
|
|
1504
|
-
{
|
|
1505
|
-
method: "POST",
|
|
1506
|
-
headers: { "content-type": "application/json" },
|
|
1507
|
-
body: {
|
|
1508
|
-
role: payload.role,
|
|
1509
|
-
keyType: payload.keyType,
|
|
1510
|
-
ephemeralPublicKey: payload.ephemeralPublicKey,
|
|
1511
|
-
longTermPublicKey: payload.longTermPublicKey,
|
|
1512
|
-
signature: payload.signature,
|
|
1513
|
-
uaid: payload.uaid,
|
|
1514
|
-
userId: payload.userId,
|
|
1515
|
-
ledgerAccountId: payload.ledgerAccountId,
|
|
1516
|
-
metadata: payload.metadata
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
);
|
|
1520
|
-
const response = this.parseWithSchema(
|
|
1521
|
-
raw,
|
|
1522
|
-
encryptionHandshakeResponseSchema,
|
|
1523
|
-
"encryption handshake response"
|
|
1524
|
-
);
|
|
1525
|
-
return response.handshake;
|
|
1526
|
-
}
|
|
1527
|
-
async registerEncryptionKey(payload) {
|
|
1528
|
-
const raw = await this.requestJson("/encryption/keys", {
|
|
1529
|
-
method: "POST",
|
|
1530
|
-
headers: { "content-type": "application/json" },
|
|
1531
|
-
body: payload
|
|
1532
|
-
});
|
|
1533
|
-
return this.parseWithSchema(
|
|
1534
|
-
raw,
|
|
1535
|
-
registerEncryptionKeyResponseSchema,
|
|
1536
|
-
"register encryption key response"
|
|
1537
|
-
);
|
|
1538
|
-
}
|
|
1539
|
-
async sendMessage(payload) {
|
|
1540
|
-
const body = {
|
|
1541
|
-
message: payload.message
|
|
1542
|
-
};
|
|
1543
|
-
if (payload.streaming !== void 0) {
|
|
1544
|
-
body.streaming = payload.streaming;
|
|
1545
|
-
}
|
|
1546
|
-
if (payload.auth) {
|
|
1547
|
-
body.auth = serialiseAuthConfig(payload.auth);
|
|
1548
|
-
}
|
|
1549
|
-
if ("uaid" in payload) {
|
|
1550
|
-
body.uaid = payload.uaid;
|
|
1551
|
-
}
|
|
1552
|
-
if ("sessionId" in payload && payload.sessionId) {
|
|
1553
|
-
body.sessionId = payload.sessionId;
|
|
1554
|
-
}
|
|
1555
|
-
if ("agentUrl" in payload && payload.agentUrl) {
|
|
1556
|
-
body.agentUrl = payload.agentUrl;
|
|
1557
|
-
}
|
|
1558
|
-
let cipherEnvelope = payload.cipherEnvelope ?? null;
|
|
1559
|
-
if (payload.encryption) {
|
|
1560
|
-
const sessionIdForEncryption = payload.encryption.sessionId ?? (typeof body.sessionId === "string" ? body.sessionId : void 0);
|
|
1561
|
-
if (!sessionIdForEncryption) {
|
|
1562
|
-
throw new Error(
|
|
1563
|
-
"sessionId is required when using encrypted chat payloads"
|
|
1564
|
-
);
|
|
1565
|
-
}
|
|
1566
|
-
if (!payload.encryption.recipients?.length) {
|
|
1567
|
-
throw new Error("recipients are required for encrypted chat payloads");
|
|
1568
|
-
}
|
|
1569
|
-
cipherEnvelope = this.encryption.encryptCipherEnvelope({
|
|
1570
|
-
...payload.encryption,
|
|
1571
|
-
sessionId: sessionIdForEncryption
|
|
1572
|
-
});
|
|
1573
|
-
}
|
|
1574
|
-
if (cipherEnvelope) {
|
|
1575
|
-
body.cipherEnvelope = cipherEnvelope;
|
|
1576
|
-
}
|
|
1577
|
-
delete body.encryption;
|
|
1578
|
-
const raw = await this.requestJson("/chat/message", {
|
|
1579
|
-
method: "POST",
|
|
1580
|
-
body,
|
|
1581
|
-
headers: { "content-type": "application/json" }
|
|
1582
|
-
});
|
|
1583
|
-
return this.parseWithSchema(
|
|
1584
|
-
raw,
|
|
1585
|
-
sendMessageResponseSchema,
|
|
1586
|
-
"chat message response"
|
|
1587
|
-
);
|
|
1588
|
-
}
|
|
1589
|
-
async endSession(sessionId) {
|
|
1590
|
-
await this.request(`/chat/session/${encodeURIComponent(sessionId)}`, {
|
|
1591
|
-
method: "DELETE"
|
|
1592
|
-
});
|
|
1593
|
-
}
|
|
1594
|
-
async generateEncryptionKeyPair(options = {}) {
|
|
1595
|
-
this.assertNodeRuntime("generateEncryptionKeyPair");
|
|
1596
|
-
const keyType = options.keyType ?? "secp256k1";
|
|
1597
|
-
if (keyType !== "secp256k1") {
|
|
1598
|
-
throw new Error("Only secp256k1 key generation is supported currently");
|
|
1599
|
-
}
|
|
1600
|
-
const privateKeyBytes = randomBytes(32);
|
|
1601
|
-
const privateKey = Buffer.from(privateKeyBytes).toString("hex");
|
|
1602
|
-
const publicKeyBytes = secp256k1.getPublicKey(privateKeyBytes, true);
|
|
1603
|
-
const publicKey = Buffer.from(publicKeyBytes).toString("hex");
|
|
1604
|
-
const envVar = options.envVar ?? "RB_ENCRYPTION_PRIVATE_KEY";
|
|
1605
|
-
const resolvedPath = options.envPath ? path.resolve(options.envPath) : void 0;
|
|
1606
|
-
if (resolvedPath) {
|
|
1607
|
-
const fsModule = getFs();
|
|
1608
|
-
if (!fsModule) {
|
|
1609
|
-
throw new Error(
|
|
1610
|
-
"File system module is not available; cannot write encryption key env file"
|
|
1611
|
-
);
|
|
1612
|
-
}
|
|
1613
|
-
const envLine = `${envVar}=${privateKey}`;
|
|
1614
|
-
if (fsModule.existsSync(resolvedPath)) {
|
|
1615
|
-
const content = fsModule.readFileSync(resolvedPath, "utf-8");
|
|
1616
|
-
const lineRegex = new RegExp(`^${envVar}=.*$`, "m");
|
|
1617
|
-
if (lineRegex.test(content)) {
|
|
1618
|
-
if (!options.overwrite) {
|
|
1619
|
-
throw new Error(
|
|
1620
|
-
`${envVar} already exists in ${resolvedPath}; set overwrite=true to replace it`
|
|
1621
|
-
);
|
|
1622
|
-
}
|
|
1623
|
-
const updated = content.replace(lineRegex, envLine);
|
|
1624
|
-
fsModule.writeFileSync(resolvedPath, updated);
|
|
1625
|
-
} else {
|
|
1626
|
-
const needsNewline = !content.endsWith("\n");
|
|
1627
|
-
fsModule.appendFileSync(
|
|
1628
|
-
resolvedPath,
|
|
1629
|
-
`${needsNewline ? "\n" : ""}${envLine}
|
|
1630
|
-
`
|
|
1631
|
-
);
|
|
1632
|
-
}
|
|
1633
|
-
} else {
|
|
1634
|
-
fsModule.writeFileSync(resolvedPath, `${envLine}
|
|
1635
|
-
`);
|
|
1636
|
-
}
|
|
1637
|
-
}
|
|
1638
|
-
return {
|
|
1639
|
-
privateKey,
|
|
1640
|
-
publicKey,
|
|
1641
|
-
envPath: resolvedPath,
|
|
1642
|
-
envVar
|
|
1643
|
-
};
|
|
1644
|
-
}
|
|
1645
|
-
buildUrl(path2) {
|
|
1646
|
-
const normalisedPath = path2.startsWith("/") ? path2 : `/${path2}`;
|
|
1647
|
-
return `${this.baseUrl}${normalisedPath}`;
|
|
1648
|
-
}
|
|
1649
|
-
async delay(ms, signal) {
|
|
1650
|
-
if (ms <= 0) {
|
|
1651
|
-
if (signal?.aborted) {
|
|
1652
|
-
throw createAbortError();
|
|
1653
|
-
}
|
|
1654
|
-
return;
|
|
1655
|
-
}
|
|
1656
|
-
await new Promise((resolve, reject) => {
|
|
1657
|
-
const timer = setTimeout(() => {
|
|
1658
|
-
if (signal) {
|
|
1659
|
-
signal.removeEventListener("abort", onAbort);
|
|
1660
|
-
}
|
|
1661
|
-
resolve();
|
|
1662
|
-
}, ms);
|
|
1663
|
-
const onAbort = () => {
|
|
1664
|
-
clearTimeout(timer);
|
|
1665
|
-
signal?.removeEventListener("abort", onAbort);
|
|
1666
|
-
reject(createAbortError());
|
|
1667
|
-
};
|
|
1668
|
-
if (signal) {
|
|
1669
|
-
if (signal.aborted) {
|
|
1670
|
-
clearTimeout(timer);
|
|
1671
|
-
reject(createAbortError());
|
|
1672
|
-
return;
|
|
1673
|
-
}
|
|
1674
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
1675
|
-
}
|
|
1676
|
-
});
|
|
1677
|
-
}
|
|
1678
|
-
async requestJson(path2, config) {
|
|
1679
|
-
const response = await this.request(path2, config);
|
|
1680
|
-
const contentType = response.headers?.get("content-type") ?? "";
|
|
1681
|
-
if (!JSON_CONTENT_TYPE.test(contentType)) {
|
|
1682
|
-
const body = await response.text();
|
|
1683
|
-
throw new RegistryBrokerParseError(
|
|
1684
|
-
"Expected JSON response from registry broker",
|
|
1685
|
-
body
|
|
1686
|
-
);
|
|
1687
|
-
}
|
|
1688
|
-
return await response.json();
|
|
1689
|
-
}
|
|
1690
|
-
async extractErrorBody(response) {
|
|
1691
|
-
const contentType = response.headers?.get("content-type") ?? "";
|
|
1692
|
-
if (JSON_CONTENT_TYPE.test(contentType)) {
|
|
1693
|
-
try {
|
|
1694
|
-
return await response.json();
|
|
1695
|
-
} catch (error) {
|
|
1696
|
-
return { parseError: String(error) };
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
240
|
+
/**
|
|
241
|
+
* Parse schedule info from transaction body (for scheduled transactions)
|
|
242
|
+
*/
|
|
243
|
+
static extractScheduleInfo(transaction) {
|
|
1699
244
|
try {
|
|
1700
|
-
|
|
245
|
+
const transactionBody = transaction._transactionBody;
|
|
246
|
+
if (transactionBody?.scheduleRef) {
|
|
247
|
+
return {
|
|
248
|
+
isScheduled: true,
|
|
249
|
+
scheduleRef: transactionBody.scheduleRef.toString()
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
const tx = transaction;
|
|
253
|
+
if (tx._scheduleId || tx.scheduleId) {
|
|
254
|
+
return {
|
|
255
|
+
isScheduled: true,
|
|
256
|
+
scheduleRef: (tx._scheduleId || tx.scheduleId)?.toString()
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
return { isScheduled: false };
|
|
1701
260
|
} catch (error) {
|
|
1702
|
-
return {
|
|
261
|
+
return { isScheduled: false };
|
|
1703
262
|
}
|
|
1704
263
|
}
|
|
1705
|
-
|
|
264
|
+
/**
|
|
265
|
+
* Parse a scheduled transaction body to extract the inner transaction
|
|
266
|
+
* This is used when a schedule contains another transaction to be executed
|
|
267
|
+
*/
|
|
268
|
+
static parseScheduledTransactionBody(scheduledTxBytes) {
|
|
1706
269
|
try {
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
);
|
|
1714
|
-
}
|
|
1715
|
-
}
|
|
1716
|
-
assertNodeRuntime(feature) {
|
|
1717
|
-
if (typeof process === "undefined" || !process.versions?.node) {
|
|
1718
|
-
throw new Error(`${feature} is only available in Node.js environments`);
|
|
1719
|
-
}
|
|
1720
|
-
}
|
|
1721
|
-
createEphemeralKeyPair() {
|
|
1722
|
-
this.assertNodeRuntime("generateEphemeralKeyPair");
|
|
1723
|
-
const privateKeyBytes = randomBytes(32);
|
|
1724
|
-
const publicKey = secp256k1.getPublicKey(privateKeyBytes, true);
|
|
1725
|
-
return {
|
|
1726
|
-
privateKey: Buffer.from(privateKeyBytes).toString("hex"),
|
|
1727
|
-
publicKey: Buffer.from(publicKey).toString("hex")
|
|
1728
|
-
};
|
|
1729
|
-
}
|
|
1730
|
-
deriveSharedSecret(options) {
|
|
1731
|
-
this.assertNodeRuntime("deriveSharedSecret");
|
|
1732
|
-
const privateKey = this.hexToBuffer(options.privateKey);
|
|
1733
|
-
const peerPublicKey = this.hexToBuffer(options.peerPublicKey);
|
|
1734
|
-
const shared = secp256k1.getSharedSecret(privateKey, peerPublicKey, true);
|
|
1735
|
-
return createHash("sha256").update(Buffer.from(shared)).digest();
|
|
1736
|
-
}
|
|
1737
|
-
buildCipherEnvelope(options) {
|
|
1738
|
-
this.assertNodeRuntime("encryptCipherEnvelope");
|
|
1739
|
-
const sharedSecret = this.normalizeSharedSecret(options.sharedSecret);
|
|
1740
|
-
const iv = randomBytes(12);
|
|
1741
|
-
const cipher = createCipheriv("aes-256-gcm", sharedSecret, iv);
|
|
1742
|
-
const aadSource = options.associatedData ?? options.sessionId;
|
|
1743
|
-
const associatedDataEncoded = aadSource ? Buffer.from(aadSource, "utf8").toString("base64") : void 0;
|
|
1744
|
-
if (aadSource) {
|
|
1745
|
-
cipher.setAAD(Buffer.from(aadSource, "utf8"));
|
|
1746
|
-
}
|
|
1747
|
-
const ciphertext = Buffer.concat([
|
|
1748
|
-
cipher.update(Buffer.from(options.plaintext, "utf8")),
|
|
1749
|
-
cipher.final()
|
|
1750
|
-
]);
|
|
1751
|
-
const tag = cipher.getAuthTag();
|
|
1752
|
-
const payload = Buffer.concat([ciphertext, tag]);
|
|
1753
|
-
return {
|
|
1754
|
-
algorithm: "aes-256-gcm",
|
|
1755
|
-
ciphertext: payload.toString("base64"),
|
|
1756
|
-
nonce: iv.toString("base64"),
|
|
1757
|
-
associatedData: associatedDataEncoded,
|
|
1758
|
-
keyLocator: {
|
|
1759
|
-
sessionId: options.sessionId,
|
|
1760
|
-
revision: options.revision ?? 1
|
|
1761
|
-
},
|
|
1762
|
-
recipients: options.recipients.map((recipient) => ({
|
|
1763
|
-
...recipient,
|
|
1764
|
-
encryptedShare: ""
|
|
1765
|
-
}))
|
|
1766
|
-
};
|
|
1767
|
-
}
|
|
1768
|
-
openCipherEnvelope(options) {
|
|
1769
|
-
this.assertNodeRuntime("decryptCipherEnvelope");
|
|
1770
|
-
const sharedSecret = this.normalizeSharedSecret(options.sharedSecret);
|
|
1771
|
-
const payload = Buffer.from(options.envelope.ciphertext, "base64");
|
|
1772
|
-
const nonce = Buffer.from(options.envelope.nonce, "base64");
|
|
1773
|
-
const ciphertext = payload.slice(0, payload.length - 16);
|
|
1774
|
-
const tag = payload.slice(payload.length - 16);
|
|
1775
|
-
const decipher = createDecipheriv("aes-256-gcm", sharedSecret, nonce);
|
|
1776
|
-
if (options.envelope.associatedData) {
|
|
1777
|
-
decipher.setAAD(Buffer.from(options.envelope.associatedData, "base64"));
|
|
1778
|
-
}
|
|
1779
|
-
decipher.setAuthTag(tag);
|
|
1780
|
-
const plaintext = Buffer.concat([
|
|
1781
|
-
decipher.update(ciphertext),
|
|
1782
|
-
decipher.final()
|
|
1783
|
-
]);
|
|
1784
|
-
return plaintext.toString(options.encoding ?? "utf8");
|
|
1785
|
-
}
|
|
1786
|
-
normalizeSharedSecret(input) {
|
|
1787
|
-
if (Buffer.isBuffer(input)) {
|
|
1788
|
-
return Buffer.from(input);
|
|
1789
|
-
}
|
|
1790
|
-
if (input instanceof Uint8Array) {
|
|
1791
|
-
return Buffer.from(input);
|
|
1792
|
-
}
|
|
1793
|
-
if (typeof input === "string") {
|
|
1794
|
-
return this.bufferFromString(input);
|
|
1795
|
-
}
|
|
1796
|
-
throw new Error("Unsupported shared secret input");
|
|
1797
|
-
}
|
|
1798
|
-
bufferFromString(value) {
|
|
1799
|
-
const trimmed = value.trim();
|
|
1800
|
-
if (!trimmed) {
|
|
1801
|
-
throw new Error("sharedSecret string cannot be empty");
|
|
1802
|
-
}
|
|
1803
|
-
const normalized = trimmed.startsWith("0x") ? trimmed.slice(2) : trimmed;
|
|
1804
|
-
if (/^[0-9a-fA-F]+$/.test(normalized) && normalized.length % 2 === 0) {
|
|
1805
|
-
return Buffer.from(normalized, "hex");
|
|
1806
|
-
}
|
|
1807
|
-
return Buffer.from(trimmed, "base64");
|
|
1808
|
-
}
|
|
1809
|
-
hexToBuffer(value) {
|
|
1810
|
-
const normalized = value.startsWith("0x") ? value.slice(2) : value;
|
|
1811
|
-
if (!/^[0-9a-fA-F]+$/.test(normalized) || normalized.length % 2 !== 0) {
|
|
1812
|
-
throw new Error("Expected hex-encoded value");
|
|
1813
|
-
}
|
|
1814
|
-
return Buffer.from(normalized, "hex");
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
const isPendingRegisterAgentResponse = (response) => response.status === "pending";
|
|
1818
|
-
const isPartialRegisterAgentResponse = (response) => response.status === "partial" && response.success === false;
|
|
1819
|
-
const isSuccessRegisterAgentResponse = (response) => response.success === true && response.status !== "pending";
|
|
1820
|
-
class EncryptedChatManager {
|
|
1821
|
-
constructor(client) {
|
|
1822
|
-
this.client = client;
|
|
1823
|
-
}
|
|
1824
|
-
registerConversationContext(context) {
|
|
1825
|
-
this.client.registerConversationContextForEncryption(context);
|
|
1826
|
-
}
|
|
1827
|
-
async startSession(options) {
|
|
1828
|
-
await this.client.encryptionReady();
|
|
1829
|
-
const session = await this.client.chat.createSession({
|
|
1830
|
-
uaid: options.uaid,
|
|
1831
|
-
senderUaid: options.senderUaid,
|
|
1832
|
-
encryptionRequested: true,
|
|
1833
|
-
historyTtlSeconds: options.historyTtlSeconds,
|
|
1834
|
-
auth: options.auth
|
|
1835
|
-
});
|
|
1836
|
-
options.onSessionCreated?.(session.sessionId);
|
|
1837
|
-
const summary = session.encryption;
|
|
1838
|
-
if (!summary?.enabled) {
|
|
1839
|
-
throw new EncryptionUnavailableError(
|
|
1840
|
-
session.sessionId,
|
|
1841
|
-
session.encryption ?? null
|
|
1842
|
-
);
|
|
1843
|
-
}
|
|
1844
|
-
const handle = await this.establishRequesterContext({
|
|
1845
|
-
sessionId: session.sessionId,
|
|
1846
|
-
summary,
|
|
1847
|
-
senderUaid: options.senderUaid,
|
|
1848
|
-
handshakeTimeoutMs: options.handshakeTimeoutMs,
|
|
1849
|
-
pollIntervalMs: options.pollIntervalMs
|
|
1850
|
-
});
|
|
1851
|
-
return handle;
|
|
1852
|
-
}
|
|
1853
|
-
async acceptSession(options) {
|
|
1854
|
-
await this.client.encryptionReady();
|
|
1855
|
-
const summary = await this.waitForEncryptionSummary(
|
|
1856
|
-
options.sessionId,
|
|
1857
|
-
options.handshakeTimeoutMs,
|
|
1858
|
-
options.pollIntervalMs
|
|
1859
|
-
);
|
|
1860
|
-
const handle = await this.establishResponderContext({
|
|
1861
|
-
sessionId: options.sessionId,
|
|
1862
|
-
summary,
|
|
1863
|
-
responderUaid: options.responderUaid,
|
|
1864
|
-
handshakeTimeoutMs: options.handshakeTimeoutMs,
|
|
1865
|
-
pollIntervalMs: options.pollIntervalMs
|
|
1866
|
-
});
|
|
1867
|
-
return handle;
|
|
1868
|
-
}
|
|
1869
|
-
async establishRequesterContext(params) {
|
|
1870
|
-
const keyPair = this.client.encryption.generateEphemeralKeyPair();
|
|
1871
|
-
await this.client.chat.submitEncryptionHandshake(params.sessionId, {
|
|
1872
|
-
role: "requester",
|
|
1873
|
-
keyType: "secp256k1",
|
|
1874
|
-
ephemeralPublicKey: keyPair.publicKey,
|
|
1875
|
-
uaid: params.senderUaid ?? params.summary.requester?.uaid ?? void 0
|
|
1876
|
-
});
|
|
1877
|
-
const { summary, record } = await this.waitForHandshakeCompletion(
|
|
1878
|
-
params.sessionId,
|
|
1879
|
-
params.handshakeTimeoutMs,
|
|
1880
|
-
params.pollIntervalMs
|
|
1881
|
-
);
|
|
1882
|
-
const responderKey = record.responder?.ephemeralPublicKey;
|
|
1883
|
-
if (!responderKey) {
|
|
1884
|
-
throw new Error("Responder handshake was not completed in time");
|
|
1885
|
-
}
|
|
1886
|
-
const sharedSecret = this.client.encryption.deriveSharedSecret({
|
|
1887
|
-
privateKey: keyPair.privateKey,
|
|
1888
|
-
peerPublicKey: responderKey
|
|
1889
|
-
}).subarray();
|
|
1890
|
-
const recipients = this.buildRecipients(summary);
|
|
1891
|
-
return this.createHandle({
|
|
1892
|
-
sessionId: params.sessionId,
|
|
1893
|
-
sharedSecret,
|
|
1894
|
-
summary,
|
|
1895
|
-
recipients,
|
|
1896
|
-
identity: summary.requester ?? void 0
|
|
1897
|
-
});
|
|
1898
|
-
}
|
|
1899
|
-
async establishResponderContext(params) {
|
|
1900
|
-
const keyPair = this.client.encryption.generateEphemeralKeyPair();
|
|
1901
|
-
await this.client.chat.submitEncryptionHandshake(params.sessionId, {
|
|
1902
|
-
role: "responder",
|
|
1903
|
-
keyType: "secp256k1",
|
|
1904
|
-
ephemeralPublicKey: keyPair.publicKey,
|
|
1905
|
-
uaid: params.responderUaid ?? params.summary.responder?.uaid ?? void 0
|
|
1906
|
-
});
|
|
1907
|
-
const { summary, record } = await this.waitForHandshakeCompletion(
|
|
1908
|
-
params.sessionId,
|
|
1909
|
-
params.handshakeTimeoutMs,
|
|
1910
|
-
params.pollIntervalMs
|
|
1911
|
-
);
|
|
1912
|
-
const requesterKey = record.requester?.ephemeralPublicKey;
|
|
1913
|
-
if (!requesterKey) {
|
|
1914
|
-
throw new Error("Requester handshake was not detected in time");
|
|
1915
|
-
}
|
|
1916
|
-
const sharedSecret = this.client.encryption.deriveSharedSecret({
|
|
1917
|
-
privateKey: keyPair.privateKey,
|
|
1918
|
-
peerPublicKey: requesterKey
|
|
1919
|
-
}).subarray();
|
|
1920
|
-
const recipients = this.buildRecipients(summary);
|
|
1921
|
-
return this.createHandle({
|
|
1922
|
-
sessionId: params.sessionId,
|
|
1923
|
-
sharedSecret,
|
|
1924
|
-
summary,
|
|
1925
|
-
recipients,
|
|
1926
|
-
identity: summary.responder ?? void 0
|
|
1927
|
-
});
|
|
1928
|
-
}
|
|
1929
|
-
async waitForHandshakeCompletion(sessionId, timeoutMs = 3e4, pollIntervalMs = 1e3) {
|
|
1930
|
-
const deadline = Date.now() + timeoutMs;
|
|
1931
|
-
while (true) {
|
|
1932
|
-
const status = await this.client.chat.getEncryptionStatus(sessionId);
|
|
1933
|
-
const summary = status.encryption;
|
|
1934
|
-
const record = summary?.handshake;
|
|
1935
|
-
if (summary && record && record.status === "complete") {
|
|
1936
|
-
return { summary, record };
|
|
1937
|
-
}
|
|
1938
|
-
if (Date.now() >= deadline) {
|
|
1939
|
-
throw new Error("Timed out waiting for encrypted handshake completion");
|
|
270
|
+
let bytes;
|
|
271
|
+
if (scheduledTxBytes.startsWith("0x")) {
|
|
272
|
+
const hexString = scheduledTxBytes.slice(2);
|
|
273
|
+
bytes = new Uint8Array(Buffer.from(hexString, "hex"));
|
|
274
|
+
} else {
|
|
275
|
+
bytes = new Uint8Array(Buffer.from(scheduledTxBytes, "base64"));
|
|
1940
276
|
}
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
async waitForEncryptionSummary(sessionId, _timeoutMs = 3e4, _pollIntervalMs = 1e3) {
|
|
1945
|
-
const status = await this.client.chat.getEncryptionStatus(sessionId);
|
|
1946
|
-
if (!status.encryption?.enabled) {
|
|
1947
|
-
throw new EncryptionUnavailableError(
|
|
1948
|
-
sessionId,
|
|
1949
|
-
status.encryption ?? null
|
|
277
|
+
const schedulableBody = proto.SchedulableTransactionBody.decode(bytes);
|
|
278
|
+
const txType = Object.keys(schedulableBody).find(
|
|
279
|
+
(key) => schedulableBody[key] !== null && key !== "transactionFee" && key !== "memo"
|
|
1950
280
|
);
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
return null;
|
|
1959
|
-
}
|
|
1960
|
-
const recipient = {};
|
|
1961
|
-
if (candidate.uaid) {
|
|
1962
|
-
recipient.uaid = candidate.uaid;
|
|
1963
|
-
}
|
|
1964
|
-
if (candidate.ledgerAccountId) {
|
|
1965
|
-
recipient.ledgerAccountId = candidate.ledgerAccountId;
|
|
1966
|
-
}
|
|
1967
|
-
if (candidate.userId) {
|
|
1968
|
-
recipient.userId = candidate.userId;
|
|
1969
|
-
}
|
|
1970
|
-
if (candidate.email) {
|
|
1971
|
-
recipient.email = candidate.email;
|
|
281
|
+
if (txType) {
|
|
282
|
+
return {
|
|
283
|
+
type: txType.toUpperCase(),
|
|
284
|
+
body: schedulableBody[txType],
|
|
285
|
+
memo: schedulableBody.memo,
|
|
286
|
+
transactionFee: schedulableBody.transactionFee?.toString()
|
|
287
|
+
};
|
|
1972
288
|
}
|
|
1973
|
-
return recipient;
|
|
1974
|
-
}).filter(
|
|
1975
|
-
(entry) => Boolean(
|
|
1976
|
-
entry?.uaid || entry?.ledgerAccountId || entry?.userId || entry?.email
|
|
1977
|
-
)
|
|
1978
|
-
);
|
|
1979
|
-
if (normalized.length > 0) {
|
|
1980
|
-
return normalized;
|
|
1981
|
-
}
|
|
1982
|
-
if (summary.responder?.uaid) {
|
|
1983
|
-
return [{ uaid: summary.responder.uaid }];
|
|
1984
|
-
}
|
|
1985
|
-
return [];
|
|
1986
|
-
}
|
|
1987
|
-
createHandle(context) {
|
|
1988
|
-
const sharedSecret = context.sharedSecret;
|
|
1989
|
-
const handle = {
|
|
1990
|
-
sessionId: context.sessionId,
|
|
1991
|
-
mode: "encrypted",
|
|
1992
|
-
summary: context.summary,
|
|
1993
|
-
send: async (options) => {
|
|
1994
|
-
const recipients = options.recipients ?? context.recipients;
|
|
1995
|
-
return this.client.chat.sendMessage({
|
|
1996
|
-
sessionId: context.sessionId,
|
|
1997
|
-
message: options.message ?? "[ciphertext omitted]",
|
|
1998
|
-
streaming: options.streaming,
|
|
1999
|
-
auth: options.auth,
|
|
2000
|
-
encryption: {
|
|
2001
|
-
plaintext: options.plaintext,
|
|
2002
|
-
sharedSecret: Buffer.from(sharedSecret),
|
|
2003
|
-
recipients
|
|
2004
|
-
}
|
|
2005
|
-
});
|
|
2006
|
-
},
|
|
2007
|
-
decryptHistoryEntry: (entry) => this.decryptEntry(entry, context.identity, sharedSecret)
|
|
2008
|
-
};
|
|
2009
|
-
this.registerConversationContext({
|
|
2010
|
-
sessionId: context.sessionId,
|
|
2011
|
-
sharedSecret,
|
|
2012
|
-
identity: context.identity
|
|
2013
|
-
});
|
|
2014
|
-
return handle;
|
|
2015
|
-
}
|
|
2016
|
-
decryptEntry(entry, identity, fallbackSecret) {
|
|
2017
|
-
const envelope = entry.cipherEnvelope;
|
|
2018
|
-
if (!envelope) {
|
|
2019
289
|
return null;
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
sharedSecret: secret
|
|
2026
|
-
});
|
|
2027
|
-
} catch (_error) {
|
|
290
|
+
} catch (error) {
|
|
291
|
+
console.warn(
|
|
292
|
+
"[ScheduleParser] Failed to parse scheduled transaction body:",
|
|
293
|
+
error
|
|
294
|
+
);
|
|
2028
295
|
return null;
|
|
2029
296
|
}
|
|
2030
297
|
}
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
}
|
|
2038
|
-
if (target.userId && candidate.userId === target.userId) {
|
|
2039
|
-
return true;
|
|
2040
|
-
}
|
|
2041
|
-
if (target.email && candidate.email?.toLowerCase() === target.email.toLowerCase()) {
|
|
2042
|
-
return true;
|
|
2043
|
-
}
|
|
2044
|
-
return false;
|
|
2045
|
-
}
|
|
2046
|
-
async delay(ms) {
|
|
2047
|
-
if (ms <= 0) {
|
|
2048
|
-
return;
|
|
2049
|
-
}
|
|
2050
|
-
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
2051
|
-
}
|
|
2052
|
-
}
|
|
2053
|
-
class EncryptionUnavailableError extends Error {
|
|
2054
|
-
constructor(sessionId, summary) {
|
|
2055
|
-
super("Encryption is not enabled for this session");
|
|
2056
|
-
this.sessionId = sessionId;
|
|
2057
|
-
this.summary = summary;
|
|
298
|
+
/**
|
|
299
|
+
* Parse Schedule Service transaction from Transaction object
|
|
300
|
+
* This is the unified entry point that delegates to the comprehensive parsing logic
|
|
301
|
+
*/
|
|
302
|
+
static parseFromTransactionObject(transaction) {
|
|
303
|
+
return this.parseScheduleTransaction(transaction);
|
|
2058
304
|
}
|
|
2059
305
|
}
|
|
2060
306
|
export {
|
|
2061
|
-
|
|
2062
|
-
RegistryBrokerError,
|
|
2063
|
-
RegistryBrokerParseError,
|
|
2064
|
-
isPartialRegisterAgentResponse,
|
|
2065
|
-
isPendingRegisterAgentResponse,
|
|
2066
|
-
isSuccessRegisterAgentResponse
|
|
307
|
+
ScheduleParser
|
|
2067
308
|
};
|
|
2068
309
|
//# sourceMappingURL=standards-sdk.es121.js.map
|