From ed20ee83df0f3945b32ef9396d4f829caa255cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yasin=20=C3=87al=C4=B1=C5=9Fkan?= Date: Mon, 12 Jan 2026 16:34:56 +0300 Subject: [PATCH 1/5] feat: add verifySignature function and parameter --- package-lock.json | 123 +++++------------------------ package.json | 5 +- src/PeraWalletConnect.ts | 70 ++++++++++++---- src/util/PeraWalletConnectError.ts | 3 +- src/util/array/arrayUtils.ts | 21 ++++- src/util/peraWalletConstants.ts | 11 ++- 6 files changed, 109 insertions(+), 124 deletions(-) diff --git a/package-lock.json b/package-lock.json index 033d754..84010d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,8 @@ "@walletconnect/types": "^1.8.0", "bowser": "2.11.0", "buffer": "^6.0.3", - "qr-code-styling": "1.6.0-rc.1" + "qr-code-styling": "1.6.0-rc.1", + "tweetnacl": "^1.0.3" }, "devDependencies": { "@hipo/eslint-config-base": "^4.1.1", @@ -39,7 +40,7 @@ "typescript": "^4.6.3" }, "peerDependencies": { - "algosdk": "^3.0.0" + "algosdk": "^3.5.2" } }, "node_modules/@babel/code-frame": { @@ -528,8 +529,7 @@ "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@types/minimist": { "version": "1.2.5", @@ -563,6 +563,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", "@typescript-eslint/scope-manager": "5.62.0", @@ -597,6 +598,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", @@ -933,6 +935,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1011,15 +1014,15 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/algorand-msgpack/-/algorand-msgpack-1.1.0.tgz", "integrity": "sha512-08k7pBQnkaUB5p+jL7f1TRaUIlTSDE0cesFu1mD7llLao+1cAhtvvZmGE3OnisTd0xOn118QMw74SRqddqaYvw==", - "peer": true, "engines": { "node": ">= 14" } }, "node_modules/algosdk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/algosdk/-/algosdk-3.0.0.tgz", - "integrity": "sha512-PIKZ/YvbBpCudduug4KSH1CY/pTotI7/ccbUIbXKtcI9Onevl+57E+K5X4ow4gsCdysZ8zVvSLdxuCcXvsmPOw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/algosdk/-/algosdk-3.5.2.tgz", + "integrity": "sha512-frhGtZl1JvfrLRKmMvUm880wj4OiWsWo2FhbreNWh7pdFsKuWPj60fV682wt/CYefLI70iwHavPOwGBkTVt0VA==", + "license": "MIT", "peer": true, "dependencies": { "algorand-msgpack": "^1.1.0", @@ -1130,7 +1133,6 @@ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -1147,7 +1149,6 @@ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -1177,7 +1178,6 @@ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -1198,7 +1198,6 @@ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -1217,7 +1216,6 @@ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -1236,7 +1234,6 @@ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, - "peer": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -1286,7 +1283,6 @@ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, - "peer": true, "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -1326,7 +1322,6 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "peer": true, "engines": { "node": "*" } @@ -1400,6 +1395,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", @@ -1517,7 +1513,6 @@ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, - "peer": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -1957,7 +1952,6 @@ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -1975,7 +1969,6 @@ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -1993,7 +1986,6 @@ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -2076,7 +2068,6 @@ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, - "peer": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -2094,7 +2085,6 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, - "peer": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -2257,7 +2247,6 @@ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, - "peer": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -2318,7 +2307,6 @@ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, - "peer": true, "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -2331,7 +2319,6 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" } @@ -2341,7 +2328,6 @@ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dev": true, - "peer": true, "dependencies": { "es-errors": "^1.3.0" }, @@ -2354,7 +2340,6 @@ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, - "peer": true, "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -2369,7 +2354,6 @@ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, - "peer": true, "dependencies": { "hasown": "^2.0.0" } @@ -2379,7 +2363,6 @@ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, - "peer": true, "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -2418,6 +2401,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -2485,7 +2469,6 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, - "peer": true, "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -2497,7 +2480,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "peer": true, "dependencies": { "ms": "^2.1.1" } @@ -2528,7 +2510,6 @@ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz", "integrity": "sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==", "dev": true, - "peer": true, "dependencies": { "debug": "^3.2.7" }, @@ -2546,7 +2527,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "peer": true, "dependencies": { "ms": "^2.1.1" } @@ -2588,7 +2568,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "peer": true, "dependencies": { "ms": "^2.1.1" } @@ -2598,7 +2577,6 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, - "peer": true, "dependencies": { "esutils": "^2.0.2" }, @@ -2611,7 +2589,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "peer": true, "bin": { "semver": "bin/semver.js" } @@ -3057,7 +3034,6 @@ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, - "peer": true, "dependencies": { "is-callable": "^1.1.3" } @@ -3122,7 +3098,6 @@ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -3147,7 +3122,6 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, - "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3207,7 +3181,6 @@ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, - "peer": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -3236,7 +3209,6 @@ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -3302,7 +3274,6 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, - "peer": true, "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -3386,7 +3357,6 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, - "peer": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -3420,7 +3390,6 @@ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, - "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3439,7 +3408,6 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, - "peer": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -3452,7 +3420,6 @@ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" }, @@ -3465,7 +3432,6 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" }, @@ -3478,7 +3444,6 @@ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, - "peer": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -3519,8 +3484,7 @@ "node_modules/hi-base32": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/hi-base32/-/hi-base32-0.5.1.tgz", - "integrity": "sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==", - "peer": true + "integrity": "sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==" }, "node_modules/hosted-git-info": { "version": "4.1.0", @@ -3771,7 +3735,6 @@ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, - "peer": true, "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -3799,7 +3762,6 @@ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -3822,7 +3784,6 @@ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, - "peer": true, "dependencies": { "has-bigints": "^1.0.1" }, @@ -3847,7 +3808,6 @@ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -3864,7 +3824,6 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" }, @@ -3892,7 +3851,6 @@ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, - "peer": true, "dependencies": { "is-typed-array": "^1.1.13" }, @@ -3908,7 +3866,6 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, - "peer": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -3960,7 +3917,6 @@ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" }, @@ -3982,7 +3938,6 @@ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, - "peer": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -4016,7 +3971,6 @@ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -4033,7 +3987,6 @@ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7" }, @@ -4049,7 +4002,6 @@ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, - "peer": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -4065,7 +4017,6 @@ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, - "peer": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -4081,7 +4032,6 @@ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, - "peer": true, "dependencies": { "which-typed-array": "^1.1.14" }, @@ -4102,7 +4052,6 @@ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -4114,8 +4063,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/isexe": { "version": "2.0.0", @@ -4146,8 +4094,7 @@ "node_modules/js-sha256": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", - "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==", - "peer": true + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" }, "node_modules/js-sha3": { "version": "0.8.0", @@ -4157,8 +4104,7 @@ "node_modules/js-sha512": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.8.0.tgz", - "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==", - "peer": true + "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -4188,7 +4134,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "peer": true, "dependencies": { "bignumber.js": "^9.0.0" } @@ -4222,7 +4167,6 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, - "peer": true, "dependencies": { "minimist": "^1.2.0" }, @@ -4704,7 +4648,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -5059,7 +5002,6 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" }, @@ -5072,7 +5014,6 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" } @@ -5082,7 +5023,6 @@ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -5101,7 +5041,6 @@ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -5120,7 +5059,6 @@ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -5135,7 +5073,6 @@ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -5438,7 +5375,6 @@ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" } @@ -6318,7 +6254,6 @@ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.6", "define-properties": "^1.2.1", @@ -6429,6 +6364,7 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, + "peer": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -7086,7 +7022,6 @@ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", @@ -7130,7 +7065,6 @@ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -7235,7 +7169,6 @@ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, - "peer": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -7253,7 +7186,6 @@ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, - "peer": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -7290,7 +7222,6 @@ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -7594,7 +7525,6 @@ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -7613,7 +7543,6 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -7628,7 +7557,6 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -7658,7 +7586,6 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, - "peer": true, "engines": { "node": ">=4" } @@ -7925,7 +7852,6 @@ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, - "peer": true, "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -7957,7 +7883,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "peer": true + "license": "Unlicense" }, "node_modules/type-check": { "version": "0.4.0", @@ -7988,7 +7914,6 @@ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -8003,7 +7928,6 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -8023,7 +7947,6 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, - "peer": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -8044,7 +7967,6 @@ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -8073,6 +7995,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8086,7 +8009,6 @@ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, - "peer": true, "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -8218,8 +8140,7 @@ "node_modules/vlq": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/vlq/-/vlq-2.0.4.tgz", - "integrity": "sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA==", - "peer": true + "integrity": "sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA==" }, "node_modules/which": { "version": "2.0.2", @@ -8241,7 +8162,6 @@ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, - "peer": true, "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -8258,7 +8178,6 @@ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, - "peer": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", diff --git a/package.json b/package.json index de63fb0..e4bdb84 100644 --- a/package.json +++ b/package.json @@ -49,10 +49,11 @@ "@walletconnect/types": "^1.8.0", "bowser": "2.11.0", "buffer": "^6.0.3", - "qr-code-styling": "1.6.0-rc.1" + "qr-code-styling": "1.6.0-rc.1", + "tweetnacl": "^1.0.3" }, "peerDependencies": { - "algosdk": "^3.0.0" + "algosdk": "^3.5.2" }, "repository": { "type": "git", diff --git a/src/PeraWalletConnect.ts b/src/PeraWalletConnect.ts index 6a2540c..eff79d7 100644 --- a/src/PeraWalletConnect.ts +++ b/src/PeraWalletConnect.ts @@ -1,5 +1,7 @@ /* eslint-disable max-lines */ import WalletConnect from "@walletconnect/client"; +import algosdk from "algosdk"; +import nacl from "tweetnacl"; import PeraWalletConnectError from "./util/PeraWalletConnectError"; import { @@ -35,6 +37,8 @@ import {isMobile} from "./util/device/deviceUtils"; import {AlgorandChainIDs} from "./util/peraWalletTypes"; import {runWebSignTransactionFlow} from "./util/sign/signTransactionFlow"; import {runWebConnectFlow} from "./util/connect/connectFlow"; +import {concatArrays} from "./util/array/arrayUtils"; +import {PERA_WALLET_SIGNATURE_PREFIX} from "./util/peraWalletConstants"; interface PeraWalletConnectOptions { bridge?: string; @@ -279,6 +283,21 @@ class PeraWalletConnect { await resetWalletDetailsFromStorage(); } + verifySignature( + data: Uint8Array, + signature: Uint8Array, + signerAddress: string + ): boolean { + try { + const {publicKey} = algosdk.decodeAddress(signerAddress); + const toBeVerified = concatArrays(PERA_WALLET_SIGNATURE_PREFIX, data); + + return nacl.sign.detached.verify(toBeVerified, signature, publicKey); + } catch (error) { + return false; + } + } + private async signTransactionWithMobile(signTxnRequestParams: PeraWalletTransaction[]) { const formattedSignTxnRequest = formatJsonRpcRequest("algo_signTxn", [ signTxnRequestParams @@ -367,14 +386,9 @@ class PeraWalletConnect { } ); - // We send the full txn group to the mobile wallet. - // Therefore, we first filter out txns that were not signed by the wallet. - // These are received as `null`. - const nonNullResponse = response.filter(Boolean) as (string | number[])[]; - - return typeof nonNullResponse[0] === "string" - ? (nonNullResponse as string[]).map(base64ToUint8Array) - : (nonNullResponse as number[][]).map((item) => Uint8Array.from(item)); + return typeof response[0] === "string" + ? (response as string[]).map(base64ToUint8Array) + : (response as number[][]).map((item) => Uint8Array.from(item)); } catch (error) { return await Promise.reject( new PeraWalletConnectError( @@ -436,6 +450,7 @@ class PeraWalletConnect { openPeraWalletSignTxnToast(); } + if (!this.connector) { throw new Error("PeraWalletConnect was not initialized correctly."); } @@ -457,10 +472,9 @@ class PeraWalletConnect { // Pera Mobile Wallet flow return this.signTransactionWithMobile(signTxnRequestParams); - // ================================================= // } - async signData(data: PeraWalletArbitraryData[], signer: string): Promise { + async signData(data: PeraWalletArbitraryData[], signer: string, validateSignature?: boolean): Promise { // eslint-disable-next-line no-magic-numbers const chainId = this.chainId || 4160; @@ -473,30 +487,52 @@ class PeraWalletConnect { openPeraWalletSignTxnToast(); } + if (!this.connector) { throw new Error("PeraWalletConnect was not initialized correctly."); } } + let signatures: Uint8Array[]; + // Pera Wallet Web flow if (this.platform === "web") { const {webWalletURL} = await getPeraConnectConfig(); - return this.signDataWithWeb({ + signatures = await this.signDataWithWeb({ data, signer, chainId, webWalletURL }); + } else { + const b64encodedData = data.map((item) => ({ + ...item, + data: Buffer.from(item.data).toString("base64") + })); + + // Pera Mobile Wallet flow + signatures = await this.signDataWithMobile({data: b64encodedData, signer, chainId}); } - const b64encodedData = data.map((item) => ({ - ...item, - data: Buffer.from(item.data).toString("base64") - })); + // Verify signatures if validateSignature is true + if (validateSignature) { + for (let i = 0; i < signatures.length; i++) { + const signature = signatures[i]; + const originalData = data[i].data; - // Pera Mobile Wallet flow - return this.signDataWithMobile({data: b64encodedData, signer, chainId}); + if (!this.verifySignature(originalData, signature, signer)) { + throw new PeraWalletConnectError( + { + type: "SIGN_DATA_VERIFICATION_FAILED" + }, + `Signature verification failed for data item at index ${i}` + ); + } + } + } + + return signatures; } } diff --git a/src/util/PeraWalletConnectError.ts b/src/util/PeraWalletConnectError.ts index 09b4fea..1354176 100644 --- a/src/util/PeraWalletConnectError.ts +++ b/src/util/PeraWalletConnectError.ts @@ -19,7 +19,8 @@ interface PeraWalletConnectErrorData { | "SIGN_TXN_CANCELLED" | "SIGN_TXN_NETWORK_MISMATCH" | "SIGN_DATA_CANCELLED" - | "SIGN_DATA_NETWORK_MISMATCH"; + | "SIGN_DATA_NETWORK_MISMATCH" + | "SIGN_DATA_VERIFICATION_FAILED"; detail?: any; } diff --git a/src/util/array/arrayUtils.ts b/src/util/array/arrayUtils.ts index a2a6837..3150cfe 100644 --- a/src/util/array/arrayUtils.ts +++ b/src/util/array/arrayUtils.ts @@ -16,4 +16,23 @@ function shuffleArray(items: T[]) { return newItems; } -export {shuffleArray}; +/** + * ConcatArrays takes n number arrays and returns a joint Uint8Array + * @param arrs - An arbitrary number of n array-like number list arguments + * @returns [a,b] + */ +function concatArrays(...arrs: ArrayLike[]) { + const size = arrs.reduce((sum, arr) => sum + arr.length, 0); + const c = new Uint8Array(size); + let offset = 0; + + for (let i = 0; i < arrs.length; i++) { + c.set(arrs[i], offset); + offset += arrs[i].length; + } + + return c; +} + + +export {shuffleArray, concatArrays}; diff --git a/src/util/peraWalletConstants.ts b/src/util/peraWalletConstants.ts index 3a54d76..704bb56 100644 --- a/src/util/peraWalletConstants.ts +++ b/src/util/peraWalletConstants.ts @@ -1,6 +1,10 @@ const PERA_WALLET_APP_DEEP_LINK = "perawallet-wc://"; const PERA_DOWNLOAD_URL = "https://perawallet.app/download/"; +// Adding "MX" prefix (bytes [77, 88]) to the signature to be consistent with algosdk.verifyBytes function +// eslint-disable-next-line no-magic-numbers +const PERA_WALLET_SIGNATURE_PREFIX = [77, 88]; + export interface PeraWebWalletURLs { ROOT: string; CONNECT: string; @@ -15,4 +19,9 @@ function getPeraWebWalletURL(webWalletURL: string): PeraWebWalletURLs { }; } -export {PERA_WALLET_APP_DEEP_LINK, getPeraWebWalletURL, PERA_DOWNLOAD_URL}; +export { + PERA_WALLET_APP_DEEP_LINK, + getPeraWebWalletURL, + PERA_DOWNLOAD_URL, + PERA_WALLET_SIGNATURE_PREFIX +}; From 7a705546c5ccb21f70404d841161f6962cc7c396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yasin=20=C3=87al=C4=B1=C5=9Fkan?= Date: Tue, 13 Jan 2026 12:25:58 +0300 Subject: [PATCH 2/5] feat(sign-data): check auth-addr before sending the sign data request --- README.md | 52 +++++++++++++++++++++++++++++++- src/PeraWalletConnect.ts | 46 +++++++++++++++++++++++++--- src/util/algod/algod.ts | 52 ++++++++++++++++++++++++++++++++ src/util/algod/algodConstants.ts | 44 +++++++++++++++++++++++++++ src/util/algod/algodTypes.ts | 39 ++++++++++++++++++++++++ src/util/algod/algodUtils.ts | 50 ++++++++++++++++++++++++++++++ 6 files changed, 277 insertions(+), 6 deletions(-) create mode 100644 src/util/algod/algod.ts create mode 100644 src/util/algod/algodConstants.ts create mode 100644 src/util/algod/algodTypes.ts create mode 100644 src/util/algod/algodUtils.ts diff --git a/README.md b/README.md index 182bac3..e66edca 100644 --- a/README.md +++ b/README.md @@ -147,14 +147,26 @@ Checks if it is on Pera Discover Browser. Possible responses: _`true | false`_ Starts the sign process and returns the signed transaction in `Uint8Array` -#### `PeraWalletConnect.signData(data: PeraWalletArbitraryData[], signer: string): Promise` +#### `PeraWalletConnect.signData(data: PeraWalletArbitraryData[], signer: string, verifySignature?: boolean): Promise` Starts the signing process for arbitrary data signing and returns the signed data in `Uint8Array`. Uses `signBytes` method of `algosdk` behind the scenes. `signer` should be a valid Algorand address that exists in the user's wallet. +**Parameters:** +- `data`: Array of arbitrary data to sign +- `signer`: Algorand address that will sign the data +- `verifySignature` (optional): If `true`, automatically detects if the account is rekeyed (has `authAddr`) and uses the `authAddr` as the signer. After signing, verifies each signature against the original data. Defaults to `false`. + +**Note:** When `verifySignature` is `true`, the function will: +1. Fetch account information from the Algorand network +2. Check if the account has an `authAddr` (rekeyed account) +3. Automatically use the `authAddr` as the signer if it exists, otherwise use the provided `signer` address +4. Verify each signature after signing to ensure data integrity +
See example ```typescript +// Basic usage const signedData: Uint8Array[] = await peraWallet.signData([ { data: new Uint8Array(Buffer.from(`timestamp//${Date.now()}`)), @@ -165,6 +177,44 @@ const signedData: Uint8Array[] = await peraWallet.signData([ message: "User agent confirmation" } ], "SAHBJDRHHRR72JHTWSXZR5VHQQUVC7S757TJZI656FWSDO3TZZWV3IGJV4"); + +// With signature verification (automatically handles rekeyed accounts) +const verifiedSignedData: Uint8Array[] = await peraWallet.signData([ + { + data: new Uint8Array(Buffer.from(`timestamp//${Date.now()}`)), + message: "Timestamp confirmation" + } +], "SAHBJDRHHRR72JHTWSXZR5VHQQUVC7S757TJZI656FWSDO3TZZWV3IGJV4", true); +``` +
+ +#### `PeraWalletConnect.verifySignature(data: Uint8Array, signature: Uint8Array, signerAddress: string): boolean` + +Verifies a signature against the provided data and signer address. This method can be used independently to verify signatures returned from `signData` or other sources. + +**Parameters:** +- `data`: The original data that will be signed (as `Uint8Array`) +- `signature`: The signature to verify (as `Uint8Array`) +- `signerAddress`: The Algorand address that should have signed the data + +**Returns:** `true` if the signature is valid, `false` otherwise. + +
+ See example + +```typescript +// Verify a signature independently +const isValid = peraWallet.verifySignature( + originalData, + signature, + "SAHBJDRHHRR72JHTWSXZR5VHQQUVC7S757TJZI656FWSDO3TZZWV3IGJV4" +); + +if (isValid) { + console.log("Signature is valid!"); +} else { + console.log("Signature verification failed!"); +} ```
diff --git a/src/PeraWalletConnect.ts b/src/PeraWalletConnect.ts index eff79d7..1c977b7 100644 --- a/src/PeraWalletConnect.ts +++ b/src/PeraWalletConnect.ts @@ -38,6 +38,10 @@ import {AlgorandChainIDs} from "./util/peraWalletTypes"; import {runWebSignTransactionFlow} from "./util/sign/signTransactionFlow"; import {runWebConnectFlow} from "./util/connect/connectFlow"; import {concatArrays} from "./util/array/arrayUtils"; +import {AlgodManager} from "./util/algod/algod"; +import {DEFAULT_ALGORAND_NODE_PROVIDER_TYPE} from "./util/algod/algodConstants"; +import {NetworkToggle} from "./util/algod/algodTypes"; +import {getNetworkFromChainId} from "./util/algod/algodUtils"; import {PERA_WALLET_SIGNATURE_PREFIX} from "./util/peraWalletConstants"; interface PeraWalletConnectOptions { @@ -78,6 +82,7 @@ class PeraWalletConnect { chainId?: AlgorandChainIDs; compactMode?: boolean; singleAccount?: boolean; + private algodClients: Map; constructor(options?: PeraWalletConnectOptions) { this.bridge = options?.bridge || ""; @@ -91,6 +96,7 @@ class PeraWalletConnect { this.chainId = options?.chainId; this.compactMode = options?.compactMode || false; this.singleAccount = options?.singleAccount || false; + this.algodClients = new Map(); } get platform() { @@ -437,6 +443,33 @@ class PeraWalletConnect { return userAget.includes("pera"); } + private getAlgodClient(network: NetworkToggle): AlgodManager { + if (!this.algodClients.has(network)) { + const algodClient = new AlgodManager({ + network, + providerType: DEFAULT_ALGORAND_NODE_PROVIDER_TYPE + }); + + this.algodClients.set(network, algodClient); + } + + return this.algodClients.get(network)!; + } + + private async getAccountAuthAddr(signer: string, chainId: AlgorandChainIDs): Promise { + try { + const network = getNetworkFromChainId(chainId); + const algodClient = this.getAlgodClient(network); + const accountInfo = await algodClient.client.accountInformation(signer).do(); + + return accountInfo.authAddr ? String(accountInfo.authAddr) : null; + } catch (error) { + // If account fetch fails, return null to fall back to using the original signer + // This ensures signing can proceed even if there's a network issue + return null; + } + } + async signTransaction( txGroups: SignerTransaction[][], signerAddress?: string @@ -474,7 +507,7 @@ class PeraWalletConnect { return this.signTransactionWithMobile(signTxnRequestParams); } - async signData(data: PeraWalletArbitraryData[], signer: string, validateSignature?: boolean): Promise { + async signData(data: PeraWalletArbitraryData[], signer: string, verifySignature?: boolean): Promise { // eslint-disable-next-line no-magic-numbers const chainId = this.chainId || 4160; @@ -493,6 +526,9 @@ class PeraWalletConnect { } } + // Fetch account information to check for authAddr (rekeyed accounts) + const authAddr = await this.getAccountAuthAddr(signer, chainId); + const effectiveSigner = authAddr || signer; let signatures: Uint8Array[]; // Pera Wallet Web flow @@ -501,7 +537,7 @@ class PeraWalletConnect { signatures = await this.signDataWithWeb({ data, - signer, + signer: effectiveSigner, chainId, webWalletURL }); @@ -512,16 +548,16 @@ class PeraWalletConnect { })); // Pera Mobile Wallet flow - signatures = await this.signDataWithMobile({data: b64encodedData, signer, chainId}); + signatures = await this.signDataWithMobile({data: b64encodedData, signer: effectiveSigner, chainId}); } // Verify signatures if validateSignature is true - if (validateSignature) { + if (verifySignature) { for (let i = 0; i < signatures.length; i++) { const signature = signatures[i]; const originalData = data[i].data; - if (!this.verifySignature(originalData, signature, signer)) { + if (!this.verifySignature(originalData, signature, effectiveSigner)) { throw new PeraWalletConnectError( { type: "SIGN_DATA_VERIFICATION_FAILED" diff --git a/src/util/algod/algod.ts b/src/util/algod/algod.ts new file mode 100644 index 0000000..db2feae --- /dev/null +++ b/src/util/algod/algod.ts @@ -0,0 +1,52 @@ +import algosdk from "algosdk"; + +import {AlgorandNodeProviderType, NetworkToggle} from "./algodTypes"; +import {getAlgosdkCredentialsForNetwork} from "./algodUtils"; + +class AlgodManager { + client: algosdk.Algodv2; + indexer: algosdk.Indexer; + providerType: AlgorandNodeProviderType; + + constructor({ + network, + providerType + }: { + network: NetworkToggle; + providerType: AlgorandNodeProviderType; + shouldCheckTransactionFee?: boolean; + }) { + const algosdkCredentials = getAlgosdkCredentialsForNetwork(network, providerType); + + this.providerType = providerType; + this.client = new algosdk.Algodv2( + algosdkCredentials.tokens.client, + algosdkCredentials.server.client, + algosdkCredentials.port + ); + this.indexer = new algosdk.Indexer( + algosdkCredentials.tokens.indexer, + algosdkCredentials.server.indexer, + algosdkCredentials.port + ); + } + + updateClient(network: NetworkToggle, providerType: AlgorandNodeProviderType) { + const algosdkCredentials = getAlgosdkCredentialsForNetwork(network, providerType); + + this.providerType = providerType; + this.client = new algosdk.Algodv2( + algosdkCredentials.tokens.client, + algosdkCredentials.server.client, + algosdkCredentials.port + ); + + this.indexer = new algosdk.Indexer( + algosdkCredentials.tokens.indexer, + algosdkCredentials.server.indexer, + algosdkCredentials.port + ); + } +} + +export {AlgodManager}; diff --git a/src/util/algod/algodConstants.ts b/src/util/algod/algodConstants.ts new file mode 100644 index 0000000..18fbec3 --- /dev/null +++ b/src/util/algod/algodConstants.ts @@ -0,0 +1,44 @@ +import {AlgodCredentials, AlgorandNodeProviderType, NetworkToggle} from "./algodTypes"; + +export const DEFAULT_ALGORAND_NODE_PROVIDER_TYPE: AlgorandNodeProviderType = "algodev"; +export const MAINNET_NODE_CHAIN_ID = 416001; +export const TESTNET_NODE_CHAIN_ID = 416002; +export const BETANET_NODE_CHAIN_ID = 416003; +export const ALGORAND_NODE_CHAIN_ID = 4160; +export const DEFAULT_ALGORAND_CLIENT_PORT = 443; +export const GENESIS_HASH_BY_NETWORK: Record = { + mainnet: "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", + testnet: "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=" +} as const; + +export const CHAIN_ID_BY_NETWORK = { + mainnet: MAINNET_NODE_CHAIN_ID, + testnet: TESTNET_NODE_CHAIN_ID, + betanet: BETANET_NODE_CHAIN_ID, + algorand: ALGORAND_NODE_CHAIN_ID +} as const; +const COMMON_ALGOD_CREDENTIALS = { + clientToken: "0dw4Qu6ckPJTQY540Z0sEokH910KUWKjsf312fxNtTcVjw5UUhhlK4s4odcXIoEz", + indexerToken: "KegWFLYQnBNVeP4oHCX64dObBk8VemzYdNqsnAOIxYQ8aqJLQTYeVDQyZNnx1PZA", + port: DEFAULT_ALGORAND_CLIENT_PORT +}; +const ALGOD_CREDENTIALS: AlgodCredentials = { + mainnet: { + algodev: { + ...COMMON_ALGOD_CREDENTIALS, + clientServer: "https://node-mainnet.chain.perawallet.app/", + indexerServer: "https://indexer-mainnet.chain.perawallet.app/", + chainId: MAINNET_NODE_CHAIN_ID + } + }, + testnet: { + algodev: { + ...COMMON_ALGOD_CREDENTIALS, + clientServer: "https://node-testnet.chain.perawallet.app/", + indexerServer: "https://indexer-testnet.chain.perawallet.app/", + chainId: TESTNET_NODE_CHAIN_ID + } + } +}; + +export default ALGOD_CREDENTIALS; diff --git a/src/util/algod/algodTypes.ts b/src/util/algod/algodTypes.ts new file mode 100644 index 0000000..31bed1a --- /dev/null +++ b/src/util/algod/algodTypes.ts @@ -0,0 +1,39 @@ +import { + MAINNET_NODE_CHAIN_ID, + TESTNET_NODE_CHAIN_ID, + BETANET_NODE_CHAIN_ID, + ALGORAND_NODE_CHAIN_ID +} from "./algodConstants"; + +export type AlgorandNodeProviderType = "algodev"; + +export type AlgodCredentialShape = Record< + AlgorandNodeProviderType, + Readonly<{ + clientToken: string; + clientServer: string; + indexerToken: string; + indexerServer: string; + port: number; + chainId?: number; + }> +>; + +export interface AlgorandNodeProvider { + type: AlgorandNodeProviderType; + isHealthy: boolean; + title: string; +} + +export interface AlgodCredentials { + mainnet: AlgodCredentialShape; + testnet: AlgodCredentialShape; +} + +export type NetworkToggle = "testnet" | "mainnet"; + +export type AlgorandChainIDs = + | typeof ALGORAND_NODE_CHAIN_ID + | typeof MAINNET_NODE_CHAIN_ID + | typeof TESTNET_NODE_CHAIN_ID + | typeof BETANET_NODE_CHAIN_ID; diff --git a/src/util/algod/algodUtils.ts b/src/util/algod/algodUtils.ts new file mode 100644 index 0000000..dc70948 --- /dev/null +++ b/src/util/algod/algodUtils.ts @@ -0,0 +1,50 @@ +import ALGOD_CREDENTIALS, { + MAINNET_NODE_CHAIN_ID, + TESTNET_NODE_CHAIN_ID, + ALGORAND_NODE_CHAIN_ID +} from "./algodConstants"; +import {AlgorandNodeProviderType, NetworkToggle} from "./algodTypes"; +import {AlgorandChainIDs} from "../peraWalletTypes"; + +function getAlgosdkCredentialsForNetwork( + network: NetworkToggle, + credentialType: AlgorandNodeProviderType +) { + const {mainnet: mainnetCredentials, testnet: testnetCredentials} = ALGOD_CREDENTIALS; + const preferredNetworkCredentials = + network === "mainnet" ? mainnetCredentials : testnetCredentials; + + return { + tokens: { + client: preferredNetworkCredentials[credentialType].clientToken, + indexer: preferredNetworkCredentials[credentialType].indexerToken + }, + server: { + client: preferredNetworkCredentials[credentialType].clientServer, + indexer: preferredNetworkCredentials[credentialType].indexerServer + }, + port: preferredNetworkCredentials[credentialType].port + }; +} + +function getChainIdForNetwork(network: NetworkToggle): number { + if (network === "mainnet") { + return MAINNET_NODE_CHAIN_ID; + } + + return TESTNET_NODE_CHAIN_ID; +} + +function getNetworkFromChainId(chainId: AlgorandChainIDs): NetworkToggle { + if (chainId === MAINNET_NODE_CHAIN_ID || chainId === ALGORAND_NODE_CHAIN_ID) { + return "mainnet"; + } + + if (chainId === TESTNET_NODE_CHAIN_ID) { + return "testnet"; + } + + return "mainnet"; +} + +export {getAlgosdkCredentialsForNetwork, getChainIdForNetwork, getNetworkFromChainId}; From c20e264c9ba00d3c671c6e1ce48c04539ef8da5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yasin=20=C3=87al=C4=B1=C5=9Fkan?= Date: Wed, 14 Jan 2026 14:54:04 +0300 Subject: [PATCH 3/5] docs: add a note for MX prefix --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e66edca..89e9f42 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,7 @@ Starts the signing process for arbitrary data signing and returns the signed dat 1. Fetch account information from the Algorand network 2. Check if the account has an `authAddr` (rekeyed account) 3. Automatically use the `authAddr` as the signer if it exists, otherwise use the provided `signer` address -4. Verify each signature after signing to ensure data integrity +4. Verify each signature after signing using the `verifySignature` method (see below)
See example @@ -190,15 +190,17 @@ const verifiedSignedData: Uint8Array[] = await peraWallet.signData([ #### `PeraWalletConnect.verifySignature(data: Uint8Array, signature: Uint8Array, signerAddress: string): boolean` -Verifies a signature against the provided data and signer address. This method can be used independently to verify signatures returned from `signData` or other sources. +Verifies a signature against the provided data and signer address. This method can be used independently to verify signatures returned from `signData` or other sources. When `signData` is called with `verifySignature: true`, it uses this method internally to verify the signatures. **Parameters:** -- `data`: The original data that will be signed (as `Uint8Array`) +- `data`: The original data that was signed (as `Uint8Array`) - `signature`: The signature to verify (as `Uint8Array`) - `signerAddress`: The Algorand address that should have signed the data **Returns:** `true` if the signature is valid, `false` otherwise. +**Note:** This method automatically prefixes the data with "MX" (bytes `[77, 88]`) before verification to be consistent with `algosdk.verifyBytes` function. This ensures compatibility with Algorand's standard signature verification format. The data passed to this method should be the original data without the "MX" prefix, as the prefix is added internally. +
See example From bb1b5e364f37ef9a1e70aa831219709c2e8f0100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yasin=20=C3=87al=C4=B1=C5=9Fkan?= Date: Thu, 15 Jan 2026 15:48:54 +0300 Subject: [PATCH 4/5] fix(sign-data): use rekeyed address only for verification --- src/PeraWalletConnect.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/PeraWalletConnect.ts b/src/PeraWalletConnect.ts index 1c977b7..602fba7 100644 --- a/src/PeraWalletConnect.ts +++ b/src/PeraWalletConnect.ts @@ -526,9 +526,6 @@ class PeraWalletConnect { } } - // Fetch account information to check for authAddr (rekeyed accounts) - const authAddr = await this.getAccountAuthAddr(signer, chainId); - const effectiveSigner = authAddr || signer; let signatures: Uint8Array[]; // Pera Wallet Web flow @@ -537,7 +534,7 @@ class PeraWalletConnect { signatures = await this.signDataWithWeb({ data, - signer: effectiveSigner, + signer, chainId, webWalletURL }); @@ -548,11 +545,14 @@ class PeraWalletConnect { })); // Pera Mobile Wallet flow - signatures = await this.signDataWithMobile({data: b64encodedData, signer: effectiveSigner, chainId}); + signatures = await this.signDataWithMobile({data: b64encodedData, signer, chainId}); } // Verify signatures if validateSignature is true if (verifySignature) { + const authAddr = await this.getAccountAuthAddr(signer, chainId); + const effectiveSigner = authAddr || signer; + for (let i = 0; i < signatures.length; i++) { const signature = signatures[i]; const originalData = data[i].data; From 55ec21ce988ce8d6e82aa12695d7fc89a0a5594f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yasin=20=C3=87al=C4=B1=C5=9Fkan?= Date: Thu, 15 Jan 2026 18:09:54 +0300 Subject: [PATCH 5/5] build: use browser compatible tweetnacl --- package-lock.json | 11 ++++++++++- package.json | 2 +- src/PeraWalletConnect.ts | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 84010d9..2b97958 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "bowser": "2.11.0", "buffer": "^6.0.3", "qr-code-styling": "1.6.0-rc.1", - "tweetnacl": "^1.0.3" + "tweetnacl-ts": "^1.0.3" }, "devDependencies": { "@hipo/eslint-config-base": "^4.1.1", @@ -7885,6 +7885,15 @@ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "license": "Unlicense" }, + "node_modules/tweetnacl-ts": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl-ts/-/tweetnacl-ts-1.0.3.tgz", + "integrity": "sha512-C5I/dWf6xjAXaCDlf84T4HvozU/8ycAlq5WRllF1hAeeq5390tfXD+bNas5bhEV0HMSOx8bsQYpLjPl8wfnEeQ==", + "license": "UNLICENSED", + "dependencies": { + "tslib": "^1" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index e4bdb84..1397bcc 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "bowser": "2.11.0", "buffer": "^6.0.3", "qr-code-styling": "1.6.0-rc.1", - "tweetnacl": "^1.0.3" + "tweetnacl-ts": "^1.0.3" }, "peerDependencies": { "algosdk": "^3.5.2" diff --git a/src/PeraWalletConnect.ts b/src/PeraWalletConnect.ts index 602fba7..47b3671 100644 --- a/src/PeraWalletConnect.ts +++ b/src/PeraWalletConnect.ts @@ -1,7 +1,7 @@ /* eslint-disable max-lines */ import WalletConnect from "@walletconnect/client"; import algosdk from "algosdk"; -import nacl from "tweetnacl"; +import {sign_detached_verify} from "tweetnacl-ts"; import PeraWalletConnectError from "./util/PeraWalletConnectError"; import { @@ -298,7 +298,7 @@ class PeraWalletConnect { const {publicKey} = algosdk.decodeAddress(signerAddress); const toBeVerified = concatArrays(PERA_WALLET_SIGNATURE_PREFIX, data); - return nacl.sign.detached.verify(toBeVerified, signature, publicKey); + return sign_detached_verify(toBeVerified, signature, publicKey); } catch (error) { return false; }