wao 0.29.2 → 0.30.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/ao.js +33 -10
- package/cjs/devs.js +122 -110
- package/cjs/hb.js +500 -367
- package/cjs/hyperbeam.js +15 -8
- package/cjs/id.js +212 -18
- package/cjs/signer.js +14 -5
- package/cjs/utils.js +6 -0
- package/cjs/workspace/package.json +1 -1
- package/cjs/workspace/test/hyperbeam.js +8 -5
- package/esm/ao.js +1 -1
- package/esm/devs.js +56 -33
- package/esm/hb.js +51 -10
- package/esm/hyperbeam.js +23 -12
- package/esm/id.js +172 -15
- package/esm/signer.js +5 -4
- package/esm/utils.js +2 -0
- package/esm/workspace/package.json +1 -1
- package/esm/workspace/test/hyperbeam.js +8 -5
- package/package.json +5 -1
package/cjs/hyperbeam.js
CHANGED
|
@@ -43,9 +43,10 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
43
43
|
c = _ref.c,
|
|
44
44
|
cmake = _ref.cmake,
|
|
45
45
|
faff = _ref.faff,
|
|
46
|
-
_ref$
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
_ref$simple_pay = _ref.simple_pay,
|
|
47
|
+
simple_pay = _ref$simple_pay === void 0 ? false : _ref$simple_pay,
|
|
48
|
+
simple_pay_price = _ref.simple_pay_price,
|
|
49
|
+
p4_non_chargable_routes = _ref.p4_non_chargable_routes,
|
|
49
50
|
p4_lua = _ref.p4_lua,
|
|
50
51
|
store_prefix = _ref.store_prefix,
|
|
51
52
|
operator = _ref.operator,
|
|
@@ -56,6 +57,7 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
56
57
|
devices = _ref.devices;
|
|
57
58
|
_classCallCheck(this, HyperBEAM);
|
|
58
59
|
this.devices = devices;
|
|
60
|
+
this.p4_non_chargable_routes = p4_non_chargable_routes;
|
|
59
61
|
(_as2 = as) !== null && _as2 !== void 0 ? _as2 : as = shell ? [] : ["genesis_wasm"];
|
|
60
62
|
this.console = console;
|
|
61
63
|
if (clearCache) {
|
|
@@ -85,8 +87,8 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
85
87
|
this.cu = cu;
|
|
86
88
|
this.store_prefix = store_prefix ? "cache-mainnet-" + Math.floor(Math.random() * 10000000) : "cache-mainnet";
|
|
87
89
|
this.p4_lua = p4_lua;
|
|
88
|
-
this.
|
|
89
|
-
this.spp =
|
|
90
|
+
this.simple_pay = simple_pay;
|
|
91
|
+
this.spp = simple_pay_price;
|
|
90
92
|
this.operator = operator;
|
|
91
93
|
this.faff = faff;
|
|
92
94
|
this.c = c;
|
|
@@ -311,7 +313,9 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
311
313
|
try {
|
|
312
314
|
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
313
315
|
var v = _step4.value;
|
|
314
|
-
if (
|
|
316
|
+
if (_typeof(v) === "object") {
|
|
317
|
+
_devs.push("#{<<\"name\">> => <<\"".concat(v.name, "\">>, <<\"module\">> => ").concat(v.module, "}"));
|
|
318
|
+
} else if (_devs2["default"][v]) _devs.push("#{<<\"name\">> => <<\"".concat(_devs2["default"][v].name, "\">>, <<\"module\">> => ").concat(_devs2["default"][v].module, "}"));
|
|
315
319
|
}
|
|
316
320
|
} catch (err) {
|
|
317
321
|
_iterator4.e(err);
|
|
@@ -329,7 +333,9 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
329
333
|
/*
|
|
330
334
|
const _routes = `, routes => [#{ <<"template">> => <<"/result/.*">>, <<"node">> => #{ <<"prefix">> => <<"http://localhost:${this.cu}">> } }, #{ <<\"template\">> => <<\"/dry-run\">>, <<\"node\">> => #{ <<\"prefix\">> => <<\"http://localhost:${this.cu}\">> } }, #{ <<"template">> => <<"/graphql">>, <<"nodes">> => [#{ <<"prefix">> => <<"http://localhost:${gateway}">>, <<"opts">> => #{ http_client => httpc, protocol => http2 } }, #{ <<"prefix">> => <<"http://localhost:${gateway}">>, <<"opts">> => #{ http_client => gun, protocol => http2 } }] }, #{ <<"template">> => <<"/raw">>, <<"node">> => #{ <<"prefix">> => <<"http://localhost:${gateway}">>, <<"opts">> => #{ http_client => gun, protocol => http2 } } }]`
|
|
331
335
|
*/
|
|
332
|
-
var _p4_non_chargable = this.
|
|
336
|
+
var _p4_non_chargable = this.p4_non_chargable ? ", p4_non_chargable_routes => [".concat(this.p4_non_chargable_routes.map(function () {
|
|
337
|
+
return "#{ <<\"template\">> => <<\"/*~node-process@1.0/*\">> }";
|
|
338
|
+
}).join(", "), "]") : this.p4_lua ? ", p4_non_chargable_routes => [#{ <<\"template\">> => <<\"/*~node-process@1.0/*\">> }, #{ <<\"template\">> => <<\"/~wao@1.0/*\">> }, #{ <<\"template\">> => <<\"/~p4@1.0/balance\">> }, #{ <<\"template\">> => <<\"/~meta@1.0/*\">> }]" : !this.simple_pay ? "" : ", p4_non_chargable_routes => [#{ <<\"template\">> => <<\"/~simple-pay@1.0/topup\">> }, #{ <<\"template\">> => <<\"/~meta@1.0/*\">> }, #{ <<\"template\">> => <<\"/~simple-pay@1.0/balance\">> }]";
|
|
333
339
|
var _operator = this.operator ? ", operator => <<\"".concat(this.operator, "\">>") : "";
|
|
334
340
|
var _spp = this.spp ? ", simple_pay_price => ".concat(this.spp) : "";
|
|
335
341
|
var _node_processes = this.p4_lua ? ", node_processes => #{ <<\"ledger\">> => #{ <<\"device\">> => <<\"process@1.0\">>, <<\"execution-device\">> => <<\"lua@5.3a\">>, <<\"scheduler-device\">> => <<\"scheduler@1.0\">>, <<\"module\">> => <<\"".concat(this.p4_lua.processor, "\">>, <<\"operator\">> => <<\"").concat(this.operator, "\">> } }") : "";
|
|
@@ -338,8 +344,9 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
338
344
|
var _faff = (0, _ramda.isNil)(this.faff) ? "" : ", faff_allow_list => [ ".concat((0, _ramda.map)(function (addr) {
|
|
339
345
|
return "<<\"".concat(addr, "\">>");
|
|
340
346
|
})(this.faff).join(", "), " ]");
|
|
341
|
-
var _on = this.p4_lua ? ", on => #{ <<\"request\">> => ".concat(processor, ", <<\"response\">> => ").concat(processor, " }") : this.
|
|
347
|
+
var _on = this.p4_lua ? ", on => #{ <<\"request\">> => ".concat(processor, ", <<\"response\">> => ").concat(processor, " }") : this.simple_pay ? ", on => #{ <<\"request\">> => #{ <<\"device\">> => <<\"p4@1.0\">>, <<\"pricing-device\">> => <<\"simple-pay@1.0\">>, <<\"ledger-device\">> => <<\"simple-pay@1.0\">> }, <<\"response\">> => #{ <<\"device\">> => <<\"p4@1.0\">>, <<\"pricing-device\">> => <<\"simple-pay@1.0\">>, <<\"ledger-device\">> => <<\"simple-pay@1.0\">> } }" : !(0, _ramda.isNil)(this.faff) ? ", on => #{ <<\"request\">> => #{ <<\"device\">> => <<\"p4@1.0\">>, <<\"pricing-device\">> => <<\"faff@1.0\">>, <<\"ledger-device\">> => <<\"faff@1.0\">> }, <<\"response\">> => #{ <<\"device\">> => <<\"p4@1.0\">>, <<\"pricing-device\">> => <<\"faff@1.0\">>, <<\"ledger-device\">> => <<\"faff@1.0\">> } }" : "";
|
|
342
348
|
var start = "hb:start_mainnet(#{ ".concat(_port).concat(_gateway).concat(_wallet).concat(_faff).concat(_bundler).concat(_on).concat(_p4_non_chargable).concat(_operator).concat(_spp).concat(_devices).concat(_node_processes, "}).");
|
|
349
|
+
console.log(start);
|
|
343
350
|
return start;
|
|
344
351
|
}
|
|
345
352
|
}, {
|
package/cjs/id.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
3
4
|
Object.defineProperty(exports, "__esModule", {
|
|
4
5
|
value: true
|
|
5
6
|
});
|
|
@@ -7,9 +8,14 @@ exports.extractCommitmentIds = extractCommitmentIds;
|
|
|
7
8
|
exports.generateCommitmentId = generateCommitmentId;
|
|
8
9
|
exports.generateHmacCommitmentId = generateHmacCommitmentId;
|
|
9
10
|
exports.generateRsaCommitmentId = generateRsaCommitmentId;
|
|
11
|
+
exports.id = id;
|
|
10
12
|
exports.parseStructuredFieldDictionary = parseStructuredFieldDictionary;
|
|
11
13
|
exports.verifyCommitmentId = verifyCommitmentId;
|
|
12
14
|
var _fastSha = require("fast-sha256");
|
|
15
|
+
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, "catch": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
16
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
17
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
18
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
13
19
|
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
14
20
|
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
21
|
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
@@ -69,21 +75,6 @@ function base64urlToBase64(str) {
|
|
|
69
75
|
return str.replace(/-/g, "+").replace(/_/g, "/");
|
|
70
76
|
}
|
|
71
77
|
|
|
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
78
|
/**
|
|
88
79
|
* Generate commitment ID for RSA-PSS and ECDSA signatures
|
|
89
80
|
* The ID is the SHA256 hash of the raw signature bytes
|
|
@@ -201,9 +192,9 @@ function extractCommitmentIds(message) {
|
|
|
201
192
|
}
|
|
202
193
|
for (var _i = 0, _Object$entries = Object.entries(message.commitments); _i < _Object$entries.length; _i++) {
|
|
203
194
|
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
204
|
-
|
|
195
|
+
_id = _Object$entries$_i[0],
|
|
205
196
|
commitment = _Object$entries$_i[1];
|
|
206
|
-
ids[
|
|
197
|
+
ids[_id] = {
|
|
207
198
|
alg: commitment.alg,
|
|
208
199
|
committer: commitment.committer,
|
|
209
200
|
device: commitment["commitment-device"]
|
|
@@ -231,4 +222,207 @@ function verifyCommitmentId(commitment, expectedId) {
|
|
|
231
222
|
}
|
|
232
223
|
}
|
|
233
224
|
|
|
234
|
-
|
|
225
|
+
/**
|
|
226
|
+
* Convert Uint8Array to base64url string
|
|
227
|
+
*/
|
|
228
|
+
function uint8ArrayToBase64url(bytes) {
|
|
229
|
+
var binary = "";
|
|
230
|
+
for (var i = 0; i < bytes.length; i++) {
|
|
231
|
+
binary += String.fromCharCode(bytes[i]);
|
|
232
|
+
}
|
|
233
|
+
var base64 = btoa(binary);
|
|
234
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Parse structured field dictionary to extract components
|
|
239
|
+
* Handles format: name=(components);params
|
|
240
|
+
*/
|
|
241
|
+
function parseSignatureInput(sigInput) {
|
|
242
|
+
// Extract components from format: name=(components);params
|
|
243
|
+
var match = sigInput.match(/[^=]+=\(([^)]+)\)/);
|
|
244
|
+
if (!match) return [];
|
|
245
|
+
|
|
246
|
+
// Split components and clean quotes
|
|
247
|
+
return match[1].split(" ").map(function (c) {
|
|
248
|
+
return c.replace(/"/g, "");
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Calculate HMAC commitment ID for HyperBEAM messages
|
|
254
|
+
*/
|
|
255
|
+
function calculateHmacId(_x) {
|
|
256
|
+
return _calculateHmacId.apply(this, arguments);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Calculate unsigned message ID following the exact Erlang flow
|
|
260
|
+
*/
|
|
261
|
+
function _calculateHmacId() {
|
|
262
|
+
_calculateHmacId = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(message) {
|
|
263
|
+
var components, sortedComponents, lines, _iterator, _step, component, fieldName, value, paramsComponents, signatureBase, messageBytes, keyBytes, hmacResult;
|
|
264
|
+
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
265
|
+
while (1) switch (_context.prev = _context.next) {
|
|
266
|
+
case 0:
|
|
267
|
+
if (message["signature-input"]) {
|
|
268
|
+
_context.next = 2;
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
throw new Error("HMAC calculation requires signature-input");
|
|
272
|
+
case 2:
|
|
273
|
+
// Parse components from signature-input
|
|
274
|
+
components = parseSignatureInput(message["signature-input"]); // Sort components AS-IS (with @ prefix)
|
|
275
|
+
sortedComponents = _toConsumableArray(components).sort(); // Build signature base in sorted order
|
|
276
|
+
lines = [];
|
|
277
|
+
_iterator = _createForOfIteratorHelper(sortedComponents);
|
|
278
|
+
try {
|
|
279
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
280
|
+
component = _step.value;
|
|
281
|
+
fieldName = component;
|
|
282
|
+
value = void 0; // For derived components (starting with @), remove @ in the signature base
|
|
283
|
+
if (component.startsWith("@")) {
|
|
284
|
+
fieldName = component.substring(1);
|
|
285
|
+
value = message[fieldName];
|
|
286
|
+
} else {
|
|
287
|
+
value = message[component];
|
|
288
|
+
}
|
|
289
|
+
if (value === undefined || value === null) {
|
|
290
|
+
value = "";
|
|
291
|
+
} else if (typeof value === "number") {
|
|
292
|
+
value = value.toString();
|
|
293
|
+
}
|
|
294
|
+
lines.push("\"".concat(fieldName, "\": ").concat(value));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Add signature-params line with sorted components (keeping @ prefix)
|
|
298
|
+
} catch (err) {
|
|
299
|
+
_iterator.e(err);
|
|
300
|
+
} finally {
|
|
301
|
+
_iterator.f();
|
|
302
|
+
}
|
|
303
|
+
paramsComponents = sortedComponents.join(" ");
|
|
304
|
+
lines.push("\"@signature-params\": (".concat(paramsComponents, ");alg=\"hmac-sha256\";keyid=\"ao\""));
|
|
305
|
+
signatureBase = lines.join("\n"); // Generate HMAC with key "ao"
|
|
306
|
+
messageBytes = new TextEncoder().encode(signatureBase);
|
|
307
|
+
keyBytes = new TextEncoder().encode("ao");
|
|
308
|
+
_context.next = 14;
|
|
309
|
+
return (0, _fastSha.hmac)(keyBytes, messageBytes);
|
|
310
|
+
case 14:
|
|
311
|
+
hmacResult = _context.sent;
|
|
312
|
+
return _context.abrupt("return", uint8ArrayToBase64url(hmacResult));
|
|
313
|
+
case 16:
|
|
314
|
+
case "end":
|
|
315
|
+
return _context.stop();
|
|
316
|
+
}
|
|
317
|
+
}, _callee);
|
|
318
|
+
}));
|
|
319
|
+
return _calculateHmacId.apply(this, arguments);
|
|
320
|
+
}
|
|
321
|
+
function calculateUnsignedId(_x2) {
|
|
322
|
+
return _calculateUnsignedId.apply(this, arguments);
|
|
323
|
+
}
|
|
324
|
+
function _calculateUnsignedId() {
|
|
325
|
+
_calculateUnsignedId = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(message) {
|
|
326
|
+
var DERIVED_COMPONENTS, httpsigMsg, _i2, _Object$entries2, _Object$entries2$_i, key, value, keys, componentsWithPrefix, lines, _iterator2, _step2, component, _key, _value, valueStr, componentsList, signatureBase, messageBytes, keyBytes, hmacResult;
|
|
327
|
+
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
328
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
329
|
+
case 0:
|
|
330
|
+
// Derived components from Erlang ?DERIVED_COMPONENTS
|
|
331
|
+
DERIVED_COMPONENTS = ["method", "target-uri", "authority", "scheme", "request-target", "path", "query", "query-param", "status"]; // Convert message for httpsig format
|
|
332
|
+
httpsigMsg = {};
|
|
333
|
+
for (_i2 = 0, _Object$entries2 = Object.entries(message); _i2 < _Object$entries2.length; _i2++) {
|
|
334
|
+
_Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2), key = _Object$entries2$_i[0], value = _Object$entries2$_i[1];
|
|
335
|
+
httpsigMsg[key.toLowerCase()] = value;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Get keys and add @ to derived components
|
|
339
|
+
keys = Object.keys(httpsigMsg);
|
|
340
|
+
componentsWithPrefix = keys.map(function (key) {
|
|
341
|
+
// Check if this is a derived component
|
|
342
|
+
if (DERIVED_COMPONENTS.includes(key.replace(/_/g, "-"))) {
|
|
343
|
+
return "@" + key;
|
|
344
|
+
}
|
|
345
|
+
return key;
|
|
346
|
+
}).sort(); // Sort AFTER adding @ prefix
|
|
347
|
+
// Build signature base - use the components in order
|
|
348
|
+
lines = [];
|
|
349
|
+
_iterator2 = _createForOfIteratorHelper(componentsWithPrefix);
|
|
350
|
+
try {
|
|
351
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
352
|
+
component = _step2.value;
|
|
353
|
+
_key = component.replace("@", "");
|
|
354
|
+
_value = httpsigMsg[_key];
|
|
355
|
+
valueStr = typeof _value === "string" ? _value : String(_value);
|
|
356
|
+
lines.push("\"".concat(_key, "\": ").concat(valueStr));
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Add signature-params line with the @ prefixes
|
|
360
|
+
} catch (err) {
|
|
361
|
+
_iterator2.e(err);
|
|
362
|
+
} finally {
|
|
363
|
+
_iterator2.f();
|
|
364
|
+
}
|
|
365
|
+
componentsList = componentsWithPrefix.map(function (k) {
|
|
366
|
+
return "\"".concat(k, "\"");
|
|
367
|
+
}).join(" ");
|
|
368
|
+
lines.push("\"@signature-params\": (".concat(componentsList, ");alg=\"hmac-sha256\";keyid=\"ao\""));
|
|
369
|
+
signatureBase = lines.join("\n"); // HMAC with key "ao"
|
|
370
|
+
messageBytes = new TextEncoder().encode(signatureBase);
|
|
371
|
+
keyBytes = new TextEncoder().encode("ao");
|
|
372
|
+
_context2.next = 15;
|
|
373
|
+
return (0, _fastSha.hmac)(keyBytes, messageBytes);
|
|
374
|
+
case 15:
|
|
375
|
+
hmacResult = _context2.sent;
|
|
376
|
+
return _context2.abrupt("return", uint8ArrayToBase64url(hmacResult));
|
|
377
|
+
case 17:
|
|
378
|
+
case "end":
|
|
379
|
+
return _context2.stop();
|
|
380
|
+
}
|
|
381
|
+
}, _callee2);
|
|
382
|
+
}));
|
|
383
|
+
return _calculateUnsignedId.apply(this, arguments);
|
|
384
|
+
}
|
|
385
|
+
function id(_x3) {
|
|
386
|
+
return _id2.apply(this, arguments);
|
|
387
|
+
} // Export all functions
|
|
388
|
+
function _id2() {
|
|
389
|
+
_id2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(message) {
|
|
390
|
+
var commitmentIds, sortedIds, idsLine, encoder, data, hashBuffer, hashArray, base64, base64url;
|
|
391
|
+
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
|
392
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
393
|
+
case 0:
|
|
394
|
+
// Get commitment IDs
|
|
395
|
+
commitmentIds = Object.keys(message.commitments || {});
|
|
396
|
+
if (!(commitmentIds.length === 0)) {
|
|
397
|
+
_context3.next = 5;
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
return _context3.abrupt("return", calculateUnsignedId(message));
|
|
401
|
+
case 5:
|
|
402
|
+
if (!(commitmentIds.length === 1)) {
|
|
403
|
+
_context3.next = 9;
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
return _context3.abrupt("return", commitmentIds[0]);
|
|
407
|
+
case 9:
|
|
408
|
+
// Multiple commitments - sort, join with ", ", and hash
|
|
409
|
+
sortedIds = commitmentIds.sort();
|
|
410
|
+
idsLine = sortedIds.join(", "); // Calculate SHA-256 hash
|
|
411
|
+
encoder = new TextEncoder();
|
|
412
|
+
data = encoder.encode(idsLine);
|
|
413
|
+
_context3.next = 15;
|
|
414
|
+
return crypto.subtle.digest("SHA-256", data);
|
|
415
|
+
case 15:
|
|
416
|
+
hashBuffer = _context3.sent;
|
|
417
|
+
hashArray = new Uint8Array(hashBuffer); // Convert to base64url
|
|
418
|
+
base64 = btoa(String.fromCharCode.apply(String, _toConsumableArray(hashArray)));
|
|
419
|
+
base64url = base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
420
|
+
return _context3.abrupt("return", base64url);
|
|
421
|
+
case 20:
|
|
422
|
+
case "end":
|
|
423
|
+
return _context3.stop();
|
|
424
|
+
}
|
|
425
|
+
}, _callee3);
|
|
426
|
+
}));
|
|
427
|
+
return _id2.apply(this, arguments);
|
|
428
|
+
}
|
package/cjs/signer.js
CHANGED
|
@@ -6,9 +6,16 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.sign = sign;
|
|
8
8
|
exports.signer = signer;
|
|
9
|
+
Object.defineProperty(exports, "verify", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function get() {
|
|
12
|
+
return _signerUtils.verify;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
9
15
|
var _send = require("./send.js");
|
|
10
16
|
var _encode = require("./encode.js");
|
|
11
17
|
var _aoconnect = require("@permaweb/aoconnect");
|
|
18
|
+
var _signerUtils = require("./signer-utils.js");
|
|
12
19
|
var _excluded = ["path", "method"],
|
|
13
20
|
_excluded2 = ["body"];
|
|
14
21
|
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
@@ -96,11 +103,13 @@ function _sign3() {
|
|
|
96
103
|
return key !== "body-keys" && key !== "path" && !bodyKeys.includes(key);
|
|
97
104
|
});
|
|
98
105
|
if (_path) signingFields.push("path");
|
|
106
|
+
/*
|
|
99
107
|
if (signingFields.length === 0 && !body) {
|
|
100
|
-
lowercaseHeaders["content-length"] = "0"
|
|
101
|
-
signingFields.push("content-length")
|
|
108
|
+
//lowercaseHeaders["content-length"] = "0"
|
|
109
|
+
//signingFields.push("content-length")
|
|
102
110
|
}
|
|
103
|
-
|
|
111
|
+
*/
|
|
112
|
+
_context3.next = 13;
|
|
104
113
|
return (0, _send.toHttpSigner)(signer)({
|
|
105
114
|
request: {
|
|
106
115
|
url: _url,
|
|
@@ -109,7 +118,7 @@ function _sign3() {
|
|
|
109
118
|
},
|
|
110
119
|
fields: signingFields
|
|
111
120
|
});
|
|
112
|
-
case
|
|
121
|
+
case 13:
|
|
113
122
|
signedRequest = _context3.sent;
|
|
114
123
|
finalHeaders = {};
|
|
115
124
|
for (_i2 = 0, _Object$entries2 = Object.entries(headersObj); _i2 < _Object$entries2.length; _i2++) {
|
|
@@ -128,7 +137,7 @@ function _sign3() {
|
|
|
128
137
|
};
|
|
129
138
|
if (body) result.body = body;
|
|
130
139
|
return _context3.abrupt("return", result);
|
|
131
|
-
case
|
|
140
|
+
case 22:
|
|
132
141
|
case "end":
|
|
133
142
|
return _context3.stop();
|
|
134
143
|
}
|
package/cjs/utils.js
CHANGED
|
@@ -10,6 +10,12 @@ Object.defineProperty(exports, "hmacid", {
|
|
|
10
10
|
return _id.generateHmacCommitmentId;
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
|
+
Object.defineProperty(exports, "id", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function get() {
|
|
16
|
+
return _id.id;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
13
19
|
exports.isData = exports.isCheckComplete = void 0;
|
|
14
20
|
exports.isJSON = isJSON;
|
|
15
21
|
exports.optServer = exports.optAO = exports.mergeOut = exports.mergeChecks = exports.ltags = exports.jsonToStr = exports.isRegExp = exports.isOutComplete = exports.isLocalhost = void 0;
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import assert from "assert"
|
|
2
2
|
import { describe, it, before, after, beforeEach } from "node:test"
|
|
3
|
-
import { HyperBEAM,
|
|
3
|
+
import { HyperBEAM, toAddr } from "wao/test"
|
|
4
4
|
import { HB } from "wao"
|
|
5
5
|
import { resolve } from "path"
|
|
6
6
|
import { readFileSync } from "fs"
|
|
7
7
|
|
|
8
8
|
const cwd = "../../HyperBEAM"
|
|
9
|
-
const wallet = ".wallet.json"
|
|
9
|
+
const wallet = resolve(process.cwd(), cwd, ".wallet.json")
|
|
10
|
+
|
|
11
|
+
const jwk = JSON.parse(readFileSync(wallet, "utf8"))
|
|
12
|
+
const addr = toAddr(jwk.n)
|
|
10
13
|
|
|
11
14
|
describe("HyperBEAM", function () {
|
|
12
15
|
let hbeam, hb, jwk
|
|
13
16
|
|
|
14
17
|
before(async () => {
|
|
15
|
-
hbeam = await new HyperBEAM({
|
|
18
|
+
hbeam = await new HyperBEAM({ cwd }).ready()
|
|
16
19
|
jwk = JSON.parse(readFileSync(resolve(process.cwd(), cwd, wallet), "utf8"))
|
|
17
20
|
})
|
|
18
21
|
|
|
@@ -21,7 +24,7 @@ describe("HyperBEAM", function () {
|
|
|
21
24
|
after(async () => hbeam.kill())
|
|
22
25
|
|
|
23
26
|
it("should run a HyperBEAM node", async () => {
|
|
24
|
-
const
|
|
25
|
-
assert.equal(
|
|
27
|
+
const { out } = await hb.getJSON({ path: "/~meta@1.0/build" })
|
|
28
|
+
assert.equal(out.node, "HyperBEAM")
|
|
26
29
|
})
|
|
27
30
|
})
|
package/esm/ao.js
CHANGED
package/esm/devs.js
CHANGED
|
@@ -1,47 +1,70 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
// fundamental
|
|
3
|
+
meta: { name: "meta@1.0", module: "dev_meta" },
|
|
4
|
+
json: { name: "json@1.0", module: "dev_codec_json" },
|
|
5
|
+
flat: { name: "flat@1.0", module: "dev_codec_flat" },
|
|
6
|
+
httpsig: { name: "httpsig@1.0", module: "dev_codec_httpsig" },
|
|
7
|
+
structured: { name: "structured@1.0", module: "dev_codec_structured" },
|
|
8
|
+
wao: { name: "wao@1.0", module: "dev_wao" },
|
|
9
|
+
|
|
10
|
+
// process
|
|
11
|
+
process: { name: "process@1.0", module: "dev_process" },
|
|
12
|
+
message: { name: "message@1.0", module: "dev_message" },
|
|
13
|
+
scheduler: { name: "scheduler@1.0", module: "dev_scheduler" },
|
|
14
|
+
|
|
15
|
+
// legacynet aos
|
|
8
16
|
"delegated-compute": {
|
|
9
17
|
name: "delegated-compute@1.0",
|
|
10
18
|
module: "dev_delegated_compute",
|
|
11
19
|
},
|
|
12
|
-
faff: { name: "faff@1.0", module: "dev_faff" },
|
|
13
|
-
flat: { name: "flat@1.0", module: "dev_codec_flat" },
|
|
14
20
|
"genesis-wasm": { name: "genesis-wasm@1.0", module: "dev_genesis_wasm" },
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
hyperbuddy: { name: "hyperbuddy@1.0", module: "dev_hyperbuddy" },
|
|
18
|
-
json: { name: "json@1.0", module: "dev_codec_json" },
|
|
19
|
-
"json-iface": { name: "json-iface@1.0", module: "dev_json_iface" },
|
|
20
|
-
"local-name": { name: "local-name@1.0", module: "dev_local_name" },
|
|
21
|
-
lookup: { name: "lookup@1.0", module: "dev_lookup" },
|
|
21
|
+
|
|
22
|
+
// hyper aos
|
|
22
23
|
lua: { name: "lua@5.3a", module: "dev_lua" },
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
|
|
25
|
+
// mainnet aos
|
|
26
|
+
wasi: { name: "wasi@1.0", module: "dev_wasi" },
|
|
27
|
+
"wasm-64": { name: "wasm-64@1.0", module: "dev_wasm" },
|
|
28
|
+
"json-iface": { name: "json-iface@1.0", module: "dev_json_iface" },
|
|
29
|
+
|
|
30
|
+
// process utils
|
|
31
|
+
"test-device": { name: "test-device@1.0", module: "dev_test" },
|
|
31
32
|
patch: { name: "patch@1.0", module: "dev_patch" },
|
|
32
|
-
poda: { name: "poda@1.0", module: "dev_poda" },
|
|
33
|
-
process: { name: "process@1.0", module: "dev_process" },
|
|
34
33
|
push: { name: "push@1.0", module: "dev_push" },
|
|
34
|
+
stack: { name: "stack@1.0", module: "dev_stack" },
|
|
35
|
+
multipass: { name: "multipass@1.0", module: "dev_multipass" },
|
|
36
|
+
|
|
37
|
+
// payment
|
|
38
|
+
faff: { name: "faff@1.0", module: "dev_faff" },
|
|
39
|
+
p4: { name: "p4@1.0", module: "dev_p4" },
|
|
40
|
+
"node-process": { name: "node-process@1.0", module: "dev_node_process" },
|
|
41
|
+
"simple-pay": { name: "simple-pay@1.0", module: "dev_simple_pay" },
|
|
42
|
+
|
|
43
|
+
// tested
|
|
44
|
+
cron: { name: "cron@1.0", module: "dev_cron" },
|
|
35
45
|
relay: { name: "relay@1.0", module: "dev_relay" },
|
|
36
46
|
router: { name: "router@1.0", module: "dev_router" },
|
|
37
|
-
|
|
38
|
-
|
|
47
|
+
|
|
48
|
+
// storage
|
|
49
|
+
cache: { name: "cache@1.0", module: "dev_cache" },
|
|
50
|
+
"local-name": { name: "local-name@1.0", module: "dev_local_name" },
|
|
51
|
+
lookup: { name: "lookup@1.0", module: "dev_lookup" },
|
|
52
|
+
name: { name: "name@1.0", module: "dev_name" },
|
|
53
|
+
|
|
54
|
+
// others
|
|
55
|
+
compute: { name: "compute@1.0", module: "dev_cu" },
|
|
56
|
+
dedup: { name: "dedup@1.0", module: "dev_dedup" },
|
|
57
|
+
manifest: { name: "manifest@1.0", module: "dev_manifest" },
|
|
58
|
+
monitor: { name: "monitor@1.0", module: "dev_monitor" },
|
|
59
|
+
|
|
60
|
+
// advanced
|
|
39
61
|
snp: { name: "snp@1.0", module: "dev_snp" },
|
|
40
|
-
stack: { name: "stack@1.0", module: "dev_stack" },
|
|
41
|
-
structured: { name: "structured@1.0", module: "dev_codec_structured" },
|
|
42
|
-
"test-device": { name: "test-device@1.0", module: "dev_test" },
|
|
43
62
|
volume: { name: "volume@1.0", module: "dev_volume" },
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
63
|
+
poda: { name: "poda@1.0", module: "dev_poda" },
|
|
64
|
+
greenzone: { name: "greenzone@1.0", module: "dev_green_zone" },
|
|
65
|
+
|
|
66
|
+
// misc
|
|
67
|
+
hyperbuddy: { name: "hyperbuddy@1.0", module: "dev_hyperbuddy" },
|
|
68
|
+
ans104: { name: "ans104@1.0", module: "dev_codec_ans104" },
|
|
69
|
+
cacheviz: { name: "cacheviz@1.0", module: "dev_cacheviz" },
|
|
47
70
|
}
|