diff --git a/package-lock.json b/package-lock.json index 9644bd8..406e5c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -160,6 +160,10 @@ "resolved": "packages/signer-ledger-cosmos", "link": true }, + "node_modules/@chorus-one/signer-ledger-ton": { + "resolved": "packages/signer-ledger-ton", + "link": true + }, "node_modules/@chorus-one/signer-local": { "resolved": "packages/signer-local", "link": true @@ -1669,18 +1673,20 @@ } }, "node_modules/@ledgerhq/devices": { - "version": "8.4.0", - "license": "Apache-2.0", + "version": "8.4.4", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.4.4.tgz", + "integrity": "sha512-sz/ryhe/R687RHtevIE9RlKaV8kkKykUV4k29e7GAVwzHX1gqG+O75cu1NCJUHLbp3eABV5FdvZejqRUlLis9A==", "dependencies": { - "@ledgerhq/errors": "^6.17.0", + "@ledgerhq/errors": "^6.19.1", "@ledgerhq/logs": "^6.12.0", "rxjs": "^7.8.1", "semver": "^7.3.5" } }, "node_modules/@ledgerhq/errors": { - "version": "6.17.0", - "license": "Apache-2.0" + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.19.1.tgz", + "integrity": "sha512-75yK7Nnit/Gp7gdrJAz0ipp31CCgncRp+evWt6QawQEtQKYEDfGo10QywgrrBBixeRxwnMy1DP6g2oCWRf1bjw==" }, "node_modules/@ledgerhq/hw-app-cosmos": { "version": "6.30.0", @@ -1692,15 +1698,43 @@ } }, "node_modules/@ledgerhq/hw-transport": { - "version": "6.31.0", - "license": "Apache-2.0", + "version": "6.31.4", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.31.4.tgz", + "integrity": "sha512-6c1ir/cXWJm5dCWdq55NPgCJ3UuKuuxRvf//Xs36Bq9BwkV2YaRQhZITAkads83l07NAdR16hkTWqqpwFMaI6A==", "dependencies": { - "@ledgerhq/devices": "^8.4.0", - "@ledgerhq/errors": "^6.17.0", + "@ledgerhq/devices": "^8.4.4", + "@ledgerhq/errors": "^6.19.1", "@ledgerhq/logs": "^6.12.0", "events": "^3.3.0" } }, + "node_modules/@ledgerhq/hw-transport-node-hid": { + "version": "6.29.5", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.29.5.tgz", + "integrity": "sha512-2bAp4K50V1kdCufU9JdQPcw4aLyvA+yQRJU/X39B+PC+rnis40gEbqNh0henhzv876sXdbNk6G/MkDWXpwDIow==", + "dependencies": { + "@ledgerhq/devices": "^8.4.4", + "@ledgerhq/errors": "^6.19.1", + "@ledgerhq/hw-transport": "^6.31.4", + "@ledgerhq/hw-transport-node-hid-noevents": "^6.30.5", + "@ledgerhq/logs": "^6.12.0", + "lodash": "^4.17.21", + "node-hid": "2.1.2", + "usb": "2.9.0" + } + }, + "node_modules/@ledgerhq/hw-transport-node-hid-noevents": { + "version": "6.30.5", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-6.30.5.tgz", + "integrity": "sha512-nOPbhFU87LgLERVAQ+HhxV8E8c+7d8ptllkgiJUc4QwL2z9zkIOAEtgdvCaZ066Oi9XGnln/GF1oAgByYnYDPw==", + "dependencies": { + "@ledgerhq/devices": "^8.4.4", + "@ledgerhq/errors": "^6.19.1", + "@ledgerhq/hw-transport": "^6.31.4", + "@ledgerhq/logs": "^6.12.0", + "node-hid": "2.1.2" + } + }, "node_modules/@ledgerhq/logs": { "version": "6.12.0", "license": "Apache-2.0" @@ -3807,6 +3841,19 @@ "tslib": "^2.4.0" } }, + "node_modules/@ton-community/ton-ledger": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@ton-community/ton-ledger/-/ton-ledger-7.2.0.tgz", + "integrity": "sha512-y3bb+l3RqN5muISVBLNBc3NbfU8FFcSjuB6rJcvP2K/YAKFtEIREpXsobQtI5NhTmRV7WwWuio4labc+QJwozg==", + "dependencies": { + "@ledgerhq/hw-transport": "^6.28.4", + "@ton/crypto": "^3.2.0", + "teslabot": "^1.5.0" + }, + "peerDependencies": { + "@ton/core": ">=0.52.2" + } + }, "node_modules/@ton/core": { "version": "0.59.1", "resolved": "https://registry.npmjs.org/@ton/core/-/core-0.59.1.tgz", @@ -3966,6 +4013,11 @@ "version": "8.3.4", "license": "MIT" }, + "node_modules/@types/w3c-web-usb": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.10.tgz", + "integrity": "sha512-CHgUI5kTc/QLMP8hODUHhge0D4vx+9UiAwIGiT0sTy/B2XpdX1U5rJt6JSISgr6ikRT7vxV9EVAFeYZqUnl1gQ==" + }, "node_modules/@types/ws": { "version": "7.4.7", "license": "MIT", @@ -4396,6 +4448,39 @@ "@noble/hashes": "^1.2.0" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/blakejs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", @@ -4769,6 +4854,11 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "node_modules/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -4982,6 +5072,20 @@ "node": ">=0.10" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", @@ -4994,6 +5098,14 @@ "node": ">=6" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "dev": true, @@ -5054,6 +5166,14 @@ "node": ">= 0.8" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -5124,6 +5244,14 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/enquirer": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", @@ -5646,6 +5774,14 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, "node_modules/eyes": { "version": "0.1.8", "engines": { @@ -5865,6 +6001,11 @@ "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", "dev": true }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -5972,6 +6113,11 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, "node_modules/glob": { "version": "7.2.3", "dev": true, @@ -6560,6 +6706,11 @@ "version": "2.0.4", "license": "ISC" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "node_modules/io-ts": { "version": "1.10.4", "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", @@ -7218,6 +7369,17 @@ "node": ">= 0.6" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "license": "ISC" @@ -7239,12 +7401,16 @@ }, "node_modules/minimist": { "version": "1.2.8", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "node_modules/mnemonist": { "version": "0.38.5", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", @@ -7375,6 +7541,11 @@ "npm": ">=1.4.0" } }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==" + }, "node_modules/napi-macros": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", @@ -7433,6 +7604,17 @@ "node": ">= 10.13" } }, + "node_modules/node-abi": { + "version": "3.74.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz", + "integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-addon-api": { "version": "5.1.0", "license": "MIT" @@ -7481,6 +7663,28 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-hid": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-2.1.2.tgz", + "integrity": "sha512-qhCyQqrPpP93F/6Wc/xUR7L8mAJW0Z6R7HMQV8jCHHksAxNDe/4z4Un/H9CpLOT+5K39OPyt9tIQlavxWES3lg==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^3.0.2", + "prebuild-install": "^7.1.1" + }, + "bin": { + "hid-showdevices": "src/show-devices.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-hid/node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -7512,7 +7716,6 @@ }, "node_modules/once": { "version": "1.4.0", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -7687,6 +7890,31 @@ "version": "1.3.6", "license": "MIT" }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "dev": true, @@ -7745,6 +7973,15 @@ "version": "1.1.0", "license": "MIT" }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "dev": true, @@ -7864,6 +8101,28 @@ "node": ">=0.6" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "license": "MIT", @@ -8225,6 +8484,49 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/slash": { "version": "3.0.0", "dev": true, @@ -8479,6 +8781,32 @@ "resolved": "https://registry.npmjs.org/symbol.inspect/-/symbol.inspect-1.0.1.tgz", "integrity": "sha512-YQSL4duoHmLhsTD1Pw8RW6TZ5MaTX5rXJnqacJottr2P2LZBF/Yvrc3ku4NUpMOm8aM0KOCqM+UAkMA5HWQCzQ==" }, + "node_modules/tar-fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", + "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/teslabot": { "version": "1.5.0", "license": "MIT" @@ -8570,6 +8898,17 @@ "fsevents": "~2.3.3" } }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/turbo": { "version": "2.0.9", "dev": true, @@ -8893,6 +9232,25 @@ "punycode": "^2.1.0" } }, + "node_modules/usb": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/usb/-/usb-2.9.0.tgz", + "integrity": "sha512-G0I/fPgfHUzWH8xo2KkDxTTFruUWfppgSFJ+bQxz/kVY2x15EQ/XDB7dqD1G432G4gBG4jYQuF3U7j/orSs5nw==", + "hasInstallScript": true, + "dependencies": { + "@types/w3c-web-usb": "^1.0.6", + "node-addon-api": "^6.0.0", + "node-gyp-build": "^4.5.0" + }, + "engines": { + "node": ">=10.20.0 <11.x || >=12.17.0 <13.0 || >=14.0.0" + } + }, + "node_modules/usb/node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, "node_modules/utf-8-validate": { "version": "5.0.10", "hasInstallScript": true, @@ -9055,7 +9413,6 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "dev": true, "license": "ISC" }, "node_modules/ws": { @@ -9324,6 +9681,18 @@ "@ledgerhq/hw-transport": "^6.31.0" } }, + "packages/signer-ledger-ton": { + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@chorus-one/signer": "^1.0.0", + "@chorus-one/ton": "^2.0.2", + "@chorus-one/utils": "^1.0.0", + "@ledgerhq/hw-transport": "^6.31.0", + "@ton-community/ton-ledger": "^7.2.0", + "@ton/ton": "^15.1.0" + } + }, "packages/signer-local": { "name": "@chorus-one/signer-local", "version": "1.0.0", @@ -9368,12 +9737,14 @@ "@chorus-one/near": "^1.0.0", "@chorus-one/signer": "^1.0.0", "@chorus-one/signer-fireblocks": "^1.0.0", + "@chorus-one/signer-ledger-ton": "^1.0.0", "@chorus-one/signer-local": "^1.0.0", "@chorus-one/solana": "^1.0.0", "@chorus-one/substrate": "^1.0.1", "@chorus-one/ton": "^2.0.0", "@chorus-one/utils": "^1.0.0", "@commander-js/extra-typings": "^11.1.0", + "@ledgerhq/hw-transport-node-hid": "^6.29.5", "chalk": "^4.1.2" }, "bin": { diff --git a/packages/signer-ledger-ton/LICENSE b/packages/signer-ledger-ton/LICENSE new file mode 100644 index 0000000..03e9851 --- /dev/null +++ b/packages/signer-ledger-ton/LICENSE @@ -0,0 +1,13 @@ +Copyright 2024 Chorus One AG + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/packages/signer-ledger-ton/README.md b/packages/signer-ledger-ton/README.md new file mode 100644 index 0000000..5d17ce0 --- /dev/null +++ b/packages/signer-ledger-ton/README.md @@ -0,0 +1,32 @@ +# Chorus One SDK: Ledger TON Signer + +Ledger signer for the Chorus One SDK, used for signing TON transactions + +## Installation + +In the project’s root directory, run the following command: + +```bash +npm install @chorus-one/signer-ledger-ton --save +``` + +## Setting Up the LedgerTonSigner + +With your mnemonic and HD path ready, you can now configure and initialize the LedgerTonSigner: + +```javascript +import { LedgerTonSigner } from '@chorus-one/signer-ledger-ton' +import TransportNodeHid from '@ledgerhq/hw-transport-node-hid' + +const signer = new LedgerTonSigner({ + transport: await TransportNodeHid.create(), + accounts: [{ hdPath: 'your-hd-path' }], + bounceable: true +}) + +await signer.init() +``` + +## License + +The Chorus One SDK is licensed under the Apache 2.0 License. For more detailed information, please refer to the [LICENSE](./LICENSE) file in the repository. diff --git a/packages/signer-ledger-ton/package.json b/packages/signer-ledger-ton/package.json new file mode 100644 index 0000000..6bcf68b --- /dev/null +++ b/packages/signer-ledger-ton/package.json @@ -0,0 +1,41 @@ +{ + "name": "@chorus-one/signer-ledger-ton", + "version": "1.0.0", + "description": "Ledger signer for the Chorus One SDK, used for signing TON transactions", + "scripts": { + "build": "rm -fr dist/* && tsc -p tsconfig.mjs.json --outDir dist/mjs && tsc -p tsconfig.cjs.json --outDir dist/cjs && bash ../../scripts/fix-package-json" + }, + "main": "dist/cjs/index.js", + "module": "dist/mjs/index.js", + "types": "dist/mjs/index.d.ts", + "exports": { + ".": { + "import": "./dist/mjs/index.js", + "require": "./dist/cjs/index.js", + "types": "./dist/mjs/index.d.ts" + } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ChorusOne/chorus-one-sdk.git", + "directory": "packages/signer-ledger-ton" + }, + "homepage": "https://chorus-one.gitbook.io/sdk", + "keywords": [ + "chorus-one", + "sdk", + "signer", + "ledger", + "ton" + ], + "author": "Chrous One AG", + "license": "Apache-2.0", + "dependencies": { + "@chorus-one/signer": "^1.0.0", + "@chorus-one/ton": "^2.0.2", + "@chorus-one/utils": "^1.0.0", + "@ledgerhq/hw-transport": "^6.31.0", + "@ton-community/ton-ledger": "^7.2.0", + "@ton/ton": "^15.1.0" + } +} diff --git a/packages/signer-ledger-ton/src/index.ts b/packages/signer-ledger-ton/src/index.ts new file mode 100644 index 0000000..c81725f --- /dev/null +++ b/packages/signer-ledger-ton/src/index.ts @@ -0,0 +1,2 @@ +export { LedgerTonSigner } from './signer' +export { LedgerTonSignerConfig } from './types.d' diff --git a/packages/signer-ledger-ton/src/signer.ts b/packages/signer-ledger-ton/src/signer.ts new file mode 100644 index 0000000..02e9375 --- /dev/null +++ b/packages/signer-ledger-ton/src/signer.ts @@ -0,0 +1,186 @@ +import { nopLogger } from '@chorus-one/utils' +import type { Logger } from '@chorus-one/utils' +import type { LedgerTonSignerConfig } from './types' +import type { Signature, SignerData } from '@chorus-one/signer' +import { TonTransport as Ton, TonPayloadFormat } from '@ton-community/ton-ledger' +import Transport from '@ledgerhq/hw-transport' +import { TonSigningData } from '@chorus-one/ton' +import { Address, Cell } from '@ton/ton' + +/** + * The LedgerTonSigner in the Chorus One SDK is a specialized implementation of the Signer interface that + * utilizes a Ledger Ton App + * + * Ledger is known for its advanced security features, including secure hardware wallets and robust key management, + * making it an ideal choice for retail and enterprise customers + */ +export class LedgerTonSigner { + private readonly config: LedgerTonSignerConfig + private readonly transport: Transport + private accounts: Map<string, { hdPath: string; publicKey: Uint8Array }> + private app?: Ton + private logger: Logger + + /** + * Constructs a new LedgerTonSigner. + * + * @param params - The parameters required to initialize the LedgerTonSigner + * @param params.transport - The Ledger HW transport object to use for communication with the Ledger device + * @param params.accounts - An array of account objects, each containing an HD path + * @param params.bounceable - Address derivation setting to enable bounceable addresses + * @param params.logger - (Optional) A logger to use for logging messages, i.e `console` + * + * @returns A new instance of LedgerTonSigner. + */ + constructor (params: { transport: Transport; accounts: [{ hdPath: string }]; bounceable: boolean; logger?: Logger }) { + const { transport, ...config } = params + + this.transport = transport + this.config = config + this.logger = params.logger ?? nopLogger + this.accounts = new Map() + } + + /** + * Initializes the signer, performing any necessary setup or configuration. + * @returns A promise that resolves once the initialization is complete. + */ + async init (): Promise<void> { + const app = new Ton(this.transport) + this.app = app + + this.config.accounts.forEach(async (account: { hdPath: string }) => { + const hdPath = account.hdPath + .replace('m/', '') + .split('/') + .map((i: string) => Number(i.replace("'", ''))) + + // TON Ledger app requires 6 elements in the HD path + if (hdPath.length < 6) { + throw new Error('Invalid path, expected at least 5 elements') + } + + const network = hdPath[2] + const chain = hdPath[3] + const testOnly = network === 1 + + const response = await app.getAddress(hdPath, { + bounceable: this.config.bounceable, + chain, + testOnly + }) + + this.accounts.set(response.address.toLowerCase(), { + hdPath: account.hdPath, + publicKey: response.publicKey + }) + }) + } + + /** + * Signs the provided data using the private key associated with the signer's address. + * + * @param signerAddress - The address of the signer + * @param signerData - The data to be signed, which can be a raw message or custom data + * + * @returns A promise that resolves to an object containing the signature and public key. + */ + async sign (signerAddress: string, signerData: SignerData): Promise<{ sig: Signature; pk: Uint8Array }> { + if (this.app === undefined) { + throw new Error('LedgerTonSigner not initialized. Did you forget to call init()?') + } + this.logger.info(`signing data from address: ${signerAddress} with Ledger Ton App`) + + if (signerData.data === undefined) { + throw new Error('missing message to sign') + } + + const data: TonSigningData = signerData.data + const account = this.getAccount(signerAddress) + const path = account.hdPath + .replace('m/', '') + .split('/') + .map((i: string) => Number(i.replace("'", ''))) + + if (data.tx.messages !== undefined && data.tx.messages.length > 1) { + throw new Error( + 'Ledger App can only sign one message per transaction. The requested TX has ' + + data.tx.messages.length + + ' messages' + ) + } + + const msg = data.tx.messages !== undefined ? data.tx.messages[0] : undefined + const timeout = data.txArgs.timeout || data.tx.validUntil || Math.floor(Date.now() / 1000) + 180 // 3 minutes + + let payload: TonPayloadFormat | undefined = undefined + if (msg !== undefined) { + if (msg.payload !== undefined && !(msg.payload instanceof Cell)) { + throw new Error('Ledger App can only sign Cell payloads') + } + payload = { + type: 'unsafe', + message: msg.payload === undefined ? Cell.EMPTY : (msg.payload as Cell) + } + } + + const common = { + sendMode: data.txArgs.sendMode, + seqno: data.txArgs.seqno, + timeout, + payload + } + + const args = + msg !== undefined + ? { + to: Address.parse(msg.address), + bounce: msg.bounceable, + amount: msg.amount, + stateInit: msg.stateInit, + ...common + } + : { + // A transaction without message is still a valid TX (e.g. for deploying wallet contract) however, + // the Ledger App requires one message to be present in the transaction, + // therefore we create a dummy message with zero amount and no stateInit + // that sends 0 tokens to self + to: Address.parse(signerAddress), + bounce: false, + amount: BigInt(0), + stateInit: undefined, + ...common + } + + const signedTx: Cell = await this.app.signTransaction(path, args) + const sig = { + // sneaking signed transaction into sig field + fullSig: signedTx.toBoc().toString('hex'), + r: '', + s: '', + v: 0 + } + + return { sig, pk: account.publicKey } + } + + /** + * Retrieves the public key associated with the signer's address. + * + * @param address - The address of the signer + * + * @returns A promise that resolves to a Uint8Array representing the public key. + */ + async getPublicKey (address: string): Promise<Uint8Array> { + return this.getAccount(address).publicKey + } + + private getAccount (address: string): { hdPath: string; publicKey: Uint8Array } { + const account = this.accounts.get(address.toLowerCase()) + if (account === undefined) { + throw new Error(`no account found for address: ${address}`) + } + + return account + } +} diff --git a/packages/signer-ledger-ton/src/types.d.ts b/packages/signer-ledger-ton/src/types.d.ts new file mode 100644 index 0000000..ae2b188 --- /dev/null +++ b/packages/signer-ledger-ton/src/types.d.ts @@ -0,0 +1,9 @@ +/** @ignore */ +export interface LedgerTonSignerConfig { + // Whether derived addresses should be bounceable + bounceable: boolean + + // BIP44 address derivation path + // e.g. 44'/607'/0'/0'/0'/0' + accounts: [{ hdPath: string }] +} diff --git a/packages/signer-ledger-ton/tsconfig.cjs.json b/packages/signer-ledger-ton/tsconfig.cjs.json new file mode 100644 index 0000000..21cff9e --- /dev/null +++ b/packages/signer-ledger-ton/tsconfig.cjs.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.cjs.json", + "compilerOptions": { + "rootDir": "src" + }, + "include": ["src"], + "exclude": ["node_modules", "dist"], + "references": [{ "path": "../signer" }, { "path": "../utils" }, { "path": "../ton" }] +} diff --git a/packages/signer-ledger-ton/tsconfig.json b/packages/signer-ledger-ton/tsconfig.json new file mode 100644 index 0000000..732a1c8 --- /dev/null +++ b/packages/signer-ledger-ton/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "baseUrl": ".", + "paths": { + "@chorus-one/signer": ["../signer/src"], + "@chorus-one/utils": ["../utils/src"] + } + }, + "include": ["src"], + "exclude": ["node_modules", "dist"], + "references": [{ "path": "../signer" }, { "path": "../utils" }, { "path": "../ton" }] +} diff --git a/packages/signer-ledger-ton/tsconfig.mjs.json b/packages/signer-ledger-ton/tsconfig.mjs.json new file mode 100644 index 0000000..2424c71 --- /dev/null +++ b/packages/signer-ledger-ton/tsconfig.mjs.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.mjs.json", + "compilerOptions": { + "rootDir": "src" + }, + "include": ["src"], + "exclude": ["node_modules", "dist"], + "references": [{ "path": "../signer" }, { "path": "../utils" }, { "path": "../ton" }] +} diff --git a/packages/staking-cli/package.json b/packages/staking-cli/package.json index 8f57773..5671b1d 100644 --- a/packages/staking-cli/package.json +++ b/packages/staking-cli/package.json @@ -31,12 +31,14 @@ "@chorus-one/near": "^1.0.0", "@chorus-one/signer": "^1.0.0", "@chorus-one/signer-fireblocks": "^1.0.0", + "@chorus-one/signer-ledger-ton": "^1.0.0", "@chorus-one/signer-local": "^1.0.0", "@chorus-one/solana": "^1.0.0", "@chorus-one/substrate": "^1.0.1", "@chorus-one/ton": "^2.0.0", "@chorus-one/utils": "^1.0.0", "@commander-js/extra-typings": "^11.1.0", + "@ledgerhq/hw-transport-node-hid": "^6.29.5", "chalk": "^4.1.2" } } diff --git a/packages/staking-cli/src/enums.ts b/packages/staking-cli/src/enums.ts index fe8bc8a..092c461 100644 --- a/packages/staking-cli/src/enums.ts +++ b/packages/staking-cli/src/enums.ts @@ -2,7 +2,8 @@ // value (not only the type) export enum SignerType { FIREBLOCKS = 'fireblocks', - LOCAL = 'local' + LOCAL = 'local', + LEDGER = 'ledger' } export enum NetworkType { diff --git a/packages/staking-cli/src/signer.ts b/packages/staking-cli/src/signer.ts index acc3456..a90dff1 100644 --- a/packages/staking-cli/src/signer.ts +++ b/packages/staking-cli/src/signer.ts @@ -6,6 +6,8 @@ import { SignerType } from './enums' import { FireblocksSigner } from '@chorus-one/signer-fireblocks' import { LocalSigner } from '@chorus-one/signer-local' import { Logger } from '@chorus-one/utils' +import { LedgerTonSigner } from '@chorus-one/signer-ledger-ton' +import TransportNodeHid from '@ledgerhq/hw-transport-node-hid' export async function newSigner ( config: Config, @@ -50,5 +52,18 @@ export async function newSigner ( ...config.localsigner }) } + case SignerType.LEDGER: { + if (config.networkType !== 'ton') { + throw new Error('Ledger signer is only supported for TON network') + } + + const transport = await TransportNodeHid.create() + + return new LedgerTonSigner({ + transport: transport, + logger: options.logger, + ...config.ledger + }) + } } } diff --git a/packages/staking-cli/src/types.d.ts b/packages/staking-cli/src/types.d.ts index 6751dce..7b3dc5a 100644 --- a/packages/staking-cli/src/types.d.ts +++ b/packages/staking-cli/src/types.d.ts @@ -8,6 +8,7 @@ import type { TonNetworkConfig } from '@chorus-one/ton' import type { SolanaNetworkConfig } from '@chorus-one/solana' import type { FireblocksSignerConfig } from '@chorus-one/signer-fireblocks' import type { LocalSignerConfig } from '@chorus-one/signer-local' +import type { LedgerTonSignerConfig } from '@chorus-one/signer-ledger-ton' interface FireblocksSignerCliConfig extends Omit<FireblocksSignerConfig, 'apiSecretKey' | 'apiKey'> { apiSecretKeyPath: string @@ -34,6 +35,9 @@ export interface Config { // use local signer (used for testing) localsigner: LocalSignerCliConfig + // use ledger hardware wallet as signer + ledger: LedgerTonSignerConfig // | LedgerCosmosSignerConfig | ... + // the network type to interact with networkType: NetworkType diff --git a/packages/ton/src/TonBaseStaker.ts b/packages/ton/src/TonBaseStaker.ts index af36282..8b71539 100644 --- a/packages/ton/src/TonBaseStaker.ts +++ b/packages/ton/src/TonBaseStaker.ts @@ -369,7 +369,7 @@ export class TonBaseStaker { if (this.addressDerivationConfig.walletContractVersion !== 4) { throw new Error('unsupported wallet contract version') } - const preparedTx = createWalletTransferV4({ + const txArgs = { seqno, // As explained here: https://docs.ton.org/develop/smart-contracts/messages#message-modes // IGNORE_ERRORS ignores only selected errors, such as insufficient funds etc @@ -386,12 +386,16 @@ export class TonBaseStaker { walletId: wallet.walletId, messages: internalMsgs, timeout: tx.validUntil - }) + } + const preparedTx = createWalletTransferV4(txArgs) const signingData: TonSigningData = { tx, + txArgs, txCell: preparedTx } + + // sign transaction via signer const signedTx = await sign(signerAddress, signer, signingData) // decide whether to deploy wallet contract along with the transaction diff --git a/packages/ton/src/tx.ts b/packages/ton/src/tx.ts index c8cdd97..6ad01d1 100644 --- a/packages/ton/src/tx.ts +++ b/packages/ton/src/tx.ts @@ -53,14 +53,22 @@ export async function sign (signerAddress: string, signer: Signer, signingData: const { sig } = await signer.sign( signerAddress, - { message: signingMessage.hash().toString('hex'), data: { tx: signingMessage } }, + { message: signingMessage.hash().toString('hex'), data: signingData }, { note: SafeJSONStringify(signingData.tx, 2) } ) + const sigbuf = Buffer.from(sig.fullSig, 'hex') - const body = beginCell() - .storeBuffer(Buffer.from(sig.fullSig, 'hex')) - .storeBuilder(signingMessage.asBuilder()) - .endCell() + // The signer can also return a signed transaction (e.g ledger signer). + // In such case the cell size will at 128 bytes + remaining transaction data + if (sigbuf.length > 128) { + const cells = Cell.fromBoc(sigbuf) + if (cells.length !== 1) { + throw new Error('signer returned ' + cells.length + 'cells instead of 1') + } + return cells[0] + } + + const body = beginCell().storeBuffer(sigbuf).storeBuilder(signingMessage.asBuilder()).endCell() return body } diff --git a/packages/ton/src/types.d.ts b/packages/ton/src/types.d.ts index 3499a06..2ec2e58 100644 --- a/packages/ton/src/types.d.ts +++ b/packages/ton/src/types.d.ts @@ -1,4 +1,4 @@ -import { Cell, StateInit, Transaction } from '@ton/ton' +import { Cell, StateInit, Transaction, MessageRelaxed } from '@ton/ton' /** @ignore */ export interface TonSigningData { @@ -7,6 +7,15 @@ export interface TonSigningData { // unsigned transaction as a Cell txCell: Cell + + // unsigned transaction arguments + txArgs: { + seqno: number + sendMode: number + walletId: number + messages: MessageRelaxed[] + timeout?: number + } } /** @ignore */