@ninsei-labs/sdk 0.39.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.
Files changed (81) hide show
  1. package/CHANGELOG.md +866 -0
  2. package/LICENSE +21 -0
  3. package/README.md +187 -0
  4. package/engine/atomic/dleq2.js +330 -0
  5. package/engine/atomic/halfenc.js +205 -0
  6. package/engine/atomic/halves.js +119 -0
  7. package/engine/atomic/order-client.js +57 -0
  8. package/engine/atomic/order.js +132 -0
  9. package/engine/atomic/orderContext.js +70 -0
  10. package/engine/atomic/orderHalfCommit.js +29 -0
  11. package/engine/core/chainSource.js +306 -0
  12. package/engine/core/clock.js +40 -0
  13. package/engine/core/config.js +885 -0
  14. package/engine/core/finality.js +93 -0
  15. package/engine/core/format.js +168 -0
  16. package/engine/core/preSignGuards.js +495 -0
  17. package/engine/core/rfqSource.js +193 -0
  18. package/engine/core/sellWindow.js +43 -0
  19. package/engine/core/store.js +100 -0
  20. package/engine/core/swap.js +1153 -0
  21. package/engine/evm/amounts.js +131 -0
  22. package/engine/evm/auth.js +156 -0
  23. package/engine/evm/claimGas.js +87 -0
  24. package/engine/evm/depositor.js +127 -0
  25. package/engine/evm/dex.js +836 -0
  26. package/engine/evm/escrow.js +208 -0
  27. package/engine/evm/factory.js +149 -0
  28. package/engine/evm/fees.js +90 -0
  29. package/engine/evm/funding.js +309 -0
  30. package/engine/evm/gasReserve.js +88 -0
  31. package/engine/evm/index.js +123 -0
  32. package/engine/evm/injected.js +175 -0
  33. package/engine/evm/permit.js +125 -0
  34. package/engine/evm/prices.js +179 -0
  35. package/engine/evm/session.js +777 -0
  36. package/engine/mock/chain.js +98 -0
  37. package/engine/monero/address.js +265 -0
  38. package/engine/monero/halvesSweep.js +68 -0
  39. package/engine/monero/node.js +110 -0
  40. package/engine/monero/scan.js +325 -0
  41. package/engine/monero/swapKeys.js +69 -0
  42. package/engine/monero/unlock.js +46 -0
  43. package/engine/monero/wallet.js +168 -0
  44. package/engine/recovery/recoveryFile.js +363 -0
  45. package/engine/recovery/restore.js +176 -0
  46. package/engine/sdk/bridge.js +609 -0
  47. package/engine/ui/dom.js +90 -0
  48. package/engine/ui/walletModal.js +132 -0
  49. package/index.d.ts +1417 -0
  50. package/package.json +74 -0
  51. package/src/actions.mjs +72 -0
  52. package/src/adapters/evm-wallet.mjs +126 -0
  53. package/src/adapters/index.mjs +21 -0
  54. package/src/adapters/local-storage.mjs +32 -0
  55. package/src/adapters/monero-wallet.mjs +185 -0
  56. package/src/adapters/monero.mjs +51 -0
  57. package/src/adapters/node-test-evm-wallet.mjs +345 -0
  58. package/src/codes.mjs +188 -0
  59. package/src/config.mjs +277 -0
  60. package/src/engine.mjs +53 -0
  61. package/src/errors.mjs +24 -0
  62. package/src/http.mjs +72 -0
  63. package/src/index.mjs +256 -0
  64. package/src/legs/evm.mjs +118 -0
  65. package/src/legs/index.mjs +50 -0
  66. package/src/levelsWalkSpec.mjs +183 -0
  67. package/src/lock.mjs +140 -0
  68. package/src/order.mjs +212 -0
  69. package/src/preflight.mjs +137 -0
  70. package/src/primitives.mjs +47 -0
  71. package/src/quoteEip712.mjs +35 -0
  72. package/src/quoteEip712Spec.mjs +214 -0
  73. package/src/quotes.mjs +465 -0
  74. package/src/record.mjs +65 -0
  75. package/src/recovery.mjs +40 -0
  76. package/src/sim.mjs +37 -0
  77. package/src/swap-flow.mjs +492 -0
  78. package/src/swaps.mjs +935 -0
  79. package/src/sweep.mjs +222 -0
  80. package/src/wallet.mjs +164 -0
  81. package/src/xmr-arrival.mjs +289 -0
@@ -0,0 +1,90 @@
1
+ // GENERATED FILE - a byte-for-byte copy of the engine module www/js/ui/dom.js for the SDK package.
2
+ // Edit the source under www/js, then run: node tools/build-sdk-engine.mjs
3
+ // tools/check-sdk-engine.mjs reddens on any drift, so a stale copy cannot ship silently.
4
+ // Everything below this header is identical to the source.
5
+
6
+ // Крошечные DOM-хелперы. Никаких фреймворков: демка должна читаться глазами.
7
+
8
+ export function h(tag, attrs = {}, children = []) {
9
+ const el = document.createElement(tag);
10
+ for (const [k, v] of Object.entries(attrs || {})) {
11
+ if (v === null || v === undefined || v === false) continue;
12
+ if (k === "class") el.className = v;
13
+ else if (k === "html") el.innerHTML = v;
14
+ else if (k === "text") el.textContent = v;
15
+ // style пишем только через CSSOM: атрибут style="..." запрещён политикой CSP
16
+ // (style-src-attr), а el.style.* и cssText - разрешены. Так эта ловушка не вернётся.
17
+ else if (k === "style") {
18
+ if (typeof v === "string") el.style.cssText = v;
19
+ else Object.assign(el.style, v);
20
+ }
21
+ else if (k.startsWith("on") && typeof v === "function") el.addEventListener(k.slice(2).toLowerCase(), v);
22
+ else el.setAttribute(k, v === true ? "" : String(v));
23
+ }
24
+ const list = Array.isArray(children) ? children : [children];
25
+ for (const c of list) {
26
+ if (c === null || c === undefined || c === false) continue;
27
+ el.appendChild(typeof c === "string" || typeof c === "number" ? document.createTextNode(String(c)) : c);
28
+ }
29
+ return el;
30
+ }
31
+
32
+ export function esc(s) {
33
+ return String(s ?? "").replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
34
+ }
35
+
36
+ export function clear(node) {
37
+ while (node.firstChild) node.removeChild(node.firstChild);
38
+ }
39
+
40
+ export function icon(name, cls = "") {
41
+ return h("i", { class: `ki-filled ki-${name} ${cls}`.trim() });
42
+ }
43
+
44
+ export function toast(message, kind = "") {
45
+ const root = document.getElementById("arToasts");
46
+ if (!root) return;
47
+ const el = h("div", { class: `ar-toast ${kind ? "ar-toast-" + kind : ""}`, text: message });
48
+ root.appendChild(el);
49
+ setTimeout(() => {
50
+ el.style.transition = "opacity .25s";
51
+ el.style.opacity = "0";
52
+ setTimeout(() => el.remove(), 260);
53
+ }, 5200);
54
+ }
55
+
56
+ export function copy(text, label = "Copied") {
57
+ const done = () => toast(label, "ok");
58
+ if (navigator.clipboard?.writeText) {
59
+ navigator.clipboard.writeText(text).then(done, () => fallback());
60
+ } else fallback();
61
+ function fallback() {
62
+ const ta = document.createElement("textarea");
63
+ ta.value = text;
64
+ document.body.appendChild(ta);
65
+ ta.select();
66
+ try { document.execCommand("copy"); done(); } catch { toast("Copy failed", "bad"); }
67
+ ta.remove();
68
+ }
69
+ }
70
+
71
+ export function download(filename, text, mime = "application/json") {
72
+ const blob = new Blob([text], { type: mime });
73
+ const url = URL.createObjectURL(blob);
74
+ const a = h("a", { href: url, download: filename });
75
+ document.body.appendChild(a);
76
+ a.click();
77
+ a.remove();
78
+ setTimeout(() => URL.revokeObjectURL(url), 4000);
79
+ }
80
+
81
+ export function kv(label, value, opts = {}) {
82
+ return h("div", { class: `ar-kv ${opts.cls || ""}`.trim() }, [
83
+ h("span", { text: label }),
84
+ typeof value === "string" ? h("span", { text: value }) : value,
85
+ ]);
86
+ }
87
+
88
+ export function link(href, text, cls = "ar-linkbtn") {
89
+ return h("a", { href, target: "_blank", rel: "noopener", class: cls, text });
90
+ }
@@ -0,0 +1,132 @@
1
+ // GENERATED FILE - a byte-for-byte copy of the engine module www/js/ui/walletModal.js for the SDK package.
2
+ // Edit the source under www/js, then run: node tools/build-sdk-engine.mjs
3
+ // tools/check-sdk-engine.mjs reddens on any drift, so a stale copy cannot ship silently.
4
+ // Everything below this header is identical to the source.
5
+
6
+ // Своя модалка подключения кошелька: выбор браузерного кошелька и QR для WalletConnect.
7
+ //
8
+ // Список браузерных кошельков приходит снаружи (setChoices) - обнаружением занимается
9
+ // www/js/evm/injected.js по EIP-6963. Здесь только отрисовка: CSP запрещает inline-стили, поэтому
10
+ // всё идёт через dom.h(), а иконки кошельков - data:-URL, что разрешено img-src 'self' data:.
11
+ //
12
+ // Почему не модалка Reown (@reown/appkit): она рисует свои стили inline - и атрибутом style="",
13
+ // и целыми <style>-блоками. CSP демки запрещает и то, и другое (ловушка №1 в
14
+ // .hermes/docs/05-frontend-stack.md), ослаблять её ради модалки мы не стали. Поэтому модалку
15
+ // рисуем сами через dom.h() (стили идут через CSSOM), а QR - генератором qrcode из бандла
16
+ // в виде data:-URL (img-src 'self' data: в CSP это разрешает).
17
+ //
18
+ // Никаких секретов здесь нет: в QR лежит открытая ссылка сессии WalletConnect (wc:...),
19
+ // её и показывать пользователю не страшно - такое же показывает любая dapp.
20
+
21
+ import { h, copy } from "./dom.js";
22
+
23
+ export function openWalletModal({ title = "Connect a wallet", subtitle = "", hint = "" } = {}) {
24
+ const refs = {};
25
+
26
+ const overlay = h("div", { class: "ar-overlay" }, [
27
+ h("div", { class: "ar-modal" }, [
28
+ h("div", { class: "ar-modal-head" }, [
29
+ h("div", { class: "ar-modal-title", text: title }),
30
+ (refs.closeBtn = h("button", { class: "ar-modal-close", type: "button", title: "Close", text: "\u00d7" })),
31
+ ]),
32
+ (refs.subtitle = h("div", { class: "ar-modal-sub", text: subtitle })),
33
+ // Список браузерных кошельков: пустой, пока не пришёл от обнаружения (тогда и не виден).
34
+ (refs.choices = h("div", { class: "ar-modal-choices" })),
35
+ (refs.qrBox = h("div", { class: "ar-modal-qr", hidden: true }, [(refs.qr = h("img", { alt: "WalletConnect QR code" }))])),
36
+ (refs.uri = h("code", { class: "ar-modal-uri" })),
37
+ (refs.status = h("div", { class: "ar-modal-status" })),
38
+ h("div", { class: "ar-modal-actions" }, [
39
+ (refs.copyBtn = h("button", { class: "ar-btn-ghost", type: "button", text: "Copy link" })),
40
+ (refs.cancelBtn = h("button", { class: "ar-btn-ghost", type: "button", text: "Cancel" })),
41
+ ]),
42
+ (refs.hint = h("div", { class: "ar-modal-hint", text: hint })),
43
+ ]),
44
+ ]);
45
+
46
+ document.body.appendChild(overlay);
47
+
48
+ const closed = { value: false };
49
+ let onCancel = null;
50
+
51
+ // Два разных выхода из модалки, и разница принципиальная:
52
+ // close() - закрывает программно (например, сессия успешно установлена);
53
+ // cancel() - пользователь отказался: вот тут-то и надо гасить сессию, которую мы просили.
54
+ // Путать их нельзя: раньше успешное подключение закрывало модалку, а та дёргала обработчик
55
+ // отмены и удаляла только что созданную сессию (в логе SDK это видно как wc_sessionDelete
56
+ // через 85 мс после wc_sessionSettle).
57
+ function close() {
58
+ if (closed.value) return;
59
+ closed.value = true;
60
+ overlay.remove();
61
+ }
62
+
63
+ function cancel() {
64
+ if (closed.value) return;
65
+ close();
66
+ if (onCancel) onCancel();
67
+ }
68
+
69
+ refs.closeBtn.addEventListener("click", cancel);
70
+ refs.cancelBtn.addEventListener("click", cancel);
71
+ refs.copyBtn.addEventListener("click", () => {
72
+ if (refs.uri.textContent) copy(refs.uri.textContent, "WalletConnect link copied");
73
+ });
74
+ overlay.addEventListener("click", (e) => {
75
+ if (e.target === overlay) cancel();
76
+ });
77
+
78
+ // setChoices([{ key, name, icon, hint, onClick }]) - список браузерных кошельков и WalletConnect.
79
+ // Иконки только из data:-URL (их отдаёт сам кошелёк по EIP-6963): внешние адреса в CSP демки не
80
+ // разрешены, и это правильно - картинка из сети не должна влиять на то, какой кошелёк выбран.
81
+ function setChoices(list) {
82
+ refs.choices.innerHTML = "";
83
+ refs.choices.hidden = !list || !list.length;
84
+ for (const item of list || []) {
85
+ const btn = h("button", { class: "ar-modal-choice", type: "button" }, [
86
+ item.icon
87
+ ? h("img", { class: "ar-modal-choice-icon", src: item.icon, alt: "" })
88
+ : h("span", { class: "ar-modal-choice-icon ar-modal-choice-icon-empty" }),
89
+ h("span", { class: "ar-modal-choice-text" }, [
90
+ h("span", { class: "ar-modal-choice-name", text: item.name }),
91
+ item.hint ? h("span", { class: "ar-modal-choice-hint", text: item.hint }) : null,
92
+ ]),
93
+ ]);
94
+ // Дальше модалку гасит тот, кто обработал выбор: у браузерного кошелька окно показывает сам
95
+ // кошелёк, а у WalletConnect нужно ещё показать QR.
96
+ btn.addEventListener("click", () => {
97
+ if (closed.value) return;
98
+ item.onClick();
99
+ });
100
+ refs.choices.appendChild(btn);
101
+ }
102
+ return refs.choices;
103
+ }
104
+
105
+ return {
106
+ closed,
107
+ setChoices,
108
+ close,
109
+ cancel,
110
+ setOnCancel(fn) {
111
+ onCancel = fn;
112
+ },
113
+ update({ qrDataUrl, uri, status, subtitle, hint: hintText, error } = {}) {
114
+ if (closed.value) return;
115
+ if (qrDataUrl) {
116
+ refs.qr.src = qrDataUrl;
117
+ // Рамку показываем только когда QR реально есть: до выбора WalletConnect это пустое место.
118
+ refs.qrBox.hidden = false;
119
+ }
120
+ if (uri !== undefined) refs.uri.textContent = uri || "";
121
+ if (subtitle !== undefined) refs.subtitle.textContent = subtitle || "";
122
+ if (hintText !== undefined) refs.hint.textContent = hintText || "";
123
+ // error важнее status: иначе переданное «попробуйте ещё раз» перетирает сам текст ошибки, и
124
+ // причина отказа видна только в тосте (раньше error влиял лишь на цвет - мёртвый параметр).
125
+ const line = error || status;
126
+ if (line !== undefined) {
127
+ refs.status.className = "ar-modal-status" + (error ? " ar-modal-status-error" : "");
128
+ refs.status.textContent = line || "";
129
+ }
130
+ },
131
+ };
132
+ }