wao 0.27.3 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cjs/id.js ADDED
@@ -0,0 +1,234 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.extractCommitmentIds = extractCommitmentIds;
7
+ exports.generateCommitmentId = generateCommitmentId;
8
+ exports.generateHmacCommitmentId = generateHmacCommitmentId;
9
+ exports.generateRsaCommitmentId = generateRsaCommitmentId;
10
+ exports.parseStructuredFieldDictionary = parseStructuredFieldDictionary;
11
+ exports.verifyCommitmentId = verifyCommitmentId;
12
+ var _fastSha = require("fast-sha256");
13
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
14
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
15
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
16
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
17
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
18
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
19
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
20
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
21
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
22
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
23
+ /**
24
+ * Parse structured field dictionary format
25
+ * Handles both complex format: name=(components);params
26
+ * and simple format: name=:value:
27
+ */
28
+ function parseStructuredFieldDictionary(input) {
29
+ // Try complex format first
30
+ var match = input.match(/([^=]+)=\((.*?)\);(.*)$/);
31
+ if (match) {
32
+ var name = match[1];
33
+ var components = match[2].split(" ");
34
+ var params = {};
35
+ var paramPairs = match[3].split(";").filter(function (p) {
36
+ return p;
37
+ });
38
+ paramPairs.forEach(function (pair) {
39
+ var _pair$split = pair.split("="),
40
+ _pair$split2 = _slicedToArray(_pair$split, 2),
41
+ key = _pair$split2[0],
42
+ value = _pair$split2[1];
43
+ if (key && value) {
44
+ params[key] = value.replace(/"/g, "");
45
+ }
46
+ });
47
+ return {
48
+ name: name,
49
+ components: components,
50
+ params: params
51
+ };
52
+ }
53
+
54
+ // Try simple format
55
+ var simpleMatch = input.match(/([^=]+)=:([^:]+):/);
56
+ if (simpleMatch) {
57
+ return {
58
+ name: simpleMatch[1],
59
+ value: simpleMatch[2]
60
+ };
61
+ }
62
+ return null;
63
+ }
64
+
65
+ /**
66
+ * Convert base64url string to base64
67
+ */
68
+ function base64urlToBase64(str) {
69
+ return str.replace(/-/g, "+").replace(/_/g, "/");
70
+ }
71
+
72
+ /**
73
+ * Convert Uint8Array to base64url string
74
+ */
75
+ function uint8ArrayToBase64url(bytes) {
76
+ // Convert to base64
77
+ var binary = "";
78
+ for (var i = 0; i < bytes.length; i++) {
79
+ binary += String.fromCharCode(bytes[i]);
80
+ }
81
+ var base64 = btoa(binary);
82
+
83
+ // Convert to base64url
84
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
85
+ }
86
+
87
+ /**
88
+ * Generate commitment ID for RSA-PSS and ECDSA signatures
89
+ * The ID is the SHA256 hash of the raw signature bytes
90
+ *
91
+ * @param {Object} commitment - The commitment object containing signature
92
+ * @returns {string} The commitment ID in base64url format
93
+ */
94
+ function generateRsaCommitmentId(commitment) {
95
+ // Extract the base64 signature from structured field format
96
+ // Format: "signature-name=:BASE64_SIGNATURE:"
97
+ var match = commitment.signature.match(/^[^=]+=:([^:]+):/);
98
+ if (!match) {
99
+ throw new Error("Invalid signature format");
100
+ }
101
+ var signatureBase64 = match[1];
102
+ // Convert base64 to Uint8Array
103
+ var signatureBinary = Uint8Array.from(atob(signatureBase64), function (c) {
104
+ return c.charCodeAt(0);
105
+ });
106
+
107
+ // SHA256 hash of the raw signature
108
+ var hashResult = (0, _fastSha.hash)(signatureBinary);
109
+ var id = uint8ArrayToBase64url(hashResult);
110
+ return id;
111
+ }
112
+
113
+ /**
114
+ * Generate HMAC commitment ID for HyperBEAM messages
115
+ * The ID is deterministic based on message content only
116
+ *
117
+ * The Erlang implementation sorts components WITH @ prefix included,
118
+ * then removes @ from derived components in the signature base.
119
+ *
120
+ * @param {Object} message - The message with signature and signature-input
121
+ * @returns {string} The commitment ID in base64url format
122
+ */
123
+ function generateHmacCommitmentId(message) {
124
+ // Parse signature-input to get components
125
+ var parsed = parseStructuredFieldDictionary(message["signature-input"]);
126
+ if (!parsed || !parsed.components) {
127
+ throw new Error("Failed to parse signature-input");
128
+ }
129
+
130
+ // Sort components AS-IS (with quotes and @ prefix)
131
+ var sortedComponents = _toConsumableArray(parsed.components).sort();
132
+
133
+ // Build signature base in sorted order
134
+ var lines = [];
135
+ sortedComponents.forEach(function (component) {
136
+ var cleanComponent = component.replace(/"/g, "");
137
+ var fieldName = cleanComponent;
138
+ var value;
139
+
140
+ // For derived components (starting with @), remove @ in the signature base
141
+ if (cleanComponent.startsWith("@")) {
142
+ fieldName = cleanComponent.substring(1);
143
+ value = message[fieldName];
144
+ } else {
145
+ value = message[cleanComponent];
146
+ }
147
+ if (value === undefined || value === null) {
148
+ value = "";
149
+ } else if (typeof value === "number") {
150
+ value = value.toString();
151
+ }
152
+ lines.push("\"".concat(fieldName, "\": ").concat(value));
153
+ });
154
+
155
+ // Add signature-params line with sorted components (keeping @ prefix)
156
+ var paramsComponents = sortedComponents.join(" ");
157
+ lines.push("\"@signature-params\": (".concat(paramsComponents, ");alg=\"hmac-sha256\";keyid=\"ao\""));
158
+ var signatureBase = lines.join("\n");
159
+
160
+ // Generate HMAC with key "ao"
161
+ // Convert string to Uint8Array
162
+ var messageBytes = new TextEncoder().encode(signatureBase);
163
+ var keyBytes = new TextEncoder().encode("ao");
164
+ var hmacResult = (0, _fastSha.hmac)(keyBytes, messageBytes);
165
+ return uint8ArrayToBase64url(hmacResult);
166
+ }
167
+
168
+ /**
169
+ * Generate commitment ID based on the algorithm type
170
+ *
171
+ * @param {Object} commitment - The commitment object containing alg, signature, etc.
172
+ * @param {Object} fullMessage - The full message (required for HMAC)
173
+ * @returns {string} The commitment ID in base64url format
174
+ */
175
+ function generateCommitmentId(commitment) {
176
+ var fullMessage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
177
+ switch (commitment.alg) {
178
+ case "rsa-pss-sha512":
179
+ case "ecdsa-p256-sha256":
180
+ return generateRsaCommitmentId(commitment);
181
+ case "hmac-sha256":
182
+ if (!fullMessage) {
183
+ throw new Error("HMAC commitment IDs require full message context");
184
+ }
185
+ return generateHmacCommitmentId(fullMessage);
186
+ default:
187
+ throw new Error("Unsupported algorithm: ".concat(commitment.alg));
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Extract all commitment IDs from a HyperBEAM message
193
+ *
194
+ * @param {Object} message - The message with commitments
195
+ * @returns {Object} Map of commitment IDs to their types
196
+ */
197
+ function extractCommitmentIds(message) {
198
+ var ids = {};
199
+ if (!message.commitments) {
200
+ return ids;
201
+ }
202
+ for (var _i = 0, _Object$entries = Object.entries(message.commitments); _i < _Object$entries.length; _i++) {
203
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
204
+ id = _Object$entries$_i[0],
205
+ commitment = _Object$entries$_i[1];
206
+ ids[id] = {
207
+ alg: commitment.alg,
208
+ committer: commitment.committer,
209
+ device: commitment["commitment-device"]
210
+ };
211
+ }
212
+ return ids;
213
+ }
214
+
215
+ /**
216
+ * Verify a commitment ID matches the expected value
217
+ *
218
+ * @param {Object} commitment - The commitment object
219
+ * @param {string} expectedId - The expected commitment ID
220
+ * @param {Object} fullMessage - The full message (required for HMAC)
221
+ * @returns {boolean} True if the ID matches
222
+ */
223
+ function verifyCommitmentId(commitment, expectedId) {
224
+ var fullMessage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
225
+ try {
226
+ var calculatedId = generateCommitmentId(commitment, fullMessage);
227
+ return calculatedId === expectedId;
228
+ } catch (error) {
229
+ console.error("Error verifying commitment ID:", error);
230
+ return false;
231
+ }
232
+ }
233
+
234
+ // Export all functions
package/cjs/send.js CHANGED
@@ -46,6 +46,8 @@ function _send() {
46
46
  while (1) switch (_context2.prev = _context2.next) {
47
47
  case 0:
48
48
  fetchImpl = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : fetch;
49
+ // IMPORTANT: Use the URL from signedMsg.url, NOT from any path header
50
+ // This ensures we send to the correct URL even if path header is different
49
51
  fetchOptions = {
50
52
  method: signedMsg.method,
51
53
  headers: signedMsg.headers,
@@ -54,6 +56,8 @@ function _send() {
54
56
  if (signedMsg.body !== undefined && signedMsg.method !== "GET" && signedMsg.method !== "HEAD") {
55
57
  fetchOptions.body = signedMsg.body;
56
58
  }
59
+
60
+ // Use the URL as provided, ignoring any path header
57
61
  _context2.next = 5;
58
62
  return fetchImpl(signedMsg.url, fetchOptions);
59
63
  case 5:
@@ -4,6 +4,7 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
+ exports.extractPublicKeyFromHeaders = extractPublicKeyFromHeaders;
7
8
  exports.send = send;
8
9
  exports.toHttpSigner = void 0;
9
10
  exports.verify = verify;
package/cjs/signer.js CHANGED
@@ -30,7 +30,9 @@ var joinUrl = function joinUrl(_ref) {
30
30
  if (path.startsWith("http://") || path.startsWith("https://")) {
31
31
  return path;
32
32
  }
33
- return url.endsWith("/") ? url.slice(0, -1) + path : url + path;
33
+ // Ensure path starts with /
34
+ var normalizedPath = path.startsWith("/") ? path : "/" + path;
35
+ return url.endsWith("/") ? url.slice(0, -1) + normalizedPath : url + normalizedPath;
34
36
  };
35
37
  function signer(config) {
36
38
  var signer = config.signer,
@@ -41,15 +43,46 @@ function signer(config) {
41
43
  }
42
44
  return /*#__PURE__*/function () {
43
45
  var _sign = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(fields) {
44
- var _fields$path, path, _fields$method, method, restFields, aoFields, encoded, headersObj, body, _url, bodySize, lowercaseHeaders, _i, _Object$entries, _Object$entries$_i, key, value, signingFields, signedRequest, finalHeaders, _i2, _Object$entries2, _Object$entries2$_i, _key, _value, result;
46
+ var _ref2,
47
+ _ref2$path,
48
+ _path,
49
+ _fields$path,
50
+ path,
51
+ _fields$method,
52
+ method,
53
+ restFields,
54
+ aoFields,
55
+ encoded,
56
+ headersObj,
57
+ body,
58
+ _url,
59
+ bodySize,
60
+ lowercaseHeaders,
61
+ _i,
62
+ _Object$entries,
63
+ _Object$entries$_i,
64
+ key,
65
+ value,
66
+ bodyKeys,
67
+ signingFields,
68
+ signedRequest,
69
+ finalHeaders,
70
+ _i2,
71
+ _Object$entries2,
72
+ _Object$entries2$_i,
73
+ _key,
74
+ _value,
75
+ result,
76
+ _args = arguments;
45
77
  return _regeneratorRuntime().wrap(function _callee$(_context) {
46
78
  while (1) switch (_context.prev = _context.next) {
47
79
  case 0:
80
+ _ref2 = _args.length > 1 && _args[1] !== undefined ? _args[1] : {}, _ref2$path = _ref2.path, _path = _ref2$path === void 0 ? false : _ref2$path;
48
81
  _fields$path = fields.path, path = _fields$path === void 0 ? "/relay/process" : _fields$path, _fields$method = fields.method, method = _fields$method === void 0 ? "POST" : _fields$method, restFields = _objectWithoutProperties(fields, _excluded);
49
82
  aoFields = _objectSpread({}, restFields);
50
- _context.next = 4;
83
+ _context.next = 5;
51
84
  return (0, _encode.enc)(aoFields);
52
- case 4:
85
+ case 5:
53
86
  encoded = _context.sent;
54
87
  headersObj = encoded ? encoded.headers : {};
55
88
  body = encoded ? encoded.body : undefined;
@@ -57,6 +90,7 @@ function signer(config) {
57
90
  url: url,
58
91
  path: path
59
92
  });
93
+ headersObj["path"] = path;
60
94
  if (body && !headersObj["content-length"]) {
61
95
  bodySize = body.size || body.byteLength || 0;
62
96
  if (bodySize > 0) {
@@ -68,14 +102,27 @@ function signer(config) {
68
102
  _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), key = _Object$entries$_i[0], value = _Object$entries$_i[1];
69
103
  lowercaseHeaders[key.toLowerCase()] = value;
70
104
  }
105
+ if (lowercaseHeaders.path && /^\//.test(lowercaseHeaders.path)) {
106
+ //const sp = lowercaseHeaders.path.split("/")
107
+ //lowercaseHeaders.path = sp.slice(sp.length - 1).join("/")
108
+ }
109
+ // Parse body-keys if present
110
+ bodyKeys = headersObj["body-keys"] ? headersObj["body-keys"].replace(/"/g, "").split(",").map(function (k) {
111
+ return k.trim();
112
+ }) : []; // Collect fields to sign from headers
71
113
  signingFields = Object.keys(lowercaseHeaders).filter(function (key) {
72
- return key !== "body-keys";
73
- });
114
+ return key !== "body-keys" && key !== "path" && !bodyKeys.includes(key);
115
+ } // Also exclude fields that are in body-keys
116
+ ); // Always include @path in the signature
117
+ //if (!signingFields.includes("path")) signingFields.push("path")
118
+
119
+ if (_path) signingFields.push("path");
120
+ // Ensure we have at least one field to sign
74
121
  if (signingFields.length === 0 && !body) {
75
122
  lowercaseHeaders["content-length"] = "0";
76
123
  signingFields.push("content-length");
77
124
  }
78
- _context.next = 15;
125
+ _context.next = 20;
79
126
  return (0, _send.toHttpSigner)(signer)({
80
127
  request: {
81
128
  url: _url,
@@ -84,7 +131,7 @@ function signer(config) {
84
131
  },
85
132
  fields: signingFields
86
133
  });
87
- case 15:
134
+ case 20:
88
135
  signedRequest = _context.sent;
89
136
  finalHeaders = {};
90
137
  for (_i2 = 0, _Object$entries2 = Object.entries(headersObj); _i2 < _Object$entries2.length; _i2++) {
@@ -103,7 +150,7 @@ function signer(config) {
103
150
  };
104
151
  if (body) result.body = body;
105
152
  return _context.abrupt("return", result);
106
- case 24:
153
+ case 29:
107
154
  case "end":
108
155
  return _context.stop();
109
156
  }
@@ -114,4 +161,6 @@ function signer(config) {
114
161
  }
115
162
  return sign;
116
163
  }();
117
- }
164
+ }
165
+
166
+ // stack / simple-pay / patch / hyperbeam / hyperbeam-aos / scheduler / cron
package/cjs/utils.js CHANGED
@@ -3,16 +3,30 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.isData = exports.isCheckComplete = exports.getTagVal = exports.getTag = exports.dirname = exports.checkTag = exports.buildTags = exports.allChecked = exports.action = void 0;
6
+ exports.getTagVal = exports.getTag = exports.dirname = exports.checkTag = exports.buildTags = exports.allChecked = exports.action = void 0;
7
+ Object.defineProperty(exports, "hmacid", {
8
+ enumerable: true,
9
+ get: function get() {
10
+ return _id.generateHmacCommitmentId;
11
+ }
12
+ });
13
+ exports.isData = exports.isCheckComplete = void 0;
7
14
  exports.isJSON = isJSON;
8
15
  exports.optServer = exports.optAO = exports.mergeOut = exports.mergeChecks = exports.ltags = exports.jsonToStr = exports.isRegExp = exports.isOutComplete = exports.isLocalhost = void 0;
9
16
  exports.parseSignatureInput = parseSignatureInput;
17
+ Object.defineProperty(exports, "rsaid", {
18
+ enumerable: true,
19
+ get: function get() {
20
+ return _id.generateRsaCommitmentId;
21
+ }
22
+ });
10
23
  exports.tags = exports.tagEq = exports.tag = exports.srcs = exports.searchTag = void 0;
11
24
  exports.toANS104Request = toANS104Request;
12
25
  exports.toAddr = toAddr;
13
26
  exports.wait = exports.validAddress = exports.udl = exports.toGraphObj = void 0;
14
27
  var _graphql = require("graphql");
15
28
  var _fastSha = _interopRequireDefault(require("fast-sha256"));
29
+ var _id = require("./id.js");
16
30
  var _ramda = require("ramda");
17
31
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
18
32
  function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }