]> zoso.dev Git - libnemo.git/commitdiff
Create our own testing framework. Needs some double-checking on accuracy.
authorChris Duncan <chris@zoso.dev>
Thu, 5 Dec 2024 23:51:10 +0000 (15:51 -0800)
committerChris Duncan <chris@zoso.dev>
Thu, 5 Dec 2024 23:51:10 +0000 (15:51 -0800)
19 files changed:
favicon.ico [new file with mode: 0644]
jest.config.ts [new file with mode: 0644]
package-lock.json
package.json
src/lib/rpc.ts
src/lib/wallet.ts
test.html
test/GLOBALS.mjs
test/create-wallet.test.mjs
test/derive-accounts.test.mjs
test/import-wallet.test.mjs
test/lock-unlock-wallet.mjs
test/main.mjs [new file with mode: 0644]
test/manage-rolodex.mjs
test/perf/account.perf.js [moved from perf/account.perf.js with 67% similarity]
test/perf/wallet.perf.js [moved from perf/wallet.perf.js with 62% similarity]
test/refresh-accounts.test.mjs
test/sign-blocks.test.mjs
test/tools.test.mjs

diff --git a/favicon.ico b/favicon.ico
new file mode 100644 (file)
index 0000000..024ed21
Binary files /dev/null and b/favicon.ico differ
diff --git a/jest.config.ts b/jest.config.ts
new file mode 100644 (file)
index 0000000..3013080
--- /dev/null
@@ -0,0 +1,199 @@
+/**
+ * For a detailed explanation regarding each configuration property, visit:
+ * https://jestjs.io/docs/configuration
+ */
+
+import type { Config } from 'jest'
+
+const config: Config = {
+       // All imported modules in your tests should be mocked automatically
+       // automock: false,
+
+       // Stop running tests after `n` failures
+       // bail: 0,
+
+       // The directory where Jest should store its cached dependency information
+       // cacheDirectory: "/tmp/jest_rs",
+
+       // Automatically clear mock calls, instances, contexts and results before every test
+       clearMocks: true,
+
+       // Indicates whether the coverage information should be collected while executing the test
+       collectCoverage: true,
+
+       // An array of glob patterns indicating a set of files for which coverage information should be collected
+       // collectCoverageFrom: undefined,
+
+       // The directory where Jest should output its coverage files
+       coverageDirectory: "coverage",
+
+       // An array of regexp pattern strings used to skip coverage collection
+       coveragePathIgnorePatterns: [
+               "/node_modules/"
+       ],
+
+       // Indicates which provider should be used to instrument code for coverage
+       coverageProvider: "v8",
+
+       // A list of reporter names that Jest uses when writing coverage reports
+       // coverageReporters: [
+       //   "json",
+       //   "text",
+       //   "lcov",
+       //   "clover"
+       // ],
+
+       // An object that configures minimum threshold enforcement for coverage results
+       // coverageThreshold: undefined,
+
+       // A path to a custom dependency extractor
+       // dependencyExtractor: undefined,
+
+       // Make calling deprecated APIs throw helpful error messages
+       // errorOnDeprecated: false,
+
+       // The default configuration for fake timers
+       // fakeTimers: {
+       //   "enableGlobally": false
+       // },
+
+       // Force coverage collection from ignored files using an array of glob patterns
+       // forceCoverageMatch: [],
+
+       // A path to a module which exports an async function that is triggered once before all test suites
+       // globalSetup: undefined,
+
+       // A path to a module which exports an async function that is triggered once after all test suites
+       // globalTeardown: undefined,
+
+       // A set of global variables that need to be available in all test environments
+       // globals: {},
+
+       // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
+       // maxWorkers: "50%",
+
+       // An array of directory names to be searched recursively up from the requiring module's location
+       moduleDirectories: [
+               "node_modules"
+       ],
+
+       // An array of file extensions your modules use
+       moduleFileExtensions: [
+               "js",
+               "mjs",
+               "cjs",
+               "jsx",
+               "ts",
+               "tsx",
+               "json",
+               "node"
+       ],
+
+       // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
+       // moduleNameMapper: {},
+
+       // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
+       // modulePathIgnorePatterns: [],
+
+       // Activates notifications for test results
+       // notify: false,
+
+       // An enum that specifies notification mode. Requires { notify: true }
+       // notifyMode: "failure-change",
+
+       // A preset that is used as a base for Jest's configuration
+       // preset: undefined,
+
+       // Run tests from one or more projects
+       // projects: undefined,
+
+       // Use this configuration option to add custom reporters to Jest
+       // reporters: undefined,
+
+       // Automatically reset mock state before every test
+       // resetMocks: false,
+
+       // Reset the module registry before running each individual test
+       // resetModules: false,
+
+       // A path to a custom resolver
+       // resolver: undefined,
+
+       // Automatically restore mock state and implementation before every test
+       // restoreMocks: false,
+
+       // The root directory that Jest should scan for tests and modules within
+       // rootDir: undefined,
+
+       // A list of paths to directories that Jest should use to search for files in
+       // roots: [
+       //   "<rootDir>"
+       // ],
+
+       // Allows you to use a custom runner instead of Jest's default test runner
+       // runner: "jest-runner",
+
+       // The paths to modules that run some code to configure or set up the testing environment before each test
+       // setupFiles: [],
+
+       // A list of paths to modules that run some code to configure or set up the testing framework before each test
+       // setupFilesAfterEnv: [],
+
+       // The number of seconds after which a test is considered as slow and reported as such in the results.
+       // slowTestThreshold: 5,
+
+       // A list of paths to snapshot serializer modules Jest should use for snapshot testing
+       // snapshotSerializers: [],
+
+       // The test environment that will be used for testing
+       testEnvironment: "jsdom",
+
+       // Options that will be passed to the testEnvironment
+       // testEnvironmentOptions: {},
+
+       // Adds a location field to test results
+       // testLocationInResults: false,
+
+       // The glob patterns Jest uses to detect test files
+       testMatch: [
+               "**/__tests__/**/*.m[jt]s?(x)",
+               "**/?(*.)+(spec|test).m[tj]s?(x)"
+       ],
+
+       // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
+       // testPathIgnorePatterns: [
+       //   "/node_modules/"
+       // ],
+
+       // The regexp pattern or array of patterns that Jest uses to detect test files
+       // testRegex: [],
+
+       // This option allows the use of a custom results processor
+       // testResultsProcessor: undefined,
+
+       // This option allows use of a custom test runner
+       // testRunner: "jest-circus/runner",
+
+       // A map from regular expressions to paths to transformers
+       transform: {},
+
+       // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
+       // transformIgnorePatterns: [
+       //   "/node_modules/",
+       //   "\\.pnp\\.[^\\/]+$"
+       // ],
+
+       // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
+       // unmockedModulePathPatterns: undefined,
+
+       // Indicates whether each individual test should be reported during the run
+       // verbose: undefined,
+
+       // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
+       // watchPathIgnorePatterns: [],
+
+       // Whether to use watchman for file crawling
+       // watchman: true,
+}
+
+export default config
index 4bd52d2bf312ac077f1d1739b0c34f52e67721c9..149f0bf83c994791a44c6235f4183362bc89ccd9 100644 (file)
@@ -16,6 +16,8 @@
                                "@types/web-bluetooth": "^0.0.20",
                                "esbuild": "^0.24.0",
                                "jest": "^29.7.0",
+                               "jest-environment-jsdom": "^29.7.0",
+                               "ts-node": "^10.9.2",
                                "typescript": "^5.6.3"
                        },
                        "funding": {
                        "dev": true,
                        "license": "MIT"
                },
+               "node_modules/@cspotcode/source-map-support": {
+                       "version": "0.8.1",
+                       "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+                       "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "@jridgewell/trace-mapping": "0.3.9"
+                       },
+                       "engines": {
+                               "node": ">=12"
+                       }
+               },
+               "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+                       "version": "0.3.9",
+                       "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+                       "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "@jridgewell/resolve-uri": "^3.0.3",
+                               "@jridgewell/sourcemap-codec": "^1.4.10"
+                       }
+               },
                "node_modules/@esbuild/linux-x64": {
                        "version": "0.24.0",
                        "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz",
                                "@sinonjs/commons": "^3.0.0"
                        }
                },
+               "node_modules/@tootallnate/once": {
+                       "version": "2.0.0",
+                       "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+                       "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+                       "dev": true,
+                       "license": "MIT",
+                       "engines": {
+                               "node": ">= 10"
+                       }
+               },
+               "node_modules/@tsconfig/node10": {
+                       "version": "1.0.11",
+                       "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
+                       "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
+                       "dev": true,
+                       "license": "MIT"
+               },
+               "node_modules/@tsconfig/node12": {
+                       "version": "1.0.11",
+                       "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+                       "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
+                       "dev": true,
+                       "license": "MIT"
+               },
+               "node_modules/@tsconfig/node14": {
+                       "version": "1.0.3",
+                       "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+                       "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
+                       "dev": true,
+                       "license": "MIT"
+               },
+               "node_modules/@tsconfig/node16": {
+                       "version": "1.0.4",
+                       "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+                       "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/@types/babel__core": {
                        "version": "7.20.5",
                        "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
                                "@types/istanbul-lib-report": "*"
                        }
                },
+               "node_modules/@types/jsdom": {
+                       "version": "20.0.1",
+                       "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz",
+                       "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "@types/node": "*",
+                               "@types/tough-cookie": "*",
+                               "parse5": "^7.0.0"
+                       }
+               },
                "node_modules/@types/node": {
                        "version": "22.10.1",
                        "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz",
                        "dev": true,
                        "license": "MIT"
                },
+               "node_modules/@types/tough-cookie": {
+                       "version": "4.0.5",
+                       "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
+                       "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/@types/w3c-web-hid": {
                        "version": "1.0.6",
                        "resolved": "https://registry.npmjs.org/@types/w3c-web-hid/-/w3c-web-hid-1.0.6.tgz",
                        "dev": true,
                        "license": "MIT"
                },
+               "node_modules/abab": {
+                       "version": "2.0.6",
+                       "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+                       "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
+                       "deprecated": "Use your platform's native atob() and btoa() methods instead",
+                       "dev": true,
+                       "license": "BSD-3-Clause"
+               },
+               "node_modules/acorn": {
+                       "version": "8.14.0",
+                       "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+                       "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+                       "dev": true,
+                       "license": "MIT",
+                       "bin": {
+                               "acorn": "bin/acorn"
+                       },
+                       "engines": {
+                               "node": ">=0.4.0"
+                       }
+               },
+               "node_modules/acorn-globals": {
+                       "version": "7.0.1",
+                       "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz",
+                       "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "acorn": "^8.1.0",
+                               "acorn-walk": "^8.0.2"
+                       }
+               },
+               "node_modules/acorn-walk": {
+                       "version": "8.3.4",
+                       "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
+                       "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "acorn": "^8.11.0"
+                       },
+                       "engines": {
+                               "node": ">=0.4.0"
+                       }
+               },
+               "node_modules/agent-base": {
+                       "version": "6.0.2",
+                       "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+                       "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "debug": "4"
+                       },
+                       "engines": {
+                               "node": ">= 6.0.0"
+                       }
+               },
                "node_modules/ansi-escapes": {
                        "version": "4.3.2",
                        "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
                                "node": ">= 8"
                        }
                },
+               "node_modules/arg": {
+                       "version": "4.1.3",
+                       "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+                       "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/argparse": {
                        "version": "1.0.10",
                        "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
                                "sprintf-js": "~1.0.2"
                        }
                },
+               "node_modules/asynckit": {
+                       "version": "0.4.0",
+                       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+                       "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/babel-jest": {
                        "version": "29.7.0",
                        "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
                        "dev": true,
                        "license": "MIT"
                },
+               "node_modules/combined-stream": {
+                       "version": "1.0.8",
+                       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+                       "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "delayed-stream": "~1.0.0"
+                       },
+                       "engines": {
+                               "node": ">= 0.8"
+                       }
+               },
                "node_modules/concat-map": {
                        "version": "0.0.1",
                        "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
                                "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
                        }
                },
+               "node_modules/create-require": {
+                       "version": "1.1.1",
+                       "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+                       "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/cross-spawn": {
                        "version": "7.0.6",
                        "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
                                "node": ">= 8"
                        }
                },
+               "node_modules/cssom": {
+                       "version": "0.5.0",
+                       "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz",
+                       "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==",
+                       "dev": true,
+                       "license": "MIT"
+               },
+               "node_modules/cssstyle": {
+                       "version": "2.3.0",
+                       "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
+                       "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "cssom": "~0.3.6"
+                       },
+                       "engines": {
+                               "node": ">=8"
+                       }
+               },
+               "node_modules/cssstyle/node_modules/cssom": {
+                       "version": "0.3.8",
+                       "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
+                       "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
+                       "dev": true,
+                       "license": "MIT"
+               },
+               "node_modules/data-urls": {
+                       "version": "3.0.2",
+                       "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz",
+                       "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "abab": "^2.0.6",
+                               "whatwg-mimetype": "^3.0.0",
+                               "whatwg-url": "^11.0.0"
+                       },
+                       "engines": {
+                               "node": ">=12"
+                       }
+               },
                "node_modules/debug": {
                        "version": "4.3.7",
                        "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
                                }
                        }
                },
+               "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==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/dedent": {
                        "version": "1.5.3",
                        "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
                                "node": ">=0.10.0"
                        }
                },
+               "node_modules/delayed-stream": {
+                       "version": "1.0.0",
+                       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+                       "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+                       "dev": true,
+                       "license": "MIT",
+                       "engines": {
+                               "node": ">=0.4.0"
+                       }
+               },
                "node_modules/detect-newline": {
                        "version": "3.1.0",
                        "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
                                "node": ">=8"
                        }
                },
+               "node_modules/diff": {
+                       "version": "4.0.2",
+                       "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+                       "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+                       "dev": true,
+                       "license": "BSD-3-Clause",
+                       "engines": {
+                               "node": ">=0.3.1"
+                       }
+               },
                "node_modules/diff-sequences": {
                        "version": "29.6.3",
                        "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
                                "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
                        }
                },
+               "node_modules/domexception": {
+                       "version": "4.0.0",
+                       "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
+                       "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==",
+                       "deprecated": "Use your platform's native DOMException instead",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "webidl-conversions": "^7.0.0"
+                       },
+                       "engines": {
+                               "node": ">=12"
+                       }
+               },
                "node_modules/electron-to-chromium": {
                        "version": "1.5.70",
                        "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.70.tgz",
                        "dev": true,
                        "license": "MIT"
                },
+               "node_modules/entities": {
+                       "version": "4.5.0",
+                       "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+                       "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+                       "dev": true,
+                       "license": "BSD-2-Clause",
+                       "engines": {
+                               "node": ">=0.12"
+                       },
+                       "funding": {
+                               "url": "https://github.com/fb55/entities?sponsor=1"
+                       }
+               },
                "node_modules/error-ex": {
                        "version": "1.3.2",
                        "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
                                "node": ">=8"
                        }
                },
+               "node_modules/escodegen": {
+                       "version": "2.1.0",
+                       "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
+                       "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+                       "dev": true,
+                       "license": "BSD-2-Clause",
+                       "dependencies": {
+                               "esprima": "^4.0.1",
+                               "estraverse": "^5.2.0",
+                               "esutils": "^2.0.2"
+                       },
+                       "bin": {
+                               "escodegen": "bin/escodegen.js",
+                               "esgenerate": "bin/esgenerate.js"
+                       },
+                       "engines": {
+                               "node": ">=6.0"
+                       },
+                       "optionalDependencies": {
+                               "source-map": "~0.6.1"
+                       }
+               },
                "node_modules/esprima": {
                        "version": "4.0.1",
                        "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
                                "node": ">=4"
                        }
                },
+               "node_modules/estraverse": {
+                       "version": "5.3.0",
+                       "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+                       "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+                       "dev": true,
+                       "license": "BSD-2-Clause",
+                       "engines": {
+                               "node": ">=4.0"
+                       }
+               },
+               "node_modules/esutils": {
+                       "version": "2.0.3",
+                       "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+                       "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+                       "dev": true,
+                       "license": "BSD-2-Clause",
+                       "engines": {
+                               "node": ">=0.10.0"
+                       }
+               },
                "node_modules/events": {
                        "version": "3.3.0",
                        "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
                                "node": ">=8"
                        }
                },
+               "node_modules/form-data": {
+                       "version": "4.0.1",
+                       "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+                       "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "asynckit": "^0.4.0",
+                               "combined-stream": "^1.0.8",
+                               "mime-types": "^2.1.12"
+                       },
+                       "engines": {
+                               "node": ">= 6"
+                       }
+               },
                "node_modules/fs.realpath": {
                        "version": "1.0.0",
                        "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
                                "node": ">= 0.4"
                        }
                },
+               "node_modules/html-encoding-sniffer": {
+                       "version": "3.0.0",
+                       "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
+                       "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "whatwg-encoding": "^2.0.0"
+                       },
+                       "engines": {
+                               "node": ">=12"
+                       }
+               },
                "node_modules/html-escaper": {
                        "version": "2.0.2",
                        "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
                        "dev": true,
                        "license": "MIT"
                },
+               "node_modules/http-proxy-agent": {
+                       "version": "5.0.0",
+                       "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+                       "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "@tootallnate/once": "2",
+                               "agent-base": "6",
+                               "debug": "4"
+                       },
+                       "engines": {
+                               "node": ">= 6"
+                       }
+               },
+               "node_modules/https-proxy-agent": {
+                       "version": "5.0.1",
+                       "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+                       "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "agent-base": "6",
+                               "debug": "4"
+                       },
+                       "engines": {
+                               "node": ">= 6"
+                       }
+               },
                "node_modules/human-signals": {
                        "version": "2.1.0",
                        "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
                                "node": ">=10.17.0"
                        }
                },
+               "node_modules/iconv-lite": {
+                       "version": "0.6.3",
+                       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+                       "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "safer-buffer": ">= 2.1.2 < 3.0.0"
+                       },
+                       "engines": {
+                               "node": ">=0.10.0"
+                       }
+               },
                "node_modules/import-local": {
                        "version": "3.2.0",
                        "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
                                "node": ">=0.12.0"
                        }
                },
+               "node_modules/is-potential-custom-element-name": {
+                       "version": "1.0.1",
+                       "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+                       "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/is-stream": {
                        "version": "2.0.1",
                        "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
                                "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
                        }
                },
+               "node_modules/jest-environment-jsdom": {
+                       "version": "29.7.0",
+                       "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz",
+                       "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "@jest/environment": "^29.7.0",
+                               "@jest/fake-timers": "^29.7.0",
+                               "@jest/types": "^29.6.3",
+                               "@types/jsdom": "^20.0.0",
+                               "@types/node": "*",
+                               "jest-mock": "^29.7.0",
+                               "jest-util": "^29.7.0",
+                               "jsdom": "^20.0.0"
+                       },
+                       "engines": {
+                               "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+                       },
+                       "peerDependencies": {
+                               "canvas": "^2.5.0"
+                       },
+                       "peerDependenciesMeta": {
+                               "canvas": {
+                                       "optional": true
+                               }
+                       }
+               },
                "node_modules/jest-environment-node": {
                        "version": "29.7.0",
                        "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
                                "js-yaml": "bin/js-yaml.js"
                        }
                },
+               "node_modules/jsdom": {
+                       "version": "20.0.3",
+                       "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz",
+                       "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "abab": "^2.0.6",
+                               "acorn": "^8.8.1",
+                               "acorn-globals": "^7.0.0",
+                               "cssom": "^0.5.0",
+                               "cssstyle": "^2.3.0",
+                               "data-urls": "^3.0.2",
+                               "decimal.js": "^10.4.2",
+                               "domexception": "^4.0.0",
+                               "escodegen": "^2.0.0",
+                               "form-data": "^4.0.0",
+                               "html-encoding-sniffer": "^3.0.0",
+                               "http-proxy-agent": "^5.0.0",
+                               "https-proxy-agent": "^5.0.1",
+                               "is-potential-custom-element-name": "^1.0.1",
+                               "nwsapi": "^2.2.2",
+                               "parse5": "^7.1.1",
+                               "saxes": "^6.0.0",
+                               "symbol-tree": "^3.2.4",
+                               "tough-cookie": "^4.1.2",
+                               "w3c-xmlserializer": "^4.0.0",
+                               "webidl-conversions": "^7.0.0",
+                               "whatwg-encoding": "^2.0.0",
+                               "whatwg-mimetype": "^3.0.0",
+                               "whatwg-url": "^11.0.0",
+                               "ws": "^8.11.0",
+                               "xml-name-validator": "^4.0.0"
+                       },
+                       "engines": {
+                               "node": ">=14"
+                       },
+                       "peerDependencies": {
+                               "canvas": "^2.5.0"
+                       },
+                       "peerDependenciesMeta": {
+                               "canvas": {
+                                       "optional": true
+                               }
+                       }
+               },
                "node_modules/jsesc": {
                        "version": "3.0.2",
                        "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
                                "url": "https://github.com/sponsors/sindresorhus"
                        }
                },
+               "node_modules/make-error": {
+                       "version": "1.3.6",
+                       "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+                       "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+                       "dev": true,
+                       "license": "ISC"
+               },
                "node_modules/makeerror": {
                        "version": "1.0.12",
                        "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
                                "node": ">=8.6"
                        }
                },
+               "node_modules/mime-db": {
+                       "version": "1.52.0",
+                       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+                       "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+                       "dev": true,
+                       "license": "MIT",
+                       "engines": {
+                               "node": ">= 0.6"
+                       }
+               },
+               "node_modules/mime-types": {
+                       "version": "2.1.35",
+                       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+                       "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "mime-db": "1.52.0"
+                       },
+                       "engines": {
+                               "node": ">= 0.6"
+                       }
+               },
                "node_modules/mimic-fn": {
                        "version": "2.1.0",
                        "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
                                "node": ">=8"
                        }
                },
+               "node_modules/nwsapi": {
+                       "version": "2.2.16",
+                       "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz",
+                       "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/once": {
                        "version": "1.4.0",
                        "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
                                "url": "https://github.com/sponsors/sindresorhus"
                        }
                },
+               "node_modules/parse5": {
+                       "version": "7.2.1",
+                       "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
+                       "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "entities": "^4.5.0"
+                       },
+                       "funding": {
+                               "url": "https://github.com/inikulin/parse5?sponsor=1"
+                       }
+               },
                "node_modules/path-exists": {
                        "version": "4.0.0",
                        "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
                                "node": ">= 6"
                        }
                },
+               "node_modules/psl": {
+                       "version": "1.15.0",
+                       "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
+                       "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "punycode": "^2.3.1"
+                       },
+                       "funding": {
+                               "url": "https://github.com/sponsors/lupomontero"
+                       }
+               },
+               "node_modules/punycode": {
+                       "version": "2.3.1",
+                       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+                       "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+                       "dev": true,
+                       "license": "MIT",
+                       "engines": {
+                               "node": ">=6"
+                       }
+               },
                "node_modules/pure-rand": {
                        "version": "6.1.0",
                        "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
                        ],
                        "license": "MIT"
                },
+               "node_modules/querystringify": {
+                       "version": "2.2.0",
+                       "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+                       "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/react-is": {
                        "version": "18.3.1",
                        "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
                                "node": ">=0.10.0"
                        }
                },
+               "node_modules/requires-port": {
+                       "version": "1.0.0",
+                       "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+                       "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/resolve": {
                        "version": "1.22.8",
                        "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
                                "tslib": "^2.1.0"
                        }
                },
+               "node_modules/safer-buffer": {
+                       "version": "2.1.2",
+                       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+                       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+                       "dev": true,
+                       "license": "MIT"
+               },
+               "node_modules/saxes": {
+                       "version": "6.0.0",
+                       "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+                       "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+                       "dev": true,
+                       "license": "ISC",
+                       "dependencies": {
+                               "xmlchars": "^2.2.0"
+                       },
+                       "engines": {
+                               "node": ">=v12.22.7"
+                       }
+               },
                "node_modules/semver": {
                        "version": "7.6.3",
                        "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
                                "url": "https://github.com/sponsors/ljharb"
                        }
                },
+               "node_modules/symbol-tree": {
+                       "version": "3.2.4",
+                       "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+                       "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/test-exclude": {
                        "version": "6.0.0",
                        "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
                                "node": ">=8.0"
                        }
                },
+               "node_modules/tough-cookie": {
+                       "version": "4.1.4",
+                       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
+                       "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
+                       "dev": true,
+                       "license": "BSD-3-Clause",
+                       "dependencies": {
+                               "psl": "^1.1.33",
+                               "punycode": "^2.1.1",
+                               "universalify": "^0.2.0",
+                               "url-parse": "^1.5.3"
+                       },
+                       "engines": {
+                               "node": ">=6"
+                       }
+               },
+               "node_modules/tr46": {
+                       "version": "3.0.0",
+                       "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
+                       "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "punycode": "^2.1.1"
+                       },
+                       "engines": {
+                               "node": ">=12"
+                       }
+               },
+               "node_modules/ts-node": {
+                       "version": "10.9.2",
+                       "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
+                       "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "@cspotcode/source-map-support": "^0.8.0",
+                               "@tsconfig/node10": "^1.0.7",
+                               "@tsconfig/node12": "^1.0.7",
+                               "@tsconfig/node14": "^1.0.0",
+                               "@tsconfig/node16": "^1.0.2",
+                               "acorn": "^8.4.1",
+                               "acorn-walk": "^8.1.1",
+                               "arg": "^4.1.0",
+                               "create-require": "^1.1.0",
+                               "diff": "^4.0.1",
+                               "make-error": "^1.1.1",
+                               "v8-compile-cache-lib": "^3.0.1",
+                               "yn": "3.1.1"
+                       },
+                       "bin": {
+                               "ts-node": "dist/bin.js",
+                               "ts-node-cwd": "dist/bin-cwd.js",
+                               "ts-node-esm": "dist/bin-esm.js",
+                               "ts-node-script": "dist/bin-script.js",
+                               "ts-node-transpile-only": "dist/bin-transpile.js",
+                               "ts-script": "dist/bin-script-deprecated.js"
+                       },
+                       "peerDependencies": {
+                               "@swc/core": ">=1.2.50",
+                               "@swc/wasm": ">=1.2.50",
+                               "@types/node": "*",
+                               "typescript": ">=2.7"
+                       },
+                       "peerDependenciesMeta": {
+                               "@swc/core": {
+                                       "optional": true
+                               },
+                               "@swc/wasm": {
+                                       "optional": true
+                               }
+                       }
+               },
                "node_modules/tslib": {
                        "version": "2.8.1",
                        "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
                        "dev": true,
                        "license": "MIT"
                },
+               "node_modules/universalify": {
+                       "version": "0.2.0",
+                       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+                       "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+                       "dev": true,
+                       "license": "MIT",
+                       "engines": {
+                               "node": ">= 4.0.0"
+                       }
+               },
                "node_modules/update-browserslist-db": {
                        "version": "1.1.1",
                        "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
                                "browserslist": ">= 4.21.0"
                        }
                },
+               "node_modules/url-parse": {
+                       "version": "1.5.10",
+                       "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+                       "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "querystringify": "^2.1.1",
+                               "requires-port": "^1.0.0"
+                       }
+               },
+               "node_modules/v8-compile-cache-lib": {
+                       "version": "3.0.1",
+                       "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+                       "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/v8-to-istanbul": {
                        "version": "9.3.0",
                        "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
                                "node": ">=10.12.0"
                        }
                },
+               "node_modules/w3c-xmlserializer": {
+                       "version": "4.0.0",
+                       "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
+                       "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "xml-name-validator": "^4.0.0"
+                       },
+                       "engines": {
+                               "node": ">=14"
+                       }
+               },
                "node_modules/walker": {
                        "version": "1.0.8",
                        "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
                                "makeerror": "1.0.12"
                        }
                },
+               "node_modules/webidl-conversions": {
+                       "version": "7.0.0",
+                       "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+                       "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+                       "dev": true,
+                       "license": "BSD-2-Clause",
+                       "engines": {
+                               "node": ">=12"
+                       }
+               },
+               "node_modules/whatwg-encoding": {
+                       "version": "2.0.0",
+                       "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
+                       "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "iconv-lite": "0.6.3"
+                       },
+                       "engines": {
+                               "node": ">=12"
+                       }
+               },
+               "node_modules/whatwg-mimetype": {
+                       "version": "3.0.0",
+                       "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
+                       "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
+                       "dev": true,
+                       "license": "MIT",
+                       "engines": {
+                               "node": ">=12"
+                       }
+               },
+               "node_modules/whatwg-url": {
+                       "version": "11.0.0",
+                       "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
+                       "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
+                       "dev": true,
+                       "license": "MIT",
+                       "dependencies": {
+                               "tr46": "^3.0.0",
+                               "webidl-conversions": "^7.0.0"
+                       },
+                       "engines": {
+                               "node": ">=12"
+                       }
+               },
                "node_modules/which": {
                        "version": "2.0.2",
                        "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
                                "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
                        }
                },
+               "node_modules/ws": {
+                       "version": "8.18.0",
+                       "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+                       "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
+                       "dev": true,
+                       "license": "MIT",
+                       "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/xml-name-validator": {
+                       "version": "4.0.0",
+                       "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+                       "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+                       "dev": true,
+                       "license": "Apache-2.0",
+                       "engines": {
+                               "node": ">=12"
+                       }
+               },
+               "node_modules/xmlchars": {
+                       "version": "2.2.0",
+                       "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+                       "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+                       "dev": true,
+                       "license": "MIT"
+               },
                "node_modules/y18n": {
                        "version": "5.0.8",
                        "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
                                "node": ">=12"
                        }
                },
+               "node_modules/yn": {
+                       "version": "3.1.1",
+                       "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+                       "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+                       "dev": true,
+                       "license": "MIT",
+                       "engines": {
+                               "node": ">=6"
+                       }
+               },
                "node_modules/yocto-queue": {
                        "version": "0.1.0",
                        "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
index f54178a7ee053880faaa61cedc1b9b71c2d645ae..106a743e1fc56db6a79aa4e31e94b64e860fe54f 100644 (file)
        },
        "scripts": {
                "build": "rm -rf dist && tsc && esbuild main.min=dist/main.js global.min=dist/global.js --outdir=dist --target=esnext --format=esm --platform=browser --bundle --sourcemap",
-               "test": "npm run build && jest",
+               "test": "npm run build && esbuild test.min=test/main.mjs --outdir=dist --target=esnext --format=esm --platform=browser --bundle --sourcemap",
                "test:node": "npm run build -- --platform=node && node --test --test-force-exit --env-file .env",
                "test:coverage": "npm run test:node -- --experimental-test-coverage",
                "test:coverage:report": "npm run test:coverage -- --test-reporter=lcov --test-reporter-destination=coverage.info && genhtml coverage.info --output-directory test/coverage && rm coverage.info && xdg-open test/coverage/index.html",
-               "test:performance": "npm run test perf/*"
+               "test:performance": "npm run build && npm run jest -- ./perf/*"
        },
        "imports": {
                "#*": "./*"
@@ -65,6 +65,8 @@
                "@types/web-bluetooth": "^0.0.20",
                "esbuild": "^0.24.0",
                "jest": "^29.7.0",
+               "jest-environment-jsdom": "^29.7.0",
+               "ts-node": "^10.9.2",
                "typescript": "^5.6.3"
        },
        "type": "module",
index 0e28d59d8441bcf31cfd4b425ca637275a7473b5..d43f23748069e71445a79dcff6abce339626ee42 100644 (file)
@@ -25,10 +25,11 @@ export class Rpc {
         * @returns {Promise<any>} JSON-formatted RPC results from the node
         */
        async call (action: string, data?: { [key: string]: any }): Promise<any> {
+               var process: any = process || null
                this.#validate(action)
                const headers: { [key: string]: string } = {}
                headers['Content-Type'] = 'application/json'
-               if (this.#n && process.env.LIBNEMO_RPC_API_KEY) {
+               if (this.#n && process?.env?.LIBNEMO_RPC_API_KEY) {
                        headers[this.#n] = process.env.LIBNEMO_RPC_API_KEY
                }
 
index 142f2b922979483d01fe2095a9f0605d69ccb061..2c3ae3bfcc5666135a50309e26eff75d801d512d 100644 (file)
@@ -272,9 +272,9 @@ export class Bip44Wallet extends Wallet {
                if (!Bip44Wallet.#isInternal) {\r
                        throw new Error(`Bip44Wallet cannot be instantiated directly. Use 'await Bip44Wallet.create()' instead.`)\r
                }\r
+               Bip44Wallet.#isInternal = false\r
                super(seed, mnemonic, id)\r
                this.#pool = new Pool(Bip44Ckd)\r
-               Bip44Wallet.#isInternal = false\r
        }\r
 \r
        /**\r
@@ -296,7 +296,6 @@ export class Bip44Wallet extends Wallet {
        */\r
        static async create (key: CryptoKey, salt?: string): Promise<Bip44Wallet>\r
        static async create (passkey: string | CryptoKey, salt: string = ''): Promise<Bip44Wallet> {\r
-               Bip44Wallet.#isInternal = true\r
                try {\r
                        const e = new Entropy()\r
                        return await Bip44Wallet.fromEntropy(passkey as string, e.hex, salt)\r
@@ -326,11 +325,11 @@ export class Bip44Wallet extends Wallet {
        */\r
        static async fromEntropy (key: CryptoKey, entropy: string, salt?: string): Promise<Bip44Wallet>\r
        static async fromEntropy (passkey: string | CryptoKey, entropy: string, salt: string = ''): Promise<Bip44Wallet> {\r
-               Bip44Wallet.#isInternal = true\r
                try {\r
                        const e = new Entropy(entropy)\r
                        const m = await Bip39Mnemonic.fromEntropy(e.hex)\r
                        const s = await m.toBip39Seed(salt)\r
+                       Bip44Wallet.#isInternal = true\r
                        const wallet = new this(s, m)\r
                        await wallet.lock(passkey as string)\r
                        return wallet\r
@@ -358,10 +357,10 @@ export class Bip44Wallet extends Wallet {
        */\r
        static async fromMnemonic (key: CryptoKey, mnemonic: string, salt?: string): Promise<Bip44Wallet>\r
        static async fromMnemonic (passkey: string | CryptoKey, mnemonic: string, salt: string = ''): Promise<Bip44Wallet> {\r
-               Bip44Wallet.#isInternal = true\r
                try {\r
                        const m = await Bip39Mnemonic.fromPhrase(mnemonic)\r
                        const s = await m.toBip39Seed(salt)\r
+                       Bip44Wallet.#isInternal = true\r
                        const wallet = new this(s, m)\r
                        await wallet.lock(passkey as string)\r
                        return wallet\r
@@ -391,13 +390,13 @@ export class Bip44Wallet extends Wallet {
        */\r
        static async fromSeed (key: CryptoKey, seed: string): Promise<Bip44Wallet>\r
        static async fromSeed (passkey: string | CryptoKey, seed: string): Promise<Bip44Wallet> {\r
-               Bip44Wallet.#isInternal = true\r
                if (seed.length !== SEED_LENGTH_BIP44) {\r
                        throw new Error(`Expected a ${SEED_LENGTH_BIP44}-character seed, but received ${seed.length}-character string.`)\r
                }\r
                if (!/^[0-9a-fA-F]+$/i.test(seed)) {\r
                        throw new Error('Seed contains invalid hexadecimal characters.')\r
                }\r
+               Bip44Wallet.#isInternal = true\r
                const wallet = new this(seed)\r
                await wallet.lock(passkey as string)\r
                return wallet\r
@@ -410,12 +409,11 @@ export class Bip44Wallet extends Wallet {
        * @returns {Bip44Wallet} Restored locked Bip44Wallet\r
        */\r
        static async restore (id: string): Promise<Bip44Wallet> {\r
-               Bip44Wallet.#isInternal = true\r
                if (typeof id !== 'string' || id === '') {\r
                        throw new TypeError('Wallet ID is required to restore')\r
                }\r
-               const wallet = new this('', undefined, id)\r
-               return wallet\r
+               Bip44Wallet.#isInternal = true\r
+               return new this('', undefined, id)\r
        }\r
 \r
        /**\r
@@ -455,8 +453,8 @@ export class Blake2bWallet extends Wallet {
                if (!Blake2bWallet.#isInternal) {\r
                        throw new Error(`Blake2bWallet cannot be instantiated directly. Use 'await Blake2bWallet.create()' instead.`)\r
                }\r
-               super(seed, mnemonic, id)\r
                Blake2bWallet.#isInternal = false\r
+               super(seed, mnemonic, id)\r
        }\r
 \r
        /**\r
@@ -476,7 +474,6 @@ export class Blake2bWallet extends Wallet {
        */\r
        static async create (key: CryptoKey): Promise<Blake2bWallet>\r
        static async create (passkey: string | CryptoKey): Promise<Blake2bWallet> {\r
-               Blake2bWallet.#isInternal = true\r
                try {\r
                        const seed = new Entropy()\r
                        return await Blake2bWallet.fromSeed(passkey as string, seed.hex)\r
@@ -504,7 +501,6 @@ export class Blake2bWallet extends Wallet {
        */\r
        static async fromSeed (key: CryptoKey, seed: string): Promise<Blake2bWallet>\r
        static async fromSeed (passkey: string | CryptoKey, seed: string): Promise<Blake2bWallet> {\r
-               Blake2bWallet.#isInternal = true\r
                if (seed.length !== SEED_LENGTH_BLAKE2B) {\r
                        throw new Error(`Expected a ${SEED_LENGTH_BLAKE2B}-character seed, but received ${seed.length}-character string.`)\r
                }\r
@@ -513,6 +509,7 @@ export class Blake2bWallet extends Wallet {
                }\r
                const s = seed\r
                const m = await Bip39Mnemonic.fromEntropy(seed)\r
+               Blake2bWallet.#isInternal = true\r
                const wallet = new this(s, m)\r
                await wallet.lock(passkey as string)\r
                return wallet\r
@@ -535,10 +532,10 @@ export class Blake2bWallet extends Wallet {
        */\r
        static async fromMnemonic (key: CryptoKey, mnemonic: string): Promise<Blake2bWallet>\r
        static async fromMnemonic (passkey: string | CryptoKey, mnemonic: string): Promise<Blake2bWallet> {\r
-               Blake2bWallet.#isInternal = true\r
                try {\r
                        const m = await Bip39Mnemonic.fromPhrase(mnemonic)\r
                        const s = await m.toBlake2bSeed()\r
+                       Blake2bWallet.#isInternal = true\r
                        const wallet = new this(s, m)\r
                        await wallet.lock(passkey as string)\r
                        return wallet\r
@@ -554,12 +551,11 @@ export class Blake2bWallet extends Wallet {
        * @returns {Blake2bWallet} Restored locked Blake2bWallet\r
        */\r
        static async restore (id: string): Promise<Blake2bWallet> {\r
-               Blake2bWallet.#isInternal = true\r
                if (typeof id !== 'string' || id === '') {\r
                        throw new TypeError('Wallet ID is required to restore')\r
                }\r
-               const wallet = new this('', undefined, id)\r
-               return wallet\r
+               Blake2bWallet.#isInternal = true\r
+               return new this('', undefined, id)\r
        }\r
 \r
        /**\r
@@ -602,9 +598,9 @@ export class LedgerWallet extends Wallet {
                if (!LedgerWallet.#isInternal) {\r
                        throw new Error(`LedgerWallet cannot be instantiated directly. Use 'await LedgerWallet.create()' instead.`)\r
                }\r
+               LedgerWallet.#isInternal = false\r
                super(undefined, undefined, id)\r
                this.#ledger = ledger\r
-               LedgerWallet.#isInternal = false\r
        }\r
 \r
        /**\r
@@ -614,9 +610,9 @@ export class LedgerWallet extends Wallet {
        * @returns {LedgerWallet} A wallet containing accounts and a Ledger device communication object\r
        */\r
        static async create (): Promise<LedgerWallet> {\r
-               LedgerWallet.#isInternal = true\r
                const { Ledger } = await import('./ledger.js')\r
                const l = await Ledger.init()\r
+               LedgerWallet.#isInternal = true\r
                return new this(l)\r
        }\r
 \r
@@ -627,12 +623,12 @@ export class LedgerWallet extends Wallet {
        * @returns {LedgerWallet} Restored LedgerWallet\r
        */\r
        static async restore (id: string): Promise<LedgerWallet> {\r
-               LedgerWallet.#isInternal = true\r
                if (typeof id !== 'string' || id === '') {\r
                        throw new TypeError('Wallet ID is required to restore')\r
                }\r
                const { Ledger } = await import('./ledger.js')\r
                const l = await Ledger.init()\r
+               LedgerWallet.#isInternal = true\r
                return new this(l, id)\r
        }\r
 \r
index 92bc8b017733fdaaafaac221887e325f7598e614..f3aa38b5a04435063c821ab07e6eae389bb63a89 100644 (file)
--- a/test.html
+++ b/test.html
@@ -1,8 +1,10 @@
 <!DOCTYPE html>
 
 <head>
+       <link rel="icon" href="./favicon.ico">
        <script type="module" src="./dist/global.min.js"></script>
-       <script type="module">
+       <script type="module" src="./dist/test.min.js"></script>
+       <!-- <script type="module">
                console.log(`bip44`)
                const bipWallet = await libnemo.Bip44Wallet.create('test')
                await bipWallet.unlock('test')
@@ -67,7 +69,7 @@
                }
                console.log(`receive done (${performance.now() - now} ms)`)
                console.log(`pow done (${performance.now() - now} ms)`)
-       </script>
+       </script> -->
        <style>body{background:black;}</style>
 </head>
 
index 1c780fdfec21e588e4bc41ebb46ce3047d3ed9f7..410d2ae33d524fbb5ef2f6b220e44c46dcfcf42a 100644 (file)
@@ -1,9 +1,6 @@
 // SPDX-FileCopyrightText: 2024 Chris Duncan <chris@zoso.dev>
 // SPDX-License-Identifier: GPL-3.0-or-later
 
-import { EventEmitter } from 'node:events'
-EventEmitter.defaultMaxListeners = navigator.hardwareConcurrency * 2
-
 if (globalThis.sessionStorage == null) {
        let _sessionStorage = {}
        Object.defineProperty(globalThis, 'sessionStorage', {
@@ -18,3 +15,74 @@ if (globalThis.sessionStorage == null) {
                enumerable: true
        })
 }
+
+export function skip (name, ...args) {
+       console.log(`SKIP: ${name}`)
+}
+
+export function test (name, fn) {
+       if (fn instanceof Promise) {
+               try {
+                       fn.then(() => console.log(`PASS: ${name}`))
+                               .catch((err) => console.error(`FAIL: ${name}`))
+               } catch (err) {
+                       console.error(`FAIL: ${name}`)
+                       console.error(err)
+               }
+       } else {
+               try {
+                       fn()
+                       console.log(`PASS: ${name}`)
+               } catch (err) {
+                       console.error(`FAIL: ${name}`)
+                       console.error(err)
+               }
+       }
+}
+
+export const assert = {
+       ok: (bool) => {
+               if (typeof bool !== 'boolean') throw new Error('Invalid assertion')
+               if (!bool) throw new Error(`test result falsy`)
+               return true
+       },
+       exists: (a) => {
+               let b = a || null
+               if (b == null) throw new Error(`argument is ${typeof a}`)
+               return b != null
+       },
+       equals: (a, b) => {
+               return a === b
+       },
+       notEqual: (a, b) => {
+               return a !== b
+       },
+       rejects: (fn, msg) => {
+               try {
+                       if (!(fn instanceof Promise)) throw new Error(msg ?? 'expected async function')
+                       fn.then(() => { throw new Error(msg ?? 'expected async function to reject') })
+                               .catch((err) => { return true })
+               } catch (err) {
+                       return true
+               }
+       },
+       resolves: (fn, msg) => {
+               try {
+                       if (!(fn instanceof Promise)) throw new Error('expected async function')
+                       fn.then(() => { return true })
+                               .catch((err) => { throw new Error(msg ?? 'expected async function to resolve') })
+                       return true
+               } catch (err) {
+                       throw new Error(msg ?? 'expected async function to resolve')
+               }
+       },
+       throws: (fn, msg) => {
+               try {
+                       const r = fn()
+                       if (r instanceof Promise) throw new Error('expected synchronous function')
+                       throw new Error(msg ?? `expected function to throw an exception`)
+               } catch (err) {
+                       return true
+               }
+       }
+}
index 80ff375a54f0d150c889608b475aa258389b622b..ec7c448515894597638987020b9fd08fa8604f74 100644 (file)
@@ -3,62 +3,59 @@
 \r
 'use strict'\r
 \r
-import '#test/GLOBALS.mjs'\r
-import { describe, expect, test } from '@jest/globals'\r
+import { assert, skip, test } from '#test/GLOBALS.mjs'\r
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { Bip44Wallet, Blake2bWallet, LedgerWallet } from '#dist/main.js'\r
 \r
-describe('creating a new wallet', async () => {\r
-       test('BIP-44 wallet with random entropy', async () => {\r
-               const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)\r
-               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+test('BIP-44 wallet with random entropy', async () => {\r
+       const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)\r
+       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
-               expect('id' in wallet).toBeTruthy()\r
-               expect(/[A-Fa-f0-9]{32,64}/.test(wallet.id)).toBeTruthy()\r
-               expect('mnemonic' in wallet).toBeTruthy()\r
-               expect(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic)).toBeTruthy()\r
-               expect('seed' in wallet).toBeTruthy()\r
-               expect(/[A-Fa-f0-9]{32,64}/.test(wallet.seed)).toBeTruthy()\r
-       })\r
-\r
-       test('BLAKE2b wallet with random entropy', async () => {\r
-               const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)\r
-               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+       assert.ok('id' in wallet)\r
+       assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.id))\r
+       assert.ok('mnemonic' in wallet)\r
+       assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic))\r
+       assert.ok('seed' in wallet)\r
+       assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.seed))\r
+})\r
 \r
-               expect('id' in wallet).toBeTruthy()\r
-               expect(/[A-Fa-f0-9]{32,64}/.test(wallet.id)).toBeTruthy()\r
-               expect('mnemonic' in wallet).toBeTruthy()\r
-               expect(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic)).toBeTruthy()\r
-               expect('seed' in wallet).toBeTruthy()\r
-               expect(/[A-Fa-f0-9]{32,64}/.test(wallet.seed)).toBeTruthy()\r
-       })\r
+test('BLAKE2b wallet with random entropy', async () => {\r
+       const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)\r
+       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
-       test('BIP-44 replace invalid salt with empty string', async () => {\r
-               const invalidArgs = [null, true, false, 0, 1, 2, { "foo": "bar" }]\r
-               for (const arg of invalidArgs) {\r
-                       //@ts-expect-error\r
-                       await assert.doesNotReject(Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD, arg), `Rejected ${arg}`)\r
-               }\r
-       })\r
+       assert.ok('id' in wallet)\r
+       assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.id))\r
+       assert.ok('mnemonic' in wallet)\r
+       assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic))\r
+       assert.ok('seed' in wallet)\r
+       assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.seed))\r
+})\r
 \r
-       test('fail when using new', async () => {\r
+test('BIP-44 replace invalid salt with empty string', async () => {\r
+       const invalidArgs = [null, true, false, 0, 1, 2, { "foo": "bar" }]\r
+       for (const arg of invalidArgs) {\r
                //@ts-expect-error\r
-               expect(() => new Bip44Wallet()).toThrow()\r
-               //@ts-expect-error\r
-               expect(() => new Blake2bWallet()).toThrow()\r
-               //@ts-expect-error\r
-               expect(() => new LedgerWallet()).toThrow()\r
-       })\r
+               assert.resolves(Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD, arg))\r
+       }\r
+})\r
 \r
-       test('fail without a password', async () => {\r
-               //@ts-expect-error\r
-               expect(async () => await Bip44Wallet.create()).rejects()\r
-               //@ts-expect-error\r
-               expect(async () => await Blake2bWallet.create()).rejects()\r
-       })\r
+test('fail when using new', () => {\r
+       //@ts-expect-error\r
+       assert.throws(() => new Bip44Wallet())\r
+       //@ts-expect-error\r
+       assert.throws(() => new Blake2bWallet())\r
+       //@ts-expect-error\r
+       assert.throws(() => new LedgerWallet())\r
+})\r
+\r
+test('fail without a password', async () => {\r
+       //@ts-expect-error\r
+       assert.rejects(Bip44Wallet.create())\r
+       //@ts-expect-error\r
+       assert.rejects(Blake2bWallet.create())\r
+})\r
 \r
-       test.skip('connect to ledger', async () => {\r
-               const wallet = await LedgerWallet.create()\r
-               expect(wallet).toBeDefined()\r
-       })\r
+skip('connect to ledger', async () => {\r
+       const wallet = await LedgerWallet.create()\r
+       assert.ok(wallet)\r
 })\r
index 9dc951331e52abb881f432eaf031eaa7f45bb58c..44ecd266f9e52746c1e51e145cc7d7688c3120d8 100644 (file)
@@ -3,46 +3,45 @@
 \r
 'use strict'\r
 \r
-import '#test/GLOBALS.mjs'\r
-import { describe, expect, test } from '@jest/globals'\r
+import { assert, skip, test } from '#test/GLOBALS.mjs'\r
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { Bip44Wallet, Blake2bWallet, LedgerWallet } from '#dist/main.js'\r
 \r
-describe('derive child accounts from the same seed', async () => {\r
+test('derive child accounts from the same seed', async () => {\r
        const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
        test('should derive the first account from the given BIP-44 seed', async () => {\r
                const accounts = await wallet.accounts()\r
 \r
-               assert.equal(accounts.length, 1)\r
-               assert.equal(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
-               assert.equal(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
-               assert.equal(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
+               assert.equals(accounts.length, 1)\r
+               assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
+               assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
+               assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
        })\r
 \r
        test('should derive low indexed accounts from the given BIP-44 seed', async () => {\r
                const accounts = await wallet.accounts(1, 2)\r
 \r
-               assert.equal(accounts.length, 2)\r
-               assert.equal(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_1)\r
-               assert.equal(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_1)\r
-               assert.equal(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_1)\r
-               assert.equal(accounts[1].privateKey, NANO_TEST_VECTORS.PRIVATE_2)\r
-               assert.equal(accounts[1].publicKey, NANO_TEST_VECTORS.PUBLIC_2)\r
-               assert.equal(accounts[1].address, NANO_TEST_VECTORS.ADDRESS_2)\r
+               assert.equals(accounts.length, 2)\r
+               assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_1)\r
+               assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_1)\r
+               assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_1)\r
+               assert.equals(accounts[1].privateKey, NANO_TEST_VECTORS.PRIVATE_2)\r
+               assert.equals(accounts[1].publicKey, NANO_TEST_VECTORS.PUBLIC_2)\r
+               assert.equals(accounts[1].address, NANO_TEST_VECTORS.ADDRESS_2)\r
        })\r
 \r
        test('should derive high indexed accounts from the given seed', async () => {\r
                const accounts = await wallet.accounts(0x70000000, 0x700000ff)\r
 \r
-               assert.equal(accounts.length, 0x100)\r
+               assert.equals(accounts.length, 0x100)\r
                for (const a of accounts) {\r
-                       assert.ok(a)\r
-                       assert.ok(a.address)\r
-                       assert.ok(a.publicKey)\r
-                       assert.ok(a.privateKey)\r
-                       assert.ok(a.index != null)\r
+                       assert.exists(a)\r
+                       assert.exists(a.address)\r
+                       assert.exists(a.publicKey)\r
+                       assert.exists(a.privateKey)\r
+                       assert.exists(a.index)\r
                }\r
        })\r
 \r
@@ -51,36 +50,36 @@ describe('derive child accounts from the same seed', async () => {
                await bwallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                const lowAccounts = await bwallet.accounts(0, 2)\r
 \r
-               assert.equal(lowAccounts.length, 3)\r
+               assert.equals(lowAccounts.length, 3)\r
                for (const a of lowAccounts) {\r
-                       assert.ok(a)\r
-                       assert.ok(a.address)\r
-                       assert.ok(a.publicKey)\r
-                       assert.ok(a.privateKey)\r
-                       assert.ok(a.index != null)\r
+                       assert.exists(a)\r
+                       assert.exists(a.address)\r
+                       assert.exists(a.publicKey)\r
+                       assert.exists(a.privateKey)\r
+                       assert.exists(a.index)\r
                }\r
 \r
                const highAccounts = await bwallet.accounts(0x70000000, 0x700000ff)\r
 \r
-               assert.equal(highAccounts.length, 0x100)\r
+               assert.equals(highAccounts.length, 0x100)\r
                for (const a of highAccounts) {\r
-                       assert.ok(a)\r
-                       assert.ok(a.address)\r
-                       assert.ok(a.publicKey)\r
-                       assert.ok(a.privateKey)\r
-                       assert.ok(a.index != null)\r
+                       assert.exists(a)\r
+                       assert.exists(a.address)\r
+                       assert.exists(a.publicKey)\r
+                       assert.exists(a.privateKey)\r
+                       assert.exists(a.index)\r
                }\r
        })\r
 })\r
 \r
-describe.skip('Ledger device accounts', async () => {\r
+skip('Ledger device accounts', async () => {\r
        const wallet = await LedgerWallet.create()\r
 \r
        test('should fetch the first account from a Ledger device', async () => {\r
                const accounts = await wallet.accounts()\r
 \r
-               assert.equal(accounts.length, 1)\r
-               assert.ok(accounts[0].publicKey)\r
-               assert.ok(accounts[0].address)\r
+               assert.equals(accounts.length, 1)\r
+               assert.exists(accounts[0].publicKey)\r
+               assert.exists(accounts[0].address)\r
        })\r
 })\r
index 56d913a1345926f9f1ac5c8e6334c4f2776bcf6c..1585620839fe903bc961e2d754d8968b749c1f92 100644 (file)
@@ -3,12 +3,11 @@
 \r
 'use strict'\r
 \r
-import '#test/GLOBALS.mjs'\r
-import { describe, expect, test } from '@jest/globals'\r
+import { assert, test } from '#test/GLOBALS.mjs'\r
 import { BIP32_TEST_VECTORS, CUSTOM_TEST_VECTORS, NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { Account, Bip44Wallet, Blake2bWallet } from '#dist/main.js'\r
 \r
-describe('import wallet with test vectors test', () => {\r
+test('import wallet with test vectors test', () => {\r
        test('should successfully import a wallet with the official Nano test vectors mnemonic', async () => {\r
                const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
                await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
@@ -17,17 +16,17 @@ describe('import wallet with test vectors test', () => {
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
                assert.ok(accounts[0] instanceof Account)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-               assert.equal(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
-               assert.equal(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
-               assert.equal(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+               assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
+               assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
+               assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
        })\r
 \r
        test('should successfully import a wallet with the checksum starting with a zero', async () => {\r
                const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, 'food define cancel major spoon trash cigar basic aim bless wolf win ability seek paddle bench seed century group they mercy address monkey cake')\r
                await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-               assert.equal(wallet.seed, 'F665F804E5907985455D1E5A7AD344843A2ED4179A7E06EEF263DE925FF6F4C0991B0A9344FCEE939FE0F1B1841B8C9B20FEACF6B954B74B2D26A01906B758E2')\r
+               assert.equals(wallet.seed, 'F665F804E5907985455D1E5A7AD344843A2ED4179A7E06EEF263DE925FF6F4C0991B0A9344FCEE939FE0F1B1841B8C9B20FEACF6B954B74B2D26A01906B758E2')\r
        })\r
 \r
        test('should successfully import a wallet with a 12-word phrase', async () => {\r
@@ -36,11 +35,11 @@ describe('import wallet with test vectors test', () => {
                const accounts = await wallet.accounts()\r
                const account = accounts[0]\r
 \r
-               assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_0)\r
-               assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_0)\r
-               assert.equal(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_0)\r
-               assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_0)\r
-               assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_0)\r
+               assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_0)\r
+               assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_0)\r
+               assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_0)\r
+               assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_0)\r
+               assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_0)\r
        })\r
 \r
        test('should successfully import a wallet with a 15-word phrase', async () => {\r
@@ -49,11 +48,11 @@ describe('import wallet with test vectors test', () => {
                const accounts = await wallet.accounts()\r
                const account = accounts[0]\r
 \r
-               assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_1)\r
-               assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_1)\r
-               assert.equal(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_1)\r
-               assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_1)\r
-               assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_1)\r
+               assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_1)\r
+               assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_1)\r
+               assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_1)\r
+               assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_1)\r
+               assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_1)\r
        })\r
 \r
        test('should successfully import a wallet with a 18-word phrase', async () => {\r
@@ -62,11 +61,11 @@ describe('import wallet with test vectors test', () => {
                const accounts = await wallet.accounts()\r
                const account = accounts[0]\r
 \r
-               assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_2)\r
-               assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_2)\r
-               assert.equal(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_2)\r
-               assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_2)\r
-               assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_2)\r
+               assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_2)\r
+               assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_2)\r
+               assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_2)\r
+               assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_2)\r
+               assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_2)\r
        })\r
 \r
        test('should successfully import a wallet with a 21-word phrase', async () => {\r
@@ -75,11 +74,11 @@ describe('import wallet with test vectors test', () => {
                const accounts = await wallet.accounts()\r
                const account = accounts[0]\r
 \r
-               assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_3)\r
-               assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_3)\r
-               assert.equal(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_3)\r
-               assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_3)\r
-               assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_3)\r
+               assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_3)\r
+               assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_3)\r
+               assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_3)\r
+               assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_3)\r
+               assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_3)\r
        })\r
 \r
        test('should successfully import a wallet with the official Nano test vectors seed', async () => {\r
@@ -90,11 +89,11 @@ describe('import wallet with test vectors test', () => {
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
                assert.ok(accounts[0] instanceof Account)\r
-               assert.equal(wallet.mnemonic, '')\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-               assert.equal(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
-               assert.equal(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
-               assert.equal(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+               assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
+               assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
+               assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
        })\r
 \r
        test('should successfully import a BIP-44 wallet with the zero seed', async () => {\r
@@ -104,15 +103,15 @@ describe('import wallet with test vectors test', () => {
 \r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.SEED_0.toUpperCase())\r
-               assert.equal(accounts.length, 4)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.SEED_0.toUpperCase())\r
+               assert.equals(accounts.length, 4)\r
                for (let i = 0; i < accounts.length; i++) {\r
                        assert.ok(accounts[i])\r
                        assert.ok(accounts[i].address)\r
                        assert.ok(accounts[i].publicKey)\r
                        assert.ok(accounts[i].privateKey)\r
-                       assert.equal(accounts[i].index, i)\r
+                       assert.equals(accounts[i].index, i)\r
                }\r
        })\r
 \r
@@ -123,15 +122,15 @@ describe('import wallet with test vectors test', () => {
 \r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
-               assert.equal(accounts.length, 4)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+               assert.equals(accounts.length, 4)\r
                for (let i = 0; i < accounts.length; i++) {\r
                        assert.ok(accounts[i])\r
                        assert.ok(accounts[i].address)\r
                        assert.ok(accounts[i].publicKey)\r
                        assert.ok(accounts[i].privateKey)\r
-                       assert.equal(accounts[i].index, i)\r
+                       assert.equals(accounts[i].index, i)\r
                }\r
        })\r
 \r
@@ -142,18 +141,18 @@ describe('import wallet with test vectors test', () => {
 \r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
                assert.ok(accounts[0] instanceof Account)\r
-               assert.equal(accounts[0].index, 0)\r
-               assert.equal(accounts[0].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_0)\r
-               assert.equal(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_0)\r
-               assert.equal(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_0)\r
+               assert.equals(accounts[0].index, 0)\r
+               assert.equals(accounts[0].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_0)\r
+               assert.equals(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_0)\r
+               assert.equals(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_0)\r
                assert.ok(accounts[1] instanceof Account)\r
-               assert.equal(accounts[1].index, 1)\r
-               assert.equal(accounts[1].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_1)\r
-               assert.equal(accounts[1].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_1)\r
-               assert.equal(accounts[1].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_1)\r
+               assert.equals(accounts[1].index, 1)\r
+               assert.equals(accounts[1].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_1)\r
+               assert.equals(accounts[1].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_1)\r
+               assert.equals(accounts[1].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_1)\r
        })\r
 \r
        test('should get identical BLAKE2b wallets when created with a seed versus with its derived mnemonic', async () => {\r
@@ -165,17 +164,17 @@ describe('import wallet with test vectors test', () => {
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
                assert.ok(walletAccount)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_2)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_2)\r
 \r
                const imported = await Blake2bWallet.fromMnemonic(TREZOR_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_2)\r
                await imported.unlock(TREZOR_TEST_VECTORS.PASSWORD)\r
                const importedAccounts = await imported.accounts()\r
                const importedAccount = importedAccounts[0]\r
 \r
-               assert.equal(imported.mnemonic, wallet.mnemonic)\r
-               assert.equal(imported.seed, wallet.seed)\r
-               assert.equal(importedAccount.privateKey, walletAccount.privateKey)\r
-               assert.equal(importedAccount.publicKey, walletAccount.publicKey)\r
+               assert.equals(imported.mnemonic, wallet.mnemonic)\r
+               assert.equals(imported.seed, wallet.seed)\r
+               assert.equals(importedAccount.privateKey, walletAccount.privateKey)\r
+               assert.equals(importedAccount.publicKey, walletAccount.publicKey)\r
        })\r
 \r
        test('should get identical BLAKE2b wallets when created with max entropy value', async () => {\r
@@ -186,16 +185,16 @@ describe('import wallet with test vectors test', () => {
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
                assert.ok(accounts[0] instanceof Account)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_3)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_3)\r
-               assert.equal(accounts[0].index, 0)\r
-               assert.equal(accounts[0].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PRIVATE_0)\r
-               assert.equal(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PUBLIC_0)\r
-               assert.equal(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_3_ADDRESS_0)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_3)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_3)\r
+               assert.equals(accounts[0].index, 0)\r
+               assert.equals(accounts[0].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PRIVATE_0)\r
+               assert.equals(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PUBLIC_0)\r
+               assert.equals(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_3_ADDRESS_0)\r
        })\r
 })\r
 \r
-describe('invalid wallet', async () => {\r
+test('invalid wallet', async () => {\r
        test('throw when given invalid entropy', async () => {\r
                assert.rejects(async () => await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C797'))\r
                assert.rejects(async () => await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C79701'))\r
@@ -204,36 +203,36 @@ describe('invalid wallet', async () => {
 \r
        test('should throw when given a seed with an invalid length', async () => {\r
                await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED + 'f'),\r
-                       { message: `Expected a ${NANO_TEST_VECTORS.BIP39_SEED.length}-character seed, but received ${NANO_TEST_VECTORS.BIP39_SEED.length + 1}-character string.` })\r
+                       `Expected a ${NANO_TEST_VECTORS.BIP39_SEED.length}-character seed, but received ${NANO_TEST_VECTORS.BIP39_SEED.length + 1}-character string.`)\r
                await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED.slice(0, -1)),\r
-                       { message: `Expected a ${NANO_TEST_VECTORS.BIP39_SEED.length}-character seed, but received ${NANO_TEST_VECTORS.BIP39_SEED.length - 1}-character string.` })\r
+                       `Expected a ${NANO_TEST_VECTORS.BIP39_SEED.length}-character seed, but received ${NANO_TEST_VECTORS.BIP39_SEED.length - 1}-character string.`)\r
        })\r
 \r
        test('should throw when given a seed containing non-hex characters', async () => {\r
                await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.SEED_0.replace(/./, 'g')),\r
-                       { message: 'Seed contains invalid hexadecimal characters.' })\r
+                       'Seed contains invalid hexadecimal characters.')\r
                await assert.rejects(Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1.replace(/./, 'g')),\r
-                       { message: 'Seed contains invalid hexadecimal characters.' })\r
+                       'Seed contains invalid hexadecimal characters.')\r
        })\r
 })\r
 \r
-describe('import from storage', async () => {\r
+test('import from storage', async () => {\r
        test('should retrieve a Bip44Wallet from storage using an ID', async () => {\r
                const id = (await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)).id\r
                const wallet = await Bip44Wallet.restore(id)\r
 \r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, '')\r
-               assert.equal(wallet.seed, '')\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
 \r
                const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
-               assert.equal(unlockResult, true)\r
+               assert.equals(unlockResult, true)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
        })\r
 \r
        test('should retrieve a Blake2bWallet from storage using an ID', async () => {\r
@@ -242,15 +241,15 @@ describe('import from storage', async () => {
 \r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, '')\r
-               assert.equal(wallet.seed, '')\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
 \r
                const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
-               assert.equal(unlockResult, true)\r
+               assert.equals(unlockResult, true)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
        })\r
 })\r
index 3c271e522d4aea47be804460877df500fbbf51eb..b583555ba10a52d8cf245e9b78f88276008b5a17 100644 (file)
@@ -3,27 +3,26 @@
 \r
 'use strict'\r
 \r
-import '#test/GLOBALS.mjs'\r
-import { describe, expect, test } from '@jest/globals'\r
+import { assert, test } from '#test/GLOBALS.mjs'\r
 import { NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { Bip44Wallet, Blake2bWallet } from '#dist/main.js'\r
 \r
-describe('locking and unlocking a Bip44Wallet', async () => {\r
+test('locking and unlocking a Bip44Wallet', async () => {\r
        test('should succeed with a password', async () => {\r
                const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
 \r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, '')\r
-               assert.equal(wallet.seed, '')\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
 \r
                const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
-               assert.equal(unlockResult, true)\r
+               assert.equals(unlockResult, true)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
        })\r
 \r
        test('should succeed with a random CryptoKey', async () => {\r
@@ -35,16 +34,16 @@ describe('locking and unlocking a Bip44Wallet', async () => {
                assert.ok(lockResult)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, '')\r
-               assert.equal(wallet.seed, '')\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
 \r
                const unlockResult = await wallet.unlock(key)\r
 \r
-               assert.equal(unlockResult, true)\r
+               assert.equals(unlockResult, true)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
        })\r
 \r
        test('should fail to unlock with different passwords', async () => {\r
@@ -53,7 +52,7 @@ describe('locking and unlocking a Bip44Wallet', async () => {
                const lockResult = await wallet.lock(TREZOR_TEST_VECTORS.PASSWORD)\r
 \r
                await assert.rejects(wallet.unlock(NANO_TEST_VECTORS.PASSWORD), { message: 'Failed to unlock wallet' })\r
-               assert.equal(lockResult, true)\r
+               assert.equals(lockResult, true)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
                assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
@@ -68,7 +67,7 @@ describe('locking and unlocking a Bip44Wallet', async () => {
                const lockResult = await wallet.lock(rightKey)\r
 \r
                await assert.rejects(wallet.unlock(wrongKey), { message: 'Failed to unlock wallet' })\r
-               assert.equal(lockResult, true)\r
+               assert.equals(lockResult, true)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
                assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
@@ -94,8 +93,8 @@ describe('locking and unlocking a Bip44Wallet', async () => {
                await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' })\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
 \r
                await wallet.lock('password')\r
 \r
@@ -115,8 +114,8 @@ describe('locking and unlocking a Bip44Wallet', async () => {
                await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' })\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
 \r
                await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
@@ -129,22 +128,22 @@ describe('locking and unlocking a Bip44Wallet', async () => {
        })\r
 })\r
 \r
-describe('locking and unlocking a Blake2bWallet', async () => {\r
+test('locking and unlocking a Blake2bWallet', async () => {\r
        test('should succeed with a password', async () => {\r
                const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)\r
 \r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, '')\r
-               assert.equal(wallet.seed, '')\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
 \r
                const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
-               assert.equal(unlockResult, true)\r
+               assert.equals(unlockResult, true)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
        })\r
 \r
        test('should succeed with a random CryptoKey', async () => {\r
@@ -153,20 +152,20 @@ describe('locking and unlocking a Blake2bWallet', async () => {
                const key = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
                const lockResult = await wallet.lock(key)\r
 \r
-               assert.equal(lockResult, true)\r
+               assert.equals(lockResult, true)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, '')\r
-               assert.equal(wallet.seed, '')\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
 \r
                const unlockResult = await wallet.unlock(key)\r
 \r
-               assert.equal(lockResult, true)\r
-               assert.equal(unlockResult, true)\r
+               assert.equals(lockResult, true)\r
+               assert.equals(unlockResult, true)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
        })\r
 \r
        test('should fail to unlock with different passwords', async () => {\r
@@ -187,7 +186,7 @@ describe('locking and unlocking a Blake2bWallet', async () => {
                const lockResult = await wallet.lock(rightKey)\r
 \r
                await assert.rejects(wallet.unlock(wrongKey), { message: 'Failed to unlock wallet' })\r
-               assert.equal(lockResult, true)\r
+               assert.equals(lockResult, true)\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
                assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
@@ -213,8 +212,8 @@ describe('locking and unlocking a Blake2bWallet', async () => {
                await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' })\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
 \r
                await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
@@ -234,8 +233,8 @@ describe('locking and unlocking a Blake2bWallet', async () => {
                await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' })\r
                assert.ok('mnemonic' in wallet)\r
                assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
 \r
                await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
diff --git a/test/main.mjs b/test/main.mjs
new file mode 100644 (file)
index 0000000..f7a990f
--- /dev/null
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: 2024 Chris Duncan <chris@zoso.dev>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import './create-wallet.test.mjs'
+import './derive-accounts.test.mjs'
+import './import-wallet.test.mjs'
+import './lock-unlock-wallet.mjs'
+import './manage-rolodex.mjs'
+import './refresh-accounts.test.mjs'
+import './sign-blocks.test.mjs'
+import './tools.test.mjs'
+
+import './perf/account.perf.js'
+import './perf/wallet.perf.js'
+
+console.log('> TESTING COMPLETE <')
index e15d22d1902897a7d8c6f9db6118d6bd3762f31d..53c0d279f9a1f1ec7f053b358e9f854b8bbd3ed5 100644 (file)
@@ -3,31 +3,30 @@
 
 'use strict'
 
-import '#test/GLOBALS.mjs'
-import { describe, expect, test } from '@jest/globals'
+import { assert, test } from '#test/GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'
 import { Rolodex, Tools } from '#dist/main.js'
 
-describe('rolodex valid contact management', async () => {
+test('rolodex valid contact management', async () => {
        test('should create a rolodex and add two contacts', async () => {
                const rolodex = new Rolodex()
-               assert.equal(rolodex.constructor, Rolodex)
+               assert.equals(rolodex.constructor, Rolodex)
                await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
                await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1)
 
-               assert.equal(rolodex.getAllNames().length, 2)
-               assert.equal(rolodex.getAllNames()[0], 'JohnDoe')
-               assert.equal(rolodex.getAllNames()[1], 'JaneSmith')
-               assert.equal(rolodex.getAddresses('JohnDoe').length, 1)
-               assert.equal(rolodex.getAddresses('JohnDoe')[0], NANO_TEST_VECTORS.ADDRESS_0)
-               assert.equal(rolodex.getAddresses('JaneSmith').length, 1)
-               assert.equal(rolodex.getAddresses('JaneSmith')[0], NANO_TEST_VECTORS.ADDRESS_1)
+               assert.equals(rolodex.getAllNames().length, 2)
+               assert.equals(rolodex.getAllNames()[0], 'JohnDoe')
+               assert.equals(rolodex.getAllNames()[1], 'JaneSmith')
+               assert.equals(rolodex.getAddresses('JohnDoe').length, 1)
+               assert.equals(rolodex.getAddresses('JohnDoe')[0], NANO_TEST_VECTORS.ADDRESS_0)
+               assert.equals(rolodex.getAddresses('JaneSmith').length, 1)
+               assert.equals(rolodex.getAddresses('JaneSmith')[0], NANO_TEST_VECTORS.ADDRESS_1)
        })
 
        test('should get a name from an address', async () => {
                const rolodex = new Rolodex()
                await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-               assert.equal(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0), 'JohnDoe')
+               assert.equals(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0), 'JohnDoe')
        })
 
        test('should add three addresses to the same contact', async () => {
@@ -35,46 +34,46 @@ describe('rolodex valid contact management', async () => {
                await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_1)
                await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_2)
                await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-               assert.equal(rolodex.getAddresses('JohnDoe').length, 3)
-               assert.equal(rolodex.getAddresses('JohnDoe')[0], NANO_TEST_VECTORS.ADDRESS_1)
-               assert.equal(rolodex.getAddresses('JohnDoe')[1], NANO_TEST_VECTORS.ADDRESS_2)
-               assert.equal(rolodex.getAddresses('JohnDoe')[2], NANO_TEST_VECTORS.ADDRESS_0)
+               assert.equals(rolodex.getAddresses('JohnDoe').length, 3)
+               assert.equals(rolodex.getAddresses('JohnDoe')[0], NANO_TEST_VECTORS.ADDRESS_1)
+               assert.equals(rolodex.getAddresses('JohnDoe')[1], NANO_TEST_VECTORS.ADDRESS_2)
+               assert.equals(rolodex.getAddresses('JohnDoe')[2], NANO_TEST_VECTORS.ADDRESS_0)
        })
 
        test('should update the name on an existing entry', async () => {
                const rolodex = new Rolodex()
                await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
                await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_0)
-               assert.equal(rolodex.getAddresses('JohnDoe').length, 0)
-               assert.equal(rolodex.getAddresses('JaneSmith').length, 1)
-               assert.equal(rolodex.getAddresses('JaneSmith')[0], NANO_TEST_VECTORS.ADDRESS_0)
+               assert.equals(rolodex.getAddresses('JohnDoe').length, 0)
+               assert.equals(rolodex.getAddresses('JaneSmith').length, 1)
+               assert.equals(rolodex.getAddresses('JaneSmith')[0], NANO_TEST_VECTORS.ADDRESS_0)
        })
 
        test('should return empty address array for an unknown contact', async () => {
                const rolodex = new Rolodex()
                await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-               assert.equal(Array.isArray(rolodex.getAddresses('JaneSmith')), true)
-               assert.equal(rolodex.getAddresses('JaneSmith').length, 0)
+               assert.equals(Array.isArray(rolodex.getAddresses('JaneSmith')), true)
+               assert.equals(rolodex.getAddresses('JaneSmith').length, 0)
        })
 
        test('should return empty address array for blank contact names', () => {
                const rolodex = new Rolodex()
                //@ts-expect-error
-               assert.equal(Array.isArray(rolodex.getAddresses(undefined)), true)
+               assert.equals(Array.isArray(rolodex.getAddresses(undefined)), true)
                //@ts-expect-error
-               assert.equal(rolodex.getAddresses(undefined).length, 0)
+               assert.equals(rolodex.getAddresses(undefined).length, 0)
                //@ts-expect-error
-               assert.equal(Array.isArray(rolodex.getAddresses(null)), true)
+               assert.equals(Array.isArray(rolodex.getAddresses(null)), true)
                //@ts-expect-error
-               assert.equal(rolodex.getAddresses(null).length, 0)
-               assert.equal(Array.isArray(rolodex.getAddresses('')), true)
-               assert.equal(rolodex.getAddresses('').length, 0)
+               assert.equals(rolodex.getAddresses(null).length, 0)
+               assert.equals(Array.isArray(rolodex.getAddresses('')), true)
+               assert.equals(rolodex.getAddresses('').length, 0)
        })
 
        test('should return null for an unknown address', async () => {
                const rolodex = new Rolodex()
                await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-               assert.equal(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1), null)
+               assert.equals(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1), null)
                assert.notEqual(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1), undefined)
        })
 
@@ -82,19 +81,19 @@ describe('rolodex valid contact management', async () => {
                const rolodex = new Rolodex()
                await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
                //@ts-expect-error
-               assert.equal(rolodex.getName(undefined), null)
+               assert.equals(rolodex.getName(undefined), null)
                //@ts-expect-error
                assert.notEqual(rolodex.getName(undefined), undefined)
                //@ts-expect-error
-               assert.equal(rolodex.getName(null), null)
+               assert.equals(rolodex.getName(null), null)
                //@ts-expect-error
                assert.notEqual(rolodex.getName(null), undefined)
-               assert.equal(rolodex.getName(''), null)
+               assert.equals(rolodex.getName(''), null)
                assert.notEqual(rolodex.getName(''), undefined)
        })
 })
 
-describe('rolodex exceptions', async () => {
+test('rolodex exceptions', async () => {
        test('should throw if adding no data', async () => {
                const rolodex = new Rolodex()
                //@ts-expect-error
@@ -122,7 +121,7 @@ describe('rolodex exceptions', async () => {
        })
 })
 
-describe('rolodex data signature verification', async () => {
+test('rolodex data signature verification', async () => {
        const data = 'Test data'
        const signature = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, data)
        const rolodex = new Rolodex()
@@ -130,12 +129,12 @@ describe('rolodex data signature verification', async () => {
        test('should verify valid data and signature', async () => {
                await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
                const result = await rolodex.verify('JohnDoe', signature, data)
-               assert.equal(result, true)
+               assert.equals(result, true)
        })
 
        test('should reject incorrect contact for signature', async () => {
                await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1)
                const result = await rolodex.verify('JaneSmith', signature, data)
-               assert.equal(result, false)
+               assert.equals(result, false)
        })
 })
similarity index 67%
rename from perf/account.perf.js
rename to test/perf/account.perf.js
index 831f275330b0cd2beae40eb89117d4ed523cee5e..e4d796a2e1d904e2fb6811caee0de4f9776d8000 100644 (file)
@@ -3,27 +3,25 @@
 
 'use strict'
 
-import '#test/GLOBALS.mjs'
-import { describe, expect, test } from '@jest/globals'
+import { assert, skip, test } from '#test/GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'
 import { Bip44Wallet, Blake2bWallet } from '#dist/main.js'
 
-console.log('child key derivation performance test')
-
-test('BIP-44 ckd', async () => {
+test('BIP-44 ckd performance test', async () => {
        const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)
        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
 
+       console.log(`HERE`)
        const accounts = await wallet.accounts(0, 0x7fff)
 
-       expect(accounts.length).toEqual(0x8000)
+       assert.equals(accounts.length, 0x8000)
 })
 
-test('BLAKE2b ckd', async () => {
+test('BLAKE2b ckd performance test', async () => {
        const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)
        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
 
        const accounts = await wallet.accounts(0, 0x7fff)
 
-       expect(accounts.length).toEqual(0x8000)
+       assert.equals(accounts.length, 0x8000)
 })
similarity index 62%
rename from perf/wallet.perf.js
rename to test/perf/wallet.perf.js
index 51cb4a854e31af732c626e1b96868fa471b990a4..7c65a683dddf748f6b44fd0e392c90c3de97638e 100644 (file)
@@ -3,25 +3,22 @@
 
 'use strict'
 
-import '#test/GLOBALS.mjs'
-import { describe, expect, test } from '@jest/globals'
+import { assert, skip, test } from '#test/GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'
 import { Bip44Wallet, Blake2bWallet } from '#dist/main.js'
 
-console.log('wallet performance test')
-
-test.skip('creating BIP-44 wallets', async () => {
+test('creating BIP-44 wallets performance test', async () => {
        const wallets = []
        for (let i = 0x80; i > 0; i--) {
                wallets.push(await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD))
        }
-       expect(wallets.length).toEqual(0x80)
+       assert.equals(wallets.length, 0x80)
 })
 
-test.skip('creating BLAKE2b wallets', async () => {
+test('creating BLAKE2b wallets performance test', async () => {
        const wallets = []
        for (let i = 0x80; i > 0; i--) {
                wallets.push(await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD))
        }
-       expect(wallets.length).toEqual(0x80)
+       assert.equals(wallets.length, 0x80)
 })
index 23010d92112a3857be1aac16bcebd52f8bbf08c0..00e76faa70780630b36e08dbb46f92773a220df7 100644 (file)
@@ -3,34 +3,39 @@
 
 'use strict'
 
-import '#test/GLOBALS.mjs'
-import { describe, expect, test } from '@jest/globals'
+import { assert, skip, test } from '#test/GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'
 import { Account, Bip44Wallet, Rpc } from '#dist/main.js'
 
 const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
 await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-const node = new Rpc(process.env.NODE_URL ?? '', process.env.API_KEY_NAME)
-
-describe.skip('refreshing account info', async () => {
+let rpc
+//@ts-expect-error
+var process = process || null
+if (process) {
+       //@ts-expect-error
+       rpc = new Rpc(process?.env?.NODE_URL ?? '', process?.env?.API_KEY_NAME)
+}
+
+skip('refreshing account info', async () => {
        test('should fetch balance, frontier, and representative', async () => {
                const accounts = await wallet.accounts()
                const account = accounts[0]
-               await account.refresh(node)
+               await account.refresh(rpc)
 
-               assert.equal(typeof account.balance, 'bigint')
+               assert.equals(typeof account.balance, 'bigint')
                assert.notEqual(account.balance, undefined)
                assert.notEqual(account.balance, null)
                assert.notEqual(account.balance, '')
                assert.notEqual(account.balance && account.balance < 0, true)
 
-               assert.equal(typeof account.frontier, 'string')
+               assert.equals(typeof account.frontier, 'string')
                assert.notEqual(account.frontier, undefined)
                assert.notEqual(account.frontier, null)
                assert.notEqual(account.frontier, '')
                assert.match(account.frontier ?? '', /^[0-9A-F]{64}$/i)
 
-               assert.equal(account.representative && account.representative.constructor, Account)
+               assert.equals(account.representative && account.representative.constructor, Account)
                assert.notEqual(account.representative, undefined)
                assert.notEqual(account.representative, null)
                assert.notEqual(account.representative, '')
@@ -42,7 +47,7 @@ describe.skip('refreshing account info', async () => {
        test('should throw when refreshing unopened account', async () => {
                const accounts = await wallet.accounts(0x7fffffff)
                const account = accounts[0]
-               await assert.rejects(account.refresh(node),
+               await assert.rejects(account.refresh(rpc),
                        { message: 'Account not found' })
        })
 
@@ -60,26 +65,26 @@ describe.skip('refreshing account info', async () => {
        })
 })
 
-describe.skip('finding next unopened account', async () => {
+skip('finding next unopened account', async () => {
        test('should return correct account from test vector', async () => {
-               const account = await wallet.getNextNewAccount(node)
+               const account = await wallet.getNextNewAccount(rpc)
                assert.ok(account)
-               assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_1)
-               assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
+               assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1)
+               assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
        })
 
        test('should return successfully for small batch size', async () => {
-               const account = await wallet.getNextNewAccount(node, 1)
+               const account = await wallet.getNextNewAccount(rpc, 1)
                assert.ok(account)
-               assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_1)
-               assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
+               assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1)
+               assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
        })
 
        test('should return successfully for large batch size', async () => {
-               const account = await wallet.getNextNewAccount(node, 100)
+               const account = await wallet.getNextNewAccount(rpc, 100)
                assert.ok(account)
-               assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_1)
-               assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
+               assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1)
+               assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
        })
 
        test('should throw on invalid node URL', async () => {
@@ -97,35 +102,35 @@ describe.skip('finding next unopened account', async () => {
 
        test('should throw on invalid batch size', async () => {
                //@ts-expect-error
-               await assert.rejects(wallet.getNextNewAccount(node, null))
-               await assert.rejects(wallet.getNextNewAccount(node, -1))
+               await assert.rejects(wallet.getNextNewAccount(rpc, null))
+               await assert.rejects(wallet.getNextNewAccount(rpc, -1))
                //@ts-expect-error
-               await assert.rejects(wallet.getNextNewAccount(node, ''))
+               await assert.rejects(wallet.getNextNewAccount(rpc, ''))
                //@ts-expect-error
-               await assert.rejects(wallet.getNextNewAccount(node, 'foo'))
+               await assert.rejects(wallet.getNextNewAccount(rpc, 'foo'))
                //@ts-expect-error
-               await assert.rejects(wallet.getNextNewAccount(node, { 'foo': 'bar' }))
+               await assert.rejects(wallet.getNextNewAccount(rpc, { 'foo': 'bar' }))
        })
 })
 
-describe.skip('refreshing wallet accounts', async () => {
+skip('refreshing wallet accounts', async () => {
        test('should get balance, frontier, and representative for one account', async () => {
-               const accounts = await wallet.refresh(node)
+               const accounts = await wallet.refresh(rpc)
                const account = accounts[0]
                assert.ok(account instanceof Account)
-               assert.equal(typeof account.balance, 'bigint')
+               assert.equals(typeof account.balance, 'bigint')
                assert.notEqual(account.frontier, undefined)
                assert.notEqual(account.frontier, null)
-               assert.equal(typeof account.frontier, 'string')
+               assert.equals(typeof account.frontier, 'string')
        })
 
        test('should get balance, frontier, and representative for multiple accounts', async () => {
-               const accounts = await wallet.refresh(node, 0, 2)
-               assert.equal(accounts.length, 1)
+               const accounts = await wallet.refresh(rpc, 0, 2)
+               assert.equals(accounts.length, 1)
                assert.ok(accounts[0] instanceof Account)
        })
 
        test('should handle failure gracefully', async () => {
-               await assert.doesNotReject(wallet.refresh(node, 0, 20))
+               await assert.doesNotReject(wallet.refresh(rpc, 0, 20))
        })
 })
index d37439cbf918e8f17b86ff8afe492646cf31c4fc..0415a97117cbfc25972105c8929c599cdb9455c0 100644 (file)
@@ -3,12 +3,11 @@
 \r
 'use strict'\r
 \r
-import '#test/GLOBALS.mjs'\r
-import { describe, expect, test } from '@jest/globals'\r
+import { assert, test } from '#test/GLOBALS.mjs'\r
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { SendBlock, ReceiveBlock, ChangeBlock } from '#dist/main.js'\r
 \r
-describe('valid blocks', async () => {\r
+test('valid blocks', async () => {\r
        test('should not allow negative balances', async () => {\r
                assert.throws(() => {\r
                        const block = new SendBlock(\r
@@ -32,7 +31,7 @@ describe('valid blocks', async () => {
                        '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D'\r
                )\r
                assert.notEqual(block.balance, 0)\r
-               assert.equal(block.balance, BigInt(0))\r
+               assert.equals(block.balance, BigInt(0))\r
        })\r
 \r
        test('should subtract balance from SendBlock correctly', async () => {\r
@@ -44,7 +43,7 @@ describe('valid blocks', async () => {
                        NANO_TEST_VECTORS.ADDRESS_2,\r
                        '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D'\r
                )\r
-               assert.equal(block.balance, 1000000000000000000000000000000n)\r
+               assert.equals(block.balance, 1000000000000000000000000000000n)\r
        })\r
 \r
        test('should add balance from ReceiveBlock correctly', async () => {\r
@@ -56,11 +55,11 @@ describe('valid blocks', async () => {
                        NANO_TEST_VECTORS.ADDRESS_2,\r
                        '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D'\r
                )\r
-               assert.equal(block.balance, 3000000000000000000000000000000n)\r
+               assert.equals(block.balance, 3000000000000000000000000000000n)\r
        })\r
 })\r
 \r
-describe('block signing tests using official test vectors', async () => {\r
+test('block signing tests using official test vectors', async () => {\r
        test('should create a valid signature for an open block', async () => {\r
                const block = new ReceiveBlock(\r
                        NANO_TEST_VECTORS.OPEN_BLOCK.account,\r
@@ -72,8 +71,8 @@ describe('block signing tests using official test vectors', async () => {
                        NANO_TEST_VECTORS.OPEN_BLOCK.work\r
                )\r
                await block.sign(NANO_TEST_VECTORS.OPEN_BLOCK.key)\r
-               assert.equal(await block.hash(), NANO_TEST_VECTORS.OPEN_BLOCK.hash)\r
-               assert.equal(block.signature, NANO_TEST_VECTORS.OPEN_BLOCK.signature)\r
+               assert.equals(await block.hash(), NANO_TEST_VECTORS.OPEN_BLOCK.hash)\r
+               assert.equals(block.signature, NANO_TEST_VECTORS.OPEN_BLOCK.signature)\r
        })\r
 \r
        test('should create a valid signature for a receive block', async () => {\r
@@ -87,8 +86,8 @@ describe('block signing tests using official test vectors', async () => {
                        NANO_TEST_VECTORS.RECEIVE_BLOCK.work\r
                )\r
                await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key)\r
-               assert.equal(await block.hash(), NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
-               assert.equal(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
+               assert.equals(await block.hash(), NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
+               assert.equals(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
        })\r
 \r
        test('should create a valid signature for a receive block without work', async () => {\r
@@ -101,9 +100,9 @@ describe('block signing tests using official test vectors', async () => {
                        NANO_TEST_VECTORS.RECEIVE_BLOCK.previous\r
                )\r
                await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key)\r
-               assert.equal(await block.hash(), NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
-               assert.equal(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
-               assert.equal(block.work, '')\r
+               assert.equals(await block.hash(), NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
+               assert.equals(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
+               assert.equals(block.work, '')\r
        })\r
 \r
        test('should create a valid signature for a send block', async () => {\r
@@ -117,8 +116,8 @@ describe('block signing tests using official test vectors', async () => {
                        NANO_TEST_VECTORS.SEND_BLOCK.work\r
                )\r
                await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key)\r
-               assert.equal(await block.hash(), NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
-               assert.equal(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
+               assert.equals(await block.hash(), NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
+               assert.equals(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
        })\r
 \r
        test('should create a valid signature for a send block without work', async () => {\r
@@ -131,9 +130,9 @@ describe('block signing tests using official test vectors', async () => {
                        NANO_TEST_VECTORS.SEND_BLOCK.previous\r
                )\r
                await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key)\r
-               assert.equal(await block.hash(), NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
-               assert.equal(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
-               assert.equal(block.work, '')\r
+               assert.equals(await block.hash(), NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
+               assert.equals(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
+               assert.equals(block.work, '')\r
        })\r
 \r
        test('should create a valid signature for a change rep block', async () => {\r
@@ -146,8 +145,8 @@ describe('block signing tests using official test vectors', async () => {
                        work,\r
                )\r
                await block.sign('781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3') // Did not find a private key at nano docs for this address\r
-               assert.equal(block.signature?.toUpperCase(), 'A3C3C66D6519CBC0A198E56855942DEACC6EF741021A1B11279269ADC587DE1DA53CD478B8A47553231104CF24D742E1BB852B0546B87038C19BAE20F9082B0D')\r
-               assert.equal(block.work, work)\r
+               assert.equals(block.signature?.toUpperCase(), 'A3C3C66D6519CBC0A198E56855942DEACC6EF741021A1B11279269ADC587DE1DA53CD478B8A47553231104CF24D742E1BB852B0546B87038C19BAE20F9082B0D')\r
+               assert.equals(block.work, work)\r
        })\r
 \r
        test('should create a valid signature for a change rep block without work', async () => {\r
@@ -158,7 +157,7 @@ describe('block signing tests using official test vectors', async () => {
                        'F3C1D7B6EE97DA09D4C00538CEA93CBA5F74D78FD3FBE71347D2DFE7E53DF327'\r
                )\r
                await block.sign(NANO_TEST_VECTORS.PRIVATE_0)\r
-               assert.equal(block.signature?.toUpperCase(), '2BD2F905E74B5BEE3E2277CED1D1E3F7535E5286B6E22F7B08A814AA9E5C4E1FEA69B61D60B435ADC2CE756E6EE5F5BE7EC691FE87E024A0B22A3D980CA5B305')\r
-               assert.equal(block.work, '')\r
+               assert.equals(block.signature?.toUpperCase(), '2BD2F905E74B5BEE3E2277CED1D1E3F7535E5286B6E22F7B08A814AA9E5C4E1FEA69B61D60B435ADC2CE756E6EE5F5BE7EC691FE87E024A0B22A3D980CA5B305')\r
+               assert.equals(block.work, '')\r
        })\r
 })\r
index 165c9ede9e33e3463784bcdd45fa68546b3a78ec..04be748e7b18a2a04deec7963507442709163dc9 100644 (file)
@@ -3,54 +3,59 @@
 \r
 'use strict'\r
 \r
-import '#test/GLOBALS.mjs'\r
-import { describe, expect, test } from '@jest/globals'\r
+import { assert, skip, test } from '#test/GLOBALS.mjs'\r
 import { RAW_MAX, NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { Bip44Wallet, Account, SendBlock, Rpc, Tools } from '#dist/main.js'\r
 \r
 const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
 await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-const rpc = new Rpc(process.env.NODE_URL ?? '', process.env.API_KEY_NAME)\r
-\r
-describe('unit conversion tests', async () => {\r
+let rpc\r
+//@ts-expect-error\r
+var process = process || null\r
+if (process) {\r
+       //@ts-expect-error\r
+       rpc = new Rpc(process?.env?.NODE_URL ?? '', process?.env?.API_KEY_NAME)\r
+}\r
+\r
+test('unit conversion tests', async () => {\r
        test('should convert nano to raw', async () => {\r
                const result = await Tools.convert('1', 'NANO', 'RAW')\r
-               assert.equal(result, '1000000000000000000000000000000')\r
+               assert.equals(result, '1000000000000000000000000000000')\r
        })\r
 \r
        test('should convert raw to nano', async () => {\r
                const result = await Tools.convert('1000000000000000000000000000000', 'RAW', 'NANO')\r
-               assert.equal(result, '1')\r
+               assert.equals(result, '1')\r
        })\r
 \r
        test('should convert 1 raw to 10^-29 nano', async () => {\r
                const result = await Tools.convert('1', 'RAW', 'NANO')\r
-               assert.equal(result, '.000000000000000000000000000001')\r
+               assert.equals(result, '.000000000000000000000000000001')\r
        })\r
 \r
        test('should ignore leading and trailing zeros', async () => {\r
                const result = await Tools.convert('0011002200.0033004400', 'nano', 'nano')\r
-               assert.equal(result, '11002200.00330044')\r
+               assert.equals(result, '11002200.00330044')\r
        })\r
 \r
        test('should convert raw to nyano', async () => {\r
                const result = await Tools.convert(RAW_MAX, 'RAW', 'NYANO')\r
-               assert.equal(result, '340282366920938.463463374607431768211455')\r
+               assert.equals(result, '340282366920938.463463374607431768211455')\r
        })\r
 \r
        test('should convert case-insensitive nyano to raw', async () => {\r
                const result = await Tools.convert('0.000000000000000123456789', 'nYaNo', 'rAw')\r
-               assert.equal(result, '123456789')\r
+               assert.equals(result, '123456789')\r
        })\r
 \r
        test('should convert nano to pico', async () => {\r
                const result = await Tools.convert('123.456', 'nano', 'pico')\r
-               assert.equal(result, '123456')\r
+               assert.equals(result, '123456')\r
        })\r
 \r
        test('should convert knano to pico', async () => {\r
                const result = await Tools.convert('123.456', 'nano', 'pico')\r
-               assert.equal(result, '123456')\r
+               assert.equals(result, '123456')\r
        })\r
 \r
        test('should throw if amount exceeds raw max', async () => {\r
@@ -74,26 +79,26 @@ describe('unit conversion tests', async () => {
        })\r
 })\r
 \r
-describe('signature tests', async () => {\r
+test('signature tests', async () => {\r
        test('should sign data with a single parameter', async () => {\r
                const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi')\r
-               assert.equal(result, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C')\r
+               assert.equals(result, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C')\r
        })\r
 \r
        test('should sign data with multiple parameters', async () => {\r
                const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi', 'somePassword')\r
-               assert.equal(result, 'BB534F9B469AF451B1941FFEF8EE461FC5D284B5D393140900C6E13A65EF08D0AE2BC77131EE182922F66C250C7237A83878160457D5C39A70E55F7FCE925804')\r
+               assert.equals(result, 'BB534F9B469AF451B1941FFEF8EE461FC5D284B5D393140900C6E13A65EF08D0AE2BC77131EE182922F66C250C7237A83878160457D5C39A70E55F7FCE925804')\r
        })\r
 \r
        test('should verify a signature using the public key', async () => {\r
                const result = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi')\r
-               assert.equal(result, true)\r
+               assert.equals(result, true)\r
 \r
                const result2 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'mir@metsanheimo.fi')\r
-               assert.equal(result2, false)\r
+               assert.equals(result2, false)\r
 \r
                const result3 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'AECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi')\r
-               assert.equal(result3, false)\r
+               assert.equals(result3, false)\r
        })\r
 \r
        test('should verify a block using the public key', async () => {\r
@@ -109,7 +114,7 @@ describe('signature tests', async () => {
                )\r
                await sendBlock.sign(account.privateKey ?? '')\r
                const valid = await sendBlock.verify(account.publicKey)\r
-               assert.equal(valid, true)\r
+               assert.equals(valid, true)\r
        })\r
 \r
        test('should reject a block using the wrong public key', async () => {\r
@@ -127,20 +132,20 @@ describe('signature tests', async () => {
 \r
                sendBlock.account = Account.fromAddress('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p')\r
                const valid = await sendBlock.verify(account.publicKey)\r
-               assert.equal(valid, false)\r
+               assert.equals(valid, false)\r
        })\r
 })\r
 \r
-describe('sweeper', async () => {\r
+test('sweeper', async () => {\r
        test('throws without required parameters', async () => {\r
                //@ts-expect-error\r
                await assert.rejects(Tools.sweep(),\r
-                       { message: 'Missing required sweep arguments' })\r
+                       'Missing required sweep arguments')\r
        })\r
 \r
-       test.skip('fails gracefully for ineligible accounts', async () => {\r
+       skip('fails gracefully for ineligible accounts', async () => {\r
                const results = await Tools.sweep(rpc, wallet, NANO_TEST_VECTORS.ADDRESS_1)\r
                assert.ok(results)\r
-               assert.equal(results.length, 1)\r
+               assert.equals(results.length, 1)\r
        })\r
 })\r