@polkahub/vault 0.3.1 → 0.4.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.
@@ -87,7 +87,9 @@ const binaryToString = (value) => Array.from(value, (b) => String.fromCharCode(b
87
87
  const stringToBinary = (value) => Uint8Array.from(value, (c) => c.charCodeAt(0) & 255);
88
88
  const createFrames = (payload) => {
89
89
  const frames = [];
90
- const frameSize = 1024;
90
+ const MAX_FRAME_SIZE = 1024;
91
+ const frameAmount = Math.ceil(payload.length / MAX_FRAME_SIZE);
92
+ const frameSize = Math.ceil(payload.length / frameAmount);
91
93
  let idx = 0;
92
94
  while (idx < payload.length) {
93
95
  frames.push(payload.subarray(idx, idx + frameSize));
@@ -1 +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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"}
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 MAX_FRAME_SIZE = 1024;\n const frameAmount = Math.ceil(payload.length / MAX_FRAME_SIZE);\n const frameSize = Math.ceil(payload.length / frameAmount);\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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"}
package/dist/provider.js CHANGED
@@ -6,10 +6,11 @@ import { createSignal } from '@react-rxjs/utils';
6
6
  import { getSs58AddressInfo, Binary } from 'polkadot-api';
7
7
  import { mergeUint8 } from 'polkadot-api/utils';
8
8
  import { merge, map, race, firstValueFrom } from 'rxjs';
9
+ import { merkleizeMetadata } from '@polkadot-api/merkleize-metadata';
9
10
 
10
11
  const polkadotVaultProviderId = "polkadot-vault";
11
12
  const createPolkadotVaultProvider = (opts) => {
12
- const { persist } = {
13
+ const { persist, getNetworkInfo } = {
13
14
  persist: localStorageProvider(polkadotVaultProviderId),
14
15
  ...opts
15
16
  };
@@ -54,19 +55,45 @@ const createPolkadotVaultProvider = (opts) => {
54
55
  return signature;
55
56
  },
56
57
  async signTx(callData, signedExtensions, metadata) {
58
+ let merkleizer = null;
57
59
  const decMeta = unifyMetadata(decAnyMetadata(metadata));
58
60
  const extra = [];
59
61
  const additionalSigned = [];
60
- decMeta.extrinsic.signedExtensions.map(({ identifier }) => {
62
+ for (const { identifier } of decMeta.extrinsic.signedExtensions) {
63
+ if (identifier === "CheckMetadataHash") {
64
+ if (getNetworkInfo) {
65
+ merkleizer = merkleizeMetadata(metadata, await getNetworkInfo());
66
+ extra.push(Uint8Array.from([1]));
67
+ additionalSigned.push(
68
+ mergeUint8([Uint8Array.from([1]), merkleizer.digest()])
69
+ );
70
+ continue;
71
+ } else {
72
+ console.warn(
73
+ "The chain supports `CheckMetadataHash`, but `getNetworkInfo` was not provided. Polkadot Vault will need the whole metadata downloaded beforehand."
74
+ );
75
+ }
76
+ }
61
77
  const signedExtension = signedExtensions[identifier];
62
78
  if (!signedExtension)
63
79
  throw new Error(`Missing ${identifier} signed extension`);
64
80
  extra.push(signedExtension.value);
65
81
  additionalSigned.push(signedExtension.additionalSigned);
66
- });
82
+ }
67
83
  const extensions = mergeUint8([...extra, ...additionalSigned]);
68
84
  const genesis = signedExtensions.CheckGenesis?.additionalSigned ?? Binary.fromHex(accountGenesis).asBytes();
69
- const qrPayload = createQrTransaction(
85
+ const qrPayload = merkleizer ? createQrProofedTransaction(
86
+ 1 /* Sr25519 */,
87
+ publicKey,
88
+ merkleizer.getProofForExtrinsicParts(
89
+ callData,
90
+ mergeUint8(extra),
91
+ mergeUint8(additionalSigned)
92
+ ),
93
+ callData,
94
+ extensions,
95
+ genesis
96
+ ) : createQrTransaction(
70
97
  1 /* Sr25519 */,
71
98
  publicKey,
72
99
  callData,
@@ -144,9 +171,9 @@ const createPolkadotVaultProvider = (opts) => {
144
171
  };
145
172
  };
146
173
  const VAULT_QR_HEADER = new Uint8Array([83]);
147
- const createQrTransaction = (encrpytion, publicKey, callData, extensions, genesisHash) => mergeUint8([
174
+ const createQrTransaction = (encryption, publicKey, callData, extensions, genesisHash) => mergeUint8([
148
175
  VAULT_QR_HEADER,
149
- new Uint8Array([encrpytion]),
176
+ new Uint8Array([encryption]),
150
177
  new Uint8Array([2 /* Tx */]),
151
178
  publicKey,
152
179
  compact.enc(callData.length),
@@ -154,13 +181,27 @@ const createQrTransaction = (encrpytion, publicKey, callData, extensions, genesi
154
181
  extensions,
155
182
  genesisHash
156
183
  ]);
184
+ const createQrProofedTransaction = (encryption, publicKey, metadataProof, callData, extensions, genesisHash) => mergeUint8([
185
+ VAULT_QR_HEADER,
186
+ new Uint8Array([encryption]),
187
+ new Uint8Array([6 /* ProofTx */]),
188
+ publicKey,
189
+ metadataProof,
190
+ compact.enc(callData.length),
191
+ callData,
192
+ extensions,
193
+ genesisHash
194
+ ]);
157
195
  const createQrMessage = (encrpytion, publicKey, data, genesisHash) => mergeUint8([
158
196
  VAULT_QR_HEADER,
159
197
  new Uint8Array([encrpytion]),
160
198
  new Uint8Array([3 /* Message */]),
161
199
  publicKey,
162
- compact.enc(data.length),
163
- data,
200
+ mergeUint8([
201
+ Binary.fromText("<Bytes>").asBytes(),
202
+ data,
203
+ Binary.fromText("</Bytes>").asBytes()
204
+ ]),
164
205
  genesisHash
165
206
  ]);
166
207
 
@@ -1 +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 AccountAddress,\n addrEq,\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} 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: AccountAddress;\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: accountGenesis,\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(accountGenesis).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 genesis =\n signedExtensions.CheckGenesis?.additionalSigned ??\n Binary.fromHex(accountGenesis).asBytes();\n\n const qrPayload = createQrTransaction(\n VaultQrEncryption.Sr25519,\n publicKey,\n callData,\n extensions,\n genesis\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 addrEq(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: (account) =>\n setVaultAccounts((v) =>\n v.filter((acc) => acc.address !== account.address)\n ),\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":"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"}
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 AccountAddress,\n addrEq,\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} from \"polkadot-api\";\nimport { mergeUint8 } from \"polkadot-api/utils\";\nimport { firstValueFrom, map, merge, race } from \"rxjs\";\nimport {\n merkleizeMetadata,\n MetadataMerkleizer,\n} from \"@polkadot-api/merkleize-metadata\";\n\nexport const polkadotVaultProviderId = \"polkadot-vault\";\nexport interface VaultAccountInfo {\n address: AccountAddress;\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 type NetworkInfo = {\n decimals: number;\n tokenSymbol: string;\n};\n\nexport const createPolkadotVaultProvider = (\n opts?: Partial<{\n persist: PersistenceProvider;\n getNetworkInfo: () => Promise<NetworkInfo>;\n }>\n): PolkadotVaultProvider => {\n const { persist, getNetworkInfo } = {\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: accountGenesis,\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(accountGenesis).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 let merkleizer: MetadataMerkleizer | null = null;\n const decMeta = unifyMetadata(decAnyMetadata(metadata));\n const extra: Array<Uint8Array> = [];\n const additionalSigned: Array<Uint8Array> = [];\n for (const { identifier } of decMeta.extrinsic.signedExtensions) {\n if (identifier === \"CheckMetadataHash\") {\n if (getNetworkInfo) {\n merkleizer = merkleizeMetadata(metadata, await getNetworkInfo());\n extra.push(Uint8Array.from([1]));\n additionalSigned.push(\n mergeUint8([Uint8Array.from([1]), merkleizer.digest()])\n );\n continue;\n } else {\n console.warn(\n \"The chain supports `CheckMetadataHash`, but `getNetworkInfo` was not provided. Polkadot Vault will need the whole metadata downloaded beforehand.\"\n );\n }\n }\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 genesis =\n signedExtensions.CheckGenesis?.additionalSigned ??\n Binary.fromHex(accountGenesis).asBytes();\n\n const qrPayload = merkleizer\n ? createQrProofedTransaction(\n VaultQrEncryption.Sr25519,\n publicKey,\n merkleizer.getProofForExtrinsicParts(\n callData,\n mergeUint8(extra),\n mergeUint8(additionalSigned)\n ),\n callData,\n extensions,\n genesis\n )\n : createQrTransaction(\n VaultQrEncryption.Sr25519,\n publicKey,\n callData,\n extensions,\n genesis\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 addrEq(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: (account) =>\n setVaultAccounts((v) =>\n v.filter((acc) => acc.address !== account.address)\n ),\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 ProofTx = 0x06,\n LoadMetadataUpdate = 0x80,\n LoadTypesUpdate = 0x81,\n AddSpecsUpdate = 0xc1,\n DerivationsImport = 0xce,\n}\n\nconst createQrTransaction = (\n encryption: VaultQrEncryption,\n publicKey: Uint8Array,\n callData: Uint8Array,\n extensions: Uint8Array,\n genesisHash: Uint8Array\n) =>\n mergeUint8([\n VAULT_QR_HEADER,\n new Uint8Array([encryption]),\n new Uint8Array([VaultQrPayloadType.Tx]),\n publicKey,\n compact.enc(callData.length),\n callData,\n extensions,\n genesisHash,\n ]);\n\nconst createQrProofedTransaction = (\n encryption: VaultQrEncryption,\n publicKey: Uint8Array,\n metadataProof: Uint8Array,\n callData: Uint8Array,\n extensions: Uint8Array,\n genesisHash: Uint8Array\n) =>\n mergeUint8([\n VAULT_QR_HEADER,\n new Uint8Array([encryption]),\n new Uint8Array([VaultQrPayloadType.ProofTx]),\n publicKey,\n metadataProof,\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 mergeUint8([\n Binary.fromText(\"<Bytes>\").asBytes(),\n data,\n Binary.fromText(\"</Bytes>\").asBytes(),\n ]),\n genesisHash,\n ]);\n"],"names":[],"mappings":";;;;;;;;;;AA8BO,MAAM,uBAAA,GAA0B;AA6BhC,MAAM,2BAAA,GAA8B,CACzC,IAAA,KAI0B;AAC1B,EAAA,MAAM,EAAE,OAAA,EAAS,cAAA,EAAe,GAAI;AAAA,IAClC,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,OAAA,EAAS;AAAA,GACX,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,cAAc,CAAA,CAAE,OAAA;AAAQ,SACzC;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,IAAI,UAAA,GAAwC,IAAA;AAC5C,QAAA,MAAM,OAAA,GAAU,aAAA,CAAc,cAAA,CAAe,QAAQ,CAAC,CAAA;AACtD,QAAA,MAAM,QAA2B,EAAC;AAClC,QAAA,MAAM,mBAAsC,EAAC;AAC7C,QAAA,KAAA,MAAW,EAAE,UAAA,EAAW,IAAK,OAAA,CAAQ,UAAU,gBAAA,EAAkB;AAC/D,UAAA,IAAI,eAAe,mBAAA,EAAqB;AACtC,YAAA,IAAI,cAAA,EAAgB;AAClB,cAAA,UAAA,GAAa,iBAAA,CAAkB,QAAA,EAAU,MAAM,cAAA,EAAgB,CAAA;AAC/D,cAAA,KAAA,CAAM,KAAK,UAAA,CAAW,IAAA,CAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AAC/B,cAAA,gBAAA,CAAiB,IAAA;AAAA,gBACf,UAAA,CAAW,CAAC,UAAA,CAAW,IAAA,CAAK,CAAC,CAAC,CAAC,CAAA,EAAG,UAAA,CAAW,MAAA,EAAQ,CAAC;AAAA,eACxD;AACA,cAAA;AAAA,YACF,CAAA,MAAO;AACL,cAAA,OAAA,CAAQ,IAAA;AAAA,gBACN;AAAA,eACF;AAAA,YACF;AAAA,UACF;AACA,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;AACA,QAAA,MAAM,aAAa,UAAA,CAAW,CAAC,GAAG,KAAA,EAAO,GAAG,gBAAgB,CAAC,CAAA;AAE7D,QAAA,MAAM,OAAA,GACJ,iBAAiB,YAAA,EAAc,gBAAA,IAC/B,OAAO,OAAA,CAAQ,cAAc,EAAE,OAAA,EAAQ;AAEzC,QAAA,MAAM,YAAY,UAAA,GACd,0BAAA;AAAA,UACE,CAAA;AAAA,UACA,SAAA;AAAA,UACA,UAAA,CAAW,yBAAA;AAAA,YACT,QAAA;AAAA,YACA,WAAW,KAAK,CAAA;AAAA,YAChB,WAAW,gBAAgB;AAAA,WAC7B;AAAA,UACA,QAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA,SACF,GACA,mBAAA;AAAA,UACE,CAAA;AAAA,UACA,SAAA;AAAA,UACA,QAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA,SACF;AACJ,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,GAAA,KACC,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,QAAQ,OAAO,CAAA,IACnC,GAAA,CAAI,OAAA,KAAY,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,OAAA,KACd,gBAAA;AAAA,MAAiB,CAAC,MAChB,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,KAAQ,GAAA,CAAI,OAAA,KAAY,OAAA,CAAQ,OAAO;AAAA;AACnD,GACJ;AACF;AAGA,MAAM,eAAA,GAAkB,IAAI,UAAA,CAAW,CAAC,EAAI,CAAC,CAAA;AAmB7C,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,0BAAA,GAA6B,CACjC,UAAA,EACA,SAAA,EACA,eACA,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,eAA2B,CAAA;AAAA,EAC3C,SAAA;AAAA,EACA,aAAA;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,UAAA,CAAW;AAAA,IACT,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,CAAE,OAAA,EAAQ;AAAA,IACnC,IAAA;AAAA,IACA,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,CAAE,OAAA;AAAQ,GACrC,CAAA;AAAA,EACD;AACF,CAAC,CAAA;;;;"}
@@ -23,8 +23,13 @@ interface PolkadotVaultProvider extends Plugin<PolkadotVaultAccount> {
23
23
  setSignature: (payload: Uint8Array<ArrayBufferLike>) => void;
24
24
  cancelTx: () => void;
25
25
  }
26
+ type NetworkInfo = {
27
+ decimals: number;
28
+ tokenSymbol: string;
29
+ };
26
30
  declare const createPolkadotVaultProvider: (opts?: Partial<{
27
31
  persist: PersistenceProvider;
32
+ getNetworkInfo: () => Promise<NetworkInfo>;
28
33
  }>) => PolkadotVaultProvider;
29
34
 
30
35
  declare const ManageVault: FC;
@@ -32,4 +37,4 @@ declare const ManageVault: FC;
32
37
  declare const VaultTxModal: FC;
33
38
 
34
39
  export { ManageVault, VaultTxModal, createPolkadotVaultProvider, polkadotVaultProviderId };
35
- export type { PolkadotVaultAccount, PolkadotVaultProvider, VaultAccountInfo };
40
+ export type { NetworkInfo, PolkadotVaultAccount, PolkadotVaultProvider, VaultAccountInfo };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polkahub/vault",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "type": "module",
@@ -23,24 +23,25 @@
23
23
  "index.css"
24
24
  ],
25
25
  "dependencies": {
26
+ "@polkadot-api/merkleize-metadata": "^1.1.27",
26
27
  "@polkadot-api/signers-common": "^0.1.18",
27
28
  "@polkadot-api/substrate-bindings": "^0.16.5",
28
29
  "@react-rxjs/core": "^0.10.8",
29
30
  "@react-rxjs/utils": "^0.9.7",
30
- "lucide-react": "^0.553.0",
31
- "polkadot-api": "^1.20.2",
31
+ "lucide-react": "^0.554.0",
32
+ "polkadot-api": "^1.20.7",
32
33
  "rxjs": "^7.8.2",
33
- "@polkahub/context": "0.3.1",
34
- "@polkahub/plugin": "0.3.1",
35
- "@polkahub/select-account": "0.3.1",
36
- "@polkahub/ui-components": "0.3.1"
34
+ "@polkahub/plugin": "0.3.2",
35
+ "@polkahub/select-account": "0.3.2",
36
+ "@polkahub/ui-components": "0.3.2",
37
+ "@polkahub/context": "0.3.2"
37
38
  },
38
39
  "peerDependencies": {
39
40
  "@types/react": "^19.2.2",
40
41
  "react": "^19.2.0"
41
42
  },
42
43
  "devDependencies": {
43
- "@types/react": "^19.2.2",
44
+ "@types/react": "^19.2.6",
44
45
  "react": "^19.2.0"
45
46
  },
46
47
  "scripts": {