diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5351475..d895f04 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,10 +10,10 @@ "dependencies": { "@heroicons/react": "^2.1.3", "@massalabs/eslint-config": "^0.0.11", - "@massalabs/massa-web3": "^4.0.1", + "@massalabs/massa-web3": "^5.1.1-dev", "@massalabs/prettier-config-as": "^0.0.2", - "@massalabs/react-ui-kit": "^0.0.5-dev", - "@massalabs/wallet-provider": "^2.0.1-dev", + "@massalabs/react-ui-kit": "../../../Tooling/ui-kit", + "@massalabs/wallet-provider": "../../../Tooling/wallet-provider", "axios": "^1.7.2", "dot-object": "^2.1.5", "eslint-plugin-html": "^8.1.1", @@ -24,7 +24,7 @@ "react-dom": "^18.2.0", "tw-colors": "^3.3.1", "vite-plugin-svgr": "^4.2.0", - "zustand": "^4.5.2" + "zustand": "^4.5.6" }, "devDependencies": { "@types/dot-object": "^2.1.6", @@ -44,10 +44,120 @@ "vite": "^5.2.0" } }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" + "../../../Tooling/ui-kit": { + "name": "@massalabs/react-ui-kit", + "version": "1.0.0", + "dependencies": { + "@headlessui/react": "^1.7.15", + "@massalabs/massa-web3": "^5.1.1-dev", + "@massalabs/wallet-provider": "../wallet-provider", + "copy-to-clipboard": "^3.3.3", + "currency.js": "^2.0.4", + "dot-object": "^2.1.5", + "minidenticons": "^4.2.1", + "react": "^18.2.0", + "react-currency-input-field": "^3.6.11", + "react-dom": "^18.2.0", + "react-hot-toast": "^2.4.1", + "react-icons": "^4.8.0", + "react-number-format": "^5.2.2", + "tw-colors": "^1.2.5", + "viem": "^2.19.4", + "vite-plugin-svgr": "^3.2.0", + "zustand": "^4.5.2" + }, + "devDependencies": { + "@babel/preset-env": "^7.21.4", + "@babel/preset-flow": "^7.21.4", + "@babel/preset-react": "^7.18.6", + "@inrupt/jest-jsdom-polyfills": "^2.4.1", + "@massalabs/eslint-config": "^0.0.9", + "@massalabs/prettier-config-as": "^0.0.2", + "@storybook/addon-essentials": "^7.4.5", + "@storybook/addon-interactions": "^7.4.5", + "@storybook/addon-links": "^7.4.5", + "@storybook/addon-styling": "^1.3.7", + "@storybook/blocks": "^7.4.5", + "@storybook/react": "^7.4.5", + "@storybook/react-vite": "^7.4.5", + "@storybook/testing-library": "^0.2.1", + "@testing-library/dom": "^9.2.0", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^14.0.0", + "@types/dot-object": "^2.1.6", + "@types/jest": "^29.5.1", + "@types/react": "^18.2.46", + "@types/react-dom": "^18.0.11", + "@types/react-test-renderer": "^18.0.0", + "@types/testing-library__jest-dom": "^5.14.5", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", + "@vitejs/plugin-react": "^4.0.0-beta.0", + "autoprefixer": "^10.4.14", + "babel-jest": "^29.5.0", + "cypress": "^13.3.0", + "cypress-image-diff-js": "^1.30.1", + "eslint": "^8.38.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.3.4", + "eslint-plugin-storybook": "^0.6.14", + "husky": "^8.0.3", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", + "lint-staged": "^13.2.1", + "postcss": "^8.4.31", + "postcss-loader": "^7.2.4", + "prop-types": "^15.8.1", + "react-test-renderer": "^18.2.0", + "storybook": "^7.4.5", + "tailwindcss": "^3.3.1", + "typescript": "^5.2.2", + "vite": "^4.5.3" + } + }, + "../../../Tooling/wallet-provider": { + "name": "@massalabs/wallet-provider", + "version": "3.1.0", + "license": "(MIT AND Apache-2.0)", + "dependencies": { + "@hicaru/bearby.js": "^0.5.9", + "@massalabs/massa-web3": "^5.1.1-dev", + "@metamask/providers": "^18.1.1", + "axios": "^0.28.0", + "bs58check": "^4.0.0", + "buffer": "^6.0.3", + "eventemitter3": "^5.0.1", + "lodash.isequal": "^4.5.0" + }, + "devDependencies": { + "@babel/preset-env": "^7.22.14", + "@massalabs/eslint-config": "^0.0.9", + "@massalabs/metamask-snap": "^1.1.0", + "@playwright/test": "^1.36.2", + "@types/jest": "^29.5.4", + "@types/node": "^18.13.0", + "babel-jest": "^29.6.4", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-jsdoc": "^41.1.1", + "husky": "^9.1.4", + "is-ci": "^3.0.1", + "jest": "^29.6.4", + "jest-environment-jsdom": "^29.6.4", + "lint-staged": "^15.2.7", + "npm-run-all": "^4.1.5", + "prettier": "^3.0.3", + "prettier-eslint": "^15.0.1", + "prettier-plugin-organize-imports": "^3.2.4", + "rimraf": "^5.0.5", + "ts-jest": "^29.1.1", + "tslib": "^2.5.0", + "tslint": "^6.1.3", + "typedoc": "^0.23.25", + "typescript": "^4.9.5" + } + }, + "../../Tooling/massa-web3": { + "extraneous": true }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", @@ -842,22 +952,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@headlessui/react": { - "version": "1.7.19", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.19.tgz", - "integrity": "sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==", - "dependencies": { - "@tanstack/react-virtual": "^3.0.0-beta.60", - "client-only": "^0.0.1" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": "^16 || ^17 || ^18", - "react-dom": "^16 || ^17 || ^18" - } - }, "node_modules/@heroicons/react": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.1.3.tgz", @@ -866,11 +960,6 @@ "react": ">= 16" } }, - "node_modules/@hicaru/bearby.js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/@hicaru/bearby.js/-/bearby.js-0.5.8.tgz", - "integrity": "sha512-K6mLazzHkDNF5Qmx5iQ4+UqmvBJxtuwg1ZHEDEvOKB1SV/QNuKJ54/HRlLMqJE0RHam2zP7s++RlnMZUIfWgGg==" - }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -1005,14 +1094,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@lukeed/csprng": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", - "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", - "engines": { - "node": ">=8" - } - }, "node_modules/@massalabs/eslint-config": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/@massalabs/eslint-config/-/eslint-config-0.0.11.tgz", @@ -1229,27 +1310,20 @@ } }, "node_modules/@massalabs/massa-web3": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@massalabs/massa-web3/-/massa-web3-4.0.3.tgz", - "integrity": "sha512-W1TtxMrTiqLfUgvIqO641M/2do6Z2Kvvq44JYhiUbteXI5S+VvCJ+HaRtIZ23r9k2wTSlSikE6j6U5bkKDMABA==", + "version": "5.1.1-dev.20250110163508", + "resolved": "https://registry.npmjs.org/@massalabs/massa-web3/-/massa-web3-5.1.1-dev.20250110163508.tgz", + "integrity": "sha512-3Lwj95vI26omSKGdnXx0rnduztzLjG/NFyY7KhWTiH1O2tQNmshb7JS9VkWb7/QSn8RJM9svfGJXwct5+bcCMA==", + "license": "MIT", "dependencies": { - "@massalabs/wallet-provider": "^2.0.0", - "@massalabs/web3-utils": "^1.4.11", "@noble/ed25519": "^1.7.3", "@noble/hashes": "^1.2.0", - "@types/ws": "^8.5.4", - "@web3pack/base58-check": "^1.0.3", - "axios": "^0.26.1", - "bignumber.js": "^9.1.1", - "bip39": "^3.0.4", - "bs58check": "^3.0.1", - "buffer": "^6.0.3", - "crypto-js": "^4.1.1", + "bs58check": "^4.0.0", + "decimal.js": "^10.4.3", "dotenv": "^16.0.3", - "js-base64": "^3.7.5", - "string_decoder": "^1.3.0", - "tslib": "^2.5.2", - "util": "^0.12.5", + "eventemitter3": "^5.0.1", + "lodash.isequal": "^4.5.0", + "secure-random": "^1.1.2", + "tslib": "^2.8.0", "varint": "^6.0.0" }, "optionalDependencies": { @@ -1257,41 +1331,6 @@ "utf-8-validate": "^6.0.2" } }, - "node_modules/@massalabs/massa-web3/node_modules/@massalabs/wallet-provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@massalabs/wallet-provider/-/wallet-provider-2.0.0.tgz", - "integrity": "sha512-3BKtYszSfKMOi85cxOB1q60uiMWYmdteV28stx2NjT42VtSyKOuWiTJq4KaWbf3ov+fkg+/HknXdl5bhDghbSQ==", - "dependencies": { - "@hicaru/bearby.js": "^0.5.7", - "@massalabs/web3-utils": "^1.4.9-dev", - "axios": "^0.28.0", - "bs58check": "^3.0.1", - "buffer": "^6.0.3", - "uid": "^2.0.1" - }, - "optionalDependencies": { - "bufferutil": "^4.0.7", - "utf-8-validate": "^6.0.2" - } - }, - "node_modules/@massalabs/massa-web3/node_modules/@massalabs/wallet-provider/node_modules/axios": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.28.1.tgz", - "integrity": "sha512-iUcGA5a7p0mVb4Gm/sy+FSECNkPFT4y7wt6OM/CDpO/OnNCvSs3PoMG8ibrC9jRoGYU0gUK5pXVC4NPXq6lHRQ==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/@massalabs/massa-web3/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, "node_modules/@massalabs/prettier-config-as": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/@massalabs/prettier-config-as/-/prettier-config-as-0.0.2.tgz", @@ -1301,556 +1340,12 @@ } }, "node_modules/@massalabs/react-ui-kit": { - "version": "0.0.5-next.20240516213908", - "resolved": "https://registry.npmjs.org/@massalabs/react-ui-kit/-/react-ui-kit-0.0.5-next.20240516213908.tgz", - "integrity": "sha512-JUnGdtQm2jRHqneYmfHGMJsZffgC8wXipzAVDRN6ypnUaDB6CEv9pdFLlO7LJf+Qpjkq9A+I14nA8FLBbIM00Q==", - "dependencies": { - "@headlessui/react": "^1.7.15", - "copy-to-clipboard": "^3.3.3", - "currency.js": "^2.0.4", - "dot-object": "^2.1.5", - "minidenticons": "^4.2.1", - "react": "^18.2.0", - "react-currency-input-field": "^3.6.11", - "react-dom": "^18.2.0", - "react-hot-toast": "^2.4.1", - "react-icons": "^4.8.0", - "react-number-format": "^5.2.2", - "tw-colors": "^1.2.5", - "viem": "^1.5.2", - "vite-plugin-svgr": "^3.2.0", - "zustand": "^4.5.2" - }, - "peerDependencies": { - "@massalabs/massa-web3": "^4.0.2-dev", - "@massalabs/wallet-provider": "^2.0.1-dev", - "@types/dot-object": "^2.1.6", - "dot-object": "^2.1.5" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "hasInstallScript": true, - "peer": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", - "peer": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/tw-colors": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/tw-colors/-/tw-colors-1.2.6.tgz", - "integrity": "sha512-/HI70siD+7/xNd52YuVtKN77As/ERrm/db6P6DJpdioZ06andLRbaMBWowHO6XagdVjZ9dBQRoQlqAENzCe8UA==", - "dependencies": { - "color": "^4.2.3", - "flat": "^5.0.2", - "lodash.foreach": "^4.5.0" - }, - "peerDependencies": { - "tailwindcss": ">=3.0.0" - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/vite": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", - "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", - "peer": true, - "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/@massalabs/react-ui-kit/node_modules/vite-plugin-svgr": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-3.3.0.tgz", - "integrity": "sha512-vWZMCcGNdPqgziYFKQ3Y95XP0d0YGp28+MM3Dp9cTa/px5CKcHHrIoPl2Jw81rgVm6/ZUNONzjXbZQZ7Kw66og==", - "dependencies": { - "@rollup/pluginutils": "^5.0.4", - "@svgr/core": "^8.1.0", - "@svgr/plugin-jsx": "^8.1.0" - }, - "peerDependencies": { - "vite": "^2.6.0 || 3 || 4" - } + "resolved": "../../../Tooling/ui-kit", + "link": true }, "node_modules/@massalabs/wallet-provider": { - "version": "2.0.1-dev.20240423112601", - "resolved": "https://registry.npmjs.org/@massalabs/wallet-provider/-/wallet-provider-2.0.1-dev.20240423112601.tgz", - "integrity": "sha512-2NvwKho1Couwd2/gXZ0ZGBymmTiuX6rxjoX2gQnEu8LI2i15uDfRba5Gv6NSSvgLcjExzbhrJOQzPRgDAJhDlQ==", - "dependencies": { - "@hicaru/bearby.js": "^0.5.7", - "@massalabs/web3-utils": "^1.4.9-dev", - "axios": "^0.28.0", - "bs58check": "^3.0.1", - "buffer": "^6.0.3", - "uid": "^2.0.1" - }, - "optionalDependencies": { - "bufferutil": "^4.0.7", - "utf-8-validate": "^6.0.2" - } - }, - "node_modules/@massalabs/wallet-provider/node_modules/axios": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.28.1.tgz", - "integrity": "sha512-iUcGA5a7p0mVb4Gm/sy+FSECNkPFT4y7wt6OM/CDpO/OnNCvSs3PoMG8ibrC9jRoGYU0gUK5pXVC4NPXq6lHRQ==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/@massalabs/web3-utils": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@massalabs/web3-utils/-/web3-utils-1.4.11.tgz", - "integrity": "sha512-9iUoSc9OZxrvx8UbDor934z0cetenEU3PlDqTa9Hsh3EuZJ9jalcEU8Q9Z+hjLn2S9Ojmqu2ldcOAxVzYeNCbw==", - "dependencies": { - "bignumber.js": "^9.1.2", - "buffer": "^6.0.3", - "events": "^3.3.0", - "string_decoder": "^1.3.0" - } + "resolved": "../../../Tooling/wallet-provider", + "link": true }, "node_modules/@microsoft/tsdoc": { "version": "0.14.2", @@ -1880,17 +1375,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@noble/ed25519": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-1.7.3.tgz", @@ -1900,14 +1384,16 @@ "type": "individual", "url": "https://paulmillr.com/funding/" } - ] + ], + "license": "MIT" }, "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", + "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", + "license": "MIT", "engines": { - "node": ">= 16" + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -2163,42 +1649,9 @@ "x64" ], "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@scure/base": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", - "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", - "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", - "dependencies": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", - "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } + "os": [ + "win32" + ] }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", @@ -2401,31 +1854,6 @@ "@svgr/core": "*" } }, - "node_modules/@tanstack/react-virtual": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.5.0.tgz", - "integrity": "sha512-rtvo7KwuIvqK9zb0VZ5IL7fiJAEnG+0EiFZz8FUOs+2mhGqdGmjKIaT1XU7Zq0eFqL0jonLlhbayJI/J2SA/Bw==", - "dependencies": { - "@tanstack/virtual-core": "3.5.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@tanstack/virtual-core": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.5.0.tgz", - "integrity": "sha512-KnPRCkQTyqhanNC0K63GBG3wA8I+D1fQuVnAvcBF8f13akOKeQp1gSbu6f77zCxhEk727iV5oQnbHLYzHrECLg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2470,7 +1898,8 @@ "node_modules/@types/dot-object": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/@types/dot-object/-/dot-object-2.1.6.tgz", - "integrity": "sha512-G1e4SNPOuO72ZXv7wz/W2x29CzQtpxko3G9hBiHqGg/AvFIKoArCs2nbc/WPXnnUkO+1dmvX9WQCyj5gIlAzZg==" + "integrity": "sha512-G1e4SNPOuO72ZXv7wz/W2x29CzQtpxko3G9hBiHqGg/AvFIKoArCs2nbc/WPXnnUkO+1dmvX9WQCyj5gIlAzZg==", + "dev": true }, "node_modules/@types/eslint": { "version": "8.56.10", @@ -2506,6 +1935,8 @@ "version": "20.12.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", + "optional": true, + "peer": true, "dependencies": { "undici-types": "~5.26.4" } @@ -2540,14 +1971,6 @@ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.8.0.tgz", @@ -2761,44 +2184,6 @@ "vite": "^4.2.0 || ^5.0.0" } }, - "node_modules/@web3pack/base-x": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@web3pack/base-x/-/base-x-1.0.2.tgz", - "integrity": "sha512-P3XgVnEQ1QFyUTmHzT1sXNprLyxE1aG8WAnk5/Fj+3j4AmsK4dRfMdV3t/aIdYP3i1KvjPRkQJhFXGpxUc+M8A==" - }, - "node_modules/@web3pack/base58-check": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@web3pack/base58-check/-/base58-check-1.0.3.tgz", - "integrity": "sha512-+s4HKOnJbIkj45jhGfSxgWkKsjBENuNbfqASPTLPy/yjGGv/jGCxzFCl0fb4gudV3x0gS50gLpJsC8qQ6cV1gw==", - "dependencies": { - "@web3pack/base-x": "^1.0.1", - "buffer": "^6.0.3", - "hash.js": "^1.1.7" - } - }, - "node_modules/abitype": { - "version": "0.9.8", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-0.9.8.tgz", - "integrity": "sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } - ], - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.19.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -3135,36 +2520,10 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base-x": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", - "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "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/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "engines": { - "node": "*" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.0.tgz", + "integrity": "sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ==", + "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", @@ -3187,14 +2546,6 @@ "wasm2js": "bin/wasm2js" } }, - "node_modules/bip39": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", - "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", - "dependencies": { - "@noble/hashes": "^1.2.0" - } - }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -3246,50 +2597,30 @@ } }, "node_modules/bs58": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", - "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "license": "MIT", "dependencies": { - "base-x": "^4.0.0" + "base-x": "^5.0.0" } }, "node_modules/bs58check": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz", - "integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-4.0.0.tgz", + "integrity": "sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g==", + "license": "MIT", "dependencies": { "@noble/hashes": "^1.2.0", - "bs58": "^5.0.0" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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.2.1" + "bs58": "^6.0.0" } }, "node_modules/bufferutil": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", - "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", + "integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" @@ -3449,11 +2780,6 @@ "node": ">=8" } }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" - }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -3541,14 +2867,6 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, - "node_modules/copy-to-clipboard": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", - "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", - "dependencies": { - "toggle-selection": "^1.0.6" - } - }, "node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -3587,11 +2905,6 @@ "node": ">= 8" } }, - "node_modules/crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" - }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -3606,15 +2919,8 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/currency.js": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/currency.js/-/currency.js-2.0.4.tgz", - "integrity": "sha512-6/OplJYgJ0RUlli74d93HJ/OsKVBi8lB1+Z6eJYS1YZzBuIp4qKKHpJ7ad+GvTlWmLR/hLJOWTykN5Nm8NJ7+w==", - "engines": { - "node": ">=4" - } + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true }, "node_modules/data-view-buffer": { "version": "1.0.1", @@ -3680,6 +2986,12 @@ } } }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "license": "MIT" + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3838,9 +3150,10 @@ } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -4541,13 +3854,11 @@ "node": ">=0.10.0" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -4914,14 +4225,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/goober": { - "version": "2.1.14", - "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz", - "integrity": "sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==", - "peerDependencies": { - "csstype": "^3.0.10" - } - }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -5001,15 +4304,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -5053,25 +4347,6 @@ "url": "https://github.com/sponsors/typicode" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "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/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -5130,21 +4405,6 @@ "node": ">= 0.4" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -5282,20 +4542,6 @@ "node": ">=8" } }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -5440,20 +4686,6 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, - "node_modules/isows": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz", - "integrity": "sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } - ], - "peerDependencies": { - "ws": "*" - } - }, "node_modules/jackspeak": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", @@ -5484,11 +4716,6 @@ "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==" }, - "node_modules/js-base64": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", - "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5617,6 +4844,12 @@ "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -5694,19 +4927,6 @@ "node": ">= 0.6" } }, - "node_modules/minidenticons": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/minidenticons/-/minidenticons-4.2.1.tgz", - "integrity": "sha512-oWfFivA0lOx/V/bO/YIJbthB26lV8JXYvhnv9zM2hNd3fzsHTXQ6c6bWZPcvhD3nnOB+lQk/D9lF43BXixrN8g==", - "engines": { - "node": ">=15.14.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, "node_modules/minimatch": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", @@ -5789,9 +5009,10 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", "optional": true, "bin": { "node-gyp-build": "bin.js", @@ -6260,16 +5481,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -6313,14 +5524,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-currency-input-field": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/react-currency-input-field/-/react-currency-input-field-3.8.0.tgz", - "integrity": "sha512-DKSIjacrvgUDOpuB16b+OVDvp5pbCt+s+RHJgpRZCHNhzg1yBpRUoy4fbnXpeOj0kdbwf5BaXCr2mAtxEujfhg==", - "peerDependencies": { - "react": "^16.9.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -6333,46 +5536,6 @@ "react": "^18.3.1" } }, - "node_modules/react-hot-toast": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz", - "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==", - "dependencies": { - "goober": "^2.1.10" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": ">=16", - "react-dom": ">=16" - } - }, - "node_modules/react-icons": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", - "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==", - "peerDependencies": { - "react": "*" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-number-format": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.3.4.tgz", - "integrity": "sha512-2hHN5mbLuCDUx19bv0Q8wet67QqYK6xmtLQeY5xx+h7UXiMmRtaCwqko4mMPoKXLc6xAzwRrutg8XbTRlsfjRg==", - "dependencies": { - "prop-types": "^15.7.2" - }, - "peerDependencies": { - "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", @@ -6538,25 +5701,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "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/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", @@ -6581,6 +5725,12 @@ "loose-envify": "^1.1.0" } }, + "node_modules/secure-random": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/secure-random/-/secure-random-1.1.2.tgz", + "integrity": "sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ==", + "license": "MIT" + }, "node_modules/semver": { "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", @@ -6721,14 +5871,6 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==" }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -7025,11 +6167,6 @@ "node": ">=8.0" } }, - "node_modules/toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" - }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -7070,9 +6207,10 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", @@ -7209,17 +6347,6 @@ "node": ">=14.17" } }, - "node_modules/uid": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", - "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", - "dependencies": { - "@lukeed/csprng": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -7237,7 +6364,9 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "optional": true, + "peer": true }, "node_modules/update-browserslist-db": { "version": "1.0.15", @@ -7277,18 +6406,20 @@ } }, "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", + "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", + "license": "MIT", "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/utf-8-validate": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.4.tgz", - "integrity": "sha512-xu9GQDeFp+eZ6LnCywXN/zBancWvOpUMzgjLPSjy4BRHSmTelvn2E0DG0o1sTiw5hkCKBHo8rwSKncfRfv2EEQ==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.5.tgz", + "integrity": "sha512-EYZR+OpIXp9Y1eG1iueg8KRsY8TuT8VNgnanZ0uA3STqhHQTLwbl+WX76/9X5OY12yQubymBpaBSmMPkSTQcKA==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" @@ -7297,18 +6428,6 @@ "node": ">=6.14.2" } }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7317,36 +6436,8 @@ "node_modules/varint": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==" - }, - "node_modules/viem": { - "version": "1.21.4", - "resolved": "https://registry.npmjs.org/viem/-/viem-1.21.4.tgz", - "integrity": "sha512-BNVYdSaUjeS2zKQgPs+49e5JKocfo60Ib2yiXOWBT6LuVxY1I/6fFX3waEtpXvL1Xn4qu+BVitVtMh9lyThyhQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@scure/bip32": "1.3.2", - "@scure/bip39": "1.2.1", - "abitype": "0.9.8", - "isows": "1.0.3", - "ws": "8.13.0" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "license": "MIT" }, "node_modules/vite": { "version": "5.2.11", @@ -7624,26 +6715,6 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, - "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -7672,11 +6743,12 @@ } }, "node_modules/zustand": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.2.tgz", - "integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==", + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.6.tgz", + "integrity": "sha512-ibr/n1hBzLLj5Y+yUcU7dYw8p6WnIVzdJbnX+1YpaScvZVF2ziugqHs+LAmHw4lWO9c/zRj+K1ncgWDQuthEdQ==", + "license": "MIT", "dependencies": { - "use-sync-external-store": "1.2.0" + "use-sync-external-store": "^1.2.2" }, "engines": { "node": ">=12.7.0" diff --git a/frontend/package.json b/frontend/package.json index d17a380..acf33bd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,10 +18,10 @@ "dependencies": { "@heroicons/react": "^2.1.3", "@massalabs/eslint-config": "^0.0.11", - "@massalabs/massa-web3": "^4.0.1", + "@massalabs/massa-web3": "^5.1.1-dev", "@massalabs/prettier-config-as": "^0.0.2", - "@massalabs/react-ui-kit": "^0.0.5-dev", - "@massalabs/wallet-provider": "^2.0.1-dev", + "@massalabs/react-ui-kit": "../../../Tooling/ui-kit", + "@massalabs/wallet-provider": "../../../Tooling/wallet-provider", "axios": "^1.7.2", "dot-object": "^2.1.5", "eslint-plugin-html": "^8.1.1", @@ -32,7 +32,7 @@ "react-dom": "^18.2.0", "tw-colors": "^3.3.1", "vite-plugin-svgr": "^4.2.0", - "zustand": "^4.5.2" + "zustand": "^4.5.6" }, "devDependencies": { "@types/dot-object": "^2.1.6", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 3bbb48a..d74f24e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,51 +1,13 @@ -import { ConnectMassaWallet } from './lib/connectMassaWallets/components/ConnectMassaWallet'; import { Card } from './components/Card'; -import { FAQ, FAQData } from './components/FAQ'; -import { Button, Toast } from '@massalabs/react-ui-kit'; +import { FAQ } from './components/FAQ'; +import { Button, ConnectMassaWallet, Toast } from '@massalabs/react-ui-kit'; import { MNSManagement } from './components/MNSManagement'; -const faqData: FAQData[] = [ - { - question: 'What is Massa Name Service ?', - answer: - 'Massa Name Service is a decentralized naming service which allows users and smart contracts to be recognized on the Massa blockchain.', - }, - { - question: 'How do I register a name ?', - answer: - 'To register a name, you need to connect your Massa wallet and enter the name you want to register in the register section. If the name is available, you can register it by paying the registration fee.', - }, - { - question: 'How much does it cost to register a name ?', - answer: - 'The cost depends on the size of the name. 10000 coins for 2 characters, 1000 coins for 3 characters, 100 coins for 4 characters, 10 coins for 5 characters and 1 coin for 6 and more characters. An little additional amount is taken to cover storage fees. You can see the exact price while typing a domain in the register section.', - }, - { - question: 'How do I transfer a name ?', - answer: - 'Massa Names are NFTs and can be transferred like any other NFT. You can transfer them on purrfect universe using the icon at the top of the page.', - }, - { - question: 'Can I change the address my name is targeting ?', - answer: - 'Yes you can change the address your name is targeting by using the edit icon in the management section. It will change the target address but you will still be the owner of the name.', - }, - { - question: 'For how long is a name registered ?', - answer: 'Forever.', - }, - { - question: 'Can I free my name and get my coins back ?', - answer: - 'Yes you can free your name using the trash icon in the management section. You will get half of the coins you paid for the registration back.', - }, -]; - function App() { return ( <> -
+
- +
- +
diff --git a/frontend/src/components/FAQ.tsx b/frontend/src/components/FAQ.tsx index f8a785f..85fc7e9 100644 --- a/frontend/src/components/FAQ.tsx +++ b/frontend/src/components/FAQ.tsx @@ -1,23 +1,18 @@ import { Accordion } from '@massalabs/react-ui-kit'; +import { faqData } from '../const/faq'; export interface FAQData { question: string; answer: string; } -interface FAQProps { - data: FAQData[]; -} - -export function FAQ(props: FAQProps) { - const { data } = props; - if (!data) return null; +export function FAQ() { return ( <>

FAQ

- {data.map((item, idx) => ( + {faqData.map((item, idx) => ( void; - getAllocCost: (data: DnsAllocParams) => Promise; +interface MnsClaimProps { + provider: Provider; } -export function MNSClaim(props: MNSClaimProps) { - const { dnsAlloc, getAllocCost } = props; - const [domain, setDomain] = useState(''); - const { connectedAccount } = useAccountStore(); - const [allocCost, setAllocCost] = useState({ - price: 0n, - }); +export function MNSClaim({ provider }: MnsClaimProps) { + const { onDomainChange, claim, error, loadPrice, allocCost, domain } = + useMnsClaim(provider); + const { mnsContract } = useMnsStore(); - function claim() { - if (!connectedAccount) { - toast.error('Please connect your wallet'); - return; - } - if (!allocCost.price) { - toast.error('Invalid price'); - return; - } - dnsAlloc({ - domain, - targetAddress: connectedAccount.address(), - coins: allocCost.price, - }); - } + useEffect(() => { + onDomainChange(domain); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [provider, mnsContract]); - function onDomainChange(domain: string) { - if (!connectedAccount) { - toast.error('Please connect your wallet'); - return; - } - if (domain == '') { - setAllocCost({ price: 0n }); - return; - } - setDomain(domain); - getAllocCost({ - domain, - targetAddress: connectedAccount?.address() ?? '', - }).then((cost) => { - setAllocCost(cost); - }); - } return (
@@ -63,16 +31,20 @@ export function MNSClaim(props: MNSClaimProps) { onDomainChange(e.target.value); }} /> - {allocCost.price !== null ? ( + + {error ? ( +

{error}

+ ) : loadPrice ? ( +

Loading price...

+ ) : (

- Price {toMAS(allocCost.price).toFixed(4)} MAS + {/* TODO: fix to get the same behavior than prod */} + Price {formatAmount(allocCost, Mas.NB_DECIMALS).preview} MAS

- ) : ( -

{allocCost.error}

)}
)}
+ {list.length === 0 && ( +
+

No MNS owned

+
+ )} {list.map((item, idx) => (
@@ -150,41 +223,48 @@ export function MNSList(props: MNSListProps) {

- - - + Change target

} + > + +
+ + + +
))} diff --git a/frontend/src/components/MNSManagement.tsx b/frontend/src/components/MNSManagement.tsx index 9cae970..3ae432b 100644 --- a/frontend/src/components/MNSManagement.tsx +++ b/frontend/src/components/MNSManagement.tsx @@ -1,37 +1,24 @@ import { useEffect } from 'react'; -import { useAccountStore } from '../lib/connectMassaWallets/store'; -import { useWriteMNS } from '../utils/write-mns-sc'; import { MNSClaim } from './MNSClaim'; import { MNSList } from './MNSList'; +import { useAccountStore } from '@massalabs/react-ui-kit'; +import { useMnsStore } from '../store/mns'; -interface MNSManagementProps { - customClass?: string; -} +export function MNSManagement() { + const { connectedAccount, network } = useAccountStore(); + const { setMnsContract, mnsContract } = useMnsStore(); -export function MNSManagement(props: MNSManagementProps) { - const { customClass } = props; - const { massaClient, connectedAccount, currentProvider, chainId } = - useAccountStore(); - const { - list, - listSpinning, - getUserEntryList, - dnsAlloc, - getAllocCost, - changeTargetAddressDnsEntry, - deleteDnsEntry, - changeOwnershipDnsEntry, - } = useWriteMNS(massaClient); + useEffect(() => { + if (connectedAccount && network) { + setMnsContract(connectedAccount, network); + } + }, [connectedAccount, network, setMnsContract]); - const connected = !!connectedAccount && !!currentProvider; + const connected = !!connectedAccount; - useEffect(() => { - if (!connectedAccount || !massaClient || listSpinning || !chainId) return; - getUserEntryList({ address: connectedAccount.address() }); - }, [connectedAccount, massaClient, chainId]); return ( -
- {!connected ? ( +
+ {!connected || !mnsContract ? (

Please connect your wallet above @@ -39,14 +26,8 @@ export function MNSManagement(props: MNSManagementProps) {

) : (
- - + +
)}
diff --git a/frontend/src/const/dataStoreKeys.ts b/frontend/src/const/dataStoreKeys.ts new file mode 100644 index 0000000..0570a22 --- /dev/null +++ b/frontend/src/const/dataStoreKeys.ts @@ -0,0 +1,21 @@ +import { strToBytes } from '@massalabs/massa-web3'; + +export const TARGET_KEY_PREFIX = [0x02]; +export const DOMAIN_KEY_PREFIX = [0x03]; +export const DOMAIN_SEPARATOR_KEY = [0x42]; + +export function getDomainKey(id: Uint8Array): Uint8Array { + return Uint8Array.from([ + ...DOMAIN_SEPARATOR_KEY, + ...DOMAIN_KEY_PREFIX, + ...id, + ]); +} + +export function getTargetKey(domain: string): Uint8Array { + return Uint8Array.from([ + ...DOMAIN_SEPARATOR_KEY, + ...TARGET_KEY_PREFIX, + ...strToBytes(domain), + ]); +} diff --git a/frontend/src/const/faq.ts b/frontend/src/const/faq.ts new file mode 100644 index 0000000..1b0f36d --- /dev/null +++ b/frontend/src/const/faq.ts @@ -0,0 +1,38 @@ +import { FAQData } from '../components/FAQ'; + +export const faqData: FAQData[] = [ + { + question: 'What is Massa Name Service ?', + answer: + 'Massa Name Service is a decentralized naming service which allows users and smart contracts to be recognized on the Massa blockchain.', + }, + { + question: 'How do I register a name ?', + answer: + 'To register a name, you need to connect your Massa wallet and enter the name you want to register in the register section. If the name is available, you can register it by paying the registration fee.', + }, + { + question: 'How much does it cost to register a name ?', + answer: + 'The cost depends on the size of the name. 10000 coins for 2 characters, 1000 coins for 3 characters, 100 coins for 4 characters, 10 coins for 5 characters and 1 coin for 6 and more characters. An little additional amount is taken to cover storage fees. You can see the exact price while typing a domain in the register section.', + }, + { + question: 'How do I transfer a name ?', + answer: + 'Massa Names are NFTs and can be transferred like any other NFT. You can transfer them on purrfect universe using the icon at the top of the page.', + }, + { + question: 'Can I change the address my name is targeting ?', + answer: + 'Yes you can change the address your name is targeting by using the edit icon in the management section. It will change the target address but you will still be the owner of the name.', + }, + { + question: 'For how long is a name registered ?', + answer: 'Forever.', + }, + { + question: 'Can I free my name and get my coins back ?', + answer: + 'Yes you can free your name using the trash icon in the management section. You will get half of the coins you paid for the registration back.', + }, +]; diff --git a/frontend/src/const/sc.ts b/frontend/src/const/sc.ts index 94b5498..d68c63e 100644 --- a/frontend/src/const/sc.ts +++ b/frontend/src/const/sc.ts @@ -1,9 +1,9 @@ -import { fromMAS } from '@massalabs/massa-web3'; +import { Mas } from '@massalabs/massa-web3'; export const MAINNET_SC_ADDRESS = import.meta.env.VITE_MAINNET_SC_ADDRESS; export const BUILDNET_SC_ADDRESS = import.meta.env.VITE_BUILDNET_SC_ADDRESS; -export const VESTING_SESSION_STORAGE_COST = fromMAS(2); +export const VESTING_SESSION_STORAGE_COST = Mas.fromMas(2n); let defaultOpFees: bigint; try { defaultOpFees = BigInt(import.meta.env.VITE_OP_FEES); diff --git a/frontend/src/hooks/useMnsClaim.ts b/frontend/src/hooks/useMnsClaim.ts new file mode 100644 index 0000000..6b8a2b4 --- /dev/null +++ b/frontend/src/hooks/useMnsClaim.ts @@ -0,0 +1,102 @@ +import { formatAmount, useHandleOperation } from '@massalabs/react-ui-kit'; +import { useState } from 'react'; +import { useMnsStore } from '../store/mns'; +import { Mas, Provider } from '@massalabs/massa-web3'; + +export function useMnsClaim(provider: Provider) { + const [domain, setDomain] = useState(''); + const { mnsContract, getAllocationCost, resolve, getUserEntryList } = + useMnsStore(); + + const { handleOperation } = useHandleOperation(); + + const [allocCost, setAllocCost] = useState(0n); + const [error, setError] = useState(null); + const [loadPrice, setLoadPrice] = useState(false); + + async function claim() { + const operation = await mnsContract.alloc(domain, provider.address, { + coins: allocCost, + }); + + await handleOperation(operation, { + pending: 'Entry registering in progress', + success: 'Successfully registered', + error: 'Failed to register', + }); + + getUserEntryList(provider, provider.address); + setDomain(''); + } + + async function onDomainChange(domain: string) { + setError(null); + setLoadPrice(true); + setDomain(domain); + + if (!domain) { + resetCostAndLoading(); + return; + } + + // TODO: Should we get owner instead of target? or both? + const target = await resolve(domain); + if (target) { + setError(`Domain already linked to ${target}`); + resetCostAndLoading(); + return; + } + + try { + const cost = await getAllocationCost({ + domain, + targetAddress: provider?.address ?? '', + }); + + const targetBalance = await provider?.balance(false); + + if (cost > targetBalance) { + setError(insufficientFundsMessage(cost, targetBalance)); + resetCostAndLoading(cost); + return; + } + + setAllocCost(cost); + } catch (err) { + handleCostError(err); + } finally { + setLoadPrice(false); + } + } + + function resetCostAndLoading(cost: bigint = 0n) { + setAllocCost(cost); + setLoadPrice(false); + } + + function insufficientFundsMessage(cost: bigint, balance: bigint) { + return `The price of the domain is ${ + formatAmount(cost, Mas.NB_DECIMALS).preview + } MAS. Your balance is ${ + formatAmount(balance, Mas.NB_DECIMALS).preview + } MAS. Please top up your account.`; + } + + function handleCostError(err: unknown) { + if (err instanceof Error) { + setError(err.message); + } else { + setError('An unexpected error occurred'); + } + resetCostAndLoading(); + } + + return { + domain, + error, + loadPrice, + allocCost, + claim, + onDomainChange, + }; +} diff --git a/frontend/src/lib/connectMassaWallets/components/BearbySvg.tsx b/frontend/src/lib/connectMassaWallets/components/BearbySvg.tsx deleted file mode 100644 index af193b4..0000000 --- a/frontend/src/lib/connectMassaWallets/components/BearbySvg.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* eslint-disable max-len */ -export function BearbySvg() { - return ( - - - - - - - - - - - - ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/BearbyWallet.tsx b/frontend/src/lib/connectMassaWallets/components/BearbyWallet.tsx deleted file mode 100644 index bf4e76c..0000000 --- a/frontend/src/lib/connectMassaWallets/components/BearbyWallet.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { useAccountStore } from '../store'; -import { ConnectedAccount } from './ConnectedAccount'; -import { MASBalance } from './MASBalance'; -import { WalletError } from './WalletError'; -import Intl from '../i18n/i18n'; -import { BEARBY_INSTALL } from '../const'; - -export default function BearbyWallet() { - const { connectedAccount } = useAccountStore(); - - if (connectedAccount) { - return ( -
- - -
- ); - } - - return ( - - ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/ConnectMassaWallet.tsx b/frontend/src/lib/connectMassaWallets/components/ConnectMassaWallet.tsx deleted file mode 100644 index a0fcb07..0000000 --- a/frontend/src/lib/connectMassaWallets/components/ConnectMassaWallet.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { useEffect, useState } from 'react'; -import { - MassaWallet as MassaWalletLogo, - Tooltip, -} from '@massalabs/react-ui-kit'; -import BearbyWallet from './BearbyWallet'; -import SelectMassaWallet from './SelectMassaWallet'; -import StationWallet from './StationWallet'; -import SwitchWalletButton from './SwitchWalletButton'; -import { ChainStatus } from './Status/ChainStatus'; -import { useAccountStore } from '../store'; -import Intl from '../i18n/i18n'; -import { SUPPORTED_MASSA_WALLETS } from '../const'; -import { BearbySvg } from './BearbySvg'; - -export const ConnectMassaWallet = () => { - const { currentProvider, providers, setCurrentProvider, isFetching } = - useAccountStore(); - - const [selectedProvider, setSelectedProvider] = useState< - SUPPORTED_MASSA_WALLETS | undefined - >(currentProvider?.name() as SUPPORTED_MASSA_WALLETS); - - useEffect(() => { - const provider = providers.find((p) => p.name() === selectedProvider); - if (provider && !currentProvider) { - setCurrentProvider(provider); - } - }, [providers, selectedProvider, currentProvider, setCurrentProvider]); - - if (!selectedProvider || isFetching) - return ( - { - setSelectedProvider(providerName); - const provider = providers.find((p) => p.name() === providerName); - if (provider) { - setCurrentProvider(provider); - } - }} - /> - ); - - function renderWallet() { - switch (selectedProvider) { - case SUPPORTED_MASSA_WALLETS.MASSASTATION: - return ; - case SUPPORTED_MASSA_WALLETS.BEARBY: - return ; - default: - // Should not happen - return <>Error: no wallet selected; - } - } - - function renderSelectedWallet() { - switch (selectedProvider) { - case SUPPORTED_MASSA_WALLETS.MASSASTATION: - return ( - <> - - {Intl.t(`connect-wallet.${SUPPORTED_MASSA_WALLETS.MASSASTATION}`)} - - ); - case SUPPORTED_MASSA_WALLETS.BEARBY: - return ( - <> - - {Intl.t(`connect-wallet.${SUPPORTED_MASSA_WALLETS.BEARBY}`)} - - ); - } - } - - return ( - <> -
-
- {renderSelectedWallet()} - - {selectedProvider === SUPPORTED_MASSA_WALLETS.BEARBY && ( - - )} -
- { - setSelectedProvider(undefined); - setCurrentProvider(); - }} - /> -
- {renderWallet()} - - ); -}; diff --git a/frontend/src/lib/connectMassaWallets/components/ConnectedAccount.tsx b/frontend/src/lib/connectMassaWallets/components/ConnectedAccount.tsx deleted file mode 100644 index ebd334a..0000000 --- a/frontend/src/lib/connectMassaWallets/components/ConnectedAccount.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Clipboard } from '@massalabs/react-ui-kit'; -import { useAccountStore } from '../store'; -import { maskAddress } from '../utils'; - -interface ConnectedAccountProps { - maskLength?: number; -} - -export function ConnectedAccount(props: ConnectedAccountProps) { - const { maskLength } = props; - const { connectedAccount } = useAccountStore(); - - return ( -
- -
- ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/FetchingComponent.tsx b/frontend/src/lib/connectMassaWallets/components/FetchingComponent.tsx deleted file mode 100644 index 1b45aee..0000000 --- a/frontend/src/lib/connectMassaWallets/components/FetchingComponent.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import Intl from '../i18n/i18n'; - -export function FetchingRound() { - return ( - - - - - ); -} - -interface FetchingCircleProps { - height?: number; - width?: number; -} - -export function FetchingLine(props: FetchingCircleProps) { - const { height = 2, width = 24 } = props; - - return ( -
-
-
-
-
-
-
- ); -} - -export function FetchingStatus() { - return ( -
- {Intl.t('general.loading')}. -
- ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/MASBalance.tsx b/frontend/src/lib/connectMassaWallets/components/MASBalance.tsx deleted file mode 100644 index 778ee26..0000000 --- a/frontend/src/lib/connectMassaWallets/components/MASBalance.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { useEffect, useState } from 'react'; -import { fromMAS } from '@massalabs/massa-web3'; -import { IAccountBalanceResponse } from '@massalabs/wallet-provider'; -import Intl from '../i18n/i18n'; -import { useAccountStore } from '../store'; -import { massaToken } from '../const'; -import { fetchMASBalance } from '../utils'; -import { formatAmount } from '@massalabs/react-ui-kit'; -import { FetchingLine } from './FetchingComponent'; - -export function MASBalance() { - const [balance, setBalance] = useState(); - - const { connectedAccount } = useAccountStore(); - - useEffect(() => { - if (!connectedAccount) return; - fetchMASBalance(connectedAccount).then((balance) => { - setBalance(balance); - }); - }, [connectedAccount, setBalance]); - - const formattedBalance = formatAmount( - fromMAS(balance?.candidateBalance || '0').toString(), - 9, - ).amountFormattedFull; - - return ( -
- {Intl.t('connect-wallet.connected-cards.wallet-balance')} - {balance === undefined ? ( - - ) : ( - <> - {formattedBalance} {massaToken} - - )} -
- ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/OperationToast.tsx b/frontend/src/lib/connectMassaWallets/components/OperationToast.tsx deleted file mode 100644 index 47b46ff..0000000 --- a/frontend/src/lib/connectMassaWallets/components/OperationToast.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import Intl from '../i18n/i18n'; -import { generateExplorerLink } from '../utils'; - -type OperationToastProps = { - title: string; - operationId?: string; - isMainnet?: boolean; -}; - -export function OperationToast({ - title, - operationId, - isMainnet, -}: OperationToastProps) { - return ( -
-

{title}

- {operationId && ( - - {Intl.t('toast.explorer')} - - )} -
- ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/SelectMassaWallet.tsx b/frontend/src/lib/connectMassaWallets/components/SelectMassaWallet.tsx deleted file mode 100644 index 256fb57..0000000 --- a/frontend/src/lib/connectMassaWallets/components/SelectMassaWallet.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Dropdown, MassaWallet } from '@massalabs/react-ui-kit'; -import Intl from '../i18n/i18n'; -import { BearbySvg } from './BearbySvg'; -import { SUPPORTED_MASSA_WALLETS } from '../const'; -import { Disconnected } from './Status/Disconnected'; - -const walletList = [ - { - name: SUPPORTED_MASSA_WALLETS.MASSASTATION, - icon: , - }, - { - name: SUPPORTED_MASSA_WALLETS.BEARBY, - icon: , - }, -]; - -interface SelectMassaWalletProps { - onClick: (providerName: SUPPORTED_MASSA_WALLETS) => void; -} - -const SelectMassaWallet = ({ onClick }: SelectMassaWalletProps) => { - const walletOptions = () => { - return walletList.map((provider) => ({ - item: Intl.t(`connect-wallet.${provider.name}`), - icon: provider.icon, - onClick: () => onClick(provider.name), - })); - }; - - return ( - <> -
-

- {Intl.t('connect-wallet.card-destination.to')} -

- -
-
- -
- - ); -}; - -export default SelectMassaWallet; diff --git a/frontend/src/lib/connectMassaWallets/components/StationSelectAccount.tsx b/frontend/src/lib/connectMassaWallets/components/StationSelectAccount.tsx deleted file mode 100644 index d0a624e..0000000 --- a/frontend/src/lib/connectMassaWallets/components/StationSelectAccount.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { Dropdown } from '@massalabs/react-ui-kit'; -import { IAccount } from '@massalabs/wallet-provider'; -import { useAccountStore } from '../store'; - -export function StationSelectAccount() { - const [accounts, connectedAccount, setConnectedAccount] = useAccountStore( - (state) => [ - state.accounts, - state.connectedAccount, - state.setConnectedAccount, - ], - ); - - const selectedAccountKey: number = (accounts || []).findIndex( - (account) => account.name() === connectedAccount?.name(), - ); - - const onAccountChange = async (account: IAccount) => { - setConnectedAccount(account); - }; - - return ( - { - return { - item: account.name(), - onClick: () => onAccountChange(account), - }; - })} - /> - ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/StationWallet.tsx b/frontend/src/lib/connectMassaWallets/components/StationWallet.tsx deleted file mode 100644 index 1aeea32..0000000 --- a/frontend/src/lib/connectMassaWallets/components/StationWallet.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { useEffect, useState } from 'react'; -import { - isMassaStationAvailable, - isMassaWalletEnabled, -} from '@massalabs/wallet-provider'; -import { ConnectedAccount } from './ConnectedAccount'; -import { MASBalance } from './MASBalance'; -import { StationSelectAccount } from './StationSelectAccount'; -import { WalletError } from './WalletError'; -import { - MASSA_STATION_INSTALL, - MASSA_STATION_STORE, - MASSA_WALLET_CREATE_ACCOUNT, -} from '../const'; -import { useAccountStore } from '../store'; -import Intl from '../i18n/i18n'; - -export default function StationWallet() { - const { accounts } = useAccountStore(); - - const [stationIsOn, setStationIsOn] = useState( - undefined, - ); - const [massaWalletIsOn, setMassaWalletIsOn] = useState( - undefined, - ); - - useEffect(() => { - isMassaStationAvailable().then((result) => { - setStationIsOn(result); - }); - isMassaWalletEnabled().then((result) => { - setMassaWalletIsOn(result); - }); - }); - - if (stationIsOn === false) { - return ( - - ); - } - - if (massaWalletIsOn === false) { - return ( - - ); - } - - if (accounts !== undefined && !accounts.length) { - return ( - - ); - } - - if (accounts === undefined) { - return
; - } - - return ( -
-
-
- -
-
- -
-
- -
- ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/Status/ChainStatus.tsx b/frontend/src/lib/connectMassaWallets/components/Status/ChainStatus.tsx deleted file mode 100644 index 6d350bc..0000000 --- a/frontend/src/lib/connectMassaWallets/components/Status/ChainStatus.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { useAccountStore } from '../../store'; -import { Connected } from './Connected'; -import { Disconnected } from './Disconnected'; - -export function ChainStatus() { - const { connectedAccount, currentProvider } = useAccountStore(); - - const connected = !!connectedAccount && !!currentProvider; - - return <>{connected ? : }; -} diff --git a/frontend/src/lib/connectMassaWallets/components/Status/Connected.tsx b/frontend/src/lib/connectMassaWallets/components/Status/Connected.tsx deleted file mode 100644 index 077d9fd..0000000 --- a/frontend/src/lib/connectMassaWallets/components/Status/Connected.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Tag } from '@massalabs/react-ui-kit'; -import { tagTypes } from '../../const'; -import Intl from '../../i18n/i18n'; - -export function Connected() { - return ( - {Intl.t('connect-wallet.tag.connected')} - ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/Status/Disconnected.tsx b/frontend/src/lib/connectMassaWallets/components/Status/Disconnected.tsx deleted file mode 100644 index 4a15b87..0000000 --- a/frontend/src/lib/connectMassaWallets/components/Status/Disconnected.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Tag } from '@massalabs/react-ui-kit'; -import Intl from '../../i18n/i18n'; -import { tagTypes } from '../../const'; - -export function Disconnected() { - return ( - - {Intl.t('connect-wallet.tag.not-connected')} - - ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/SwitchWalletButton.tsx b/frontend/src/lib/connectMassaWallets/components/SwitchWalletButton.tsx deleted file mode 100644 index a82474e..0000000 --- a/frontend/src/lib/connectMassaWallets/components/SwitchWalletButton.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import Intl from '../i18n/i18n'; - -export default function SwitchWalletButton({ - onClick, -}: { - onClick: () => void; -}) { - return ( -
-

- {Intl.t('connect-wallet.card-destination.switch')} -

-
- ); -} diff --git a/frontend/src/lib/connectMassaWallets/components/WalletError.tsx b/frontend/src/lib/connectMassaWallets/components/WalletError.tsx deleted file mode 100644 index 1302613..0000000 --- a/frontend/src/lib/connectMassaWallets/components/WalletError.tsx +++ /dev/null @@ -1,23 +0,0 @@ -interface WalletErrorProps { - description: string; - link: string; - linkLabel: string; -} - -export function WalletError(props: WalletErrorProps) { - const { description, link, linkLabel } = props; - - return ( -
- {description} - - {linkLabel} - -
- ); -} diff --git a/frontend/src/lib/connectMassaWallets/const.ts b/frontend/src/lib/connectMassaWallets/const.ts deleted file mode 100644 index ba24047..0000000 --- a/frontend/src/lib/connectMassaWallets/const.ts +++ /dev/null @@ -1,27 +0,0 @@ -export const MASSA = 'Massa'; -export const tagTypes = { - success: 'success', - error: 'error', - warning: 'warning', - info: 'info', -}; -export const MASSA_STATION_INSTALL = 'https://station.massa.net'; -export const MASSA_STATION_STORE = 'https://station.massa/web/store'; -export const MASSA_WALLET_CREATE_ACCOUNT = - 'http://station.massa/plugin/massa-labs/massa-wallet/web-app/account-create'; -export const massaToken = 'MAS'; -export const BEARBY_INSTALL = 'https://bearby.io'; -export enum SUPPORTED_MASSA_WALLETS { - MASSASTATION = 'MASSASTATION', - BEARBY = 'BEARBY', -} - -export const INTL = { - EN_us: 'en_US', - FR_fr: 'fr_FR', -}; - -export const MASSA_EXPLO_URL = 'https://massexplo.io/tx/'; -export const MASSA_EXPLO_EXTENSION = '?network=buildnet'; -export const MASSA_EXPLORER_URL = - 'https://explorer.massa.net/mainnet/operation/'; diff --git a/frontend/src/lib/connectMassaWallets/hooks/write-sc.tsx b/frontend/src/lib/connectMassaWallets/hooks/write-sc.tsx deleted file mode 100644 index ccf2a67..0000000 --- a/frontend/src/lib/connectMassaWallets/hooks/write-sc.tsx +++ /dev/null @@ -1,174 +0,0 @@ -import { useState } from 'react'; -import { - Client, - EOperationStatus, - ICallData, - MAX_GAS_CALL, -} from '@massalabs/massa-web3'; -import { ToastContent, toast } from '@massalabs/react-ui-kit'; - -import { OperationToast } from '../components/OperationToast'; -import { logSmartContractEvents } from '../utils'; -import Intl from '../i18n/i18n'; - -interface ToasterMessage { - pending: string; - success: string; - error: string; - timeout?: string; -} - -function minBigInt(a: bigint, b: bigint) { - return a < b ? a : b; -} - -export function useWriteSmartContract( - client?: Client, - isMainnet: boolean = true, -) { - const [isPending, setIsPending] = useState(false); - const [isOpPending, setIsOpPending] = useState(false); - const [isSuccess, setIsSuccess] = useState(false); - const [isError, setIsError] = useState(false); - const [opId, setOpId] = useState(undefined); - - function callSmartContract( - targetFunction: string, - targetAddress: string, - parameter: number[], - messages: ToasterMessage, - coins = BigInt(0), - ) { - if (!client) { - throw new Error('Massa client not found'); - } - if (isOpPending) { - throw new Error('Operation is already pending'); - } - setIsSuccess(false); - setIsError(false); - setIsOpPending(false); - setIsPending(true); - let operationId: string | undefined; - let toastId: string | undefined; - - const callData = { - targetAddress, - targetFunction, - parameter, - coins, - } as ICallData; - - client - .smartContracts() - .readSmartContract(callData) - .then((response) => { - const gasCost = BigInt(response.info.gas_cost); - return minBigInt(gasCost + (gasCost * 20n) / 100n, MAX_GAS_CALL); - }) - .then((maxGas: bigint) => { - callData.maxGas = maxGas; - return client.smartContracts().callSmartContract(callData); - }) - .then((opId) => { - operationId = opId; - setOpId(operationId); - setIsOpPending(true); - toastId = toast.loading( - (t) => ( - - - - ), - { - duration: Infinity, - }, - ); - return client - .smartContracts() - .awaitMultipleRequiredOperationStatus(operationId, [ - EOperationStatus.SPECULATIVE_ERROR, - EOperationStatus.FINAL_ERROR, - EOperationStatus.FINAL_SUCCESS, - ]); - }) - .then((status: EOperationStatus) => { - if (status !== EOperationStatus.FINAL_SUCCESS) { - throw new Error('Operation failed', { cause: { status } }); - } - setIsSuccess(true); - setIsOpPending(false); - setIsPending(false); - toast.dismiss(toastId); - toast.success((t) => ( - - - - )); - }) - .catch((error) => { - console.error(error); - toast.dismiss(toastId); - setIsError(true); - setIsOpPending(false); - setIsPending(false); - - if (!operationId) { - console.error('Operation ID not found'); - toast.error((t) => ( - - - - )); - return; - } - - if ( - [ - EOperationStatus.FINAL_ERROR, - EOperationStatus.SPECULATIVE_ERROR, - ].includes(error.cause?.status) - ) { - toast.error((t) => ( - - - - )); - logSmartContractEvents(client, operationId); - } else { - toast.error((t) => ( - - - - )); - } - }); - } - - return { - opId, - isOpPending, - isPending, - isSuccess, - isError, - callSmartContract, - }; -} diff --git a/frontend/src/lib/connectMassaWallets/i18n/en_US.json b/frontend/src/lib/connectMassaWallets/i18n/en_US.json deleted file mode 100644 index 71db27d..0000000 --- a/frontend/src/lib/connectMassaWallets/i18n/en_US.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "toast": { - "explorer": "view in explorer" - }, - "steps": { - "failed-timeout": "Operation failed due to timeout, please retry with more fees." - }, - "connect-wallet": { - "title": "Connect wallets", - "connected": "Connected wallets", - "description": "Connect wallets for {network1} and {network2}, to bridge tokens.", - "button": "Connect", - "card-destination": { - "from": "Ethereum wallet", - "to": "Massa wallet", - "non-massa-wallet": "Switch accounts directly within your wallet.", - "switch": "switch wallet", - "select-wallet": "Select wallet", - "your-wallet": "Your wallet", - "bearby-not-installed": "Bearby extension is either turned off or not installed. Make sure the extension is on and refresh the page.", - "get-bearby": "Get Bearby here", - "massa-station-not-detected": "Massa Station desktop app is not detected. Make sure the app is opened, or click below to install it.", - "get-massa-station": "Get Massa Station", - "massa-wallet-not-detected": "Massa Wallet is not detected. Make sure the plugin is installed, or click below to install it.", - "get-massa-wallet": "Get Massa Wallet", - "massa-wallet-no-account": "No wallet accounts found in Massa Wallet.", - "massa-wallet-create-account": "Create an account", - "not-detected": "wallet is not detected." - }, - "MASSASTATION": "MassaWallet", - "BEARBY": "Bearby", - "connected-cards": { - "wallet-balance": "Balance: " - }, - "connect-massa": { - "unsupported-net": "Switch to 'buildnet' in top-right corner of Station's homepage" - }, - "wrong-chain": "Wrong wallet network. Please, switch to {network} in your {name} wallet settings.", - "connect-metamask": { - "connect-to-metamask": "Connect to Metamask", - "invalid-network": "Current network is not supported. Please, switch to {network}.", - "switch-network": "Switch network", - "no-metamask": "It seems like you don't have Metamask installed.", - "install-metamask": "Install Metamask" - }, - "tag": { - "not-connected": "Not connected", - "connected": "Connected", - "wrong-chain": "Unsupported network", - "wrong-chain-massa-station-tooltip": "Switch to {network} in top-right corner of Station's homepage", - "wrong-chain-bearby-tooltip": "Switch to {network} in top-left corner of Bearby's extension" - } - } -} diff --git a/frontend/src/lib/connectMassaWallets/i18n/i18n.ts b/frontend/src/lib/connectMassaWallets/i18n/i18n.ts deleted file mode 100644 index 5a86b0c..0000000 --- a/frontend/src/lib/connectMassaWallets/i18n/i18n.ts +++ /dev/null @@ -1,72 +0,0 @@ -import dot from 'dot-object'; -import enUs from './en_US.json'; -import { INTL } from '../const'; - -type Copy = Record; - -class I18n { - private lang: string; - private copy: Copy; - - constructor() { - this.lang = this._getLang(); - this.copy = this._getCopy(); - } - - public t(key: string, interpolations?: Record): string { - const copy = this.copy; - // we are using pick in order to make life easier when the day for plurals and copy with params arrives - const result = dot.pick(key, copy); - - if (!result) { - console.warn(`I18n::t:: No translation found for key ${key}`); - } - - return interpolations - ? this._interpolateKeys(result, interpolations) - : result ?? key; - } - - private _getLang(): string { - const urlParams = new URLSearchParams(window.location.search); - const fromUrl = urlParams.get('l'); - - if (fromUrl) { - localStorage.setItem('massa-station-lang', fromUrl); - } - - return fromUrl || localStorage.getItem('massa-station-lang') || INTL.EN_us; - } - - private _getCopy(): Copy { - const lang = this.lang; - - if (lang === INTL.EN_us) { - return enUs; - } else { - console.warn( - `I18n::_getCopy:: We may not support yet ${lang}. Loading 'en_US' then... `, - ); - return enUs; - } - } - - private _interpolateKeys( - str: string, - replacements: Record, - char1 = '{', - char2 = '}', - ): string { - const regex = new RegExp(`${char1}[^${char2}]*${char2}`, 'g'); - - return str.replace(regex, (match) => { - const key = match.slice(1, -1); - return replacements[key] ?? match; - }); - } -} - -const Intl = new I18n(); -Object.freeze(Intl); - -export default Intl; diff --git a/frontend/src/lib/connectMassaWallets/store/accountStore.ts b/frontend/src/lib/connectMassaWallets/store/accountStore.ts deleted file mode 100644 index c1fd22d..0000000 --- a/frontend/src/lib/connectMassaWallets/store/accountStore.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { Client, ClientFactory } from '@massalabs/massa-web3'; -import { IAccount, IProvider } from '@massalabs/wallet-provider'; -import { SUPPORTED_MASSA_WALLETS } from '../const'; - -async function handleBearbyAccountChange( - newAddress: string, - store: AccountStoreState, -) { - const { connectedAccount, currentProvider, setConnectedAccount } = store; - - const oldAddress = connectedAccount?.address(); - - if (newAddress !== oldAddress) { - const newAccounts = await currentProvider?.accounts(); - - if (newAccounts?.length) { - // Bearby returns only one account - const newAccount = newAccounts[0]; - setConnectedAccount(newAccount); - } - } -} - -export interface AccountStoreState { - connectedAccount?: IAccount; - massaClient?: Client; - accounts?: IAccount[]; - currentProvider?: IProvider; - providers: IProvider[]; - isFetching: boolean; - accountObserver?: { - unsubscribe: () => void; - }; - networkObserver?: { - unsubscribe: () => void; - }; - chainId?: bigint; - - setCurrentProvider: (provider?: IProvider) => void; - setProviders: (providers: IProvider[]) => void; - - setConnectedAccount: (account?: IAccount) => void; - refreshMassaClient: () => void; -} - -const accountStore = ( - set: (params: Partial) => void, - get: () => AccountStoreState, -) => ({ - accounts: undefined, - connectedAccount: undefined, - accountObserver: undefined, - networkObserver: undefined, - massaClient: undefined, - currentProvider: undefined, - providers: [], - isFetching: false, - chainId: undefined, - - setCurrentProvider: (currentProvider?: IProvider) => { - try { - set({ isFetching: true }); - - const previousProvider = get().currentProvider; - - if (previousProvider?.name() !== currentProvider?.name()) { - get().accountObserver?.unsubscribe(); - get().networkObserver?.unsubscribe(); - set({ accountObserver: undefined, networkObserver: undefined }); - } - if (!currentProvider) { - set({ - currentProvider: undefined, - connectedAccount: undefined, - accounts: undefined, - }); - return; - } - - if (!get().networkObserver) { - const networkObserver = currentProvider.listenNetworkChanges( - async () => { - get().refreshMassaClient(); - set({ chainId: await currentProvider.getChainId() }); - }, - ); - set({ networkObserver }); - } - - if (currentProvider?.name() === SUPPORTED_MASSA_WALLETS.BEARBY) { - currentProvider - .connect() - .then(() => { - // get current network - currentProvider - .getChainId() - .then((chainId) => { - set({ chainId }); - }) - .catch((error) => { - console.warn('error getting network from bearby', error); - }); - // subscribe to network events - const observer = currentProvider.listenAccountChanges( - (newAddress: string) => { - handleBearbyAccountChange(newAddress, get()); - }, - ); - set({ currentProvider, accountObserver: observer }); - - // get connected account - currentProvider - .accounts() - .then((accounts) => { - // bearby expose only 1 account - get().setConnectedAccount(accounts[0]); - set({ accounts }); - }) - .catch((error) => { - console.warn('error getting accounts from bearby', error); - }); - }) - .catch((error) => { - console.warn('error connecting to bearby', error); - }); - return; - } - - set({ currentProvider }); - - currentProvider - .accounts() - .then((accounts) => { - set({ accounts }); - - const selectedAccount = accounts[0]; - get().setConnectedAccount(selectedAccount); - }) - .catch((error) => { - console.warn('error getting accounts from provider', error); - }); - } finally { - set({ isFetching: false }); - } - }, - - setProviders: (providers: IProvider[]) => { - set({ providers }); - - // if current provider is not in the new list of providers, unset it - if (!providers.some((p) => p.name() === get().currentProvider?.name())) { - set({ - massaClient: undefined, - currentProvider: undefined, - connectedAccount: undefined, - accounts: undefined, - }); - } - }, - - // set the connected account, and update the massa client - setConnectedAccount: async (connectedAccount?: IAccount) => { - set({ connectedAccount }); - if (connectedAccount) { - const currentProvider = get().currentProvider; - if (!currentProvider) throw new Error('No provider found'); - const provider = currentProvider; - // update the massa client with the new account - set({ - massaClient: await ClientFactory.fromWalletProvider( - provider, - connectedAccount, - ), - }); - } - }, - - refreshMassaClient: async () => { - const provider = get().currentProvider; - if (!provider) return; - - const connectedAccount = get().connectedAccount; - if (!connectedAccount) return; - set({ - massaClient: await ClientFactory.fromWalletProvider( - provider, - connectedAccount, - ), - }); - }, -}); - -export default accountStore; diff --git a/frontend/src/lib/connectMassaWallets/store/index.ts b/frontend/src/lib/connectMassaWallets/store/index.ts deleted file mode 100644 index 5e44ddb..0000000 --- a/frontend/src/lib/connectMassaWallets/store/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import accountStore, { AccountStoreState } from './accountStore'; -import { ProvidersListener } from '@massalabs/wallet-provider'; -import { create } from 'zustand'; - -export const useAccountStore = create((set, get) => ({ - ...accountStore(set, get), -})); - -async function initAccountStore() { - new ProvidersListener(2_000).subscribe((providers) => { - useAccountStore.getState().setProviders(providers); - }); -} - -async function initializeStores() { - await initAccountStore(); -} - -initializeStores(); diff --git a/frontend/src/lib/connectMassaWallets/utils.ts b/frontend/src/lib/connectMassaWallets/utils.ts deleted file mode 100644 index c97129c..0000000 --- a/frontend/src/lib/connectMassaWallets/utils.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { toast } from '@massalabs/react-ui-kit'; -import { IAccount, IAccountBalanceResponse } from '@massalabs/wallet-provider'; -import { Client } from '@massalabs/massa-web3'; -import Intl from './i18n/i18n'; -import { - MASSA_EXPLORER_URL, - MASSA_EXPLO_EXTENSION, - MASSA_EXPLO_URL, -} from './const'; - -export function logSmartContractEvents( - client: Client, - operationId: string, -): void { - client - .smartContracts() - .getFilteredScOutputEvents({ - emitter_address: null, - start: null, - end: null, - original_caller_address: null, - original_operation_id: operationId, - is_final: null, - }) - .then((events) => { - events.map((l) => - console.error(`opId ${operationId}: execution error ${l.data}`), - ); - }); -} - -export function generateExplorerLink(opId: string, isMainnet = true): string { - const buildnetExplorerUrl = `${MASSA_EXPLO_URL}${opId}${MASSA_EXPLO_EXTENSION}`; - const mainnetExplorerUrl = `${MASSA_EXPLORER_URL}${opId}`; - const explorerUrl = isMainnet ? mainnetExplorerUrl : buildnetExplorerUrl; - - return explorerUrl; -} - -/** - * Masks the middle of an address with a specified character. - * @param str - The address to mask. - * @param mask - The character to use for masking. Defaults to `.`. - * @returns The masked address. - */ -export function maskAddress(str: string, length = 4, mask = '...'): string { - const start = length; - const end = str?.length - length; - - return str ? str?.substring(0, start) + mask + str?.substring(end) : ''; -} - -export async function fetchMASBalance( - account: IAccount, -): Promise { - try { - return account.balance(); - } catch (error) { - console.error('Error while retrieving balance: ', error); - toast.error(Intl.t('index.balance.error')); - return { finalBalance: '0', candidateBalance: '0' }; - } -} diff --git a/frontend/src/store/mns.ts b/frontend/src/store/mns.ts new file mode 100644 index 0000000..e2917d8 --- /dev/null +++ b/frontend/src/store/mns.ts @@ -0,0 +1,163 @@ +import { create } from 'zustand'; +import { DnsUserEntryListResult, DnsAllocParams } from '../utils/interface'; +import { + Account, + Args, + CHAIN_ID, + JsonRpcProvider, + MNS, + Network, + Provider, + U256, + bytesToStr, +} from '@massalabs/massa-web3'; +import { getTargetKey, getDomainKey } from '../const/dataStoreKeys'; + +interface MnsStoreState { + mnsContract: MNS; + list: DnsUserEntryListResult[]; + listSpinning: boolean; + resolve: (domain: string) => Promise; + getAllocationCost: (params: DnsAllocParams) => Promise; + getUserEntryList: (provider: Provider, userAddress: string) => Promise; + fetchDomains: ( + provider: Provider, + tokenIdsBytes: Uint8Array[], + ) => Promise; + fetchTargets: (provider: Provider, domains: string[]) => Promise; + setMnsContract: (provider: Provider, network: Network) => void; +} + +const createMnsStore = () => + create((set, get) => ({ + mnsContract: MNS.buildnet(JsonRpcProvider.buildnet()), + list: [], + listSpinning: false, + + resolve: async (domain: string) => { + return await get().mnsContract.resolve(domain); + }, + + getAllocationCost: async (params: DnsAllocParams) => { + try { + return await get().mnsContract.dnsAllocCost(params.domain); + } catch (error) { + throw Error( + 'Name can only be 2-100 characters long and can contain only lowercase letters, numbers, and hyphens.', + ); + } + }, + + getUserEntryList: async (provider: Provider, userAddress: string) => { + set({ listSpinning: true }); + + try { + const resultBalance = await provider.readSC({ + target: get().mnsContract.address, + func: 'balanceOf', + parameter: new Args().addString(userAddress), + // TODO: Check why readOnly fails when using caller with no transaction + caller: 'AU1dvPZNjcTQfNQQuysWyxLLhEzw4kB9cGW2RMMVAQGrkzZHqWGD', + }); + + console.log(resultBalance); + + const balance = U256.fromBytes(resultBalance.value); + + if (balance === 0n) { + set({ list: [] }); + set({ listSpinning: false }); + return; + } + + const filter = `ownedTokens${userAddress}`; + const ownedKeys = await provider.getStorageKeys( + get().mnsContract.address, + filter, + false, + ); + + if (!ownedKeys) { + set({ list: [] }); + set({ listSpinning: false }); + return; + } + + const tokenIdsBytes = ownedKeys.map((key) => key.slice(filter.length)); + const tokenIds = tokenIdsBytes.map((bytes) => + U256.fromBytes(Uint8Array.from(bytes)), + ); + + const domains = await get().fetchDomains(provider, tokenIdsBytes); + const targets = await get().fetchTargets(provider, domains); + + const newList = domains.map((domain, index) => ({ + domain, + targetAddress: targets[index], + tokenId: tokenIds[index], + })); + + set({ list: newList }); + } catch (error) { + set({ list: [] }); + } finally { + set({ listSpinning: false }); + } + }, + + async fetchDomains( + provider: Provider, + tokenIdsBytes: Uint8Array[], + ): Promise { + const mnsContract = get().mnsContract; + if (!mnsContract) { + throw new Error('MNS contract not set'); + } + const domainsDataStoreEntries = tokenIdsBytes.map((id) => + getDomainKey(id), + ); + const domainsRes = await provider.readStorage( + mnsContract.address, + domainsDataStoreEntries, + false, + ); + return domainsRes.map(bytesToStr); + }, + + async fetchTargets( + provider: Provider, + domains: string[], + ): Promise { + const mnsContract = get().mnsContract; + if (!mnsContract) { + throw new Error('MNS contract not set'); + } + + const targetDataStoreEntries = domains.map((d) => getTargetKey(d)); + + const targetsRes = await provider.readStorage( + mnsContract.address, + targetDataStoreEntries, + false, + ); + + return targetsRes.map(bytesToStr); + }, + + setMnsContract: (provider: Provider, network: Network) => { + switch (network.chainId) { + case CHAIN_ID.Buildnet: + set({ mnsContract: MNS.buildnet(provider) }); + break; + case CHAIN_ID.Mainnet: + set({ mnsContract: MNS.mainnet(provider) }); + break; + default: + throw new Error( + 'SC_ADDRESS not found for chainId : ' + network.chainId, + ); + } + }, + })); + +export const useMnsStore = createMnsStore(); diff --git a/frontend/src/store/store.ts b/frontend/src/store/store.ts new file mode 100644 index 0000000..3cc602a --- /dev/null +++ b/frontend/src/store/store.ts @@ -0,0 +1,3 @@ +export async function initApp() { + // Set MNSObjectStore +} diff --git a/frontend/src/utils/interface.ts b/frontend/src/utils/interface.ts new file mode 100644 index 0000000..f399cba --- /dev/null +++ b/frontend/src/utils/interface.ts @@ -0,0 +1,17 @@ +export interface DnsAllocParams { + domain: string; + targetAddress: string; + coins?: bigint; +} + +export interface DnsTransferParams { + currentOwner: string; + newOwner: string; + tokenId: bigint; +} + +export interface DnsUserEntryListResult { + domain: string; + targetAddress: string; + tokenId: bigint; +} diff --git a/frontend/src/utils/write-mns-sc.tsx b/frontend/src/utils/write-mns-sc.tsx deleted file mode 100644 index 9bf2fdd..0000000 --- a/frontend/src/utils/write-mns-sc.tsx +++ /dev/null @@ -1,491 +0,0 @@ -import { - Args, - CHAIN_ID, - Client, - EOperationStatus, - ICallData, - IDatastoreEntryInput, - MAX_GAS_CALL, - bytesToStr, - bytesToU256, - bytesToU64, - strToBytes, - toMAS, -} from '@massalabs/massa-web3'; -import { ToastContent, toast } from '@massalabs/react-ui-kit'; -import { useState } from 'react'; -import { - DEFAULT_OP_FEES, - MAINNET_SC_ADDRESS, - BUILDNET_SC_ADDRESS, -} from '../const/sc'; -import { OperationToast } from '../lib/connectMassaWallets/components/OperationToast'; -import { logSmartContractEvents } from '../lib/connectMassaWallets/utils'; -import { useAccountStore } from '../lib/connectMassaWallets/store'; -import { isEqual } from 'lodash'; - -interface ToasterMessage { - pending: string; - success: string; - error: string; - timeout?: string; -} - -export interface DnsAllocParams { - domain: string; - targetAddress: string; - coins?: bigint; -} - -export interface DnsDeleteParams { - tokenId: bigint; -} - -interface DnsUserEntryListParams { - address: string; -} - -export interface DnsChangeTargetParams { - domain: string; - targetAddress: string; -} - -export interface DnsTransferParams { - currentOwner: string; - newOwner: string; - tokenId: bigint; -} - -export interface DnsUserEntryListResult { - domain: string; - targetAddress: string; - tokenId: bigint; -} - -export interface DnsGetAllocCostResponse { - price: bigint | null; - error?: string; -} - -type callSmartContractOptions = { - coins?: bigint; - fee?: bigint; - showInProgressToast?: boolean; -}; - -function minBigInt(a: bigint, b: bigint) { - return a < b ? a : b; -} - -function getScAddress(chainId: bigint | undefined) { - switch (chainId) { - case CHAIN_ID.BuildNet: - return BUILDNET_SC_ADDRESS; - case CHAIN_ID.MainNet: - return MAINNET_SC_ADDRESS; - default: - throw new Error('SC_ADDRESS not found for chainId : ' + chainId); - } -} - -export function useWriteMNS(client?: Client) { - const [isPending, setIsPending] = useState(false); - const [isSuccess, setIsSuccess] = useState(false); - const [isError, setIsError] = useState(false); - const [opId, setOpId] = useState(undefined); - const [list, setList] = useState([]); - const [listSpinning, setListSpinning] = useState(false); - const { chainId } = useAccountStore(); - - async function getAllocCost( - params: DnsAllocParams, - ): Promise { - const SC_ADDRESS = getScAddress(chainId); - - let price = 0n; - try { - let args = new Args(); - args.addString(params.domain); - args.addString(params.targetAddress); - let response = await client?.smartContracts().readSmartContract({ - targetAddress: SC_ADDRESS, - targetFunction: 'dnsAllocCost', - parameter: args.serialize(), - }); - if (!response) { - return { - price: null, - error: 'Failed to get alloc cost', - }; - } - price = bytesToU64(response.returnValue); - } catch (error) { - return { - price: null, - error: - 'Name can only be 2-100 characters long and can contains only lowercase letters, numbers and hyphens.', - }; - } - try { - let args = new Args(); - args.addString(params.domain); - let result = await client?.smartContracts().readSmartContract({ - targetAddress: SC_ADDRESS, - targetFunction: 'dnsResolve', - parameter: args.serialize(), - }); - if (!result) { - return { - price: null, - error: 'Failed to get alloc cost', - }; - } - return { - price: null, - error: `Domain already registered by ${bytesToStr(result.returnValue)}`, - }; - } catch (error) { - try { - let resultBalance = await client - ?.publicApi() - .getAddresses([params.targetAddress]); - if (!resultBalance) { - return { - price: null, - error: 'Failed to get alloc cost', - }; - } - let balance = BigInt( - ( - parseFloat(resultBalance[0].candidate_balance) * 1_000_000_000 - ).toFixed(0), - ); - if (balance < price) { - return { - price: null, - error: `The price of the domain is ${toMAS(price).toFixed( - 4, - )} MAS. Your balance is ${toMAS(balance).toFixed( - 4, - )} MAS. Please top up your account.`, - }; - } - } catch (error) { - return { - price: null, - error: - 'Your account does not exist in the Massa network. Transfer 0.1 MAS to your account to create it onchain.', - }; - } - return { - price: price, - }; - } - } - - function callSmartContract( - targetFunction: string, - parameter: number[], - messages: ToasterMessage, - { - coins = BigInt(0), - fee = DEFAULT_OP_FEES, - showInProgressToast = false, - }: callSmartContractOptions = {}, - ) { - if (!client) { - throw new Error('Massa client not found'); - } - if (isPending) { - throw new Error('Operation is already pending'); - } - setIsSuccess(false); - setIsError(false); - setIsPending(false); - let operationId: string | undefined; - let toastId: string | undefined; - - const SC_ADDRESS = getScAddress(chainId); - - const callData = { - targetAddress: SC_ADDRESS, - targetFunction, - parameter, - coins, - fee, - } as ICallData; - - client - .smartContracts() - .readSmartContract(callData) - .then((response) => { - const gasCost = BigInt(response.info.gas_cost); - return minBigInt(gasCost + (gasCost * 20n) / 100n, MAX_GAS_CALL); - }) - .then((maxGas: bigint) => { - callData.maxGas = maxGas; - return client.smartContracts().callSmartContract(callData); - }) - .then((opId) => { - operationId = opId; - setOpId(opId); - setIsPending(true); - if (showInProgressToast) { - toastId = toast.loading( - (t) => ( - - - - ), - { - duration: Infinity, - }, - ); - } - return client - .smartContracts() - .awaitMultipleRequiredOperationStatus(opId, [ - EOperationStatus.SPECULATIVE_ERROR, - EOperationStatus.FINAL_ERROR, - EOperationStatus.SPECULATIVE_SUCCESS, - ]); - }) - .then((status: EOperationStatus) => { - if (status !== EOperationStatus.SPECULATIVE_SUCCESS) { - throw new Error('Operation failed', { cause: { status } }); - } - setIsSuccess(true); - setIsPending(false); - toast.dismiss(toastId); - const baseAccount = client.wallet().getBaseAccount(); - if (client && baseAccount) { - getUserEntryList({ - address: baseAccount.address()!, - }); - } - toast.success((t) => ( - - - - )); - }) - .catch((error) => { - console.error(error); - toast.dismiss(toastId); - setIsError(true); - setIsPending(false); - - if (!operationId) { - console.error('Operation ID not found'); - toast.error((t) => ( - - - - )); - return; - } - - if ( - [ - EOperationStatus.FINAL_ERROR, - EOperationStatus.SPECULATIVE_ERROR, - ].includes(error.cause?.status) - ) { - toast.error((t) => ( - - - - )); - logSmartContractEvents(client, operationId); - } else { - toast.error((t) => ( - - - - )); - } - }); - } - - function dnsAlloc(params: DnsAllocParams) { - let args = new Args(); - args.addString(params.domain); - args.addString(params.targetAddress); - callSmartContract( - 'dnsAlloc', - args.serialize(), - { - pending: 'Entry registering in progress', - success: 'Successfully registered', - error: 'Failed to register', - }, - { coins: params.coins, showInProgressToast: true }, - ); - } - - async function getUserEntryList( - params: DnsUserEntryListParams, - ): Promise { - setListSpinning(true); - const SC_ADDRESS = getScAddress(chainId); - - let resultBalance = await client?.smartContracts().readSmartContract({ - targetAddress: SC_ADDRESS, - targetFunction: 'balanceOf', - parameter: new Args().addString(params.address).serialize(), - }); - if (!resultBalance) { - toast.error('Failed to get user entry list', { duration: 5000 }); - setListSpinning(false); - return []; - } - - let list: DnsUserEntryListResult[] = []; - - const addressInfo = await client?.publicApi().getAddresses([SC_ADDRESS]); - const filter = [ - ...strToBytes('ownedTokens'), - ...strToBytes(params.address), - ]; - const ownedKeys = addressInfo?.[0].candidate_datastore_keys.filter( - (key) => { - return isEqual(key.slice(0, filter.length), filter); - }, - ); - - if (ownedKeys) { - const tokenIdsBytes = ownedKeys.map((key) => key.slice(filter.length)); - const tokenIds = tokenIdsBytes.map((val) => - bytesToU256(Uint8Array.from(val)), - ); - - const DOMAIN_SEPARATOR_KEY = [0x42]; - const DOMAIN_KEY_PREFIX = [0x3]; - const TARGET_KEY_PREFIX = [0x02]; - - const domainsDataStoreEntries: IDatastoreEntryInput[] = tokenIdsBytes.map( - (tokenIdBytes) => ({ - address: SC_ADDRESS, - key: Uint8Array.from([ - ...DOMAIN_SEPARATOR_KEY, - ...DOMAIN_KEY_PREFIX, - ...tokenIdBytes, - ]), - }), - ); - - const domainsRes = await client! - .publicApi() - .getDatastoreEntries(domainsDataStoreEntries); - const domains = domainsRes.map((val) => bytesToStr(val.candidate_value!)); - - const targetDataStoreEntries: IDatastoreEntryInput[] = domains.map( - (domain) => ({ - address: SC_ADDRESS, - key: Uint8Array.from([ - ...DOMAIN_SEPARATOR_KEY, - ...TARGET_KEY_PREFIX, - ...strToBytes(domain), - ]), - }), - ); - const targetsRes = await client! - .publicApi() - .getDatastoreEntries(targetDataStoreEntries); - const targets = targetsRes.map((val) => bytesToStr(val.candidate_value!)); - - if ( - targets.length !== domains.length || - domains.length !== tokenIds.length || - tokenIds.length !== targets.length - ) { - console.error('Inconsistent data for owned MNS'); - } - - list = domains.map((domain, index) => ({ - domain, - targetAddress: targets[index], - tokenId: tokenIds[index], - })); - } - - setList(list); - setListSpinning(false); - return list; - } - - function deleteDnsEntry(params: DnsDeleteParams) { - let args = new Args(); - args.addU256(BigInt(params.tokenId)); - callSmartContract( - 'dnsFree', - args.serialize(), - { - pending: 'Entry deleting in progress', - success: 'Successfully deleted', - error: 'Failed to delete', - }, - { showInProgressToast: true }, - ); - } - - function changeTargetAddressDnsEntry(params: DnsChangeTargetParams) { - let args = new Args(); - args.addString(params.domain); - args.addString(params.targetAddress); - callSmartContract( - 'dnsUpdateTarget', - args.serialize(), - { - pending: 'Updating target address in progress', - success: 'Successfully updated', - error: 'Failed to update', - }, - { showInProgressToast: true }, - ); - } - - function changeOwnershipDnsEntry(params: DnsTransferParams) { - let args = new Args(); - args.addString(params.currentOwner); - args.addString(params.newOwner); - args.addU256(BigInt(params.tokenId)); - callSmartContract( - 'transferFrom', - args.serialize(), - { - pending: 'Updating ownership in progress', - success: 'Successfully updated', - error: 'Failed to update', - }, - { showInProgressToast: true }, - ); - } - - return { - opId, - isPending, - isSuccess, - isError, - list, - listSpinning, - dnsAlloc, - getAllocCost, - getUserEntryList, - deleteDnsEntry, - changeTargetAddressDnsEntry, - changeOwnershipDnsEntry, - }; -}