From 2ff79446f8726e059daf8f480d2a4a2dd3a292ad Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 24 Apr 2024 21:41:13 -0700 Subject: [PATCH 1/3] MockWallet --- package.json | 10 +- packages/core/src/bases/chain-wallet.ts | 1 + packages/test/.editorconfig | 12 + packages/test/.eslintignore | 7 + packages/test/.eslintrc.json | 82 ++++ packages/test/.gitignore | 49 +++ packages/test/.npmignore | 32 ++ packages/test/.npmrc | 1 + packages/test/.prettierrc.json | 7 + packages/test/LICENSE | 32 ++ packages/test/README.md | 59 +++ packages/test/__tests__/cosmos-kit.test.ts | 12 + packages/test/index.ts | 2 + packages/test/jest.config.js | 19 + packages/test/package.json | 83 ++++ packages/test/src/mock-extension/constant.ts | 2 + .../mock-extension/extension/chain-wallet.ts | 7 + .../src/mock-extension/extension/client.ts | 154 ++++++++ .../src/mock-extension/extension/index.ts | 4 + .../mock-extension/extension/main-wallet.ts | 22 ++ .../src/mock-extension/extension/registry.ts | 25 ++ .../src/mock-extension/extension/types.ts | 86 +++++ .../src/mock-extension/extension/utils.ts | 47 +++ packages/test/src/mock-extension/index.ts | 2 + packages/test/src/mock-extension/mock.ts | 5 + packages/test/src/mocker/index.ts | 156 ++++++++ packages/test/tsconfig.json | 28 ++ yarn.lock | 360 +++--------------- 28 files changed, 996 insertions(+), 310 deletions(-) create mode 100644 packages/test/.editorconfig create mode 100644 packages/test/.eslintignore create mode 100644 packages/test/.eslintrc.json create mode 100644 packages/test/.gitignore create mode 100644 packages/test/.npmignore create mode 100644 packages/test/.npmrc create mode 100644 packages/test/.prettierrc.json create mode 100644 packages/test/LICENSE create mode 100644 packages/test/README.md create mode 100644 packages/test/__tests__/cosmos-kit.test.ts create mode 100644 packages/test/index.ts create mode 100644 packages/test/jest.config.js create mode 100644 packages/test/package.json create mode 100644 packages/test/src/mock-extension/constant.ts create mode 100644 packages/test/src/mock-extension/extension/chain-wallet.ts create mode 100644 packages/test/src/mock-extension/extension/client.ts create mode 100644 packages/test/src/mock-extension/extension/index.ts create mode 100644 packages/test/src/mock-extension/extension/main-wallet.ts create mode 100644 packages/test/src/mock-extension/extension/registry.ts create mode 100644 packages/test/src/mock-extension/extension/types.ts create mode 100644 packages/test/src/mock-extension/extension/utils.ts create mode 100644 packages/test/src/mock-extension/index.ts create mode 100644 packages/test/src/mock-extension/mock.ts create mode 100644 packages/test/src/mocker/index.ts create mode 100644 packages/test/tsconfig.json diff --git a/package.json b/package.json index 52d82ac4a..f2a7f1a88 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "pub": "lerna publish" }, "devDependencies": { - "@types/jest": "29.0.3", + "@types/jest": "^29.5.11", "@types/node": "18.7.18", "@typescript-eslint/eslint-plugin": "5.38.0", "@typescript-eslint/parser": "5.38.0", @@ -31,13 +31,11 @@ "eslint-plugin-prettier": "4.2.1", "eslint-plugin-simple-import-sort": "8.0.0", "eslint-plugin-unused-imports": "2.0.0", - "jest": "29.0.3", - "jest-in-case": "1.0.2", + "jest": "^29.6.2", "lerna": "7.1.1", "prettier": "2.7.1", - "publish-scripts": "0.1.0", "rimraf": "3.0.2", - "ts-jest": "29.0.1", + "ts-jest": "^29.1.1", "typescript": "4.8.3" }, "workspaces": [ @@ -51,4 +49,4 @@ "dependencies": { "@leapwallet/cosmos-social-login-capsule-provider-ui": "^0.0.46" } -} +} \ No newline at end of file diff --git a/packages/core/src/bases/chain-wallet.ts b/packages/core/src/bases/chain-wallet.ts index 30f28ff44..728547009 100644 --- a/packages/core/src/bases/chain-wallet.ts +++ b/packages/core/src/bases/chain-wallet.ts @@ -50,6 +50,7 @@ export class ChainWalletBase extends WalletBase { } get isTestNet() { + // TODO query in Chain.network_type return this.chainName.includes('testnet'); } diff --git a/packages/test/.editorconfig b/packages/test/.editorconfig new file mode 100644 index 000000000..4a7ea3036 --- /dev/null +++ b/packages/test/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/packages/test/.eslintignore b/packages/test/.eslintignore new file mode 100644 index 000000000..91689c308 --- /dev/null +++ b/packages/test/.eslintignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +main/ +module/ +types/ +coverage/ +/index.ts \ No newline at end of file diff --git a/packages/test/.eslintrc.json b/packages/test/.eslintrc.json new file mode 100644 index 000000000..d95fc326b --- /dev/null +++ b/packages/test/.eslintrc.json @@ -0,0 +1,82 @@ +{ + "plugins": [ + "@typescript-eslint", + "simple-import-sort", + "unused-imports" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + // configures both eslint-plugin-prettier and eslint-config-prettier + "plugin:prettier/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module", + "project": "tsconfig.json" + }, + "env": { + "es6": true, + "browser": true, + "node": true, + "jest": true + }, + "rules": { + "simple-import-sort/imports": 2, + "simple-import-sort/exports": 2, + "prettier/prettier": 2, + "unused-imports/no-unused-imports": 2, + "no-console": 1, + "no-debugger": 2, + "no-alert": 2, + "no-await-in-loop": 0, + "no-prototype-builtins": 0, + "no-return-assign": [ + "error", + "except-parens" + ], + "no-restricted-syntax": [ + 2, + "ForInStatement", + "LabeledStatement", + "WithStatement" + ], + "no-unused-vars": 0, + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "React|res|next|^_" + } + ], + "prefer-const": [ + "error", + { + "destructuring": "all" + } + ], + "no-unused-expressions": [ + 2, + { + "allowTaggedTemplates": true + } + ], + "comma-dangle": 0, + "jsx-quotes": [ + 2, + "prefer-double" + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + 2, + "single", + { + "avoidEscape": true, + "allowTemplateLiterals": true + } + ] + } +} \ No newline at end of file diff --git a/packages/test/.gitignore b/packages/test/.gitignore new file mode 100644 index 000000000..cba0431de --- /dev/null +++ b/packages/test/.gitignore @@ -0,0 +1,49 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# dist +main +module +dist + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +# Editors +.idea + +# Lib +lib + +# npm package lock +package-lock.json +yarn.lock + +# others +.DS_Store diff --git a/packages/test/.npmignore b/packages/test/.npmignore new file mode 100644 index 000000000..cc2605fa8 --- /dev/null +++ b/packages/test/.npmignore @@ -0,0 +1,32 @@ +*.log +npm-debug.log* + +# Coverage directory used by tools like istanbul +coverage +.nyc_output + +# Dependency directories +node_modules + +# npm package lock +package-lock.json +yarn.lock + +# project files +__fixtures__ +__tests__ +.babelrc +.babelrc.js +.editorconfig +.eslintignore +.eslintrc +.eslintrc.js +.gitignore +.travis.yml +.vscode +CHANGELOG.md +examples +jest.config.js +package.json +src +test \ No newline at end of file diff --git a/packages/test/.npmrc b/packages/test/.npmrc new file mode 100644 index 000000000..a21347f1b --- /dev/null +++ b/packages/test/.npmrc @@ -0,0 +1 @@ +scripts-prepend-node-path=true \ No newline at end of file diff --git a/packages/test/.prettierrc.json b/packages/test/.prettierrc.json new file mode 100644 index 000000000..4aa2a0dc9 --- /dev/null +++ b/packages/test/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "useTabs": false +} \ No newline at end of file diff --git a/packages/test/LICENSE b/packages/test/LICENSE new file mode 100644 index 000000000..bfcca3529 --- /dev/null +++ b/packages/test/LICENSE @@ -0,0 +1,32 @@ +The Clear BSD License + +Copyright (c) 2022 CosmosKit Contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted (subject to the limitations in the disclaimer +below) provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY +THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/test/README.md b/packages/test/README.md new file mode 100644 index 000000000..4525096f7 --- /dev/null +++ b/packages/test/README.md @@ -0,0 +1,59 @@ +# cosmos-kit + +

+ +

+ +

+ + + + + + + + +

+ +CosmosKit is a wallet adapter for developers to build apps that quickly and easily interact with Cosmos blockchains and wallets. + +@cosmos-kit/react is the React integration for CosmosKit. + +## Documentation + +[docs.cosmology.zone/cosmos-kit](https://docs.cosmology.zone/cosmos-kit) + +## Installation + +```sh +yarn add @cosmos-kit/react @cosmos-kit/core @cosmos-kit/keplr chain-registry +``` + +## Provider + +- [ChainProvider](https://docs.cosmology.zone/cosmos-kit/provider/chain-provider) + +## Hooks + +- [useChain](https://docs.cosmology.zone/cosmos-kit/hooks/use-chain) + +## Related + +Checkout these related projects: + +* [@cosmwasm/ts-codegen](https://github.com/CosmWasm/ts-codegen) for generated CosmWasm contract Typescript classes +* [@cosmology/telescope](https://github.com/cosmology-tech/telescope) Your Frontend Companion for Building with TypeScript with Cosmos SDK Modules. +* [chain-registry](https://github.com/cosmology-tech/chain-registry) Get everything from token symbols, logos, and IBC denominations for all assets you want to support in your application. +* [cosmos-kit](https://github.com/cosmology-tech/cosmos-kit) Experience the convenience of connecting with a variety of web3 wallets through a single, streamlined interface ⚛️ +* [create-cosmos-app](https://github.com/cosmology-tech/create-cosmos-app) set up a modern Cosmos app by running one command. +* [starship](https://github.com/cosmology-tech/starship) a k8s-based unified development environment for Cosmos Ecosystem + +## Credits + +🛠 Built by Cosmology — if you like our tools, please consider delegating to [our validator ⚛️](https://cosmology.zone/validator) + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED “AS IS”, AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code or CLI, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. \ No newline at end of file diff --git a/packages/test/__tests__/cosmos-kit.test.ts b/packages/test/__tests__/cosmos-kit.test.ts new file mode 100644 index 000000000..da32c052e --- /dev/null +++ b/packages/test/__tests__/cosmos-kit.test.ts @@ -0,0 +1,12 @@ +import { MockWallet } from '../src/mocker'; + +describe('Wallet functionality', () => { + const wallet = new MockWallet(); + + it('should handle key retrieval', async () => { + const key = await wallet.getKey('cosmos'); + expect(key.bech32Address).toBe('cosmos1...'); + }); + + // Add more tests as needed +}); diff --git a/packages/test/index.ts b/packages/test/index.ts new file mode 100644 index 000000000..e31be21f6 --- /dev/null +++ b/packages/test/index.ts @@ -0,0 +1,2 @@ +// not for module, but for local development. +export * from './src'; diff --git a/packages/test/jest.config.js b/packages/test/jest.config.js new file mode 100644 index 000000000..49970653f --- /dev/null +++ b/packages/test/jest.config.js @@ -0,0 +1,19 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +const path = require('path'); +module.exports = { + preset: "ts-jest", + testEnvironment: "node", + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + babelConfig: false, + tsconfig: "tsconfig.json", + }, + ], + }, + transformIgnorePatterns: [`/node_modules/*`], + testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + modulePathIgnorePatterns: ["dist/*"] +}; diff --git a/packages/test/package.json b/packages/test/package.json new file mode 100644 index 000000000..223ce501b --- /dev/null +++ b/packages/test/package.json @@ -0,0 +1,83 @@ +{ + "name": "@cosmos-kit/test", + "version": "2.11.0", + "description": "cosmos-kit wallet connector", + "author": "developers@cosmology.zone", + "contributors": [ + { + "name": "Jun Liu" + }, + { + "name": "Dan Lynch" + }, + { + "name": "Noah Saso" + }, + { + "name": "Eliot Baker" + }, + { + "name": "Delivan Jeonghyeok Yoo" + } + ], + "homepage": "https://github.com/cosmology-tech/cosmos-kit#readme", + "license": "SEE LICENSE IN LICENSE", + "source": "./src/index.ts", + "main": "cjs/index.js", + "module": "esm/index.js", + "types": "cjs/index.d.ts", + "directories": { + "lib": "src", + "test": "__tests__" + }, + "files": [ + "cjs", + "esm", + "!CHANGELOG.md", + "!LICENSE" + ], + "scripts": { + "build:cjs": "yarn tsc -p tsconfig.json --outDir cjs --module commonjs || true", + "build:esm": "yarn tsc -p tsconfig.json --outDir esm --module es2022 || true", + "clean:cjs": "rimraf cjs", + "clean:esm": "rimraf esm", + "clean": "npm run clean:cjs && npm run clean:esm", + "build": "npm run clean && npm run build:cjs && npm run build:esm", + "prepare": "npm run build", + "lint": "eslint --ext .tsx,.ts .", + "format": "eslint --ext .tsx,.ts --fix .", + "test": "jest", + "test:watch": "jest --watch", + "test:debug": "node --inspect node_modules/.bin/jest --runInBand", + "clear": "rm -rf ./dist" + }, + "private": true, + "publishConfig": { + "access": "restricted" + }, + "repository": { + "type": "git", + "url": "https://github.com/cosmology-tech/cosmos-kit" + }, + "keywords": [ + "cosmos", + "cosmos-kit", + "cosmostation", + "leap", + "keplr", + "wallet" + ], + "bugs": { + "url": "https://github.com/cosmology-tech/cosmos-kit/issues" + }, + "dependencies": { + "@chain-registry/types": "^0.28.1", + "@cosmos-kit/core": "^2.9.0", + "chain-registry": "^1.45.1", + "@chain-registry/keplr": "1.28.0", + "@cosmjs/amino": "^0.32.3", + "@cosmjs/proto-signing": "^0.32.3", + "@keplr-wallet/types": "^0.12.58" + }, + "browserslist": "> 0.5%, last 2 versions, not dead" +} \ No newline at end of file diff --git a/packages/test/src/mock-extension/constant.ts b/packages/test/src/mock-extension/constant.ts new file mode 100644 index 000000000..88427e385 --- /dev/null +++ b/packages/test/src/mock-extension/constant.ts @@ -0,0 +1,2 @@ +export const ICON = + 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTY2IiBoZWlnaHQ9IjE2NiIgdmlld0JveD0iMCAwIDE2NiAxNjYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF83ODBfNjEwKSI+CjxyZWN0IHdpZHRoPSIxNjYiIGhlaWdodD0iMTY2IiBmaWxsPSIjQzVGRkNFIi8+CjxwYXRoIGQ9Ik0xMzguNjE0IDEwMC40NDVDMTM4LjYxNCAxMjAuMjE3IDExNC40ODMgMTI4LjI1MiA4NC41MjE2IDEyOC4yNTJDNTQuNTYwMyAxMjguMjUyIDMwLjA3ODQgMTIwLjIxNyAzMC4wNzg0IDEwMC40NDVDMzAuMDc4NCA4MC42NzI0IDU0LjM4NDYgNjQuNjczIDg0LjM0NiA2NC42NzNDMTE0LjMwNyA2NC42NzMgMTM4LjYxNCA4MC43MDc0IDEzOC42MTQgMTAwLjQ0NVoiIGZpbGw9IiMyNEE5NUEiLz4KPHBhdGggZD0iTTEzMy4xMDMgNTcuMzQ3MkMxMzMuMTAzIDQ2LjkzNyAxMjQuNjAzIDM4LjQ4MzIgMTE0LjEzNiAzOC40ODMyQzEwOC42OTMgMzguNDgzMiAxMDMuNzg3IDQwLjc3MTkgMTAwLjMzIDQ0LjQxNzFDOTkuNzk0NCA0NC45ODE4IDk5LjAxMTggNDUuMjU2OSA5OC4yNDkgNDUuMTAyOUM5My44NjkgNDQuMjE4NSA4OS4yMzU1IDQzLjcyMzIgODQuNDU1NSA0My43MjMyQzc5LjY3NiA0My43MjMyIDc1LjA0MyA0NC4xODkzIDcwLjY2MzQgNDUuMDk1QzY5Ljg5OTggNDUuMjUyOSA2OS4xMTM4IDQ0Ljk4MjMgNjguNTc1IDQ0LjQxODZDNjUuMDkgNDAuNzcyNSA2MC4xODY3IDM4LjQ4MzIgNTQuNzc1MiAzOC40ODMyQzQ0LjMwOCAzOC40ODMyIDM1LjgwNzkgNDYuOTM3IDM1LjgwNzkgNTcuMzQ3MkMzNS44MDc5IDYwLjM4MzQgMzYuNTI2MiA2My4yMjczIDM3Ljc5MTMgNjUuNzU3QzM4LjA5NDMgNjYuMzYyOCAzOC4xMjQ4IDY3LjA3MjEgMzcuODYyNyA2Ny42OTY2QzM2LjYzNTMgNzAuNjIxMiAzNS45ODM1IDczLjcwOTEgMzUuOTgzNSA3Ni45MDk4QzM1Ljk4MzUgOTUuMjQ5OCA1Ny42OTA1IDExMC4wOTYgODQuNDU1NSAxMTAuMDk2QzExMS4yMjEgMTEwLjA5NiAxMzIuOTI4IDk1LjI0OTggMTMyLjkyOCA3Ni45MDk4QzEzMi45MjggNzMuNzA5MSAxMzIuMjc2IDcwLjYyMTIgMTMxLjA0OCA2Ny42OTY2QzEzMC43ODYgNjcuMDcyMSAxMzAuODE3IDY2LjM2MjggMTMxLjEyIDY1Ljc1N0MxMzIuMzg1IDYzLjIyNzMgMTMzLjEwMyA2MC4zODM0IDEzMy4xMDMgNTcuMzQ3MloiIGZpbGw9IiMzMkRBNkQiLz4KPHBhdGggZD0iTTUzLjIyNzEgNjcuODExOUM1OS42Mjg3IDY3LjgxMTkgNjQuODE4MyA2Mi42NTA2IDY0LjgxODMgNTYuMjgzOUM2NC44MTgzIDQ5LjkxNzEgNTkuNjI4NyA0NC43NTU5IDUzLjIyNzEgNDQuNzU1OUM0Ni44MjU1IDQ0Ljc1NTkgNDEuNjM2IDQ5LjkxNzEgNDEuNjM2IDU2LjI4MzlDNDEuNjM2IDYyLjY1MDYgNDYuODI1NSA2Ny44MTE5IDUzLjIyNzEgNjcuODExOVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik0xMTUuMDY1IDY3LjgxMTlDMTIxLjQ2NiA2Ny44MTE5IDEyNi42NTYgNjIuNjUwNiAxMjYuNjU2IDU2LjI4MzlDMTI2LjY1NiA0OS45MTcxIDEyMS40NjYgNDQuNzU1OSAxMTUuMDY1IDQ0Ljc1NTlDMTA4LjY2MyA0NC43NTU5IDEwMy40NzQgNDkuOTE3MSAxMDMuNDc0IDU2LjI4MzlDMTAzLjQ3NCA2Mi42NTA2IDEwOC42NjMgNjcuODExOSAxMTUuMDY1IDY3LjgxMTlaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNDcuMDc1OSAxMjYuODI5QzQ5LjU2OTggMTI2LjgyOSA1MS41MzY4IDEyNC42NjMgNTEuMjU1OCAxMjIuMjE4QzUwLjIzNzIgMTEzLjU1NCA0NS45MTY4IDk0Ljc5NSAyNi45MTQ0IDgzLjUxMTVDNi4wODM2OCA3MS4xMzg3IDE1Ljk5NDEgMTA0LjAzNCAyMC4xMzY1IDExNi4wMTlDMjAuOTc0NCAxMTguNDQzIDIwLjAwMjcgMTIxLjEzNSAxNy43NzgzIDEyMi40MTFMMTYuNDEyMSAxMjMuMTk2QzE0LjY1NTkgMTI0LjIwOSAxNS4zOTM1IDEyNi44MjkgMTcuMzk1NiAxMjYuODI5SDQ3LjA3NTlaIiBmaWxsPSIjMzJEQTZEIi8+CjxwYXRoIGQ9Ik0xMjIuNTY2IDEyNi44MjlDMTIwLjMxOCAxMjYuODI5IDExOC41NjIgMTI0LjY2MyAxMTguODA4IDEyMi4yMThDMTE5LjY4NiAxMTMuNTg5IDEyMy42MiA5NC43OTUgMTQwLjc2MSA4My41MTE1QzE1OS43NDEgNzEuMDQyNiAxNTAuNTAzIDEwNC41NDcgMTQ2LjgxNSAxMTYuMjk0QzE0Ni4wOTIgMTE4LjU5OCAxNDYuOTgyIDEyMS4xMDYgMTQ5LjAyMiAxMjIuMzk5TDE1MC4yOCAxMjMuMTk2QzE1MS44NiAxMjQuMjA5IDE1MS4xOTMgMTI2LjgyOSAxNDkuNDAyIDEyNi44MjlIMTIyLjU2NloiIGZpbGw9IiMzMkRBNkQiLz4KPHBhdGggZD0iTTUzLjI0MjggNjMuMTc4N0M1Ny4wNjE3IDYzLjE3ODcgNjAuMTU3NiA2MC4wODI4IDYwLjE1NzYgNTYuMjYzOUM2MC4xNTc2IDUyLjQ0NSA1Ny4wNjE3IDQ5LjM0OTEgNTMuMjQyOCA0OS4zNDkxQzQ5LjQyMzkgNDkuMzQ5MSA0Ni4zMjggNTIuNDQ1IDQ2LjMyOCA1Ni4yNjM5QzQ2LjMyOCA2MC4wODI4IDQ5LjQyMzkgNjMuMTc4NyA1My4yNDI4IDYzLjE3ODdaIiBmaWxsPSIjMDkyNTExIi8+CjxwYXRoIGQ9Ik0xMTUuMDgxIDYzLjE3ODdDMTE4LjkgNjMuMTc4NyAxMjEuOTk1IDYwLjA4MjggMTIxLjk5NSA1Ni4yNjM5QzEyMS45OTUgNTIuNDQ1IDExOC45IDQ5LjM0OTEgMTE1LjA4MSA0OS4zNDkxQzExMS4yNjIgNDkuMzQ5MSAxMDguMTY2IDUyLjQ0NSAxMDguMTY2IDU2LjI2MzlDMTA4LjE2NiA2MC4wODI4IDExMS4yNjIgNjMuMTc4NyAxMTUuMDgxIDYzLjE3ODdaIiBmaWxsPSIjMDkyNTExIi8+CjxwYXRoIGQ9Ik05OS43OTk1IDgzLjAxNzZDMTAxLjUxNCA4My4xNjUxIDEwMi44MSA4NC42ODYyIDEwMi4zNzggODYuMzUxOEMxMDIuMDI5IDg3LjY5NzkgMTAxLjUyOSA4OS4wMDM5IDEwMC44ODYgOTAuMjQ0MkM5OS43NjMgOTIuNDA5IDk4LjIyNDYgOTQuMzMxNSA5Ni4zNTg2IDk1LjkwMThDOTQuNDkyNyA5Ny40NzIyIDkyLjMzNTcgOTguNjU5NiA5MC4wMTA4IDk5LjM5NjNDODcuNjg2IDEwMC4xMzMgODUuMjM4OCAxMDAuNDA1IDgyLjgwOSAxMDAuMTk2QzgwLjM3OTEgOTkuOTg2NiA3OC4wMTQzIDk5LjMwMSA3NS44NDk0IDk4LjE3OEM3My42ODQ2IDk3LjA1NTEgNzEuNzYyMSA5NS41MTY3IDcwLjE5MTcgOTMuNjUwN0M2OC42MjE0IDkxLjc4NDggNjcuNDM0IDg5LjYyNzggNjYuNjk3MiA4Ny4zMDI5QzY2LjE3MDEgODUuNjM5NiA2NS44ODExIDgzLjkxMzUgNjUuODM1OSA4Mi4xNzYxQzY1LjgwNiA4MS4wMjk0IDY2LjgyNDQgODAuMTgwOCA2Ny45NjczIDgwLjI3OTFMODQuNDAwNyA4MS42OTI4TDk5Ljc5OTUgODMuMDE3NloiIGZpbGw9IiMwOTI1MTEiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF83ODBfNjEwIj4KPHJlY3Qgd2lkdGg9IjE2NiIgaGVpZ2h0PSIxNjYiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg=='; diff --git a/packages/test/src/mock-extension/extension/chain-wallet.ts b/packages/test/src/mock-extension/extension/chain-wallet.ts new file mode 100644 index 000000000..a1c89a018 --- /dev/null +++ b/packages/test/src/mock-extension/extension/chain-wallet.ts @@ -0,0 +1,7 @@ +import { ChainRecord, ChainWalletBase, Wallet } from '@cosmos-kit/core'; + +export class ChainMockExtension extends ChainWalletBase { + constructor(walletInfo: Wallet, chainInfo: ChainRecord) { + super(walletInfo, chainInfo); + } +} diff --git a/packages/test/src/mock-extension/extension/client.ts b/packages/test/src/mock-extension/extension/client.ts new file mode 100644 index 000000000..c957c6ae5 --- /dev/null +++ b/packages/test/src/mock-extension/extension/client.ts @@ -0,0 +1,154 @@ +import { chainRegistryChainToKeplr } from '@chain-registry/keplr'; +import { StdSignature, StdSignDoc } from '@cosmjs/amino'; +import { Algo, OfflineDirectSigner } from '@cosmjs/proto-signing'; +import { + BroadcastMode, + ChainRecord, + ExtendedHttpEndpoint, + SignType, + SuggestToken, +} from '@cosmos-kit/core'; +import { DirectSignDoc, SignOptions, WalletClient } from '@cosmos-kit/core'; +import Long from 'long'; + +import { Mock } from './types'; + +export class MockClient implements WalletClient { + readonly client: Mock; + private _defaultSignOptions: SignOptions = { + preferNoSetFee: false, + preferNoSetMemo: true, + disableBalanceCheck: true, + }; + + get defaultSignOptions() { + return this._defaultSignOptions; + } + + setDefaultSignOptions(options: SignOptions) { + this._defaultSignOptions = options; + } + + constructor(client: Mock) { + this.client = client; + } + + async enable(chainIds: string | string[]) { + await this.client.enable(chainIds); + } + + async suggestToken({ chainId, tokens, type }: SuggestToken) { + if (type === 'cw20') { + for (const { contractAddress } of tokens) { + await this.client.suggestCW20Token(chainId, contractAddress); + } + } + } + + async addChain(chainInfo: ChainRecord) { + const suggestChain = chainRegistryChainToKeplr( + chainInfo.chain, + chainInfo.assetList ? [chainInfo.assetList] : [] + ); + + if (chainInfo.preferredEndpoints?.rest?.[0]) { + (suggestChain.rest as string | ExtendedHttpEndpoint) = + chainInfo.preferredEndpoints?.rest?.[0]; + } + + if (chainInfo.preferredEndpoints?.rpc?.[0]) { + (suggestChain.rpc as string | ExtendedHttpEndpoint) = + chainInfo.preferredEndpoints?.rpc?.[0]; + } + + await this.client.experimentalSuggestChain(suggestChain); + } + + async disconnect() { + await this.client.disconnect(); + } + + async getSimpleAccount(chainId: string) { + const { address, username } = await this.getAccount(chainId); + return { + namespace: 'cosmos', + chainId, + address, + username, + }; + } + + async getAccount(chainId: string) { + const key = await this.client.getKey(chainId); + return { + username: key.name, + address: key.bech32Address, + algo: key.algo as Algo, + pubkey: key.pubKey, + isNanoLedger: key.isNanoLedger, + }; + } + + getOfflineSigner(chainId: string, preferredSignType?: SignType) { + switch (preferredSignType) { + case 'amino': + return this.getOfflineSignerAmino(chainId); + case 'direct': + return this.getOfflineSignerDirect(chainId); + default: + return this.getOfflineSignerAmino(chainId); + } + // return this.client.getOfflineSignerAuto(chainId); + } + + getOfflineSignerAmino(chainId: string) { + return this.client.getOfflineSignerOnlyAmino(chainId); + } + + getOfflineSignerDirect(chainId: string) { + return this.client.getOfflineSigner(chainId) as OfflineDirectSigner; + } + + async signAmino( + chainId: string, + signer: string, + signDoc: StdSignDoc, + signOptions?: SignOptions + ) { + return await this.client.signAmino( + chainId, + signer, + signDoc, + signOptions || this.defaultSignOptions + ); + } + + async signArbitrary( + chainId: string, + signer: string, + data: string | Uint8Array + ): Promise { + return await this.client.signArbitrary(chainId, signer, data); + } + + async signDirect( + chainId: string, + signer: string, + signDoc: DirectSignDoc, + signOptions?: SignOptions + ) { + return await this.client.signDirect( + chainId, + signer, + { + ...signDoc, + accountNumber: Long.fromString(signDoc.accountNumber.toString()), + }, + signOptions || this.defaultSignOptions + ); + } + + async sendTx(chainId: string, tx: Uint8Array, mode: BroadcastMode) { + return await this.client.sendTx(chainId, tx, mode); + } +} diff --git a/packages/test/src/mock-extension/extension/index.ts b/packages/test/src/mock-extension/extension/index.ts new file mode 100644 index 000000000..f488a5ae7 --- /dev/null +++ b/packages/test/src/mock-extension/extension/index.ts @@ -0,0 +1,4 @@ +export * from './chain-wallet'; +export * from './main-wallet'; +export * from './registry'; +export * from './types'; diff --git a/packages/test/src/mock-extension/extension/main-wallet.ts b/packages/test/src/mock-extension/extension/main-wallet.ts new file mode 100644 index 000000000..61edb4317 --- /dev/null +++ b/packages/test/src/mock-extension/extension/main-wallet.ts @@ -0,0 +1,22 @@ +import { Wallet } from '@cosmos-kit/core'; +import { MainWalletBase } from '@cosmos-kit/core'; + +import { ChainMockExtension } from './chain-wallet'; +import { MockClient } from './client'; +import { getMockFromExtension } from './utils'; + +export class MockExtensionWallet extends MainWalletBase { + constructor(walletInfo: Wallet) { + super(walletInfo, ChainMockExtension); + } + + async initClient() { + this.initingClient(); + try { + const mock = await getMockFromExtension(); + this.initClientDone(mock ? new MockClient(mock) : undefined); + } catch (error) { + this.initClientError(error); + } + } +} diff --git a/packages/test/src/mock-extension/extension/registry.ts b/packages/test/src/mock-extension/extension/registry.ts new file mode 100644 index 000000000..043c5b2c5 --- /dev/null +++ b/packages/test/src/mock-extension/extension/registry.ts @@ -0,0 +1,25 @@ +import { Wallet } from '@cosmos-kit/core'; + +import { ICON } from '../constant'; + +export const mockExtensionInfo: Wallet = { + name: 'mock-extension', + prettyName: 'Mock', + logo: ICON, + mode: 'extension', + mobileDisabled: () => true, + rejectMessage: { + source: 'Request rejected', + }, + connectEventNamesOnWindow: ['mock_keystorechange'], + downloads: [ + { + device: 'desktop', + browser: 'chrome', + link: 'https://chrome.google.com/webstore/detail/mock-cosmos-wallet/fcfcfllfndlomdhbehjjcoimbgofdncg', + }, + { + link: 'https://chrome.google.com/webstore/detail/mock-cosmos-wallet/fcfcfllfndlomdhbehjjcoimbgofdncg', + }, + ], +}; diff --git a/packages/test/src/mock-extension/extension/types.ts b/packages/test/src/mock-extension/extension/types.ts new file mode 100644 index 000000000..ad2098f5b --- /dev/null +++ b/packages/test/src/mock-extension/extension/types.ts @@ -0,0 +1,86 @@ +import { + AminoSignResponse, + OfflineAminoSigner, + StdSignature, + StdSignDoc, +} from '@cosmjs/amino'; +import { OfflineDirectSigner, OfflineSigner } from '@cosmjs/proto-signing'; +import { DirectSignResponse } from '@cosmjs/proto-signing'; +import { BroadcastMode } from '@cosmos-kit/core'; +import type { ChainInfo } from '@keplr-wallet/types'; + +export interface Key { + readonly name: string; + readonly algo: string; + readonly pubKey: Uint8Array; + readonly address: Uint8Array; + readonly bech32Address: string; + readonly isNanoLedger: boolean; +} +export interface MockSignOptions { + readonly preferNoSetFee?: boolean; + readonly preferNoSetMemo?: boolean; + readonly disableBalanceCheck?: boolean; +} + +export interface Mock { + defaultOptions: { + sign?: MockSignOptions; + }; + disconnect(): Promise; + enable(chainIds: string | string[]): Promise; + suggestToken(chainId: string, contractAddress: string): Promise; + suggestCW20Token(chainId: string, contractAddress: string): Promise; + mode: 'extension'; + getKey(chainId: string): Promise; + getOfflineSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner; + getOfflineSignerOnlyAmino(chainId: string): OfflineAminoSigner; + getOfflineSignerAuto(chainId: string): Promise; + signAmino( + chainId: string, + signer: string, + signDoc: StdSignDoc, + signOptions?: MockSignOptions + ): Promise; + signDirect( + chainId: string, + signer: string, + signDoc: { + /** SignDoc bodyBytes */ + bodyBytes?: Uint8Array | null; + /** SignDoc authInfoBytes */ + authInfoBytes?: Uint8Array | null; + /** SignDoc chainId */ + chainId?: string | null; + /** SignDoc accountNumber */ + accountNumber?: Long | null; + }, + signOptions?: MockSignOptions + ): Promise; + signArbitrary( + chainId: string, + signer: string, + data: string | Uint8Array + ): Promise; + getEnigmaPubKey(chainId: string): Promise; + getEnigmaTxEncryptionKey( + chainId: string, + nonce: Uint8Array + ): Promise; + enigmaEncrypt( + chainId: string, + contractCodeHash: string, + msg: object + ): Promise; + enigmaDecrypt( + chainId: string, + ciphertext: Uint8Array, + nonce: Uint8Array + ): Promise; + sendTx( + chainId: string, + tx: Uint8Array, + mode: BroadcastMode + ): Promise; + experimentalSuggestChain(chainInfo: ChainInfo): Promise; +} diff --git a/packages/test/src/mock-extension/extension/utils.ts b/packages/test/src/mock-extension/extension/utils.ts new file mode 100644 index 000000000..44ec2fac1 --- /dev/null +++ b/packages/test/src/mock-extension/extension/utils.ts @@ -0,0 +1,47 @@ +import { ClientNotExistError } from '@cosmos-kit/core'; + +import { Mock } from './types'; + +interface MockWindow { + mock?: Mock; +} + +export const getMockFromExtension: () => Promise< + Mock | undefined +> = async () => { + if (typeof window === 'undefined') { + return void 0; + } + + const mock = (window as MockWindow).mock; + + if (mock) { + return mock; + } + + if (document.readyState === 'complete') { + if (mock) { + return mock; + } else { + throw ClientNotExistError; + } + } + + return new Promise((resolve, reject) => { + const documentStateChange = (event: Event) => { + if ( + event.target && + (event.target as Document).readyState === 'complete' + ) { + if (mock) { + resolve(mock); + } else { + reject(ClientNotExistError.message); + } + document.removeEventListener('readystatechange', documentStateChange); + } + }; + + document.addEventListener('readystatechange', documentStateChange); + }); +}; diff --git a/packages/test/src/mock-extension/index.ts b/packages/test/src/mock-extension/index.ts new file mode 100644 index 000000000..478131c10 --- /dev/null +++ b/packages/test/src/mock-extension/index.ts @@ -0,0 +1,2 @@ +export * from './extension'; +export * from './mock'; diff --git a/packages/test/src/mock-extension/mock.ts b/packages/test/src/mock-extension/mock.ts new file mode 100644 index 000000000..ba15321a6 --- /dev/null +++ b/packages/test/src/mock-extension/mock.ts @@ -0,0 +1,5 @@ +import { mockExtensionInfo, MockExtensionWallet } from './extension'; + +const mockExtension = new MockExtensionWallet(mockExtensionInfo); + +export const wallets = [mockExtension]; diff --git a/packages/test/src/mocker/index.ts b/packages/test/src/mocker/index.ts new file mode 100644 index 000000000..b35b8b5b6 --- /dev/null +++ b/packages/test/src/mocker/index.ts @@ -0,0 +1,156 @@ +// @ts-nocheck +import { + AminoSignResponse, + OfflineAminoSigner, + StdSignature, + StdSignDoc, +} from '@cosmjs/amino'; +import { OfflineDirectSigner, OfflineSigner } from '@cosmjs/proto-signing'; +import { DirectSignResponse } from '@cosmjs/proto-signing'; +import { BroadcastMode } from '@cosmos-kit/core'; +import Long from 'long'; + +import { Key, Mock, MockSignOptions } from '../mock-extension/extension/types'; + +export class MockWallet implements Mock { + defaultOptions = { + sign: { + preferNoSetFee: false, + preferNoSetMemo: false, + disableBalanceCheck: false, + }, + }; + + mode = 'extension' as const; + + async disconnect(): Promise { + // Simulate disconnect logic + } + + async enable(chainIds: string | string[]): Promise { + // Simulate enabling logic + } + + async suggestToken(chainId: string, contractAddress: string): Promise { + // Simulate suggesting a token + } + + async suggestCW20Token( + chainId: string, + contractAddress: string + ): Promise { + // Simulate suggesting a CW20 token + } + + async getKey(chainId: string): Promise { + return { + name: 'Test Key', + algo: 'secp256k1', + pubKey: new Uint8Array(), + address: new Uint8Array(), + bech32Address: 'cosmos1...', + isNanoLedger: false, + }; + } + + async getOfflineSigner( + chainId: string + ): Promise { + return { + // Implement Offline Signer logic as needed + } as OfflineAminoSigner & OfflineDirectSigner; + } + + async getOfflineSignerOnlyAmino( + chainId: string + ): Promise { + return { + // Implement Offline Amino Signer logic as needed + } as OfflineAminoSigner; + } + + async getOfflineSignerAuto(chainId: string): Promise { + return { + // Implement Auto Signer logic as needed + } as OfflineSigner; + } + + async signAmino( + chainId: string, + signer: string, + signDoc: StdSignDoc, + signOptions?: MockSignOptions + ): Promise { + return { + signed: signDoc, + signature: new Uint8Array(), + }; + } + + async signDirect( + chainId: string, + signer: string, + signDoc: { + bodyBytes?: Uint8Array | null; + authInfoBytes?: Uint8Array | null; + chainId?: string | null; + accountNumber?: Long | null; + }, + signOptions?: MockSignOptions + ): Promise { + return { + signed: signDoc, + signature: new Uint8Array(), + }; + } + + async signArbitrary( + chainId: string, + signer: string, + data: string | Uint8Array + ): Promise { + return { + pubKey: new Uint8Array(), + signature: new Uint8Array(), + }; + } + + async getEnigmaPubKey(chainId: string): Promise { + return new Uint8Array(); + } + + async getEnigmaTxEncryptionKey( + chainId: string, + nonce: Uint8Array + ): Promise { + return new Uint8Array(); + } + + async enigmaEncrypt( + chainId: string, + contractCodeHash: string, + msg: object + ): Promise { + return new Uint8Array(); + } + + async enigmaDecrypt( + chainId: string, + ciphertext: Uint8Array, + nonce: Uint8Array + ): Promise { + return new Uint8Array(); + } + + async sendTx( + chainId: string, + tx: Uint8Array, + mode: BroadcastMode + ): Promise { + return new Uint8Array(); + } + + async experimentalSuggestChain(chainInfo: ChainInfo): Promise { + // Simulate suggesting a chain + } +} diff --git a/packages/test/tsconfig.json b/packages/test/tsconfig.json new file mode 100644 index 000000000..12107ca6b --- /dev/null +++ b/packages/test/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "rootDir": "src", + "jsx": "react-jsx", + "skipLibCheck": true, + "emitDeclarationOnly": false, + "declaration": true, + "esModuleInterop": true, + "target": "es2022", + "module": "es2022", + "lib": [ + "es2022", + "DOM" + ], + "sourceMap": false, + "isolatedModules": false, + "downlevelIteration": true, + "moduleResolution": "node", + "resolveJsonModule": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 8fecbe0a4..572ed0f7e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1208,6 +1208,11 @@ dependencies: "@babel/runtime" "^7.21.0" +"@chain-registry/types@^0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@chain-registry/types/-/types-0.28.1.tgz#953317ab3d1608fb68fc58ba2d91a58582043ee8" + integrity sha512-Xr9CCR2n5EU02b0Aw4Uh72WEsFKThx5QrVIgzc54uFHn/wxnyXvFdYWak7UwJuhhk6SbYT17GH8cfPBO/MID0g== + "@chain-registry/utils@^1.15.0", "@chain-registry/utils@^1.19.11": version "1.19.11" resolved "https://registry.yarnpkg.com/@chain-registry/utils/-/utils-1.19.11.tgz#1175dd32e297d1e2b07de940ad9ed2abf69bddbe" @@ -2771,6 +2776,16 @@ "@babel/runtime" "^7.21.0" axios "0.27.2" +"@cosmos-kit/leap-metamask-cosmos-snap@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@cosmos-kit/leap-metamask-cosmos-snap/-/leap-metamask-cosmos-snap-0.6.2.tgz#951d3934c781a8135247e5270bdb52a5fb6be311" + integrity sha512-47Kq0ZrXNinbTfNH0i0GtxdfIDkq7iaixLQ5p9qc56CtiqBtT4bSrZoYqUl3nlM7iFKTtrb7FdCPkAVkWpYUew== + dependencies: + "@chain-registry/keplr" "1.28.0" + "@cosmos-kit/core" "^2.8.9" + "@leapwallet/cosmos-snap-provider" "0.1.25" + "@metamask/providers" "^11.1.1" + "@cosmos-kit/leap@latest": version "2.6.12" resolved "https://registry.yarnpkg.com/@cosmos-kit/leap/-/leap-2.6.12.tgz#769bbb2426049bfa8d4b71e3aa1f8d4ae1b1aba1" @@ -3727,7 +3742,7 @@ jest-util "^29.7.0" slash "^3.0.0" -"@jest/core@^29.0.3", "@jest/core@^29.7.0": +"@jest/core@^29.7.0": version "29.7.0" resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== @@ -3895,7 +3910,7 @@ slash "^3.0.0" write-file-atomic "^4.0.2" -"@jest/types@^29.0.3", "@jest/types@^29.6.3": +"@jest/types@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== @@ -7434,10 +7449,10 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@29.0.3": - version "29.0.3" - resolved "https://registry.npmjs.org/@types/jest/-/jest-29.0.3.tgz" - integrity sha512-F6ukyCTwbfsEX5F2YmVYmM5TcTHy1q9P5rWlRbrk56KyMh3v9xRGUO3aa8+SkvMi0SHXtASJv1283enXimC0Og== +"@types/jest@^29.5.11": + version "29.5.12" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" + integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== dependencies: expect "^29.0.0" pretty-format "^29.0.0" @@ -8519,16 +8534,6 @@ ansi-colors@^4.1.1: resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -ansi-escapes@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz" - integrity sha512-tH/fSoQp4DrEodDK3QpdiWiZTSe7sBJ9eOqcQBZ0o9HTM+5M/viSEn+sPMoTuPjQQ8n++w3QJoPEjt8LVPcrCg== - -ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" @@ -8536,21 +8541,6 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.21.3" -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" - integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== - -ansi-regex@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz" - integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" @@ -8566,11 +8556,6 @@ ansi-sequence-parser@^1.1.0: resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" - integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== - ansi-styles@^3.1.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" @@ -9394,6 +9379,13 @@ chain-registry@^1.23.0: "@babel/runtime" "^7.21.0" "@chain-registry/types" "^0.18.12" +chain-registry@^1.45.1: + version "1.45.1" + resolved "https://registry.yarnpkg.com/chain-registry/-/chain-registry-1.45.1.tgz#a2b2eca835d6df6aeecf0c1198bcfed5ad0f874e" + integrity sha512-pgU21rxSu4oonNVeu8iXiKyYoxjC1Q8OmpycL6xbnPV9zGT8NK2IMpt1rWNW0QEZJ0zMWr+P32pyZ7DAYicdFA== + dependencies: + "@chain-registry/types" "^0.28.1" + chalk@2.3.0: version "2.3.0" resolved "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz" @@ -9416,17 +9408,6 @@ chalk@5.2.0: resolved "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz" integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== -chalk@^1.0.0, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" - integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" @@ -9474,11 +9455,6 @@ character-reference-invalid@^2.0.0: resolved "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz" integrity sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw== -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz" - integrity sha512-j/Toj7f1z98Hh2cYo2BVr85EpIRWqUi7rtRSGxh/cqUjqrnJe9l9UE7IUGd2vQ2p+kSHLkSzObQPZPLUC6TQwg== - chardet@^0.7.0: version "0.7.0" resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz" @@ -9553,13 +9529,6 @@ cli-cursor@3.1.0, cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz" - integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== - dependencies: - restore-cursor "^2.0.0" - cli-cursor@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz" @@ -9577,11 +9546,6 @@ cli-spinners@^2.5.0, cli-spinners@^2.6.1: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== -cli-width@^2.0.0: - version "2.2.1" - resolved "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz" - integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== - cli-width@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz" @@ -9714,11 +9678,6 @@ color2k@^2.0.2: resolved "https://registry.yarnpkg.com/color2k/-/color2k-2.0.3.tgz#a771244f6b6285541c82aa65ff0a0c624046e533" integrity sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog== -colors@^1.1.2: - version "1.4.0" - resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - columnify@1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz" @@ -10942,7 +10901,7 @@ escalade@^3.1.1: resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -11494,15 +11453,6 @@ extension-port-stream@^2.1.1: dependencies: webextension-polyfill ">=0.10.0 <1.0" -external-editor@^2.0.4: - version "2.2.0" - resolved "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== - dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" - tmp "^0.0.33" - external-editor@^3.0.3: version "3.1.0" resolved "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz" @@ -11599,13 +11549,6 @@ figures@3.2.0, figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz" - integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== - dependencies: - escape-string-regexp "^1.0.5" - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" @@ -11819,11 +11762,6 @@ function-bind@^1.1.2: resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -fuzzy@^0.1.3: - version "0.1.3" - resolved "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz" - integrity sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w== - gauge@^4.0.3: version "4.0.4" resolved "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz" @@ -11992,7 +11930,7 @@ glob@7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^10.2.2, glob@^10.3.10, glob@^10.3.3, glob@^10.3.7: +glob@^10.2.2, glob@^10.3.10: version "10.3.12" resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" integrity sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg== @@ -12155,13 +12093,6 @@ hard-rejection@^2.1.0: resolved "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz" integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" - integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== - dependencies: - ansi-regex "^2.0.0" - has-flag@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz" @@ -12518,7 +12449,7 @@ iconv-lite@0.6, iconv-lite@^0.6.2: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -iconv-lite@^0.4.17, iconv-lite@^0.4.24: +iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -12603,11 +12534,6 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== - ini@^1.3.2, ini@^1.3.8: version "1.3.8" resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" @@ -12631,58 +12557,6 @@ inline-style-parser@0.1.1: resolved "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== -inquirer-autocomplete-prompt@^0.11.1: - version "0.11.1" - resolved "https://registry.npmjs.org/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-0.11.1.tgz" - integrity sha512-VM4eNiyRD4CeUc2cyKni+F8qgHwL9WC4LdOr+mEC85qP/QNsDV+ysVqUrJYhw1TmDQu1QVhc8hbaL7wfk8SJxw== - dependencies: - ansi-escapes "^2.0.0" - chalk "^1.1.3" - figures "^2.0.0" - inquirer "3.1.1" - lodash "^4.17.4" - run-async "^2.3.0" - util "^0.10.3" - -inquirer@3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/inquirer/-/inquirer-3.1.1.tgz" - integrity sha512-H50sHQwgvvaTBd3HpKMVtL/u6LoHDvYym51gd7bGQe/+9HkCE+J0/3N5FJLfd6O6oz44hHewC2Pc2LodzWVafQ== - dependencies: - ansi-escapes "^2.0.0" - chalk "^1.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.4" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx-lite "^4.0.8" - rx-lite-aggregates "^4.0.8" - string-width "^2.0.0" - strip-ansi "^3.0.0" - through "^2.3.6" - -inquirer@^6.0.0: - version "6.5.2" - resolved "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz" - integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.12" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - inquirer@^8.2.4: version "8.2.6" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" @@ -12704,15 +12578,6 @@ inquirer@^8.2.4: through "^2.3.6" wrap-ansi "^6.0.1" -inquirerer@^0.1.3: - version "0.1.3" - resolved "https://registry.npmjs.org/inquirerer/-/inquirerer-0.1.3.tgz" - integrity sha512-yGgLUOqPxTsINBjZNZeLi3cv2zgxXtw9feaAOSJf2j6AqIT5Uxs5ZOqOrfAf+xP65Sicla1FD3iDxa3D6TsCAQ== - dependencies: - colors "^1.1.2" - inquirer "^6.0.0" - inquirer-autocomplete-prompt "^0.11.1" - "internmap@1 - 2": version "2.0.3" resolved "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz" @@ -12842,11 +12707,6 @@ is-extglob@^2.1.1: resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" @@ -13210,7 +13070,7 @@ jest-circus@^29.7.0: slash "^3.0.0" stack-utils "^2.0.3" -jest-cli@^29.0.3: +jest-cli@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== @@ -13319,11 +13179,6 @@ jest-haste-map@^29.7.0: optionalDependencies: fsevents "^2.3.2" -jest-in-case@1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/jest-in-case/-/jest-in-case-1.0.2.tgz" - integrity sha512-2DE6Gdwnh5jkCYTePWoQinF+zne3lCADibXoYJEt8PS84JaRug0CyAOrEgzMxbzln3YcSY2PBeru7ct4tbflYA== - jest-leak-detector@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" @@ -13528,15 +13383,15 @@ jest-worker@^29.7.0: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@29.0.3: - version "29.0.3" - resolved "https://registry.npmjs.org/jest/-/jest-29.0.3.tgz" - integrity sha512-ElgUtJBLgXM1E8L6K1RW1T96R897YY/3lRYqq9uVcPWtP2AAl/nQ16IYDh/FzQOOQ12VEuLdcPU83mbhG2C3PQ== +jest@^29.6.2: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== dependencies: - "@jest/core" "^29.0.3" - "@jest/types" "^29.0.3" + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" import-local "^3.0.2" - jest-cli "^29.0.3" + jest-cli "^29.7.0" jiti@^1.18.2, jiti@^1.21.0: version "1.21.0" @@ -13665,7 +13520,7 @@ json-stringify-safe@^5.0.1: resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json5@^2.2.1, json5@^2.2.2, json5@^2.2.3: +json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -14167,7 +14022,7 @@ lodash.mergewith@4.6.2: resolved "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz" integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== -lodash@^4.17.12, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.3.0: +lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -15106,11 +14961,6 @@ mime@^3.0.0: resolved "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz" integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" @@ -15199,7 +15049,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8: +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -15302,11 +15152,6 @@ mkdirp@^2.1.6: resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz" integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== -mkdirp@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz" - integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== - mlly@^1.2.0, mlly@^1.6.1: version "1.6.1" resolved "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz" @@ -15380,11 +15225,6 @@ multimatch@5.0.0: arrify "^2.0.1" minimatch "^3.0.4" -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz" - integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== - mute-stream@0.0.8: version "0.0.8" resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" @@ -15956,13 +15796,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz" - integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== - dependencies: - mimic-fn "^1.0.0" - onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" @@ -16727,19 +16560,6 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" -publish-scripts@0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/publish-scripts/-/publish-scripts-0.1.0.tgz" - integrity sha512-cF4AYXPUKbU6Cw1PWY4b1CCl0+tsM13WdppqoBbD37lNvXf8vX6jgie/JDLH3jlSHDNCYuOolqLVMmdNlWWRjQ== - dependencies: - "@babel/runtime" "^7.19.0" - fuzzy "^0.1.3" - glob "^10.3.3" - inquirerer "^0.1.3" - minimist "^1.2.8" - mkdirp "^3.0.1" - rimraf "^5.0.1" - pump@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" @@ -17424,14 +17244,6 @@ resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20 path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz" - integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" @@ -17472,13 +17284,6 @@ rimraf@^4.4.1: dependencies: glob "^9.2.0" -rimraf@^5.0.1: - version "5.0.5" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.5.tgz#9be65d2d6e683447d2e9013da2bf451139a61ccf" - integrity sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A== - dependencies: - glob "^10.3.7" - ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz" @@ -17536,7 +17341,7 @@ rpc-websockets@^7.5.1: bufferutil "^4.0.1" utf-8-validate "^5.0.2" -run-async@^2.2.0, run-async@^2.3.0, run-async@^2.4.0: +run-async@^2.4.0: version "2.4.1" resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== @@ -17553,19 +17358,7 @@ rw@1: resolved "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz" integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz" - integrity sha512-3xPNZGW93oCjiO7PtKxRK6iOVYBWBvtf9QHDfU23Oc+dLIQmAV//UnyXV/yihv81VS/UqoQPk4NegS8EFi55Hg== - dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz" - integrity sha512-Cun9QucwK6MIrp3mry/Y7hqD1oFqTYLQ4pGxaHTjIdaFDWRGGLikqp6u8LcWJnzpoALg9hap+JGk8sFIUuEGNA== - -rxjs@^6.4.0, rxjs@^6.6.3: +rxjs@^6.6.3: version "6.6.7" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== @@ -17664,18 +17457,18 @@ semver@7.5.3: dependencies: lru-cache "^6.0.0" -semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: +semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.4" resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - semver@^7.5.0, semver@^7.5.4: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" @@ -18091,14 +17884,6 @@ string-length@^4.0.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^2.0.0, string-width@^2.1.0: - version "2.1.1" - resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" @@ -18137,27 +17922,6 @@ stringify-entities@^4.0.0: dependencies: ansi-regex "^5.0.1" -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" - integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.1.0: - version "5.2.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" @@ -18270,11 +18034,6 @@ superstruct@^1.0.3: resolved "https://registry.npmjs.org/superstruct/-/superstruct-1.0.3.tgz" integrity sha512-8iTn3oSS8nRGn+C2pgXSKPI3jmpm6FExNazNpjvqS6ZUJQCej3PUXEKM8NjHBOs54ExM+LPW/FBRhymrdcCiSg== -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" - integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== - supports-color@^4.0.0: version "4.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz" @@ -18590,18 +18349,18 @@ ts-interface-checker@^0.1.9: resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== -ts-jest@29.0.1: - version "29.0.1" - resolved "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.1.tgz" - integrity sha512-htQOHshgvhn93QLxrmxpiQPk69+M1g7govO1g6kf6GsjCv4uvRV0znVmDrrvjUrVCnTYeY4FBxTYYYD4airyJA== +ts-jest@^29.1.1: + version "29.1.2" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09" + integrity sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g== dependencies: bs-logger "0.x" fast-json-stable-stringify "2.x" jest-util "^29.0.0" - json5 "^2.2.1" + json5 "^2.2.3" lodash.memoize "4.x" make-error "1.x" - semver "7.x" + semver "^7.5.3" yargs-parser "^21.0.1" ts-morph@^18.0.0: @@ -19124,13 +18883,6 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util@^0.10.3: - version "0.10.4" - resolved "https://registry.npmjs.org/util/-/util-0.10.4.tgz" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== - dependencies: - inherits "2.0.3" - util@^0.12.4, util@^0.12.5: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" From 333577c07e59a6a71b2f84470ea3c4c85ab5a70c Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 24 Apr 2024 21:52:35 -0700 Subject: [PATCH 2/3] setup --- packages/test/__tests__/cosmos-kit.test.ts | 15 +++++++ .../src/mock-extension/extension/utils.ts | 45 +++---------------- packages/test/src/mocker/setup.ts | 12 +++++ 3 files changed, 32 insertions(+), 40 deletions(-) create mode 100644 packages/test/src/mocker/setup.ts diff --git a/packages/test/__tests__/cosmos-kit.test.ts b/packages/test/__tests__/cosmos-kit.test.ts index da32c052e..2d6a3266d 100644 --- a/packages/test/__tests__/cosmos-kit.test.ts +++ b/packages/test/__tests__/cosmos-kit.test.ts @@ -1,3 +1,4 @@ +import { getMockFromExtension } from '../src/mock-extension/extension/utils'; import { MockWallet } from '../src/mocker'; describe('Wallet functionality', () => { @@ -10,3 +11,17 @@ describe('Wallet functionality', () => { // Add more tests as needed }); + +describe('getMockFromExtension', () => { + it('returns the provided mock', async () => { + const mock = new MockWallet(); + // @ts-ignore + const result = await getMockFromExtension({ mock }); + expect(result).toEqual(mock); + }); + + it('instantiates MockWallet if no mock is provided', async () => { + const result = await getMockFromExtension(); + expect(result).toBeInstanceOf(MockWallet); + }); +}); diff --git a/packages/test/src/mock-extension/extension/utils.ts b/packages/test/src/mock-extension/extension/utils.ts index 44ec2fac1..ac541902d 100644 --- a/packages/test/src/mock-extension/extension/utils.ts +++ b/packages/test/src/mock-extension/extension/utils.ts @@ -1,47 +1,12 @@ -import { ClientNotExistError } from '@cosmos-kit/core'; - +import { MockWallet } from '../../mocker'; // Ensure this path is correct import { Mock } from './types'; interface MockWindow { mock?: Mock; } -export const getMockFromExtension: () => Promise< - Mock | undefined -> = async () => { - if (typeof window === 'undefined') { - return void 0; - } - - const mock = (window as MockWindow).mock; - - if (mock) { - return mock; - } - - if (document.readyState === 'complete') { - if (mock) { - return mock; - } else { - throw ClientNotExistError; - } - } - - return new Promise((resolve, reject) => { - const documentStateChange = (event: Event) => { - if ( - event.target && - (event.target as Document).readyState === 'complete' - ) { - if (mock) { - resolve(mock); - } else { - reject(ClientNotExistError.message); - } - document.removeEventListener('readystatechange', documentStateChange); - } - }; - - document.addEventListener('readystatechange', documentStateChange); - }); +export const getMockFromExtension: ( + mockWindow?: MockWindow +) => Promise = async (_window: any) => { + return new MockWallet(); }; diff --git a/packages/test/src/mocker/setup.ts b/packages/test/src/mocker/setup.ts new file mode 100644 index 000000000..cdfcdd70b --- /dev/null +++ b/packages/test/src/mocker/setup.ts @@ -0,0 +1,12 @@ +import { getMockFromExtension } from '../mock-extension/extension/utils'; + +// Example of using getMockFromExtension in an application setting +export async function setupWallet() { + try { + const wallet = await getMockFromExtension(); + // Proceed with using the wallet + console.log('Wallet enabled:', wallet.mode); + } catch (error) { + console.error('Failed to get wallet:', error); + } +} From a80163d6f0d9ba67b31702d46b9e9a942c87d691 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 24 Apr 2024 22:27:43 -0700 Subject: [PATCH 3/3] wip --- .../test/__tests__/chain-wallet-base.test.ts | 54 +++++++++++++++++ .../test/__tests__/wallet-manager.test.ts | 60 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 packages/test/__tests__/chain-wallet-base.test.ts create mode 100644 packages/test/__tests__/wallet-manager.test.ts diff --git a/packages/test/__tests__/chain-wallet-base.test.ts b/packages/test/__tests__/chain-wallet-base.test.ts new file mode 100644 index 000000000..4cf93ed9f --- /dev/null +++ b/packages/test/__tests__/chain-wallet-base.test.ts @@ -0,0 +1,54 @@ +import { ChainWalletBase, ChainRecord } from "@cosmos-kit/core"; +import { chains } from "chain-registry"; +import { mockExtensionInfo as walletInfo } from '../src/mock-extension/extension/registry'; + +// Mock global window object +global.window = { + // @ts-ignore + localStorage: { + getItem: jest.fn(), + setItem: jest.fn(), + removeItem: jest.fn() + } +}; + + +const chainRecord: ChainRecord = { + name: 'cosmoshub', + chain: chains.find(c => c.chain_name === 'cosmoshub'), + clientOptions: { + preferredSignType: 'direct' + }, +}; + +const chainWallet = new ChainWalletBase(walletInfo, chainRecord); + +async function connectAndFetchAccount() { + try { + await chainWallet.update({ connect: true }); + console.log('Connected and account data fetched:', chainWallet.data); + } catch (error) { + console.error('Failed to connect or fetch account data:', error); + } +} + +connectAndFetchAccount(); + +describe('ChainWalletBase', () => { + let chainWallet; + beforeEach(() => { + chainWallet = new ChainWalletBase(walletInfo, chainRecord); + // Mocking necessary methods and properties + // jest.spyOn(chainWallet, 'connectChains').mockResolvedValue(undefined); + jest.spyOn(chainWallet.client, 'getSimpleAccount').mockResolvedValue({ + namespace: 'cosmos', + chainId: 'cosmoshub-4', + address: 'cosmos1...' + }); + }); + + it('should update and fetch account data', async () => { + await expect(chainWallet.update({ connect: true })).resolves.not.toThrow(); + expect(chainWallet.data.address).toBe('cosmos1...'); + }); +}); diff --git a/packages/test/__tests__/wallet-manager.test.ts b/packages/test/__tests__/wallet-manager.test.ts new file mode 100644 index 000000000..b2f054458 --- /dev/null +++ b/packages/test/__tests__/wallet-manager.test.ts @@ -0,0 +1,60 @@ +import { WalletManager, Logger, ChainRecord, Session } from '@cosmos-kit/core'; +import { chains, assets } from 'chain-registry'; +import { MockExtensionWallet } from '../src/mock-extension/extension'; +import { mockExtensionInfo as walletInfo } from '../src/mock-extension/extension/registry'; + +const logger = new Logger(); function logoutUser() { + console.log('Session expired. Logging out user.'); + // Code to log out user +} + +// Session duration set for 30 minutes +const userSession = new Session({ + duration: 30 * 60 * 1000, // 30 minutes in milliseconds + callback: logoutUser +}); + +// Start the session when the user logs in +userSession.update(); + +const mainWalletBase = new MockExtensionWallet(walletInfo) + +describe('WalletManager', () => { + let walletManager: WalletManager; + + beforeEach(() => { + walletManager = new WalletManager( + chains, + [mainWalletBase], + logger, + true, // throwErrors + true, // subscribeConnectEvents + false // disableIframe + ); + }); + + it('should initialize with provided configurations', () => { + expect(walletManager.throwErrors).toBe(true); + expect(walletManager.subscribeConnectEvents).toBe(true); + expect(walletManager.disableIframe).toBe(false); + expect(walletManager.chainRecords).toHaveLength(2); // Assuming `convertChain` is mocked + }); + + it('should handle onMounted lifecycle correctly', async () => { + // Mock environment parser + jest.mock('Bowser', () => ({ + getParser: () => ({ + getBrowserName: jest.fn().mockReturnValue('chrome'), + getPlatform: jest.fn().mockReturnValue({ type: 'desktop' }), + getOSName: jest.fn().mockReturnValue('windows') + }) + })); + + await walletManager.onMounted(); + + expect(walletManager.walletRepos).toHaveLength(2); // Depends on internal logic + expect(logger.debug).toHaveBeenCalled(); // Check if debug logs are called + }); + + // Add more tests as needed for each method +});