diff --git a/example/package.json b/example/package.json index 63c5824..52c48ee 100644 --- a/example/package.json +++ b/example/package.json @@ -10,6 +10,8 @@ "preview": "vite preview" }, "dependencies": { + "@gear-js/api": "^0.44.2", + "@polkadot/api": "^16.4.9", "react": "^19.1.1", "react-dom": "^19.1.1" }, diff --git a/example/pnpm-lock.yaml b/example/pnpm-lock.yaml index 77085a4..d2afd1b 100644 --- a/example/pnpm-lock.yaml +++ b/example/pnpm-lock.yaml @@ -8,6 +8,12 @@ importers: .: dependencies: + '@gear-js/api': + specifier: ^0.44.2 + version: 0.44.2(@polkadot/api@16.4.9)(@polkadot/wasm-crypto@7.5.1(@polkadot/util@13.5.7)(@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7))))(rxjs@7.8.2) + '@polkadot/api': + specifier: ^16.4.9 + version: 16.4.9 react: specifier: ^19.1.1 version: 19.1.1 @@ -26,7 +32,7 @@ importers: version: 19.1.9(@types/react@19.1.13) '@vitejs/plugin-react': specifier: ^5.0.3 - version: 5.0.3(vite@7.1.7) + version: 5.0.3(vite@7.1.7(@types/node@24.9.1)) eslint: specifier: ^9.36.0 version: 9.36.0 @@ -50,10 +56,10 @@ importers: version: '@varan-wallet/varan-connect@file:..(react@19.1.1)' vite: specifier: ^7.1.7 - version: 7.1.7 + version: 7.1.7(@types/node@24.9.1) vite-plugin-mkcert: specifier: ^1.17.8 - version: 1.17.8(vite@7.1.7) + version: 1.17.8(vite@7.1.7(@types/node@24.9.1)) packages: @@ -334,6 +340,13 @@ packages: resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@gear-js/api@0.44.2': + resolution: {integrity: sha512-367E+S5pfgxrTj+QY21qLGu+4CocKAUdbqXyYUVIPBJhkBXLBvcM9iGh6T0jXI2HC7hWncRFtne3DWvd6V6Rng==} + peerDependencies: + '@polkadot/api': ^16.4.1 + '@polkadot/wasm-crypto': ^7.5.1 + rxjs: ^7.8.2 + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -366,6 +379,14 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@noble/curves@1.9.7': + resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -378,6 +399,173 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@polkadot-api/json-rpc-provider-proxy@0.1.0': + resolution: {integrity: sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg==} + + '@polkadot-api/json-rpc-provider@0.0.1': + resolution: {integrity: sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA==} + + '@polkadot-api/metadata-builders@0.3.2': + resolution: {integrity: sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg==} + + '@polkadot-api/observable-client@0.3.2': + resolution: {integrity: sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug==} + peerDependencies: + '@polkadot-api/substrate-client': 0.1.4 + rxjs: '>=7.8.0' + + '@polkadot-api/substrate-bindings@0.6.0': + resolution: {integrity: sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw==} + + '@polkadot-api/substrate-client@0.1.4': + resolution: {integrity: sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A==} + + '@polkadot-api/utils@0.1.0': + resolution: {integrity: sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA==} + + '@polkadot/api-augment@16.4.9': + resolution: {integrity: sha512-3C5g6VUjs3cOwZmI2QDxZnwyLXI7554+fxQ/Mi5q12l7/5D5UrvDcDxFKUMALEUJRixGUvQ5T0f8s4mTHO/QsQ==} + engines: {node: '>=18'} + + '@polkadot/api-base@16.4.9': + resolution: {integrity: sha512-pv1n3bhMaA83+OBIw/tInfpuoRnpTBqzQKrkSYTVlbF+tlK0X3zl7iX0vxy1YJaL2vVQUiPR2tP3wnzz1mv7qg==} + engines: {node: '>=18'} + + '@polkadot/api-derive@16.4.9': + resolution: {integrity: sha512-3SgE7QOGy/G48hrz3rumzyJ2So875b/9pZXnp0b1Jm0c7p/nKwdcNK1nuWp/nMZ8RiEZpicVYmmkuytEXOwmkA==} + engines: {node: '>=18'} + + '@polkadot/api@16.4.9': + resolution: {integrity: sha512-bcJebd7RFWZYNL6hBwwLOq3jly3C5VL8BADqY2yu+ZfoFYQqdg7VrYhcmnl8O5IiG1DOpYIbuekRpKuBMkjNmw==} + engines: {node: '>=18'} + + '@polkadot/keyring@13.5.7': + resolution: {integrity: sha512-S75K2m2AoiTMnns7ko3t72jvyJRmrqdFFPldLdPdjRuds+E8OFewcwms/aXHGn9IwViWHFX6PSx0QAzWN/qWzQ==} + engines: {node: '>=18'} + peerDependencies: + '@polkadot/util': 13.5.7 + '@polkadot/util-crypto': 13.5.7 + + '@polkadot/networks@13.5.7': + resolution: {integrity: sha512-RdQcgaPy68NRSI7UTBdxr1aw66MXVdbpGhpWQpLf3/7puUdwkem6KxqFNnC9/kJSXRlyYGeYHN9Hsf4+CTWBSQ==} + engines: {node: '>=18'} + + '@polkadot/rpc-augment@16.4.9': + resolution: {integrity: sha512-J/6A2NgM92K8vHKGqUo877dPEOzYDoAm/8Ixrbq64obYnaVl5kAN+cctyRR0ywOTrY1wyRJmVa6Y83IPMgbX/A==} + engines: {node: '>=18'} + + '@polkadot/rpc-core@16.4.9': + resolution: {integrity: sha512-yOe0envLjrAffxL5NI1U9XaSt7bst93TVQdOyPw0HKCLc3uCJWnrnq8CKvdmR7IfHop+A1rkLaWyfY3tWcUMrA==} + engines: {node: '>=18'} + + '@polkadot/rpc-provider@16.4.9': + resolution: {integrity: sha512-1q+KVu2t2eTe5pLE+KaXXlU9itMc7LHFqssPFZi5VIZG+ORjAy2FmxwxWZmDlo/P12ZTD5CpJiJchtJ9Z6X0Zw==} + engines: {node: '>=18'} + + '@polkadot/types-augment@16.4.9': + resolution: {integrity: sha512-uTl3kJ01v3POJzIruzVtWshWjpd8nUmeREE0FSyYS6nb99mEk3nVy3w6V3dsHjEBF2X7FdU2ePTbr9mK0MI5AA==} + engines: {node: '>=18'} + + '@polkadot/types-codec@16.4.9': + resolution: {integrity: sha512-yw03qNA1QlXhvQ1zPE/+Km0t4tU3505chWJgR7m8sDehQkKXF0rNYURPuAVE+LpkzSyacJr9KU1X4Nkg42VfuQ==} + engines: {node: '>=18'} + + '@polkadot/types-create@16.4.9': + resolution: {integrity: sha512-428fwkPmQnENZdbX8bmc4dSqkVm328c1/Byxaa67gNsexeYi3XCFqjFC4toDECHNWW2YYN0XuPK6ieunPZuFpQ==} + engines: {node: '>=18'} + + '@polkadot/types-known@16.4.9': + resolution: {integrity: sha512-VzP0NZnthqz1hDXcF7VJbzMe/G589gaIVI5Y8NbGVYBwsR4BaxU3msLguM2MFlVCTOCCDlC8SJOezgaeWfg2DA==} + engines: {node: '>=18'} + + '@polkadot/types-support@16.4.9': + resolution: {integrity: sha512-NiSGYEVeyXo/8a/O5kIEZDpHE6zrcZtFeyrWLIPtjbIV0PfuJzl1Bc0i8rGZWcn/ZdZjnSYg++l33sTb2GaJOQ==} + engines: {node: '>=18'} + + '@polkadot/types@16.4.9': + resolution: {integrity: sha512-nfXIviIBohn603Q8t6vDQYrKDMeisVFN7EjDVOIYLXFMwbe9MvTW6i/NLyu9m42O8Z76O+yUisMazaE4046xJA==} + engines: {node: '>=18'} + + '@polkadot/util-crypto@13.5.7': + resolution: {integrity: sha512-SNzfAmtSSfUnQesrGLxc1RDg1arsvFSsAkH0xulffByqJfLugB3rZWJXIKqKNfcRZtomsMMURPeW7lfpAomSug==} + engines: {node: '>=18'} + peerDependencies: + '@polkadot/util': 13.5.7 + + '@polkadot/util@13.5.7': + resolution: {integrity: sha512-5Rhp6/FDI55iCJcGd/9bMQaF0E26OE+uZwz68JuRW75DW8v7zsN3bnjnVqk3KO/c4u5EgLSqbhXPuyW24BP1+Q==} + engines: {node: '>=18'} + + '@polkadot/wasm-bridge@7.5.1': + resolution: {integrity: sha512-E+N3CSnX3YaXpAmfIQ+4bTyiAqJQKvVcMaXjkuL8Tp2zYffClWLG5e+RY15Uh+EWfUl9If4y6cLZi3D5NcpAGQ==} + engines: {node: '>=18'} + peerDependencies: + '@polkadot/util': '*' + '@polkadot/x-randomvalues': '*' + + '@polkadot/wasm-crypto-asmjs@7.5.1': + resolution: {integrity: sha512-jAg7Uusk+xeHQ+QHEH4c/N3b1kEGBqZb51cWe+yM61kKpQwVGZhNdlWetW6U23t/BMyZArIWMsZqmK/Ij0PHog==} + engines: {node: '>=18'} + peerDependencies: + '@polkadot/util': '*' + + '@polkadot/wasm-crypto-init@7.5.1': + resolution: {integrity: sha512-Obu4ZEo5jYO6sN31eqCNOXo88rPVkP9TrUOyynuFCnXnXr8V/HlmY/YkAd9F87chZnkTJRlzak17kIWr+i7w3A==} + engines: {node: '>=18'} + peerDependencies: + '@polkadot/util': '*' + '@polkadot/x-randomvalues': '*' + + '@polkadot/wasm-crypto-wasm@7.5.1': + resolution: {integrity: sha512-S2yQSGbOGTcaV6UdipFVyEGanJvG6uD6Tg7XubxpiGbNAblsyYKeFcxyH1qCosk/4qf+GIUwlOL4ydhosZflqg==} + engines: {node: '>=18'} + peerDependencies: + '@polkadot/util': '*' + + '@polkadot/wasm-crypto@7.5.1': + resolution: {integrity: sha512-acjt4VJ3w19v7b/SIPsV/5k9s6JsragHKPnwoZ0KTfBvAFXwzz80jUzVGxA06SKHacfCUe7vBRlz7M5oRby1Pw==} + engines: {node: '>=18'} + peerDependencies: + '@polkadot/util': '*' + '@polkadot/x-randomvalues': '*' + + '@polkadot/wasm-util@7.5.1': + resolution: {integrity: sha512-sbvu71isFhPXpvMVX+EkRnUg/+54Tx7Sf9BEMqxxoPj7cG1I/MKeDEwbQz6MaU4gm7xJqvEWCAemLFcXfHQ/2A==} + engines: {node: '>=18'} + peerDependencies: + '@polkadot/util': '*' + + '@polkadot/x-bigint@13.5.7': + resolution: {integrity: sha512-NbN4EPbMBhjOXoWj0BVcT49/obzusFWPKbSyBxbZi8ITBaIIgpncgcCfXY4rII6Fqh74khx9jdevWge/6ycepQ==} + engines: {node: '>=18'} + + '@polkadot/x-fetch@13.5.7': + resolution: {integrity: sha512-ZlPtWJAq7xMMr8wo9API8l6mKRr/6kClF0Hm1CVhQgZruFTZd7A2XZfETMg49yaRouy16SRI85WhIw+pXfQd3g==} + engines: {node: '>=18'} + + '@polkadot/x-global@13.5.7': + resolution: {integrity: sha512-TkBxLfeKtj0laCzXp2lvRhwSIeXSxIu7LAWpfAUW4SYNFQvtgIS0x0Bq70CUW3lcy0wqTrSG2cqzfnbomB0Djw==} + engines: {node: '>=18'} + + '@polkadot/x-randomvalues@13.5.7': + resolution: {integrity: sha512-NEElpdu+Wqlr6USoh3abQfe0MaWlFlynPiqkA0/SJjK+0V0UOw0CyPwPgGrGa71/ju+1bsnu/ySshXqCR8HXTw==} + engines: {node: '>=18'} + peerDependencies: + '@polkadot/util': 13.5.7 + '@polkadot/wasm-util': '*' + + '@polkadot/x-textdecoder@13.5.7': + resolution: {integrity: sha512-wjSj+T2pBA1uW9dDYriZMAv4WgXl5zcWblxwOsZd3V/qxifMSlSLAy0WeC+08DD6TXGQYCOU0uOALsDivkUDZA==} + engines: {node: '>=18'} + + '@polkadot/x-textencoder@13.5.7': + resolution: {integrity: sha512-h6RsGUY8ZZrfqsbojD1VqTqmXcojDSfbXQHhVcAWqgceeh9JOOw8Q6yzhv+KpPelqKq/map3bobJaebQ8QNTMw==} + engines: {node: '>=18'} + + '@polkadot/x-ws@13.5.7': + resolution: {integrity: sha512-ZdmFhL3gDMRxJXqN7a88BIU1sm2IgAFnn+jMcjjJXwP5qEuP9ejwPHQL0EFOw6sqtylfQUFuWvahvIZT7MbQ5g==} + engines: {node: '>=18'} + '@rolldown/pluginutils@1.0.0-beta.35': resolution: {integrity: sha512-slYrCpoxJUqzFDDNlvrOYRazQUNRvWPjXA17dAOISY3rDMxX6k8K4cj2H+hEYMHF81HO3uNd5rHVigAWRM5dSg==} @@ -491,6 +679,27 @@ packages: cpu: [x64] os: [win32] + '@scure/base@1.2.6': + resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} + + '@substrate/connect-extension-protocol@2.2.2': + resolution: {integrity: sha512-t66jwrXA0s5Goq82ZtjagLNd7DPGCNjHeehRlE/gcJmJ+G56C0W+2plqOMRicJ8XGR1/YFnUSEqUFiSNbjGrAA==} + + '@substrate/connect-known-chains@1.10.3': + resolution: {integrity: sha512-OJEZO1Pagtb6bNE3wCikc2wrmvEU5x7GxFFLqqbz1AJYYxSlrPCGu4N2og5YTExo4IcloNMQYFRkBGue0BKZ4w==} + + '@substrate/connect@0.8.11': + resolution: {integrity: sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw==} + deprecated: versions below 1.x are no longer maintained + + '@substrate/light-client-extension-helpers@1.0.0': + resolution: {integrity: sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg==} + peerDependencies: + smoldot: 2.x + + '@substrate/ss58-registry@1.51.0': + resolution: {integrity: sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ==} + '@twa-dev/sdk@8.0.2': resolution: {integrity: sha512-Pp5GxnxP2blboVZFiM9aWjs4cb8IpW3x2jP3kLOMvIqy0jzNUTuFHkwHtx+zEvh/UcF2F+wmS8G6ebIA0XPXcg==} peerDependencies: @@ -511,12 +720,18 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/bn.js@5.2.0': + resolution: {integrity: sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/node@24.9.1': + resolution: {integrity: sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==} + '@types/react-dom@19.1.9': resolution: {integrity: sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==} peerDependencies: @@ -627,6 +842,9 @@ packages: resolution: {integrity: sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==} hasBin: true + bn.js@5.2.2: + resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -681,6 +899,10 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -786,6 +1008,9 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -811,6 +1036,10 @@ packages: picomatch: optional: true + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -843,6 +1072,10 @@ packages: resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -954,6 +1187,9 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -1003,6 +1239,10 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + mock-socket@9.3.1: + resolution: {integrity: sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==} + engines: {node: '>= 8'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1014,6 +1254,19 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + nock@13.5.6: + resolution: {integrity: sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==} + engines: {node: '>= 10.13'} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + node-releases@2.0.21: resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==} @@ -1060,6 +1313,10 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + propagate@2.0.1: + resolution: {integrity: sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==} + engines: {node: '>= 8'} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -1099,6 +1356,12 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + + scale-ts@1.6.1: + resolution: {integrity: sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g==} + scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} @@ -1119,6 +1382,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + smoldot@2.0.26: + resolution: {integrity: sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -1145,6 +1411,9 @@ packages: peerDependencies: typescript: '>=4.8.4' + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -1161,6 +1430,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + update-browserslist-db@1.1.3: resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true @@ -1216,6 +1488,10 @@ packages: yaml: optional: true + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -1225,6 +1501,18 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -1468,6 +1756,12 @@ snapshots: '@eslint/core': 0.15.2 levn: 0.4.1 + '@gear-js/api@0.44.2(@polkadot/api@16.4.9)(@polkadot/wasm-crypto@7.5.1(@polkadot/util@13.5.7)(@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7))))(rxjs@7.8.2)': + dependencies: + '@polkadot/api': 16.4.9 + '@polkadot/wasm-crypto': 7.5.1(@polkadot/util@13.5.7)(@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7))) + rxjs: 7.8.2 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -1498,6 +1792,12 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@noble/curves@1.9.7': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/hashes@1.8.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1510,6 +1810,321 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 + '@polkadot-api/json-rpc-provider-proxy@0.1.0': + optional: true + + '@polkadot-api/json-rpc-provider@0.0.1': + optional: true + + '@polkadot-api/metadata-builders@0.3.2': + dependencies: + '@polkadot-api/substrate-bindings': 0.6.0 + '@polkadot-api/utils': 0.1.0 + optional: true + + '@polkadot-api/observable-client@0.3.2(@polkadot-api/substrate-client@0.1.4)(rxjs@7.8.2)': + dependencies: + '@polkadot-api/metadata-builders': 0.3.2 + '@polkadot-api/substrate-bindings': 0.6.0 + '@polkadot-api/substrate-client': 0.1.4 + '@polkadot-api/utils': 0.1.0 + rxjs: 7.8.2 + optional: true + + '@polkadot-api/substrate-bindings@0.6.0': + dependencies: + '@noble/hashes': 1.8.0 + '@polkadot-api/utils': 0.1.0 + '@scure/base': 1.2.6 + scale-ts: 1.6.1 + optional: true + + '@polkadot-api/substrate-client@0.1.4': + dependencies: + '@polkadot-api/json-rpc-provider': 0.0.1 + '@polkadot-api/utils': 0.1.0 + optional: true + + '@polkadot-api/utils@0.1.0': + optional: true + + '@polkadot/api-augment@16.4.9': + dependencies: + '@polkadot/api-base': 16.4.9 + '@polkadot/rpc-augment': 16.4.9 + '@polkadot/types': 16.4.9 + '@polkadot/types-augment': 16.4.9 + '@polkadot/types-codec': 16.4.9 + '@polkadot/util': 13.5.7 + tslib: 2.8.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@polkadot/api-base@16.4.9': + dependencies: + '@polkadot/rpc-core': 16.4.9 + '@polkadot/types': 16.4.9 + '@polkadot/util': 13.5.7 + rxjs: 7.8.2 + tslib: 2.8.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@polkadot/api-derive@16.4.9': + dependencies: + '@polkadot/api': 16.4.9 + '@polkadot/api-augment': 16.4.9 + '@polkadot/api-base': 16.4.9 + '@polkadot/rpc-core': 16.4.9 + '@polkadot/types': 16.4.9 + '@polkadot/types-codec': 16.4.9 + '@polkadot/util': 13.5.7 + '@polkadot/util-crypto': 13.5.7(@polkadot/util@13.5.7) + rxjs: 7.8.2 + tslib: 2.8.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@polkadot/api@16.4.9': + dependencies: + '@polkadot/api-augment': 16.4.9 + '@polkadot/api-base': 16.4.9 + '@polkadot/api-derive': 16.4.9 + '@polkadot/keyring': 13.5.7(@polkadot/util-crypto@13.5.7(@polkadot/util@13.5.7))(@polkadot/util@13.5.7) + '@polkadot/rpc-augment': 16.4.9 + '@polkadot/rpc-core': 16.4.9 + '@polkadot/rpc-provider': 16.4.9 + '@polkadot/types': 16.4.9 + '@polkadot/types-augment': 16.4.9 + '@polkadot/types-codec': 16.4.9 + '@polkadot/types-create': 16.4.9 + '@polkadot/types-known': 16.4.9 + '@polkadot/util': 13.5.7 + '@polkadot/util-crypto': 13.5.7(@polkadot/util@13.5.7) + eventemitter3: 5.0.1 + rxjs: 7.8.2 + tslib: 2.8.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@polkadot/keyring@13.5.7(@polkadot/util-crypto@13.5.7(@polkadot/util@13.5.7))(@polkadot/util@13.5.7)': + dependencies: + '@polkadot/util': 13.5.7 + '@polkadot/util-crypto': 13.5.7(@polkadot/util@13.5.7) + tslib: 2.8.1 + + '@polkadot/networks@13.5.7': + dependencies: + '@polkadot/util': 13.5.7 + '@substrate/ss58-registry': 1.51.0 + tslib: 2.8.1 + + '@polkadot/rpc-augment@16.4.9': + dependencies: + '@polkadot/rpc-core': 16.4.9 + '@polkadot/types': 16.4.9 + '@polkadot/types-codec': 16.4.9 + '@polkadot/util': 13.5.7 + tslib: 2.8.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@polkadot/rpc-core@16.4.9': + dependencies: + '@polkadot/rpc-augment': 16.4.9 + '@polkadot/rpc-provider': 16.4.9 + '@polkadot/types': 16.4.9 + '@polkadot/util': 13.5.7 + rxjs: 7.8.2 + tslib: 2.8.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@polkadot/rpc-provider@16.4.9': + dependencies: + '@polkadot/keyring': 13.5.7(@polkadot/util-crypto@13.5.7(@polkadot/util@13.5.7))(@polkadot/util@13.5.7) + '@polkadot/types': 16.4.9 + '@polkadot/types-support': 16.4.9 + '@polkadot/util': 13.5.7 + '@polkadot/util-crypto': 13.5.7(@polkadot/util@13.5.7) + '@polkadot/x-fetch': 13.5.7 + '@polkadot/x-global': 13.5.7 + '@polkadot/x-ws': 13.5.7 + eventemitter3: 5.0.1 + mock-socket: 9.3.1 + nock: 13.5.6 + tslib: 2.8.1 + optionalDependencies: + '@substrate/connect': 0.8.11 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@polkadot/types-augment@16.4.9': + dependencies: + '@polkadot/types': 16.4.9 + '@polkadot/types-codec': 16.4.9 + '@polkadot/util': 13.5.7 + tslib: 2.8.1 + + '@polkadot/types-codec@16.4.9': + dependencies: + '@polkadot/util': 13.5.7 + '@polkadot/x-bigint': 13.5.7 + tslib: 2.8.1 + + '@polkadot/types-create@16.4.9': + dependencies: + '@polkadot/types-codec': 16.4.9 + '@polkadot/util': 13.5.7 + tslib: 2.8.1 + + '@polkadot/types-known@16.4.9': + dependencies: + '@polkadot/networks': 13.5.7 + '@polkadot/types': 16.4.9 + '@polkadot/types-codec': 16.4.9 + '@polkadot/types-create': 16.4.9 + '@polkadot/util': 13.5.7 + tslib: 2.8.1 + + '@polkadot/types-support@16.4.9': + dependencies: + '@polkadot/util': 13.5.7 + tslib: 2.8.1 + + '@polkadot/types@16.4.9': + dependencies: + '@polkadot/keyring': 13.5.7(@polkadot/util-crypto@13.5.7(@polkadot/util@13.5.7))(@polkadot/util@13.5.7) + '@polkadot/types-augment': 16.4.9 + '@polkadot/types-codec': 16.4.9 + '@polkadot/types-create': 16.4.9 + '@polkadot/util': 13.5.7 + '@polkadot/util-crypto': 13.5.7(@polkadot/util@13.5.7) + rxjs: 7.8.2 + tslib: 2.8.1 + + '@polkadot/util-crypto@13.5.7(@polkadot/util@13.5.7)': + dependencies: + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@polkadot/networks': 13.5.7 + '@polkadot/util': 13.5.7 + '@polkadot/wasm-crypto': 7.5.1(@polkadot/util@13.5.7)(@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7))) + '@polkadot/wasm-util': 7.5.1(@polkadot/util@13.5.7) + '@polkadot/x-bigint': 13.5.7 + '@polkadot/x-randomvalues': 13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7)) + '@scure/base': 1.2.6 + tslib: 2.8.1 + + '@polkadot/util@13.5.7': + dependencies: + '@polkadot/x-bigint': 13.5.7 + '@polkadot/x-global': 13.5.7 + '@polkadot/x-textdecoder': 13.5.7 + '@polkadot/x-textencoder': 13.5.7 + '@types/bn.js': 5.2.0 + bn.js: 5.2.2 + tslib: 2.8.1 + + '@polkadot/wasm-bridge@7.5.1(@polkadot/util@13.5.7)(@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7)))': + dependencies: + '@polkadot/util': 13.5.7 + '@polkadot/wasm-util': 7.5.1(@polkadot/util@13.5.7) + '@polkadot/x-randomvalues': 13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7)) + tslib: 2.8.1 + + '@polkadot/wasm-crypto-asmjs@7.5.1(@polkadot/util@13.5.7)': + dependencies: + '@polkadot/util': 13.5.7 + tslib: 2.8.1 + + '@polkadot/wasm-crypto-init@7.5.1(@polkadot/util@13.5.7)(@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7)))': + dependencies: + '@polkadot/util': 13.5.7 + '@polkadot/wasm-bridge': 7.5.1(@polkadot/util@13.5.7)(@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7))) + '@polkadot/wasm-crypto-asmjs': 7.5.1(@polkadot/util@13.5.7) + '@polkadot/wasm-crypto-wasm': 7.5.1(@polkadot/util@13.5.7) + '@polkadot/wasm-util': 7.5.1(@polkadot/util@13.5.7) + '@polkadot/x-randomvalues': 13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7)) + tslib: 2.8.1 + + '@polkadot/wasm-crypto-wasm@7.5.1(@polkadot/util@13.5.7)': + dependencies: + '@polkadot/util': 13.5.7 + '@polkadot/wasm-util': 7.5.1(@polkadot/util@13.5.7) + tslib: 2.8.1 + + '@polkadot/wasm-crypto@7.5.1(@polkadot/util@13.5.7)(@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7)))': + dependencies: + '@polkadot/util': 13.5.7 + '@polkadot/wasm-bridge': 7.5.1(@polkadot/util@13.5.7)(@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7))) + '@polkadot/wasm-crypto-asmjs': 7.5.1(@polkadot/util@13.5.7) + '@polkadot/wasm-crypto-init': 7.5.1(@polkadot/util@13.5.7)(@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7))) + '@polkadot/wasm-crypto-wasm': 7.5.1(@polkadot/util@13.5.7) + '@polkadot/wasm-util': 7.5.1(@polkadot/util@13.5.7) + '@polkadot/x-randomvalues': 13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7)) + tslib: 2.8.1 + + '@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7)': + dependencies: + '@polkadot/util': 13.5.7 + tslib: 2.8.1 + + '@polkadot/x-bigint@13.5.7': + dependencies: + '@polkadot/x-global': 13.5.7 + tslib: 2.8.1 + + '@polkadot/x-fetch@13.5.7': + dependencies: + '@polkadot/x-global': 13.5.7 + node-fetch: 3.3.2 + tslib: 2.8.1 + + '@polkadot/x-global@13.5.7': + dependencies: + tslib: 2.8.1 + + '@polkadot/x-randomvalues@13.5.7(@polkadot/util@13.5.7)(@polkadot/wasm-util@7.5.1(@polkadot/util@13.5.7))': + dependencies: + '@polkadot/util': 13.5.7 + '@polkadot/wasm-util': 7.5.1(@polkadot/util@13.5.7) + '@polkadot/x-global': 13.5.7 + tslib: 2.8.1 + + '@polkadot/x-textdecoder@13.5.7': + dependencies: + '@polkadot/x-global': 13.5.7 + tslib: 2.8.1 + + '@polkadot/x-textencoder@13.5.7': + dependencies: + '@polkadot/x-global': 13.5.7 + tslib: 2.8.1 + + '@polkadot/x-ws@13.5.7': + dependencies: + '@polkadot/x-global': 13.5.7 + tslib: 2.8.1 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@rolldown/pluginutils@1.0.0-beta.35': {} '@rollup/rollup-android-arm-eabi@4.52.2': @@ -1578,6 +2193,39 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.52.2': optional: true + '@scure/base@1.2.6': {} + + '@substrate/connect-extension-protocol@2.2.2': + optional: true + + '@substrate/connect-known-chains@1.10.3': + optional: true + + '@substrate/connect@0.8.11': + dependencies: + '@substrate/connect-extension-protocol': 2.2.2 + '@substrate/connect-known-chains': 1.10.3 + '@substrate/light-client-extension-helpers': 1.0.0(smoldot@2.0.26) + smoldot: 2.0.26 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + optional: true + + '@substrate/light-client-extension-helpers@1.0.0(smoldot@2.0.26)': + dependencies: + '@polkadot-api/json-rpc-provider': 0.0.1 + '@polkadot-api/json-rpc-provider-proxy': 0.1.0 + '@polkadot-api/observable-client': 0.3.2(@polkadot-api/substrate-client@0.1.4)(rxjs@7.8.2) + '@polkadot-api/substrate-client': 0.1.4 + '@substrate/connect-extension-protocol': 2.2.2 + '@substrate/connect-known-chains': 1.10.3 + rxjs: 7.8.2 + smoldot: 2.0.26 + optional: true + + '@substrate/ss58-registry@1.51.0': {} + '@twa-dev/sdk@8.0.2(react@19.1.1)': dependencies: '@twa-dev/types': 8.0.2 @@ -1606,10 +2254,18 @@ snapshots: dependencies: '@babel/types': 7.28.4 + '@types/bn.js@5.2.0': + dependencies: + '@types/node': 24.9.1 + '@types/estree@1.0.8': {} '@types/json-schema@7.0.15': {} + '@types/node@24.9.1': + dependencies: + undici-types: 7.16.0 + '@types/react-dom@19.1.9(@types/react@19.1.13)': dependencies: '@types/react': 19.1.13 @@ -1713,11 +2369,12 @@ snapshots: '@varan-wallet/varan-connect@file:..(react@19.1.1)': dependencies: + '@polkadot/util': 13.5.7 '@twa-dev/sdk': 8.0.2(react@19.1.1) transitivePeerDependencies: - react - '@vitejs/plugin-react@5.0.3(vite@7.1.7)': + '@vitejs/plugin-react@5.0.3(vite@7.1.7(@types/node@24.9.1))': dependencies: '@babel/core': 7.28.4 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4) @@ -1725,7 +2382,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.35 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 7.1.7 + vite: 7.1.7(@types/node@24.9.1) transitivePeerDependencies: - supports-color @@ -1762,6 +2419,8 @@ snapshots: baseline-browser-mapping@2.8.6: {} + bn.js@5.2.2: {} + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -1819,6 +2478,8 @@ snapshots: csstype@3.1.3: {} + data-uri-to-buffer@4.0.1: {} + debug@4.4.3: dependencies: ms: 2.1.3 @@ -1958,6 +2619,8 @@ snapshots: esutils@2.0.3: {} + eventemitter3@5.0.1: {} + fast-deep-equal@3.1.3: {} fast-glob@3.3.3: @@ -1980,6 +2643,11 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -2012,6 +2680,10 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + fsevents@2.3.3: optional: true @@ -2100,6 +2772,8 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json-stringify-safe@5.0.1: {} + json5@2.2.3: {} keyv@4.5.4: @@ -2144,12 +2818,30 @@ snapshots: dependencies: brace-expansion: 2.0.2 + mock-socket@9.3.1: {} + ms@2.1.3: {} nanoid@3.3.11: {} natural-compare@1.4.0: {} + nock@13.5.6: + dependencies: + debug: 4.4.3 + json-stringify-safe: 5.0.1 + propagate: 2.0.1 + transitivePeerDependencies: + - supports-color + + node-domexception@1.0.0: {} + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + node-releases@2.0.21: {} optionator@0.9.4: @@ -2191,6 +2883,8 @@ snapshots: prelude-ls@1.2.1: {} + propagate@2.0.1: {} + proxy-from-env@1.1.0: {} punycode@2.3.1: {} @@ -2242,6 +2936,13 @@ snapshots: dependencies: queue-microtask: 1.2.3 + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + scale-ts@1.6.1: + optional: true + scheduler@0.26.0: {} semver@6.3.1: {} @@ -2254,6 +2955,14 @@ snapshots: shebang-regex@3.0.0: {} + smoldot@2.0.26: + dependencies: + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + optional: true + source-map-js@1.2.1: {} strip-json-comments@3.1.1: {} @@ -2275,6 +2984,8 @@ snapshots: dependencies: typescript: 5.8.3 + tslib@2.8.1: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -2292,6 +3003,8 @@ snapshots: typescript@5.8.3: {} + undici-types@7.16.0: {} + update-browserslist-db@1.1.3(browserslist@4.26.2): dependencies: browserslist: 4.26.2 @@ -2302,16 +3015,16 @@ snapshots: dependencies: punycode: 2.3.1 - vite-plugin-mkcert@1.17.8(vite@7.1.7): + vite-plugin-mkcert@1.17.8(vite@7.1.7(@types/node@24.9.1)): dependencies: axios: 1.12.2(debug@4.4.3) debug: 4.4.3 picocolors: 1.1.1 - vite: 7.1.7 + vite: 7.1.7(@types/node@24.9.1) transitivePeerDependencies: - supports-color - vite@7.1.7: + vite@7.1.7(@types/node@24.9.1): dependencies: esbuild: 0.25.10 fdir: 6.5.0(picomatch@4.0.3) @@ -2320,14 +3033,19 @@ snapshots: rollup: 4.52.2 tinyglobby: 0.2.15 optionalDependencies: + '@types/node': 24.9.1 fsevents: 2.3.3 + web-streams-polyfill@3.3.3: {} + which@2.0.2: dependencies: isexe: 2.0.0 word-wrap@1.2.5: {} + ws@8.18.3: {} + yallist@3.1.1: {} yocto-queue@0.1.0: {} diff --git a/example/src/App.tsx b/example/src/App.tsx index fafa092..f985976 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,5 +1,6 @@ import { useState } from 'react'; import './App.css' +import { GearApi } from '@gear-js/api'; const RAW_TRANSACTION = '0xd10204680359836ffbbdaee026cac6008a4c1f68e9fee5fc2949e0ab3ac3f478b7446a8a0dd90114506f6b657220526567697374657218506c617965724cd84143c22eb3da602607c1bd992dbd6db170e21d1b45b99278dbca78831af7028be58d11229c7b53a181793ada6c38754c3b30cc27cb607741d99e7bbadc7c687d165102b787e3e17957eee3435455613ff857a91389b1ae0a24e0618f1afcd6266268020000000000000000000000000000000000000001' @@ -24,6 +25,22 @@ function App() { } } + const test = async () => { + const extension = await varanWallet.enable?.('current'); + const address = (await extension?.accounts.get())?.[0].address; + if (!address) { + console.log('[VARANINJECT] address not found'); + return; + } + const apiPromise = new GearApi({ providerAddress: 'wss://rpc.vara.network' }); + await apiPromise.isReady; + const tx = apiPromise.balance.transfer('kGi1Ui7VXBFmPmaoMD5xgWd2VHNixZ5BbLNhHFYD39T85rUi3', 100) + console.log('[VARANINJECT] tx', tx); + // @ts-expect-error - signer is not typed + const result = await tx.signAndSend(address, { signer: extension?.signer }) + console.log('[VARANINJECT] result', result); + } + const signTransaction = async () => { const extension = await varanWallet.enable?.('current'); const address = (await extension?.accounts.get())?.[0].address; @@ -34,7 +51,7 @@ function App() { const signature = await extension?.signer?.signRaw?.({ address: address, data: RAW_TRANSACTION, - type: 'payload', + type: 'bytes', }); console.log('[VARANINJECT] signature', signature); setSignature(signature?.signature || ''); @@ -53,6 +70,7 @@ function App() {
DATA
{data}
+ {isConnected && <> diff --git a/example/src/main.tsx b/example/src/main.tsx index 1229348..997b8b8 100644 --- a/example/src/main.tsx +++ b/example/src/main.tsx @@ -5,7 +5,7 @@ import App from './App.tsx' import { injectVaranWallet } from 'varan-inject' import WebApp from '@twa-dev/sdk' injectVaranWallet(WebApp, { - callbackUrl: 'test_y_maxim_bbbbot/start?startapp=' + callbackUrl: 'test_y_maxim_bbbbot/start?startapp=', // callbackUrl: 'ZkPokerTestBot/zkPoker?startapp=' }) diff --git a/package.json b/package.json index cb992e2..49caa87 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ }, "homepage": "https://gitlab.mind-dev.com/pb/varan-connect#readme", "dependencies": { + "@polkadot/util": "13.5.7", "@twa-dev/sdk": "^8.0.2" }, "devDependencies": { diff --git a/src/api.ts b/src/api.ts new file mode 100644 index 0000000..75c8108 --- /dev/null +++ b/src/api.ts @@ -0,0 +1,65 @@ +import type { + ServerMessage, + ConnectResponseMessage, + SignTransactionResponseMessage +} from './socket'; + +const API_URL = 'https://connect.varan.app'; + +/** + * Sends a connect response message to the API + * This will be received by the client's WebSocket and handled by the socket + * @param message The connect response message + * @param connectionId The unique connection ID from WebSocket + * @returns Promise resolving when the message is sent + */ +export async function sendConnect( + message: ConnectResponseMessage, + connectionId: string, +): Promise { + await sendServerMessage(message, connectionId); +} + +/** + * Sends a signed transaction response message to the API + * This will be received by the client's WebSocket and handled by the socket + * @param message The sign transaction response message + * @param connectionId The unique connection ID from WebSocket + * @returns Promise resolving when the message is sent + */ +export async function sendSignedTransaction( + message: SignTransactionResponseMessage, + connectionId: string, +): Promise { + await sendServerMessage(message, connectionId); +} + +/** + * Sends any server message to the API + * This will be received by the client's WebSocket and handled by the socket + * @param message The server message to send + * @param connectionId The unique connection ID from WebSocket + * @returns Promise resolving when the message is sent + */ +async function sendServerMessage( + message: ServerMessage, + connectionId: string, +): Promise { + try { + const response = await fetch(`${API_URL}/send/${connectionId}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(message), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + } catch (error) { + console.error('[VARANINJECT] Error sending server message:', error); + throw error; + } +} + diff --git a/src/index.ts b/src/index.ts index a2680a9..5d0b64f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,9 @@ export { injectVaranWallet } from './varan-wallet'; +export { sendConnect, sendSignedTransaction } from './api'; +export type { + ConnectRequest, + SignTransactionRequest, + ConnectResponseMessage, + SignTransactionResponseMessage, + ServerMessage +} from './socket'; diff --git a/src/socket.ts b/src/socket.ts new file mode 100644 index 0000000..8af072e --- /dev/null +++ b/src/socket.ts @@ -0,0 +1,351 @@ +// Base WebSocket message structure +export interface WebSocketMessage { + type: 'connection' | 'acknowledgment' | 'server_message' | 'data'; + id?: string; + data?: unknown; + message?: unknown; +} + +// Connection message - sent by server when client connects +export interface ConnectionMessage extends WebSocketMessage { + type: 'connection'; + id: string; +} + +// Acknowledgment message - sent by server to acknowledge received data +export interface AcknowledgmentMessage extends WebSocketMessage { + type: 'acknowledgment'; +} + +// Server message wrapper - contains actual message data +export interface ServerMessageWrapper extends WebSocketMessage { + type: 'server_message'; + message: ServerMessage; +} + +// Data message wrapper - contains data payload +export interface DataMessageWrapper extends WebSocketMessage { + type: 'data'; + data: ServerMessage; +} + +// Server messages that can be sent/received +export type ServerMessage = + | ConnectResponseMessage + | SignTransactionResponseMessage + | GenericServerMessage; + +// Connect response - sent when wallet connection is established +export interface ConnectResponseMessage { + type: 'connect'; + success: boolean; + wallets?: string[]; + error?: string; +} + +// Sign transaction response - sent when transaction signing is complete +export interface SignTransactionResponseMessage { + type: 'signTransaction'; + id: number; + success: boolean; + signedTx?: string; + error?: string; +} + +// Generic server message for extensibility +export interface GenericServerMessage { + type: string; + [key: string]: unknown; +} + +// Client request messages sent via API +export interface ConnectRequest { + method: 'connect'; +} + +export interface SignTransactionRequest { + method: 'sT'; + id: number; + tx: `p:${string}` | `bytes:${string}`; + wallet?: string; +} + +export type ClientRequest = ConnectRequest | SignTransactionRequest; + +// Message handler type +export interface MessageHandler { + (data: T): void; +} + +// Socket configuration +export interface SocketConfig { + wsUrl?: string; + apiUrl?: string; +} + +export class WalletSocket { + private ws: WebSocket | null = null; + private uniqueId: string | null = null; + private reconnectAttempts = 0; + private maxReconnectAttempts = 5; + private reconnectDelay = 1000; + private isConnecting = false; + private messageHandlers: Map> = new Map(); + private connectionPromise: Promise | null = null; + private connectionResolve: (() => void) | null = null; + + constructor( + private readonly wsUrl: string = 'wss://connect.varan.app', + private readonly apiUrl: string = 'https://connect.varan.app' + ) {} + + async connect(): Promise { + if (this.connectionPromise) { + return this.connectionPromise.then(() => this.uniqueId!); + } + + this.connectionPromise = new Promise((resolve, reject) => { + if (this.ws?.readyState === WebSocket.OPEN && this.uniqueId) { + resolve(); + return; + } + + if (this.isConnecting) { + // Wait for existing connection attempt + const checkInterval = setInterval(() => { + if (!this.isConnecting && this.uniqueId) { + clearInterval(checkInterval); + resolve(); + } + }, 100); + return; + } + + this.isConnecting = true; + this.reconnectAttempts = 0; + + try { + this.ws = new WebSocket(this.wsUrl); + + this.ws.onopen = (): void => { + console.log('[VARANINJECT] WebSocket connection opened'); + this.isConnecting = false; + this.reconnectAttempts = 0; + }; + + this.ws.onmessage = (event: MessageEvent): void => { + try { + const message: WebSocketMessage = JSON.parse(event.data as string); + this.handleMessage(message); + } catch (error) { + console.error('[VARANINJECT] Error parsing WebSocket message:', error); + } + }; + + this.ws.onerror = (error: Event): void => { + console.error('[VARANINJECT] WebSocket error:', error); + this.isConnecting = false; + if (this.reconnectAttempts < this.maxReconnectAttempts) { + this.attemptReconnect(); + } else { + reject(error); + } + }; + + this.ws.onclose = (): void => { + console.log('[VARANINJECT] WebSocket connection closed'); + this.isConnecting = false; + if (!this.uniqueId) { + // Connection closed before we got an ID, attempt reconnect + if (this.reconnectAttempts < this.maxReconnectAttempts) { + this.attemptReconnect(); + } + } + }; + + // Store resolve function to call when connection message is received + this.connectionResolve = (): void => { + this.connectionResolve = null; + resolve(); + }; + + } catch (error) { + this.isConnecting = false; + reject(error); + } + }); + + await this.connectionPromise; + return this.uniqueId!; + } + + private handleMessage(message: WebSocketMessage): void { + if (message.type === 'connection' && message.id) { + const connMessage = message as ConnectionMessage; + this.uniqueId = connMessage.id; + console.log(`[VARANINJECT] Unique ID received: ${this.uniqueId}`); + // Resolve connection promise if pending + if (this.connectionResolve) { + this.connectionResolve(); + } + } else if (message.type === 'acknowledgment') { + console.log('[VARANINJECT] Data acknowledged by server'); + } else if (message.type === 'server_message') { + console.log('[VARANINJECT] Received server message'); + const serverWrapper = message as ServerMessageWrapper; + if (serverWrapper.message) { + this.handleServerMessage(serverWrapper.message); + } + } else if (message.type === 'data' && message.data) { + console.log('[VARANINJECT] Received data message'); + const dataWrapper = message as DataMessageWrapper; + if (dataWrapper.data) { + // Type guard to ensure data is a ServerMessage + const serverData = dataWrapper.data as ServerMessage; + this.handleServerMessage(serverData); + } + } + } + + private handleServerMessage(data: ServerMessage): void { + // Check if there's a handler for this message type + if (this.messageHandlers.has(data.type)) { + const handler = this.messageHandlers.get(data.type); + handler?.(data); + } + + // Also check for request ID handlers (for signTransaction messages) + if ('id' in data && typeof data.id === 'number') { + const requestId = String(data.id); + const handler = this.messageHandlers.get(`request_${requestId}`); + if (handler) { + handler(data); + this.messageHandlers.delete(`request_${requestId}`); + } + } + } + + async send(data: ClientRequest): Promise { + const id = await this.ensureConnected(); + + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + throw new Error('WebSocket is not connected'); + } + + const message = { + ...data, + id, + }; + + this.ws.send(JSON.stringify(message)); + } + + async sendViaAPI(data: ClientRequest): Promise { + const id = await this.ensureConnected(); + + try { + const response = await fetch(`${this.apiUrl}/send/${id}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('[VARANINJECT] Error sending data via API:', error); + throw error; + } + } + + async getData(): Promise { + const id = await this.ensureConnected(); + + try { + const response = await fetch(`${this.apiUrl}/data/${id}`); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('[VARANINJECT] Error getting data:', error); + throw error; + } + } + + onMessage( + type: string, + handler: MessageHandler + ): () => void { + this.messageHandlers.set(type, handler as MessageHandler); + + // Return unsubscribe function + return () => { + this.messageHandlers.delete(type); + }; + } + + waitForResponse( + requestId: string | number, + timeout: number = 30000 + ): Promise { + return new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + this.messageHandlers.delete(`request_${requestId}`); + reject(new Error(`Timeout waiting for response to request ${requestId}`)); + }, timeout); + + this.messageHandlers.set(`request_${requestId}`, (data: ServerMessage) => { + clearTimeout(timeoutId); + resolve(data as T); + }); + }); + } + + private async ensureConnected(): Promise { + if (!this.uniqueId || !this.ws || this.ws.readyState !== WebSocket.OPEN) { + return await this.connect(); + } + return this.uniqueId; + } + + private attemptReconnect(): void { + this.reconnectAttempts++; + const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1); + + console.log(`[VARANINJECT] Attempting to reconnect in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`); + + setTimeout(() => { + this.connectionPromise = null; + this.connectionResolve = null; + this.connect().catch(console.error); + }, delay); + } + + disconnect(): void { + if (this.ws) { + this.ws.close(); + this.ws = null; + } + this.uniqueId = null; + this.connectionPromise = null; + this.connectionResolve = null; + this.messageHandlers.clear(); + } + + getUniqueId(): string | null { + return this.uniqueId; + } + + isConnected(): boolean { + return this.ws !== null && this.ws.readyState === WebSocket.OPEN && !!this.uniqueId; + } +} + diff --git a/src/store.ts b/src/store.ts index e26ec25..1d06c88 100644 --- a/src/store.ts +++ b/src/store.ts @@ -21,16 +21,11 @@ const defaultStore: WalletStoreType = { export class WalletStore { private readonly store: WalletStorage; - private readonly storeSubscribe: (cb: (ev: StorageEvent) => void) => void; private _store: WalletStoreType; constructor() { this.store = window.localStorage as WalletStorage; this._store = Object.assign(defaultStore, JSON.parse(this.store.getItem(VARAN_WALLET_LS_KEY) || '{}')); - this.storeSubscribe = (cb): void => { - window.addEventListener('storage', cb); - }; - this._setupListeners(); } private callbacks: { @@ -44,69 +39,6 @@ export class WalletStore { transactions: [], }; - private _setupListeners(): void { - let currentState = this._store; - this.storeSubscribe(ev => { - ev.stopImmediatePropagation(); - if (ev.key !== VARAN_WALLET_LS_KEY) return; - - const data = JSON.parse(ev.newValue || '{}') as WalletStoreType; - const keys = Object.keys(data) as (keyof WalletStoreType)[]; - for (const key of keys) { - if (key === 'injectedMetadataKnown') continue; - if (key === 'accounts') { - const currentAccounts = currentState[key]; - const dataAccounts = data[key]; - if (currentAccounts.length !== dataAccounts.length) { - currentState = data; - this._store = data; - this.dispatch(key); - continue; - } - - let shouldDispatch = false; - dataAccounts.forEach(account => { - if (!currentAccounts.includes(account)) { - shouldDispatch = true; - } - }); - - if (shouldDispatch) { - currentState = data; - this._store = data; - this.dispatch(key); - } - continue; - } - if (key === 'transactions') { - const currentTransactions = currentState[key]; - const dataTransactions = data[key]; - if (currentTransactions.length !== dataTransactions.length) { - currentState = data; - this._store = data; - this.dispatch(key); - continue; - } - - let shouldDispatch = false; - dataTransactions.forEach(transaction => { - const currentTransaction = currentTransactions.find(t => t.id === transaction.id); - if (currentTransaction && currentTransaction.status !== transaction.status) { - shouldDispatch = true; - } - }); - - if (shouldDispatch) { - currentState = data; - this._store = data; - this.dispatch(key); - } - continue; - } - } - }); - } - private dispatch(key: Key): void { const callbacks = this.callbacks[key]; if (!callbacks || callbacks.length === 0) return; diff --git a/src/types.ts b/src/types.ts index 028fb33..6c5b1d8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,12 +7,6 @@ declare global { export type WalletStorage = Storage; -export type InjectionConfig = { - callbackUrl: string; - connectTimeout?: number; - closeAppOnActions?: boolean; -} - export type WebApp = typeof WebAppConst; export interface ConnectRequest { method: 'connect'; @@ -20,10 +14,10 @@ export interface ConnectRequest { } export interface SignTransactionRequest { - method: 'signTransaction'; + method: 'sT'; id: number; - tx: string; - wallet: string; + tx: `p:${string}` | `bytes:${string}`; + wallet?: string; callback: string; } diff --git a/src/varan-wallet.ts b/src/varan-wallet.ts index c18cf21..0e307fc 100644 --- a/src/varan-wallet.ts +++ b/src/varan-wallet.ts @@ -1,24 +1,12 @@ -import type { WebApp, InjectionConfig } from './types'; +import type { WebApp } from './types'; import { Wallet } from './wallet'; -const defaultInjectionConfig: Required = { - callbackUrl: '', - connectTimeout: 30_000, - closeAppOnActions: true, -} - -const injectVaranWallet = (webApp: WebApp, config: InjectionConfig = defaultInjectionConfig): void => { +const injectVaranWallet = (webApp: WebApp): void => { const isInTelegram = webApp.platform !== 'unknown'; if (!isInTelegram) return; - const callbackUrl = config.callbackUrl || defaultInjectionConfig.callbackUrl; - - if (!callbackUrl) { - throw new Error('Callback URL must be provided to injectVaranWallet'); - } - - const wallet = new Wallet(webApp, { ...defaultInjectionConfig, ...config }); + const wallet = new Wallet(webApp); window.injectedWeb3 = { varan: wallet, diff --git a/src/wallet.ts b/src/wallet.ts index ecb4666..e8fe26c 100644 --- a/src/wallet.ts +++ b/src/wallet.ts @@ -1,30 +1,28 @@ -import type { ConnectRequest, SignTransactionRequest, WebApp } from "./types"; -import type { InjectionConfig } from "./types"; +import type { WebApp } from "./types"; import { WalletStore } from "./store"; import type { Injected, InjectedAccount, InjectedExtension, InjectedMetadataKnown, InjectedWindowProvider } from "@polkadot/extension-inject/types"; -import { encodeRequest } from "./encryption"; -import { SignerPayloadRaw, SignerResult } from "@polkadot/types/types"; -import { generateRequestId, parseSignedTxFromStartParam, parseWalletsFromStartParam } from "./helpers"; +import { SignerPayloadJSON, SignerPayloadRaw, SignerResult } from "@polkadot/types/types"; +import { generateRequestId } from "./helpers"; import { mockAccountsSubscribe } from "./constants"; - +import { + WalletSocket, + type ConnectResponseMessage, + type SignTransactionResponseMessage, + type ConnectRequest, + type SignTransactionRequest +} from "./socket"; export class Wallet implements InjectedWindowProvider { - private readonly varanWalletUrl!: string; private readonly store: WalletStore; + private readonly socket: WalletSocket; private readonly name = 'Varan Wallet'; - private readonly callbackUrl: string; - private readonly connectTimeout: number; - private readonly closeAppOnActions: boolean; + private readonly varanWalletUrl = 'https://t.me/varanwalletbot/start?startapp='; constructor( private readonly webApp: WebApp, - { callbackUrl, connectTimeout, closeAppOnActions }: Required, ) { - this.varanWalletUrl = 'https://t.me/varanwalletbot/start?startapp='; this.store = new WalletStore(); - this.callbackUrl = callbackUrl; - this.connectTimeout = connectTimeout; - this.closeAppOnActions = closeAppOnActions; - void this._startParamsCheck(); + this.socket = new WalletSocket(); + void this._initializeSocket(); } get version(): string { @@ -34,48 +32,44 @@ export class Wallet implements InjectedWindowProvider { private get signer(): InjectedExtension['signer'] { return { signRaw: (raw) => this.signRawTransaction(raw), + signPayload: (payload) => this.signPayloadTransaction(payload), }; } - private async _startParamsCheck(): Promise { - let actions = 0; - const newWalletAddresses = parseWalletsFromStartParam(this.webApp); - const currentAccounts = await this.accounts; + private async _initializeSocket(): Promise { + try { + await this.socket.connect(); + + // Listen for wallet connection messages + this.socket.onMessage('connect', (data) => { + if (data.success && data.wallets && Array.isArray(data.wallets)) { + const allWallets = Array.from( + new Set( + this.store.get('accounts').concat(data.wallets) + ) + ); + this.store.set('accounts', allWallets); + } + }); - if (newWalletAddresses) { - const allWallets = Array.from( - new Set( - currentAccounts - .map(a => a.address) - .concat(newWalletAddresses) - ) - ) - - this.store.set('accounts', allWallets); - actions += 1; - } - - const tx = parseSignedTxFromStartParam(this.webApp); - - if (tx) { - const currentTransactions = this.store.get('transactions'); - - const pendingTransactionIndex = currentTransactions.findIndex(t => t.id === tx.id && t.status === 'signing'); - if (pendingTransactionIndex === -1) return; - - currentTransactions[pendingTransactionIndex] = { - ...currentTransactions[pendingTransactionIndex], - status: tx.success ? 'success' : 'failed', - signedTx: tx.signedTx ? tx.signedTx : '', - }; - - this.store.set('transactions', currentTransactions); - actions += 1; - } - - - if (actions && this.closeAppOnActions) { - this.webApp.close(); + // Listen for transaction signing responses + this.socket.onMessage('signTransaction', (data) => { + const currentTransactions = this.store.get('transactions'); + const pendingTransactionIndex = currentTransactions.findIndex( + t => t.id === data.id && t.status === 'signing' + ); + + if (pendingTransactionIndex !== -1) { + currentTransactions[pendingTransactionIndex] = { + ...currentTransactions[pendingTransactionIndex], + status: data.success ? 'success' : 'failed', + signedTx: data.signedTx || '', + }; + this.store.set('transactions', currentTransactions); + } + }); + } catch (error) { + console.error('[VARANINJECT] Error initializing socket:', error); } } @@ -100,7 +94,7 @@ export class Wallet implements InjectedWindowProvider { private get extensionMetadata(): InjectedExtension['metadata'] { const metadata = this.store.get('injectedMetadataKnown'); - const setMetadata = async (metadata: InjectedMetadataKnown) => { + const setMetadata = async (metadata: InjectedMetadataKnown): Promise => { await this.store.set('injectedMetadataKnown', metadata); return true; }; @@ -114,87 +108,159 @@ export class Wallet implements InjectedWindowProvider { }; } + private async signPayloadTransaction(payload: SignerPayloadJSON): Promise { + const accounts = await this.accounts; + if (!accounts.length) throw new Error('No accounts found'); + + const address = accounts.find(a => a.address === payload.address); + if (!address) throw new Error('Provided account was not found'); + + const requestId = generateRequestId(); + const request: SignTransactionRequest = { + method: 'sT', + tx: `p:${JSON.stringify(payload)}`, + id: requestId, + }; + + console.log('[VARANINJECT] signPayloadTransaction request', request); + + // Store transaction as pending + const currentTransactions = this.store.get('transactions'); + currentTransactions.push({ + id: requestId, + signedTx: '', + status: 'signing', + }); + this.store.set('transactions', currentTransactions); + + // Send via WebSocket + await this.socket.sendViaAPI(request); + + const botUrl = `${this.varanWalletUrl}${this.socket.getUniqueId()}`; + + this.webApp.openTelegramLink(botUrl); + + // Wait for response + return new Promise((resolve, reject) => { + const unsubscribe = this.socket.onMessage('signTransaction', (data) => { + if (data.id === requestId) { + unsubscribe(); + + const currentTransactions = this.store.get('transactions'); + const transaction = currentTransactions.find(t => t.id === requestId); + + if (transaction && transaction.status !== 'signing') { + if (transaction.status === 'success') { + resolve({ + id: transaction.id, + signature: transaction.signedTx, + } as SignerResult); + } else { + reject(new Error('Transaction signing failed')); + } + } + } + }); + }); + } + private async signRawTransaction(raw: SignerPayloadRaw): Promise { + if (raw.type === 'payload') { + console.log('[VARANINJECT] signRawTransaction payload', raw.data); + return this.signPayloadTransaction(JSON.parse(raw.data)); + } + const accounts = await this.accounts; if (!accounts.length) throw new Error('No accounts found'); const address = accounts.find(a => a.address === raw.address); if (!address) throw new Error('Provided account was not found'); + const requestId = generateRequestId(); const request: SignTransactionRequest = { - method: 'signTransaction', - tx: raw.data, + method: 'sT', + tx: `bytes:${raw.data}`, wallet: raw.address, - callback: this.callbackUrl, - id: generateRequestId(), + id: requestId, }; - - const encodedRequest = encodeRequest(request); - const botUrl = `${this.varanWalletUrl}${encodedRequest}`; - this.store.set('transactions', [{ - id: request.id, + + // Store transaction as pending + const currentTransactions = this.store.get('transactions'); + currentTransactions.push({ + id: requestId, signedTx: '', status: 'signing', - }]); - - this.webApp.openTelegramLink(botUrl); + }); + this.store.set('transactions', currentTransactions); - return new Promise((resolve) => { - const id = this.store.subscribe('transactions', (transactions) => { - const pendingTransaction = transactions.find(t => t.id === request.id && t.status !== 'signing'); - if (pendingTransaction) { - this.store.unsubscribe('transactions', id); - resolve({ - id: pendingTransaction.id, - signature: pendingTransaction.signedTx, - } as SignerResult); + // Send via WebSocket + await this.socket.sendViaAPI(request); + + // Wait for response + return new Promise((resolve, reject) => { + const unsubscribe = this.socket.onMessage('signTransaction', (data) => { + if (data.id === requestId) { + unsubscribe(); + + const currentTransactions = this.store.get('transactions'); + const transaction = currentTransactions.find(t => t.id === requestId); + + if (transaction && transaction.status !== 'signing') { + if (transaction.status === 'success') { + resolve({ + id: transaction.id, + signature: transaction.signedTx, + } as SignerResult); + } else { + reject(new Error('Transaction signing failed')); + } + } } }); }); } private async _connect(): Promise { - const request: ConnectRequest = { - method: 'connect', - callback: this.callbackUrl, - }; + try { + // Ensure socket is connected + await this.socket.connect(); - const encodedRequest = encodeRequest(request); - console.log('encodedRequest', encodedRequest); - const botUrl = `${this.varanWalletUrl}${encodedRequest}`; - console.log('botUrl', botUrl); - await this.webApp.openTelegramLink(botUrl); + // Send connect request via WebSocket + await this.socket.sendViaAPI({ + method: 'connect', + } as ConnectRequest); - return new Promise((resolve) => { - const id = this.store.subscribe('accounts', (accounts) => { - if (accounts.length) { - this.store.unsubscribe('accounts', id); - resolve(); - } + const botUrl = `${this.varanWalletUrl}${this.socket.getUniqueId()}`; + await this.webApp.openTelegramLink(botUrl); + + // Wait for accounts to be populated + return new Promise((resolve) => { + const unsubscribe = this.socket.onMessage('connect', (data) => { + if (data.success && data.wallets && data.wallets.length > 0) { + unsubscribe(); + resolve(); + } + }); }); - }); + } catch (error) { + console.error('[VARANINJECT] Connect error:', error); + throw error; + } } async connect(): Promise { const accounts = await this.accounts; if (!accounts.length) { - await Promise.race([ - this._connect(), - new Promise((_, reject) => { - setTimeout(() => { - reject(new Error('Connect timeout')); - }, this.connectTimeout); - }) - ]); + await this._connect(); } - return Promise.resolve({ + return { name: this.name, version: this.version, accounts: this.extensionAccounts, signer: this.signer, metadata: this.extensionMetadata, - }); + }; } async enable(): Promise {