@polkahub/vault 0.1.0-pre.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.
@@ -0,0 +1,155 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { ModalContext, usePlugin, AddressIdentity, AddressBalance } from '@polkahub/context';
3
+ import { useSetSelectedAccount } from '@polkahub/select-account';
4
+ import { SourceButton, Button } from '@polkahub/ui-components';
5
+ import { useStateObservable } from '@react-rxjs/core';
6
+ import { Trash2, ChevronLeft, Camera } from 'lucide-react';
7
+ import { getSs58AddressInfo } from 'polkadot-api';
8
+ import { useContext, useEffect, useCallback } from 'react';
9
+ import vaultImg from './assets/vault.webp.js';
10
+ import { polkadotVaultProviderId } from './provider.js';
11
+ import { QrCamera } from './QrCamera.js';
12
+
13
+ const ManageVault = () => {
14
+ const { setContent } = useContext(ModalContext);
15
+ return /* @__PURE__ */ jsx(
16
+ SourceButton,
17
+ {
18
+ label: "Vault",
19
+ onClick: () => setContent(/* @__PURE__ */ jsx(VaultAccounts, { setContent })),
20
+ children: /* @__PURE__ */ jsx("img", { src: vaultImg, alt: "Vault", className: "h-10 rounded" })
21
+ }
22
+ );
23
+ };
24
+ const VaultAccounts = ({ setContent }) => {
25
+ const polkadotVaultProvider = usePlugin(
26
+ polkadotVaultProviderId
27
+ );
28
+ const vaultAccounts = useStateObservable(polkadotVaultProvider.accounts$);
29
+ const selectAccount = useSetSelectedAccount();
30
+ useEffect(() => {
31
+ if (vaultAccounts.length === 0) {
32
+ setContent(
33
+ /* @__PURE__ */ jsx(
34
+ ScanAccount,
35
+ {
36
+ onScanned: () => setContent(/* @__PURE__ */ jsx(VaultAccounts, { setContent })),
37
+ onClose: () => setContent(null)
38
+ }
39
+ )
40
+ );
41
+ }
42
+ }, [vaultAccounts, setContent]);
43
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
44
+ vaultAccounts.length ? /* @__PURE__ */ jsxs("div", { children: [
45
+ /* @__PURE__ */ jsx("h3", { className: "font-medium text-muted-foreground", children: "Added addresses" }),
46
+ /* @__PURE__ */ jsx("ul", { className: "space-y-2", children: vaultAccounts.map((acc) => /* @__PURE__ */ jsxs(
47
+ "li",
48
+ {
49
+ className: "flex gap-2 items-center",
50
+ children: [
51
+ /* @__PURE__ */ jsx(
52
+ Button,
53
+ {
54
+ variant: "outline",
55
+ className: "text-destructive",
56
+ type: "button",
57
+ onClick: () => polkadotVaultProvider.removeAccount(acc),
58
+ children: /* @__PURE__ */ jsx(Trash2, {})
59
+ }
60
+ ),
61
+ /* @__PURE__ */ jsx(AddressIdentity, { addr: acc.address }),
62
+ /* @__PURE__ */ jsx("div", { className: "grow" }),
63
+ /* @__PURE__ */ jsx(AddressBalance, { addr: acc.address }),
64
+ selectAccount && /* @__PURE__ */ jsx(
65
+ Button,
66
+ {
67
+ variant: "secondary",
68
+ onClick: () => {
69
+ selectAccount(acc);
70
+ },
71
+ children: "Select"
72
+ }
73
+ )
74
+ ]
75
+ },
76
+ `${acc.address}-${acc.genesis}`
77
+ )) })
78
+ ] }) : null,
79
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
80
+ /* @__PURE__ */ jsxs(
81
+ Button,
82
+ {
83
+ onClick: () => setContent(null),
84
+ variant: "secondary",
85
+ type: "button",
86
+ children: [
87
+ /* @__PURE__ */ jsx(ChevronLeft, {}),
88
+ "Back"
89
+ ]
90
+ }
91
+ ),
92
+ /* @__PURE__ */ jsxs(
93
+ Button,
94
+ {
95
+ type: "button",
96
+ onClick: () => setContent(
97
+ /* @__PURE__ */ jsx(
98
+ ScanAccount,
99
+ {
100
+ onScanned: () => setContent(/* @__PURE__ */ jsx(VaultAccounts, { setContent })),
101
+ onClose: () => setContent(/* @__PURE__ */ jsx(VaultAccounts, { setContent }))
102
+ }
103
+ )
104
+ ),
105
+ children: [
106
+ /* @__PURE__ */ jsx(Camera, {}),
107
+ "Scan new account"
108
+ ]
109
+ }
110
+ )
111
+ ] })
112
+ ] });
113
+ };
114
+ const ScanAccount = ({
115
+ onScanned,
116
+ onClose
117
+ }) => {
118
+ const polkadotVaultProvider = usePlugin(
119
+ polkadotVaultProviderId
120
+ );
121
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
122
+ /* @__PURE__ */ jsx("p", { children: "Scan your account QR from the vault app" }),
123
+ /* @__PURE__ */ jsx(
124
+ QrCamera,
125
+ {
126
+ onRead: useCallback(
127
+ (res) => {
128
+ const split = res.split(":");
129
+ if (split[0] !== "substrate" || split.length != 3 || !split[2].startsWith("0x")) {
130
+ throw new Error("Invalid QR");
131
+ }
132
+ const [, address, genesis] = split;
133
+ const account = getSs58AddressInfo(address);
134
+ if (!account.isValid) {
135
+ throw new Error("Invalid QR");
136
+ }
137
+ polkadotVaultProvider.addAccount({
138
+ address,
139
+ genesis
140
+ });
141
+ onScanned();
142
+ },
143
+ [onScanned, polkadotVaultProvider]
144
+ )
145
+ }
146
+ ),
147
+ /* @__PURE__ */ jsxs(Button, { onClick: onClose, variant: "secondary", type: "button", children: [
148
+ /* @__PURE__ */ jsx(ChevronLeft, {}),
149
+ "Back"
150
+ ] })
151
+ ] });
152
+ };
153
+
154
+ export { ManageVault };
155
+ //# sourceMappingURL=ManageVault.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ManageVault.js","sources":["../src/ManageVault.tsx"],"sourcesContent":["import {\n AddressBalance,\n AddressIdentity,\n ModalContext,\n usePlugin,\n} from \"@polkahub/context\";\nimport { useSetSelectedAccount } from \"@polkahub/select-account\";\nimport { Button, SourceButton } from \"@polkahub/ui-components\";\nimport { useStateObservable } from \"@react-rxjs/core\";\nimport { Camera, ChevronLeft, Trash2 } from \"lucide-react\";\nimport { getSs58AddressInfo } from \"polkadot-api\";\nimport { ReactNode, useCallback, useContext, useEffect, type FC } from \"react\";\nimport vaultImg from \"./assets/vault.webp\";\nimport { PolkadotVaultProvider, polkadotVaultProviderId } from \"./provider\";\nimport { QrCamera } from \"./QrCamera\";\n\nexport const ManageVault: FC = () => {\n const { setContent } = useContext(ModalContext)!;\n\n return (\n <SourceButton\n label=\"Vault\"\n onClick={() => setContent(<VaultAccounts setContent={setContent} />)}\n >\n <img src={vaultImg} alt=\"Vault\" className=\"h-10 rounded\" />\n </SourceButton>\n );\n};\n\nconst VaultAccounts: FC<{\n setContent: (element: ReactNode) => void;\n}> = ({ setContent }) => {\n const polkadotVaultProvider = usePlugin<PolkadotVaultProvider>(\n polkadotVaultProviderId\n )!;\n const vaultAccounts = useStateObservable(polkadotVaultProvider.accounts$);\n const selectAccount = useSetSelectedAccount();\n\n useEffect(() => {\n if (vaultAccounts.length === 0) {\n setContent(\n <ScanAccount\n onScanned={() =>\n setContent(<VaultAccounts setContent={setContent} />)\n }\n onClose={() => setContent(null)}\n />\n );\n }\n }, [vaultAccounts, setContent]);\n\n return (\n <div className=\"space-y-4\">\n {vaultAccounts.length ? (\n <div>\n <h3 className=\"font-medium text-muted-foreground\">Added addresses</h3>\n <ul className=\"space-y-2\">\n {vaultAccounts.map((acc) => (\n <li\n key={`${acc.address}-${acc.genesis}`}\n className=\"flex gap-2 items-center\"\n >\n <Button\n variant=\"outline\"\n className=\"text-destructive\"\n type=\"button\"\n onClick={() => polkadotVaultProvider.removeAccount(acc)}\n >\n <Trash2 />\n </Button>\n <AddressIdentity addr={acc.address} />\n <div className=\"grow\" />\n <AddressBalance addr={acc.address} />\n {selectAccount && (\n <Button\n variant=\"secondary\"\n onClick={() => {\n selectAccount(acc);\n }}\n >\n Select\n </Button>\n )}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n <div className=\"flex items-center justify-between\">\n <Button\n onClick={() => setContent(null)}\n variant=\"secondary\"\n type=\"button\"\n >\n <ChevronLeft />\n Back\n </Button>\n <Button\n type=\"button\"\n onClick={() =>\n setContent(\n <ScanAccount\n onScanned={() =>\n setContent(<VaultAccounts setContent={setContent} />)\n }\n onClose={() =>\n setContent(<VaultAccounts setContent={setContent} />)\n }\n />\n )\n }\n >\n <Camera />\n Scan new account\n </Button>\n </div>\n </div>\n );\n};\n\nconst ScanAccount: FC<{ onScanned: () => void; onClose: () => void }> = ({\n onScanned,\n onClose,\n}) => {\n const polkadotVaultProvider = usePlugin<PolkadotVaultProvider>(\n polkadotVaultProviderId\n )!;\n\n return (\n <div className=\"space-y-2\">\n <p>Scan your account QR from the vault app</p>\n <QrCamera\n onRead={useCallback(\n (res) => {\n // Expected format: `substrate:${Addr}:${genesis}`\n const split = res.split(\":\");\n if (\n split[0] !== \"substrate\" ||\n split.length != 3 ||\n !split[2].startsWith(\"0x\")\n ) {\n throw new Error(\"Invalid QR\");\n }\n const [, address, genesis] = split;\n const account = getSs58AddressInfo(address);\n if (!account.isValid) {\n throw new Error(\"Invalid QR\");\n }\n\n polkadotVaultProvider.addAccount({\n address,\n genesis,\n });\n onScanned();\n },\n [onScanned, polkadotVaultProvider]\n )}\n />\n <Button onClick={onClose} variant=\"secondary\" type=\"button\">\n <ChevronLeft />\n Back\n </Button>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useState, useCallback } from 'react';
3
+ import videoError from './assets/video-error.svg.js';
4
+ import videoPlaceholder from './assets/video-placeholder.svg.js';
5
+ import { QRCanvas, frontalCamera, frameLoop } from './qr/dom.js';
6
+
7
+ const canvas = new QRCanvas({});
8
+ const QrCamera = ({
9
+ onRead
10
+ }) => {
11
+ const [error, setError] = useState(null);
12
+ const ref = useCallback(
13
+ (element) => {
14
+ let stopped = false;
15
+ let camera = null;
16
+ async function showCamera() {
17
+ camera = await frontalCamera(element);
18
+ if (stopped) {
19
+ setTimeout(() => camera?.stop(), 1e3);
20
+ camera = null;
21
+ return;
22
+ }
23
+ if (!camera) {
24
+ setError("camera");
25
+ return;
26
+ }
27
+ const stop = frameLoop(() => {
28
+ if (!camera || stopped) {
29
+ stop();
30
+ return;
31
+ }
32
+ const res = camera.readFrame(canvas);
33
+ if (!res) return;
34
+ try {
35
+ onRead(res);
36
+ } catch (ex) {
37
+ console.error(ex);
38
+ setError("invalid_qr");
39
+ }
40
+ });
41
+ }
42
+ showCamera();
43
+ return () => {
44
+ stopped = true;
45
+ camera?.stop();
46
+ };
47
+ },
48
+ [onRead]
49
+ );
50
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("video", { ref, poster: error ? videoError : videoPlaceholder }) });
51
+ };
52
+
53
+ export { QrCamera };
54
+ //# sourceMappingURL=QrCamera.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QrCamera.js","sources":["../src/QrCamera.tsx"],"sourcesContent":["import { useCallback, useState, type FC } from \"react\";\nimport videoError from \"./assets/video-error.svg\";\nimport videoPlaceholder from \"./assets/video-placeholder.svg\";\nimport { frameLoop, frontalCamera, QRCanvas } from \"./qr/dom\";\n\nconst canvas = new QRCanvas({});\n\ntype QrCamera = Awaited<ReturnType<typeof frontalCamera>>;\n\nexport const QrCamera: FC<{ onRead: (payload: string) => void }> = ({\n onRead,\n}) => {\n const [error, setError] = useState<null | \"camera\" | \"invalid_qr\">(null);\n\n const ref = useCallback(\n (element: HTMLVideoElement) => {\n let stopped = false;\n let camera: QrCamera | null = null;\n async function showCamera() {\n camera = await frontalCamera(element);\n if (stopped) {\n setTimeout(() => camera?.stop(), 1000);\n camera = null;\n return;\n }\n if (!camera) {\n setError(\"camera\");\n return;\n }\n\n const stop = frameLoop(() => {\n if (!camera || stopped) {\n stop();\n return;\n }\n\n const res = camera.readFrame(canvas);\n if (!res) return;\n\n try {\n onRead(res);\n } catch (ex) {\n console.error(ex);\n setError(\"invalid_qr\");\n }\n });\n }\n showCamera();\n\n return () => {\n stopped = true;\n camera?.stop();\n };\n },\n [onRead]\n );\n\n return (\n <div>\n <video ref={ref} poster={error ? videoError : videoPlaceholder} />\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;AAKA,MAAM,MAAA,GAAS,IAAI,QAAA,CAAS,EAAE,CAAA;AAIvB,MAAM,WAAsD,CAAC;AAAA,EAClE;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAyC,IAAI,CAAA;AAEvE,EAAA,MAAM,GAAA,GAAM,WAAA;AAAA,IACV,CAAC,OAAA,KAA8B;AAC7B,MAAA,IAAI,OAAA,GAAU,KAAA;AACd,MAAA,IAAI,MAAA,GAA0B,IAAA;AAC9B,MAAA,eAAe,UAAA,GAAa;AAC1B,QAAA,MAAA,GAAS,MAAM,cAAc,OAAO,CAAA;AACpC,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,UAAA,CAAW,MAAM,MAAA,EAAQ,IAAA,EAAK,EAAG,GAAI,CAAA;AACrC,UAAA,MAAA,GAAS,IAAA;AACT,UAAA;AAAA,QACF;AACA,QAAA,IAAI,CAAC,MAAA,EAAQ;AACX,UAAA,QAAA,CAAS,QAAQ,CAAA;AACjB,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,IAAA,GAAO,UAAU,MAAM;AAC3B,UAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,YAAA,IAAA,EAAK;AACL,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,GAAA,GAAM,MAAA,CAAO,SAAA,CAAU,MAAM,CAAA;AACnC,UAAA,IAAI,CAAC,GAAA,EAAK;AAEV,UAAA,IAAI;AACF,YAAA,MAAA,CAAO,GAAG,CAAA;AAAA,UACZ,SAAS,EAAA,EAAI;AACX,YAAA,OAAA,CAAQ,MAAM,EAAE,CAAA;AAChB,YAAA,QAAA,CAAS,YAAY,CAAA;AAAA,UACvB;AAAA,QACF,CAAC,CAAA;AAAA,MACH;AACA,MAAA,UAAA,EAAW;AAEX,MAAA,OAAO,MAAM;AACX,QAAA,OAAA,GAAU,IAAA;AACV,QAAA,MAAA,EAAQ,IAAA,EAAK;AAAA,MACf,CAAA;AAAA,IACF,CAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,uBACE,GAAA,CAAC,SACC,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAM,KAAU,MAAA,EAAQ,KAAA,GAAQ,UAAA,GAAa,gBAAA,EAAkB,CAAA,EAClE,CAAA;AAEJ;;;;"}
@@ -0,0 +1,107 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogBody, Button } from '@polkahub/ui-components';
3
+ import { useStateObservable } from '@react-rxjs/core';
4
+ import { Camera, ChevronLeft } from 'lucide-react';
5
+ import { Binary } from 'polkadot-api';
6
+ import { mergeUint8 } from 'polkadot-api/utils';
7
+ import { useState, useCallback, useEffect } from 'react';
8
+ import { encodeQR } from './qr/index.js';
9
+ import { QrCamera } from './QrCamera.js';
10
+ import { usePlugin } from '@polkahub/context';
11
+ import { polkadotVaultProviderId } from './provider.js';
12
+
13
+ const VaultTxModal = () => {
14
+ const polkadotVaultProvider = usePlugin(
15
+ polkadotVaultProviderId
16
+ );
17
+ const activeTx = useStateObservable(polkadotVaultProvider.activeTx$);
18
+ return /* @__PURE__ */ jsx(Dialog, { open: !!activeTx, onOpenChange: polkadotVaultProvider.cancelTx, children: /* @__PURE__ */ jsxs(DialogContent, { children: [
19
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "Vault Transaction" }) }),
20
+ /* @__PURE__ */ jsx(DialogBody, { children: /* @__PURE__ */ jsx(VaultTxContent, { activeTx }) })
21
+ ] }) });
22
+ };
23
+ const VaultTxContent = ({ activeTx }) => {
24
+ const polkadotVaultProvider = usePlugin(
25
+ polkadotVaultProviderId
26
+ );
27
+ const [mode, setMode] = useState("tx");
28
+ const onRead = useCallback(
29
+ (res) => polkadotVaultProvider.setSignature(Binary.fromHex(res).asBytes()),
30
+ [polkadotVaultProvider]
31
+ );
32
+ if (mode === "tx") {
33
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
34
+ /* @__PURE__ */ jsx(VaultTx, { tx: activeTx }),
35
+ /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", onClick: () => setMode("sig"), children: [
36
+ /* @__PURE__ */ jsx(Camera, {}),
37
+ "Scan Signature"
38
+ ] })
39
+ ] });
40
+ }
41
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
42
+ /* @__PURE__ */ jsx(QrCamera, { onRead }),
43
+ /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", onClick: () => setMode("tx"), children: [
44
+ /* @__PURE__ */ jsx(ChevronLeft, {}),
45
+ "Back"
46
+ ] })
47
+ ] });
48
+ };
49
+ const uint8ToB64 = (value) => {
50
+ if ("toBase64" in value) {
51
+ return value.toBase64();
52
+ }
53
+ let binary = "";
54
+ for (let i = 0; i < value.length; i++) {
55
+ binary += String.fromCharCode(value[i]);
56
+ }
57
+ return window.btoa(binary);
58
+ };
59
+ const VaultTx = ({ tx }) => {
60
+ const [imgSrc, setImgSrc] = useState(null);
61
+ useEffect(() => {
62
+ if (!tx) return;
63
+ const frames = createFrames(tx);
64
+ const drawFrame = (frame) => {
65
+ const encoded = encodeQR(binaryToString(frame), "gif", {
66
+ encoding: "byte",
67
+ textEncoder: stringToBinary,
68
+ scale: 4
69
+ });
70
+ setImgSrc(`data:image/gif;base64,${uint8ToB64(encoded)}`);
71
+ };
72
+ drawFrame(frames[0]);
73
+ if (frames.length === 1) return;
74
+ let i = 1;
75
+ const token = setInterval(() => {
76
+ drawFrame(frames[i]);
77
+ i = (i + 1) % frames.length;
78
+ }, 300);
79
+ return () => clearInterval(token);
80
+ }, [tx]);
81
+ return /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
82
+ /* @__PURE__ */ jsx("p", { children: "Scan the transaction with your device" }),
83
+ /* @__PURE__ */ jsx("img", { src: imgSrc ?? void 0, className: "m-auto" })
84
+ ] });
85
+ };
86
+ const binaryToString = (value) => Array.from(value, (b) => String.fromCharCode(b)).join("");
87
+ const stringToBinary = (value) => Uint8Array.from(value, (c) => c.charCodeAt(0) & 255);
88
+ const createFrames = (payload) => {
89
+ const frames = [];
90
+ const frameSize = 1024;
91
+ let idx = 0;
92
+ while (idx < payload.length) {
93
+ frames.push(payload.subarray(idx, idx + frameSize));
94
+ idx += frameSize;
95
+ }
96
+ return frames.map(
97
+ (f, i) => mergeUint8([
98
+ new Uint8Array([0]),
99
+ Binary.fromHex(frames.length.toString(16).padStart(4, "0")).asBytes(),
100
+ Binary.fromHex(i.toString(16).padStart(4, "0")).asBytes(),
101
+ f
102
+ ])
103
+ );
104
+ };
105
+
106
+ export { VaultTxModal };
107
+ //# sourceMappingURL=VaultTxModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VaultTxModal.js","sources":["../src/VaultTxModal.tsx"],"sourcesContent":["import {\n Button,\n Dialog,\n DialogBody,\n DialogContent,\n DialogHeader,\n DialogTitle,\n} from \"@polkahub/ui-components\";\nimport { useStateObservable } from \"@react-rxjs/core\";\nimport { Camera, ChevronLeft } from \"lucide-react\";\nimport { Binary } from \"polkadot-api\";\nimport { mergeUint8 } from \"polkadot-api/utils\";\nimport { useCallback, useEffect, useState, type FC } from \"react\";\nimport encodeQr from \"./qr\";\nimport { QrCamera } from \"./QrCamera\";\nimport { usePlugin } from \"@polkahub/context\";\nimport { PolkadotVaultProvider, polkadotVaultProviderId } from \"./provider\";\n\nexport const VaultTxModal: FC = () => {\n const polkadotVaultProvider = usePlugin<PolkadotVaultProvider>(\n polkadotVaultProviderId\n )!;\n const activeTx = useStateObservable(polkadotVaultProvider.activeTx$);\n\n return (\n <Dialog open={!!activeTx} onOpenChange={polkadotVaultProvider.cancelTx}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Vault Transaction</DialogTitle>\n </DialogHeader>\n <DialogBody>\n <VaultTxContent activeTx={activeTx} />\n </DialogBody>\n </DialogContent>\n </Dialog>\n );\n};\n\nconst VaultTxContent: FC<{\n activeTx: Uint8Array<ArrayBufferLike> | null;\n}> = ({ activeTx }) => {\n const polkadotVaultProvider = usePlugin<PolkadotVaultProvider>(\n polkadotVaultProviderId\n )!;\n const [mode, setMode] = useState<\"tx\" | \"sig\">(\"tx\");\n\n const onRead = useCallback(\n (res: string) =>\n polkadotVaultProvider.setSignature(Binary.fromHex(res).asBytes()),\n [polkadotVaultProvider]\n );\n\n if (mode === \"tx\") {\n return (\n <div className=\"flex flex-col items-center gap-2\">\n <VaultTx tx={activeTx} />\n <Button type=\"button\" variant=\"outline\" onClick={() => setMode(\"sig\")}>\n <Camera />\n Scan Signature\n </Button>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col items-center gap-2\">\n <QrCamera onRead={onRead} />\n <Button type=\"button\" variant=\"outline\" onClick={() => setMode(\"tx\")}>\n <ChevronLeft />\n Back\n </Button>\n </div>\n );\n};\n\nconst uint8ToB64 = (value: Uint8Array) => {\n if (\"toBase64\" in value) {\n return (value as any).toBase64() as string;\n }\n\n let binary = \"\";\n for (let i = 0; i < value.length; i++) {\n binary += String.fromCharCode(value[i]);\n }\n return window.btoa(binary);\n};\n\nconst VaultTx: FC<{\n tx: Uint8Array<ArrayBufferLike> | null;\n}> = ({ tx }) => {\n const [imgSrc, setImgSrc] = useState<string | null>(null);\n\n useEffect(() => {\n if (!tx) return;\n\n const frames = createFrames(tx);\n const drawFrame = (frame: Uint8Array) => {\n const encoded = encodeQr(binaryToString(frame), \"gif\", {\n encoding: \"byte\",\n textEncoder: stringToBinary,\n scale: 4,\n });\n\n setImgSrc(`data:image/gif;base64,${uint8ToB64(encoded)}`);\n };\n drawFrame(frames[0]);\n\n if (frames.length === 1) return;\n\n let i = 1;\n const token = setInterval(() => {\n drawFrame(frames[i]);\n i = (i + 1) % frames.length;\n }, 300);\n return () => clearInterval(token);\n }, [tx]);\n\n return (\n <div className=\"text-center\">\n <p>Scan the transaction with your device</p>\n <img src={imgSrc ?? undefined} className=\"m-auto\" />\n </div>\n );\n};\n\nconst binaryToString = (value: Uint8Array) =>\n Array.from(value, (b) => String.fromCharCode(b)).join(\"\");\nconst stringToBinary = (value: string) =>\n Uint8Array.from(value, (c) => c.charCodeAt(0) & 0xff);\n\nconst createFrames = (payload: Uint8Array): Uint8Array[] => {\n const frames = [];\n const frameSize = 1024;\n\n let idx = 0;\n while (idx < payload.length) {\n frames.push(payload.subarray(idx, idx + frameSize));\n idx += frameSize;\n }\n\n return frames.map(\n (f, i): Uint8Array =>\n mergeUint8([\n new Uint8Array([0x00]),\n Binary.fromHex(frames.length.toString(16).padStart(4, \"0\")).asBytes(),\n Binary.fromHex(i.toString(16).padStart(4, \"0\")).asBytes(),\n f,\n ])\n );\n};\n"],"names":["encodeQr"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ var vaultImg = "data:image/webp;base64,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";
2
+
3
+ export { vaultImg as default };
4
+ //# sourceMappingURL=vault.webp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.webp.js","sources":["../../src/assets/vault.webp"],"sourcesContent":["export default \"data:image/webp;base64,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\""],"names":[],"mappings":"AAAA,eAAe;;;;"}
@@ -0,0 +1,4 @@
1
+ var videoError = "data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22640%22%20height%3D%22360%22%20viewBox%3D%220%200%20640%20360%22%20role%3D%22img%22%20aria-labelledby%3D%22title%20desc%22%3E%3Ctitle%20id%3D%22title%22%3ECamera%20error%20placeholder%3C%2Ftitle%3E%3Cdesc%20id%3D%22desc%22%3ERed%20tinted%20panel%20with%20a%20strikethrough%20camera%20icon%20indicating%20the%20camera%20failed%20to%20load.%3C%2Fdesc%3E%3Cdefs%3E%3ClinearGradient%20id%3D%22bg%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%22100%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23ffeaea%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23fcd4d4%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%22640%22%20height%3D%22360%22%20fill%3D%22url%28%23bg%29%22%20rx%3D%2216%22%2F%3E%3Cg%20fill%3D%22none%22%20stroke%3D%22%23c62828%22%20stroke-width%3D%2212%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%22200%22%20y%3D%22120%22%20width%3D%22180%22%20height%3D%22120%22%20rx%3D%2224%22%2F%3E%3Cpath%20d%3D%22M380%20140l60-32v144l-60-32z%22%20fill%3D%22%23ffeaea%22%2F%3E%3Cline%20x1%3D%22180%22%20y1%3D%22110%22%20x2%3D%22460%22%20y2%3D%22250%22%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%22320%22%20y%3D%22300%22%20text-anchor%3D%22middle%22%20font-family%3D%22sans-serif%22%20font-size%3D%2224%22%20fill%3D%22%238e1b1b%22%3EUnable%20to%20access%20camera%3C%2Ftext%3E%3C%2Fsvg%3E";
2
+
3
+ export { videoError as default };
4
+ //# sourceMappingURL=video-error.svg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-error.svg.js","sources":["../../src/assets/video-error.svg"],"sourcesContent":["export default \"data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22640%22%20height%3D%22360%22%20viewBox%3D%220%200%20640%20360%22%20role%3D%22img%22%20aria-labelledby%3D%22title%20desc%22%3E%3Ctitle%20id%3D%22title%22%3ECamera%20error%20placeholder%3C%2Ftitle%3E%3Cdesc%20id%3D%22desc%22%3ERed%20tinted%20panel%20with%20a%20strikethrough%20camera%20icon%20indicating%20the%20camera%20failed%20to%20load.%3C%2Fdesc%3E%3Cdefs%3E%3ClinearGradient%20id%3D%22bg%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%22100%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23ffeaea%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23fcd4d4%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%22640%22%20height%3D%22360%22%20fill%3D%22url%28%23bg%29%22%20rx%3D%2216%22%2F%3E%3Cg%20fill%3D%22none%22%20stroke%3D%22%23c62828%22%20stroke-width%3D%2212%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%22200%22%20y%3D%22120%22%20width%3D%22180%22%20height%3D%22120%22%20rx%3D%2224%22%2F%3E%3Cpath%20d%3D%22M380%20140l60-32v144l-60-32z%22%20fill%3D%22%23ffeaea%22%2F%3E%3Cline%20x1%3D%22180%22%20y1%3D%22110%22%20x2%3D%22460%22%20y2%3D%22250%22%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%22320%22%20y%3D%22300%22%20text-anchor%3D%22middle%22%20font-family%3D%22sans-serif%22%20font-size%3D%2224%22%20fill%3D%22%238e1b1b%22%3EUnable%20to%20access%20camera%3C%2Ftext%3E%3C%2Fsvg%3E\""],"names":[],"mappings":"AAAA,iBAAe;;;;"}
@@ -0,0 +1,4 @@
1
+ var videoPlaceholder = "data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22640%22%20height%3D%22360%22%20viewBox%3D%220%200%20640%20360%22%20role%3D%22img%22%20aria-labelledby%3D%22title%20desc%22%3E%3Ctitle%20id%3D%22title%22%3ECamera%20loading%20placeholder%3C%2Ftitle%3E%3Cdesc%20id%3D%22desc%22%3EMuted%20gradient%20background%20with%20a%20camera%20icon%20to%20show%20while%20the%20video%20stream%20is%20loading.%3C%2Fdesc%3E%3Cdefs%3E%3ClinearGradient%20id%3D%22bg%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%22100%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23f6f7f8%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23e6e8eb%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%22640%22%20height%3D%22360%22%20fill%3D%22url%28%23bg%29%22%20rx%3D%2216%22%2F%3E%3Cg%20fill%3D%22none%22%20stroke%3D%22%239aa0a6%22%20stroke-width%3D%2210%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%22200%22%20y%3D%22120%22%20width%3D%22180%22%20height%3D%22120%22%20rx%3D%2224%22%2F%3E%3Cpath%20d%3D%22M380%20140l60-32v144l-60-32z%22%20fill%3D%22%23f6f7f8%22%2F%3E%3Ccircle%20cx%3D%22260%22%20cy%3D%22180%22%20r%3D%2212%22%2F%3E%3Cpath%20d%3D%22M240%20220h100%22%20stroke-width%3D%228%22%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%22320%22%20y%3D%22300%22%20text-anchor%3D%22middle%22%20font-family%3D%22sans-serif%22%20font-size%3D%2224%22%20fill%3D%22%237c828a%22%3ECamera%20loading%E2%80%A6%3C%2Ftext%3E%3C%2Fsvg%3E";
2
+
3
+ export { videoPlaceholder as default };
4
+ //# sourceMappingURL=video-placeholder.svg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-placeholder.svg.js","sources":["../../src/assets/video-placeholder.svg"],"sourcesContent":["export default \"data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22640%22%20height%3D%22360%22%20viewBox%3D%220%200%20640%20360%22%20role%3D%22img%22%20aria-labelledby%3D%22title%20desc%22%3E%3Ctitle%20id%3D%22title%22%3ECamera%20loading%20placeholder%3C%2Ftitle%3E%3Cdesc%20id%3D%22desc%22%3EMuted%20gradient%20background%20with%20a%20camera%20icon%20to%20show%20while%20the%20video%20stream%20is%20loading.%3C%2Fdesc%3E%3Cdefs%3E%3ClinearGradient%20id%3D%22bg%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%22100%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23f6f7f8%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23e6e8eb%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%22640%22%20height%3D%22360%22%20fill%3D%22url%28%23bg%29%22%20rx%3D%2216%22%2F%3E%3Cg%20fill%3D%22none%22%20stroke%3D%22%239aa0a6%22%20stroke-width%3D%2210%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%22200%22%20y%3D%22120%22%20width%3D%22180%22%20height%3D%22120%22%20rx%3D%2224%22%2F%3E%3Cpath%20d%3D%22M380%20140l60-32v144l-60-32z%22%20fill%3D%22%23f6f7f8%22%2F%3E%3Ccircle%20cx%3D%22260%22%20cy%3D%22180%22%20r%3D%2212%22%2F%3E%3Cpath%20d%3D%22M240%20220h100%22%20stroke-width%3D%228%22%2F%3E%3C%2Fg%3E%3Ctext%20x%3D%22320%22%20y%3D%22300%22%20text-anchor%3D%22middle%22%20font-family%3D%22sans-serif%22%20font-size%3D%2224%22%20fill%3D%22%237c828a%22%3ECamera%20loading%E2%80%A6%3C%2Ftext%3E%3C%2Fsvg%3E\""],"names":[],"mappings":"AAAA,uBAAe;;;;"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { createPolkadotVaultProvider, polkadotVaultProviderId } from './provider.js';
2
+ export { ManageVault } from './ManageVault.js';
3
+ export { VaultTxModal } from './VaultTxModal.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -0,0 +1,165 @@
1
+ import { createV4Tx } from '@polkadot-api/signers-common';
2
+ import { unifyMetadata, decAnyMetadata, compact } from '@polkadot-api/substrate-bindings';
3
+ import { localStorageProvider, persistedState } from '@polkahub/plugin';
4
+ import { state, withDefault } from '@react-rxjs/core';
5
+ import { createSignal } from '@react-rxjs/utils';
6
+ import { getSs58AddressInfo, Binary } from 'polkadot-api';
7
+ import { mergeUint8 } from 'polkadot-api/utils';
8
+ import { merge, map, race, firstValueFrom } from 'rxjs';
9
+
10
+ const polkadotVaultProviderId = "polkadot-vault";
11
+ const createPolkadotVaultProvider = (opts) => {
12
+ const { persist } = {
13
+ persist: localStorageProvider(polkadotVaultProviderId),
14
+ ...opts
15
+ };
16
+ const [vaultAccounts$, setVaultAccounts] = persistedState(
17
+ persist,
18
+ []
19
+ );
20
+ const [newTx$, setTx] = createSignal();
21
+ const [scannedSignature$, setSignature] = createSignal();
22
+ const [cancelledTx$, cancelTx] = createSignal();
23
+ const activeTx$ = state(
24
+ merge(newTx$, merge(scannedSignature$, cancelledTx$).pipe(map(() => null))),
25
+ null
26
+ );
27
+ const currentScannedSignature$ = race(
28
+ scannedSignature$,
29
+ merge(newTx$, cancelledTx$).pipe(map(() => null))
30
+ );
31
+ const createVaultSigner = ({
32
+ address,
33
+ genesis
34
+ }) => {
35
+ const info = getSs58AddressInfo(address);
36
+ if (!info.isValid) {
37
+ throw new Error("Invalid SS58 address " + address);
38
+ }
39
+ const publicKey = info.publicKey;
40
+ return {
41
+ publicKey,
42
+ async signBytes(data) {
43
+ const qrPayload = createQrMessage(
44
+ 1 /* Sr25519 */,
45
+ publicKey,
46
+ data,
47
+ Binary.fromHex(genesis).asBytes()
48
+ );
49
+ setTx(qrPayload);
50
+ const signature = await firstValueFrom(currentScannedSignature$);
51
+ if (!signature) {
52
+ throw new Error("Cancelled");
53
+ }
54
+ return signature;
55
+ },
56
+ async signTx(callData, signedExtensions, metadata) {
57
+ const decMeta = unifyMetadata(decAnyMetadata(metadata));
58
+ const extra = [];
59
+ const additionalSigned = [];
60
+ decMeta.extrinsic.signedExtensions.map(({ identifier }) => {
61
+ const signedExtension = signedExtensions[identifier];
62
+ if (!signedExtension)
63
+ throw new Error(`Missing ${identifier} signed extension`);
64
+ extra.push(signedExtension.value);
65
+ additionalSigned.push(signedExtension.additionalSigned);
66
+ });
67
+ const extensions = mergeUint8([...extra, ...additionalSigned]);
68
+ const qrPayload = createQrTransaction(
69
+ 1 /* Sr25519 */,
70
+ publicKey,
71
+ callData,
72
+ extensions,
73
+ Binary.fromHex(genesis).asBytes()
74
+ );
75
+ setTx(qrPayload);
76
+ const signature = await firstValueFrom(currentScannedSignature$);
77
+ if (!signature) {
78
+ throw new Error("Cancelled");
79
+ }
80
+ const tx = createV4Tx(
81
+ decMeta,
82
+ publicKey,
83
+ // Remove encryption code, we already know it
84
+ signature.slice(1),
85
+ extra,
86
+ callData,
87
+ // TODO schema?
88
+ "Sr25519"
89
+ );
90
+ return tx;
91
+ }
92
+ };
93
+ };
94
+ const accountInfoToAccount = (info) => ({
95
+ provider: polkadotVaultProviderId,
96
+ address: info.address,
97
+ genesis: info.genesis,
98
+ signer: createVaultSigner(info)
99
+ });
100
+ const accounts$ = vaultAccounts$.pipeState(
101
+ map((accounts) => accounts.map(accountInfoToAccount)),
102
+ withDefault([])
103
+ );
104
+ return {
105
+ id: polkadotVaultProviderId,
106
+ serialize: ({ address, genesis, provider }) => ({
107
+ address,
108
+ provider,
109
+ extra: genesis
110
+ }),
111
+ deserialize: (account) => firstValueFrom(
112
+ vaultAccounts$.pipe(
113
+ map(
114
+ (accounts) => accounts.find(
115
+ (acc) => acc.address === account.address && acc.genesis === account.extra
116
+ ) ?? null
117
+ ),
118
+ map(
119
+ (info) => info ? accountInfoToAccount(info) : null
120
+ )
121
+ )
122
+ ),
123
+ accounts$,
124
+ activeTx$,
125
+ cancelTx,
126
+ setSignature,
127
+ setTx,
128
+ setAccounts: setVaultAccounts,
129
+ addAccount: (account) => {
130
+ const accountKey = `${account.address}:${account.genesis}`;
131
+ setVaultAccounts((oldAccounts) => {
132
+ if (oldAccounts.some(
133
+ (acc) => `${acc.address}:${acc.genesis}` === accountKey
134
+ ))
135
+ return oldAccounts;
136
+ return [...oldAccounts, account];
137
+ });
138
+ return accountInfoToAccount(account);
139
+ },
140
+ removeAccount: (addr) => setVaultAccounts((v) => v.filter((acc) => acc !== addr))
141
+ };
142
+ };
143
+ const VAULT_QR_HEADER = new Uint8Array([83]);
144
+ const createQrTransaction = (encrpytion, publicKey, callData, extensions, genesisHash) => mergeUint8([
145
+ VAULT_QR_HEADER,
146
+ new Uint8Array([encrpytion]),
147
+ new Uint8Array([2 /* Tx */]),
148
+ publicKey,
149
+ compact.enc(callData.length),
150
+ callData,
151
+ extensions,
152
+ genesisHash
153
+ ]);
154
+ const createQrMessage = (encrpytion, publicKey, data, genesisHash) => mergeUint8([
155
+ VAULT_QR_HEADER,
156
+ new Uint8Array([encrpytion]),
157
+ new Uint8Array([3 /* Message */]),
158
+ publicKey,
159
+ compact.enc(data.length),
160
+ data,
161
+ genesisHash
162
+ ]);
163
+
164
+ export { createPolkadotVaultProvider, polkadotVaultProviderId };
165
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sources":["../src/provider.ts"],"sourcesContent":["import { createV4Tx } from \"@polkadot-api/signers-common\";\nimport {\n compact,\n decAnyMetadata,\n unifyMetadata,\n} from \"@polkadot-api/substrate-bindings\";\nimport {\n Account,\n localStorageProvider,\n persistedState,\n PersistenceProvider,\n Plugin,\n} from \"@polkahub/plugin\";\nimport { DefaultedStateObservable, state, withDefault } from \"@react-rxjs/core\";\nimport { createSignal } from \"@react-rxjs/utils\";\nimport {\n Binary,\n getSs58AddressInfo,\n HexString,\n PolkadotSigner,\n SS58String,\n} from \"polkadot-api\";\nimport { mergeUint8 } from \"polkadot-api/utils\";\nimport { firstValueFrom, map, merge, race } from \"rxjs\";\n\nexport const polkadotVaultProviderId = \"polkadot-vault\";\nexport interface VaultAccountInfo {\n address: SS58String;\n genesis: HexString;\n}\nexport interface PolkadotVaultAccount extends Account {\n provider: \"polkadot-vault\";\n genesis: HexString;\n}\n\nexport interface PolkadotVaultProvider extends Plugin<PolkadotVaultAccount> {\n id: \"polkadot-vault\";\n accounts$: DefaultedStateObservable<PolkadotVaultAccount[]>;\n\n setAccounts: (payload: VaultAccountInfo[]) => void;\n addAccount: (payload: VaultAccountInfo) => PolkadotVaultAccount;\n removeAccount: (payload: VaultAccountInfo) => void;\n\n activeTx$: DefaultedStateObservable<Uint8Array<ArrayBufferLike> | null>;\n setTx: (payload: Uint8Array<ArrayBufferLike>) => void;\n setSignature: (payload: Uint8Array<ArrayBufferLike>) => void;\n cancelTx: () => void;\n}\n\nexport const createPolkadotVaultProvider = (\n opts?: Partial<{\n persist: PersistenceProvider;\n }>\n): PolkadotVaultProvider => {\n const { persist } = {\n persist: localStorageProvider(polkadotVaultProviderId),\n ...opts,\n };\n\n const [vaultAccounts$, setVaultAccounts] = persistedState(\n persist,\n [] as VaultAccountInfo[]\n );\n\n const [newTx$, setTx] = createSignal<Uint8Array>();\n const [scannedSignature$, setSignature] = createSignal<Uint8Array>();\n const [cancelledTx$, cancelTx] = createSignal();\n\n const activeTx$ = state(\n merge(newTx$, merge(scannedSignature$, cancelledTx$).pipe(map(() => null))),\n null\n );\n const currentScannedSignature$ = race(\n scannedSignature$,\n merge(newTx$, cancelledTx$).pipe(map(() => null))\n );\n\n const createVaultSigner = ({\n address,\n genesis,\n }: VaultAccountInfo): PolkadotSigner => {\n const info = getSs58AddressInfo(address);\n if (!info.isValid) {\n throw new Error(\"Invalid SS58 address \" + address);\n }\n\n const publicKey = info.publicKey;\n\n return {\n publicKey,\n async signBytes(data) {\n const qrPayload = createQrMessage(\n VaultQrEncryption.Sr25519,\n publicKey,\n data,\n Binary.fromHex(genesis).asBytes()\n );\n setTx(qrPayload);\n\n const signature = await firstValueFrom(currentScannedSignature$);\n if (!signature) {\n throw new Error(\"Cancelled\");\n }\n\n return signature;\n },\n async signTx(callData, signedExtensions, metadata) {\n const decMeta = unifyMetadata(decAnyMetadata(metadata));\n const extra: Array<Uint8Array> = [];\n const additionalSigned: Array<Uint8Array> = [];\n decMeta.extrinsic.signedExtensions.map(({ identifier }) => {\n const signedExtension = signedExtensions[identifier];\n if (!signedExtension)\n throw new Error(`Missing ${identifier} signed extension`);\n extra.push(signedExtension.value);\n additionalSigned.push(signedExtension.additionalSigned);\n });\n const extensions = mergeUint8([...extra, ...additionalSigned]);\n\n const qrPayload = createQrTransaction(\n VaultQrEncryption.Sr25519,\n publicKey,\n callData,\n extensions,\n Binary.fromHex(genesis).asBytes()\n );\n setTx(qrPayload);\n\n const signature = await firstValueFrom(currentScannedSignature$);\n if (!signature) {\n throw new Error(\"Cancelled\");\n }\n\n const tx = createV4Tx(\n decMeta,\n publicKey,\n // Remove encryption code, we already know it\n signature.slice(1),\n extra,\n callData,\n // TODO schema?\n \"Sr25519\"\n );\n\n return tx;\n },\n };\n };\n\n const accountInfoToAccount = (\n info: VaultAccountInfo\n ): PolkadotVaultAccount => ({\n provider: polkadotVaultProviderId,\n address: info.address,\n genesis: info.genesis,\n signer: createVaultSigner(info),\n });\n\n const accounts$ = vaultAccounts$.pipeState(\n map((accounts) => accounts.map(accountInfoToAccount)),\n withDefault([])\n );\n\n return {\n id: polkadotVaultProviderId,\n serialize: ({ address, genesis, provider }) => ({\n address,\n provider,\n extra: genesis,\n }),\n deserialize: (account) =>\n firstValueFrom(\n vaultAccounts$.pipe(\n map(\n (accounts) =>\n accounts.find(\n (acc) =>\n acc.address === account.address &&\n acc.genesis === account.extra\n ) ?? null\n ),\n map((info): PolkadotVaultAccount | null =>\n info ? accountInfoToAccount(info) : null\n )\n )\n ),\n accounts$,\n activeTx$,\n cancelTx,\n setSignature,\n setTx,\n setAccounts: setVaultAccounts,\n addAccount: (account) => {\n const accountKey = `${account.address}:${account.genesis}`;\n setVaultAccounts((oldAccounts) => {\n if (\n oldAccounts.some(\n (acc) => `${acc.address}:${acc.genesis}` === accountKey\n )\n )\n return oldAccounts;\n return [...oldAccounts, account];\n });\n return accountInfoToAccount(account);\n },\n removeAccount: (addr) =>\n setVaultAccounts((v) => v.filter((acc) => acc !== addr)),\n };\n};\n\n// https://github.com/novasamatech/parity-signer/blob/738e34f0b60f86b718267cfe1ca766bd291640ed/docs/src/development/UOS.md\nconst VAULT_QR_HEADER = new Uint8Array([0x53]);\nenum VaultQrEncryption {\n Ed25519 = 0x00,\n Sr25519 = 0x01,\n Ecdsa = 0x02,\n Unsigned = 0xff,\n}\nenum VaultQrPayloadType {\n LegacyTx = 0x00,\n Tx = 0x02,\n Message = 0x03,\n BulkTx = 0x04,\n LoadMetadataUpdate = 0x80,\n LoadTypesUpdate = 0x81,\n AddSpecsUpdate = 0xc1,\n DerivationsImport = 0xce,\n}\n\nconst createQrTransaction = (\n encrpytion: VaultQrEncryption,\n publicKey: Uint8Array,\n callData: Uint8Array,\n extensions: Uint8Array,\n genesisHash: Uint8Array\n) =>\n mergeUint8([\n VAULT_QR_HEADER,\n new Uint8Array([encrpytion]),\n new Uint8Array([VaultQrPayloadType.Tx]),\n publicKey,\n compact.enc(callData.length),\n callData,\n extensions,\n genesisHash,\n ]);\n\nconst createQrMessage = (\n encrpytion: VaultQrEncryption,\n publicKey: Uint8Array,\n data: Uint8Array,\n genesisHash: Uint8Array\n) =>\n mergeUint8([\n VAULT_QR_HEADER,\n new Uint8Array([encrpytion]),\n new Uint8Array([VaultQrPayloadType.Message]),\n publicKey,\n compact.enc(data.length),\n data,\n genesisHash,\n ]);\n"],"names":[],"mappings":";;;;;;;;;AAyBO,MAAM,uBAAA,GAA0B;AAwBhC,MAAM,2BAAA,GAA8B,CACzC,IAAA,KAG0B;AAC1B,EAAA,MAAM,EAAE,SAAQ,GAAI;AAAA,IAClB,OAAA,EAAS,qBAAqB,uBAAuB,CAAA;AAAA,IACrD,GAAG;AAAA,GACL;AAEA,EAAA,MAAM,CAAC,cAAA,EAAgB,gBAAgB,CAAA,GAAI,cAAA;AAAA,IACzC,OAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,CAAC,MAAA,EAAQ,KAAK,CAAA,GAAI,YAAA,EAAyB;AACjD,EAAA,MAAM,CAAC,iBAAA,EAAmB,YAAY,CAAA,GAAI,YAAA,EAAyB;AACnE,EAAA,MAAM,CAAC,YAAA,EAAc,QAAQ,CAAA,GAAI,YAAA,EAAa;AAE9C,EAAA,MAAM,SAAA,GAAY,KAAA;AAAA,IAChB,KAAA,CAAM,MAAA,EAAQ,KAAA,CAAM,iBAAA,EAAmB,YAAY,CAAA,CAAE,IAAA,CAAK,GAAA,CAAI,MAAM,IAAI,CAAC,CAAC,CAAA;AAAA,IAC1E;AAAA,GACF;AACA,EAAA,MAAM,wBAAA,GAA2B,IAAA;AAAA,IAC/B,iBAAA;AAAA,IACA,KAAA,CAAM,QAAQ,YAAY,CAAA,CAAE,KAAK,GAAA,CAAI,MAAM,IAAI,CAAC;AAAA,GAClD;AAEA,EAAA,MAAM,oBAAoB,CAAC;AAAA,IACzB,OAAA;AAAA,IACA;AAAA,GACF,KAAwC;AACtC,IAAA,MAAM,IAAA,GAAO,mBAAmB,OAAO,CAAA;AACvC,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,MAAA,MAAM,IAAI,KAAA,CAAM,uBAAA,GAA0B,OAAO,CAAA;AAAA,IACnD;AAEA,IAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AAEvB,IAAA,OAAO;AAAA,MACL,SAAA;AAAA,MACA,MAAM,UAAU,IAAA,EAAM;AACpB,QAAA,MAAM,SAAA,GAAY,eAAA;AAAA,UAChB,CAAA;AAAA,UACA,SAAA;AAAA,UACA,IAAA;AAAA,UACA,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CAAE,OAAA;AAAQ,SAClC;AACA,QAAA,KAAA,CAAM,SAAS,CAAA;AAEf,QAAA,MAAM,SAAA,GAAY,MAAM,cAAA,CAAe,wBAAwB,CAAA;AAC/D,QAAA,IAAI,CAAC,SAAA,EAAW;AACd,UAAA,MAAM,IAAI,MAAM,WAAW,CAAA;AAAA,QAC7B;AAEA,QAAA,OAAO,SAAA;AAAA,MACT,CAAA;AAAA,MACA,MAAM,MAAA,CAAO,QAAA,EAAU,gBAAA,EAAkB,QAAA,EAAU;AACjD,QAAA,MAAM,OAAA,GAAU,aAAA,CAAc,cAAA,CAAe,QAAQ,CAAC,CAAA;AACtD,QAAA,MAAM,QAA2B,EAAC;AAClC,QAAA,MAAM,mBAAsC,EAAC;AAC7C,QAAA,OAAA,CAAQ,UAAU,gBAAA,CAAiB,GAAA,CAAI,CAAC,EAAE,YAAW,KAAM;AACzD,UAAA,MAAM,eAAA,GAAkB,iBAAiB,UAAU,CAAA;AACnD,UAAA,IAAI,CAAC,eAAA;AACH,YAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,UAAU,CAAA,iBAAA,CAAmB,CAAA;AAC1D,UAAA,KAAA,CAAM,IAAA,CAAK,gBAAgB,KAAK,CAAA;AAChC,UAAA,gBAAA,CAAiB,IAAA,CAAK,gBAAgB,gBAAgB,CAAA;AAAA,QACxD,CAAC,CAAA;AACD,QAAA,MAAM,aAAa,UAAA,CAAW,CAAC,GAAG,KAAA,EAAO,GAAG,gBAAgB,CAAC,CAAA;AAE7D,QAAA,MAAM,SAAA,GAAY,mBAAA;AAAA,UAChB,CAAA;AAAA,UACA,SAAA;AAAA,UACA,QAAA;AAAA,UACA,UAAA;AAAA,UACA,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CAAE,OAAA;AAAQ,SAClC;AACA,QAAA,KAAA,CAAM,SAAS,CAAA;AAEf,QAAA,MAAM,SAAA,GAAY,MAAM,cAAA,CAAe,wBAAwB,CAAA;AAC/D,QAAA,IAAI,CAAC,SAAA,EAAW;AACd,UAAA,MAAM,IAAI,MAAM,WAAW,CAAA;AAAA,QAC7B;AAEA,QAAA,MAAM,EAAA,GAAK,UAAA;AAAA,UACT,OAAA;AAAA,UACA,SAAA;AAAA;AAAA,UAEA,SAAA,CAAU,MAAM,CAAC,CAAA;AAAA,UACjB,KAAA;AAAA,UACA,QAAA;AAAA;AAAA,UAEA;AAAA,SACF;AAEA,QAAA,OAAO,EAAA;AAAA,MACT;AAAA,KACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,oBAAA,GAAuB,CAC3B,IAAA,MAC0B;AAAA,IAC1B,QAAA,EAAU,uBAAA;AAAA,IACV,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,MAAA,EAAQ,kBAAkB,IAAI;AAAA,GAChC,CAAA;AAEA,EAAA,MAAM,YAAY,cAAA,CAAe,SAAA;AAAA,IAC/B,IAAI,CAAC,QAAA,KAAa,QAAA,CAAS,GAAA,CAAI,oBAAoB,CAAC,CAAA;AAAA,IACpD,WAAA,CAAY,EAAE;AAAA,GAChB;AAEA,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,uBAAA;AAAA,IACJ,WAAW,CAAC,EAAE,OAAA,EAAS,OAAA,EAAS,UAAS,MAAO;AAAA,MAC9C,OAAA;AAAA,MACA,QAAA;AAAA,MACA,KAAA,EAAO;AAAA,KACT,CAAA;AAAA,IACA,WAAA,EAAa,CAAC,OAAA,KACZ,cAAA;AAAA,MACE,cAAA,CAAe,IAAA;AAAA,QACb,GAAA;AAAA,UACE,CAAC,aACC,QAAA,CAAS,IAAA;AAAA,YACP,CAAC,QACC,GAAA,CAAI,OAAA,KAAY,QAAQ,OAAA,IACxB,GAAA,CAAI,YAAY,OAAA,CAAQ;AAAA,WAC5B,IAAK;AAAA,SACT;AAAA,QACA,GAAA;AAAA,UAAI,CAAC,IAAA,KACH,IAAA,GAAO,oBAAA,CAAqB,IAAI,CAAA,GAAI;AAAA;AACtC;AACF,KACF;AAAA,IACF,SAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,KAAA;AAAA,IACA,WAAA,EAAa,gBAAA;AAAA,IACb,UAAA,EAAY,CAAC,OAAA,KAAY;AACvB,MAAA,MAAM,aAAa,CAAA,EAAG,OAAA,CAAQ,OAAO,CAAA,CAAA,EAAI,QAAQ,OAAO,CAAA,CAAA;AACxD,MAAA,gBAAA,CAAiB,CAAC,WAAA,KAAgB;AAChC,QAAA,IACE,WAAA,CAAY,IAAA;AAAA,UACV,CAAC,QAAQ,CAAA,EAAG,GAAA,CAAI,OAAO,CAAA,CAAA,EAAI,GAAA,CAAI,OAAO,CAAA,CAAA,KAAO;AAAA,SAC/C;AAEA,UAAA,OAAO,WAAA;AACT,QAAA,OAAO,CAAC,GAAG,WAAA,EAAa,OAAO,CAAA;AAAA,MACjC,CAAC,CAAA;AACD,MAAA,OAAO,qBAAqB,OAAO,CAAA;AAAA,IACrC,CAAA;AAAA,IACA,aAAA,EAAe,CAAC,IAAA,KACd,gBAAA,CAAiB,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,KAAQ,GAAA,KAAQ,IAAI,CAAC;AAAA,GAC3D;AACF;AAGA,MAAM,eAAA,GAAkB,IAAI,UAAA,CAAW,CAAC,EAAI,CAAC,CAAA;AAkB7C,MAAM,sBAAsB,CAC1B,UAAA,EACA,WACA,QAAA,EACA,UAAA,EACA,gBAEA,UAAA,CAAW;AAAA,EACT,eAAA;AAAA,EACA,IAAI,UAAA,CAAW,CAAC,UAAU,CAAC,CAAA;AAAA,EAC3B,IAAI,UAAA,CAAW,CAAC,CAAA,UAAsB,CAAA;AAAA,EACtC,SAAA;AAAA,EACA,OAAA,CAAQ,GAAA,CAAI,QAAA,CAAS,MAAM,CAAA;AAAA,EAC3B,QAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAC,CAAA;AAEH,MAAM,kBAAkB,CACtB,UAAA,EACA,SAAA,EACA,IAAA,EACA,gBAEA,UAAA,CAAW;AAAA,EACT,eAAA;AAAA,EACA,IAAI,UAAA,CAAW,CAAC,UAAU,CAAC,CAAA;AAAA,EAC3B,IAAI,UAAA,CAAW,CAAC,CAAA,eAA2B,CAAA;AAAA,EAC3C,SAAA;AAAA,EACA,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,MAAM,CAAA;AAAA,EACvB,IAAA;AAAA,EACA;AACF,CAAC,CAAA;;;;"}