From a06a331d855aa3158ee3bbb075a087d1878f126a Mon Sep 17 00:00:00 2001 From: Eric Corson Date: Wed, 19 Jul 2023 10:25:09 +0900 Subject: [PATCH 1/2] chore: rename anoma to namada Closes #323. --- README.md | 6 ++-- apps/extension/README.md | 8 ++--- apps/extension/package.json | 18 +++++----- .../src/App/Accounts/AccountListing.tsx | 6 ++-- apps/extension/src/App/Accounts/Accounts.tsx | 2 +- .../extension/src/App/Accounts/AddAccount.tsx | 6 ++-- apps/extension/src/App/App.tsx | 10 +++--- .../src/App/LockWrapper/LockWrapper.tsx | 2 +- apps/extension/src/App/Login/Login.tsx | 2 +- .../DeleteAccount/DeleteAccount.tsx | 4 +-- .../Settings/ExtraSettings/ExtraSettings.tsx | 2 +- .../ResetPassword/ResetPassword.tsx | 4 +-- apps/extension/src/App/Settings/Settings.tsx | 6 ++-- apps/extension/src/App/Setup/Setup.tsx | 2 +- apps/extension/src/Approvals/Approvals.tsx | 4 +-- .../ApproveConnection/ApproveConnection.tsx | 2 +- .../ApproveTransfer/ApproveTransfer.tsx | 6 ++-- .../ApproveTransfer/ConfirmTransfer.tsx | 4 +-- .../Setup/AccountCreation/AccountCreation.tsx | 2 +- .../Steps/SeedPhrase/SeedPhrase.tsx | 4 +-- .../SeedPhraseConfirmation.tsx | 2 +- .../Setup/Common/Completion/Completion.tsx | 4 +-- .../Common/Password/Password.components.ts | 2 +- .../src/Setup/Common/Password/Password.tsx | 2 +- .../src/Setup/ImportAccount/ImportAccount.tsx | 2 +- .../ImportAccount/Steps/SeedPhraseImport.tsx | 2 +- apps/extension/src/Setup/Ledger/Ledger.tsx | 4 +-- apps/extension/src/Setup/Setup.tsx | 2 +- apps/extension/src/Setup/Start/Start.tsx | 4 +-- .../src/background/approvals/service.ts | 4 +-- .../src/background/chains/handler.ts | 2 +- .../src/background/chains/messages.ts | 2 +- .../src/background/chains/service.ts | 6 ++-- apps/extension/src/background/index.ts | 14 ++++---- .../src/background/keyring/crypto.ts | 6 ++-- .../src/background/keyring/keyring.ts | 14 ++++---- .../src/background/keyring/messages.ts | 6 ++-- .../src/background/keyring/service.ts | 14 ++++---- .../extension/src/background/keyring/types.ts | 2 +- .../extension/src/background/keyring/utils.ts | 2 +- .../extension/src/background/ledger/ledger.ts | 2 +- .../src/background/offscreen/offscreen.html | 2 +- .../src/background/offscreen/utils.ts | 2 +- .../src/background/web-workers/index.ts | 2 +- .../web-workers/submit-transfer-web-worker.ts | 8 ++--- apps/extension/src/content/events.ts | 2 +- apps/extension/src/content/index.ts | 14 ++++---- apps/extension/src/content/injected.ts | 14 ++++---- .../src/extension/ExtensionRouter.ts | 6 ++-- apps/extension/src/extension/utils.ts | 6 ++-- apps/extension/src/manifest/_base.json | 4 +-- apps/extension/src/manifest/v2/_base.json | 8 ++--- apps/extension/src/manifest/v3/_base.json | 6 ++-- .../{InjectedAnoma.ts => InjectedNamada.ts} | 6 ++-- .../{Anoma.test.ts => Namada.test.ts} | 30 ++++++++-------- .../src/provider/{Anoma.ts => Namada.ts} | 4 +-- apps/extension/src/provider/Proxy.ts | 8 ++--- apps/extension/src/provider/Signer.ts | 18 +++++----- apps/extension/src/provider/data.mock.ts | 4 +-- apps/extension/src/provider/index.ts | 4 +-- apps/extension/src/provider/messages.ts | 2 +- apps/extension/src/provider/types.ts | 8 ++--- apps/extension/src/public/approvals.html | 6 ++-- apps/extension/src/public/popup.html | 6 ++-- apps/extension/src/public/setup.html | 6 ++-- apps/extension/src/router/types/enums.ts | 18 +++++----- apps/extension/src/services/requester.tsx | 6 ++-- apps/extension/src/test/init.ts | 24 ++++++------- apps/extension/webpack.config.js | 2 +- apps/namada-interface/README.md | 10 +++--- apps/namada-interface/package.json | 12 +++---- .../AccountOverview.components.ts | 2 +- .../App/AccountOverview/AccountOverview.tsx | 12 +++---- .../DerivedAccounts.components.ts | 2 +- .../DerivedAccounts/DerivedAccounts.tsx | 6 ++-- .../src/App/App.components.ts | 2 +- apps/namada-interface/src/App/App.tsx | 8 ++--- .../src/App/Bridge/Bridge.tsx | 2 +- .../src/App/Governance/Governance.tsx | 2 +- apps/namada-interface/src/App/NotFound.tsx | 2 +- .../PublicGoodsFunding/PublicGoodsFunding.tsx | 2 +- apps/namada-interface/src/App/Redirect.tsx | 2 +- .../src/App/Settings/Settings.tsx | 2 +- .../SettingsWalletSettings.tsx | 6 ++-- .../NewBondingPosition.components.ts | 2 +- .../NewBondingPosition/NewBondingPosition.tsx | 4 +-- .../src/App/Staking/Staking.tsx | 6 ++-- .../StakingOverview/StakingOverview.tsx | 2 +- .../Staking/UnbondPosition/UnbondPosition.tsx | 4 +-- .../ValidatorDetails/ValidatorDetails.tsx | 4 +-- .../MainContainerNavigation.tsx | 2 +- .../StakingAndGovernance.tsx | 4 +-- apps/namada-interface/src/App/Toast/toast.tsx | 2 +- .../src/App/Token/IBCTransfer/IBCTransfer.tsx | 10 +++--- .../src/App/Token/TokenDetails.tsx | 10 +++--- .../App/Token/TokenReceive/TokenReceive.tsx | 4 +-- .../Token/TokenSend/TokenSend.components.ts | 2 +- .../src/App/Token/TokenSend/TokenSend.tsx | 8 ++--- .../src/App/Token/TokenSend/TokenSendForm.tsx | 6 ++-- .../App/Token/Transfers/TransferDetails.tsx | 10 +++--- .../src/App/Token/Transfers/Transfers.tsx | 8 ++--- .../TopNavigation/topNavigation.components.ts | 2 +- .../src/App/TopNavigation/topNavigation.tsx | 10 +++--- .../topNavigationLoggedIn.components.ts | 2 +- .../TopNavigation/topNavigationLoggedIn.tsx | 4 +-- apps/namada-interface/src/App/types.ts | 8 ++--- apps/namada-interface/src/index.tsx | 2 +- .../extensionEvents/handlers/index.ts | 2 +- .../extensionEvents/handlers/keplr.ts | 2 +- .../extensionEvents/handlers/metamask.ts | 2 +- .../handlers/{anoma.ts => namada.ts} | 16 ++++----- .../src/services/extensionEvents/provider.tsx | 36 +++++++++---------- .../src/services/integrations/provider.tsx | 2 +- .../slices/StakingAndGovernance/actions.ts | 8 ++--- apps/namada-interface/src/slices/accounts.ts | 6 ++-- apps/namada-interface/src/slices/coins.ts | 4 +-- apps/namada-interface/src/slices/settings.ts | 2 +- apps/namada-interface/src/slices/transfers.ts | 4 +-- apps/namada-interface/src/store/mocks.ts | 28 +++++++-------- apps/namada-interface/src/store/store.ts | 2 +- apps/namada-interface/src/styled.d.ts | 2 +- package.json | 2 +- packages/chains/package.json | 4 +-- packages/chains/src/chains/cosmos.ts | 2 +- packages/chains/src/chains/ethereum.ts | 2 +- packages/chains/src/chains/namada.ts | 4 +-- packages/components/package.json | 6 ++-- .../src/Button/button.components.ts | 2 +- .../components/src/Input/input.components.ts | 2 +- .../src/Select/Select.components.ts | 2 +- .../src/Toggle/toggle.components.ts | 2 +- packages/crypto/README.md | 2 +- packages/crypto/lib/Cargo.toml | 2 +- packages/crypto/lib/src/lib.rs | 2 +- packages/crypto/package.json | 4 +-- packages/hooks/README.md | 2 +- packages/hooks/package.json | 10 +++--- packages/hooks/src/useIntegration.ts | 14 ++++---- packages/hooks/src/useUntil.ts | 2 +- packages/integrations/README.md | 2 +- packages/integrations/package.json | 8 ++--- packages/integrations/src/Keplr.test.ts | 2 +- packages/integrations/src/Keplr.ts | 4 +-- packages/integrations/src/Metamask.ts | 4 +-- .../integrations/src/{Anoma.ts => Namada.ts} | 30 ++++++++-------- packages/integrations/src/index.ts | 4 +-- .../integrations/src/types/Integration.ts | 2 +- packages/shared/README.md | 2 +- packages/shared/lib/Cargo.toml | 2 +- packages/shared/lib/src/lib.rs | 2 +- packages/shared/lib/src/sdk/mod.js | 2 +- packages/shared/lib/src/types/masp.rs | 8 ++--- packages/shared/package.json | 4 +-- packages/storage/package.json | 4 +-- packages/storage/src/store/Store.ts | 2 +- packages/types/README.md | 10 +++--- packages/types/package.json | 4 +-- packages/types/src/chain.ts | 8 ++--- packages/types/src/events.ts | 10 +++--- packages/types/src/index.ts | 2 +- packages/types/src/{anoma.ts => namada.ts} | 6 ++-- packages/utils/README.md | 2 +- packages/utils/package.json | 4 +-- packages/utils/src/helpers/index.ts | 2 +- packages/utils/src/theme/theme.ts | 2 +- specs/browser-extension/integration.md | 12 +++---- specs/browser-extension/security.md | 2 +- specs/interface/shielded-transfers.md | 12 +++---- specs/interface/transparent-transactions.md | 8 ++--- specs/packages/overview.md | 2 +- specs/packages/sdk.md | 4 +-- 171 files changed, 482 insertions(+), 484 deletions(-) rename apps/extension/src/provider/{InjectedAnoma.ts => InjectedNamada.ts} (96%) rename apps/extension/src/provider/{Anoma.test.ts => Namada.test.ts} (86%) rename apps/extension/src/provider/{Anoma.ts => Namada.ts} (96%) rename apps/namada-interface/src/services/extensionEvents/handlers/{anoma.ts => namada.ts} (76%) rename packages/integrations/src/{Anoma.ts => Namada.ts} (75%) rename packages/types/src/{anoma.ts => namada.ts} (90%) diff --git a/README.md b/README.md index 9dd246aaf6..243676d038 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,6 @@ for solving possible issue see [Troubleshooting](#troubleshooting) ## Introduction -This is the main app of the project and it is the user interface of the application. It is based on create-react-app and uses TypeScript. Some of its' functionality is split to external project living in this repository, under the directory `packages`. They are: [anoma-lib](#anoma-lib), [key-management](#key-management), [masp-web](#masp-web). All of those dependencies use Rust code that is compiled to WASM with [bindgen](https://rustwasm.github.io/wasm-bindgen). Anoma-wallet and its developers do not have to care about this fact, except when compiling the dependencies in the beginning. All of the libraries using WASM exposes a usual TypeScript interface. - This is the `namada-interface` monorepo. Within it, you will find the code for the web wallet implementation. it contains the following packages: ```bash @@ -49,14 +47,14 @@ namada-interface/ ├── namada-interface/ # Main wallet React App ├── extension/ # Browser Extension React App └── packages/ - ├── crypto/ # Crypto functions related to anoma extension and interface + ├── crypto/ # Crypto functions related to namada extension and interface ├── integrations/ # Third-party wallet integrations ├── masp-web/ # utilities for performing MASP actions ├── rpc/ # Library for handling HTTP and WebSocket RPC calls ├── seed-management/ # Seed management library ├── session/ # Session management library ├── shared/ # Package for interfacing with `namada/shared` - ├── tx/ # Library for interfacing with Anoma transactions + ├── tx/ # Library for interfacing with Namada transactions ├── utils/ # Shared utilities ├── wallet/ # Library for deriving keys └── wasm/ # Legacy wasm library diff --git a/apps/extension/README.md b/apps/extension/README.md index 54e623bfad..d73968913b 100644 --- a/apps/extension/README.md +++ b/apps/extension/README.md @@ -1,6 +1,6 @@ -# Anoma Browser Extension +# Namada Browser Extension -This is the Anoma Browser Extension project. +This is the Namada Browser Extension project. ## Usage @@ -52,10 +52,10 @@ Once you have run `yarn build`, you can use the files in `./dist` to install the 1. In Firefox, navigate to `about:debugging#/runtime/this-firefox` 2. Select `Load Temporary Add-On...` -3. Navigate to either the `build/browser/manifest.json` or the `build/firefox/anoma_extension-0.1.0.zip` file to install +3. Navigate to either the `build/browser/manifest.json` or the `build/firefox/namada_extension-0.1.0.zip` file to install The extension should be installed. Currently, this is enabled for `namada.me`, so navigating to that page will call the `content` scripts, -hopefully instantiating an instance of the `Anoma()` class API for handling communication between client and key store. +hopefully instantiating an instance of the `Namada()` class API for handling communication between client and key store. ## Notes diff --git a/apps/extension/package.json b/apps/extension/package.json index 9ed075975a..a9b975be3e 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -1,7 +1,7 @@ { - "name": "@anoma/extension", + "name": "@namada/extension", "version": "0.1.0", - "description": "Anoma Browser Extension", + "description": "Namada Browser Extension", "repository": "https://github.com/anoma/namada-interface/", "author": "Heliax Dev ", "license": "MIT", @@ -26,13 +26,13 @@ "wasm:build:dev": "./scripts/build.sh" }, "dependencies": { - "@anoma/chains": "0.1.0", - "@anoma/components": "0.1.0", - "@anoma/crypto": "0.1.0", - "@anoma/shared": "0.1.0", - "@anoma/storage": "0.1.0", - "@anoma/types": "0.1.0", - "@anoma/utils": "0.1.0", + "@namada/chains": "0.1.0", + "@namada/components": "0.1.0", + "@namada/crypto": "0.1.0", + "@namada/shared": "0.1.0", + "@namada/storage": "0.1.0", + "@namada/types": "0.1.0", + "@namada/utils": "0.1.0", "@cosmjs/encoding": "^0.29.0", "@ledgerhq/hw-transport": "^6.28.3", "@ledgerhq/hw-transport-webhid": "^6.27.14", diff --git a/apps/extension/src/App/Accounts/AccountListing.tsx b/apps/extension/src/App/Accounts/AccountListing.tsx index 6393fcd63c..a061517e10 100644 --- a/apps/extension/src/App/Accounts/AccountListing.tsx +++ b/apps/extension/src/App/Accounts/AccountListing.tsx @@ -1,8 +1,8 @@ import { useNavigate } from "react-router-dom"; -import { Icon, IconName } from "@anoma/components"; -import { AccountType, Bip44Path, DerivedAccount } from "@anoma/types"; -import { shortenAddress } from "@anoma/utils"; +import { Icon, IconName } from "@namada/components"; +import { AccountType, Bip44Path, DerivedAccount } from "@namada/types"; +import { shortenAddress } from "@namada/utils"; import { TopLevelRoute } from "App/types"; import { diff --git a/apps/extension/src/App/Accounts/Accounts.tsx b/apps/extension/src/App/Accounts/Accounts.tsx index 6193a90ba2..fef97fa160 100644 --- a/apps/extension/src/App/Accounts/Accounts.tsx +++ b/apps/extension/src/App/Accounts/Accounts.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { DerivedAccount } from "@anoma/types"; +import { DerivedAccount } from "@namada/types"; import { AccountsContainer, AccountsList, diff --git a/apps/extension/src/App/Accounts/AddAccount.tsx b/apps/extension/src/App/Accounts/AddAccount.tsx index ff2f4dd6a8..3b823b4df4 100644 --- a/apps/extension/src/App/Accounts/AddAccount.tsx +++ b/apps/extension/src/App/Accounts/AddAccount.tsx @@ -7,9 +7,9 @@ import { Input, InputVariants, Toggle, -} from "@anoma/components"; -import { AccountType, DerivedAccount } from "@anoma/types"; -import { chains, defaultChainId } from "@anoma/chains"; +} from "@namada/components"; +import { AccountType, DerivedAccount } from "@namada/types"; +import { chains, defaultChainId } from "@namada/chains"; import { ExtensionRequester } from "extension"; import { Ports } from "router"; diff --git a/apps/extension/src/App/App.tsx b/apps/extension/src/App/App.tsx index 5bd85db9f7..e669253b88 100644 --- a/apps/extension/src/App/App.tsx +++ b/apps/extension/src/App/App.tsx @@ -2,10 +2,10 @@ import React, { useEffect, useState } from "react"; import { ThemeProvider } from "styled-components"; import { Routes, Route, useNavigate } from "react-router-dom"; -import { DerivedAccount } from "@anoma/types"; -import { getTheme } from "@anoma/utils"; -import { Icon, IconName } from "@anoma/components"; -import { useUntil } from "@anoma/hooks"; +import { DerivedAccount } from "@namada/types"; +import { getTheme } from "@namada/utils"; +import { Icon, IconName } from "@namada/components"; +import { useUntil } from "@namada/hooks"; import { Ports } from "router"; import { @@ -188,7 +188,7 @@ export const App: React.FC = () => { - Anoma Browser Extension + Namada Browser Extension { diff --git a/apps/extension/src/Approvals/Approvals.tsx b/apps/extension/src/Approvals/Approvals.tsx index 979b3d0efe..d689ad1f31 100644 --- a/apps/extension/src/Approvals/Approvals.tsx +++ b/apps/extension/src/Approvals/Approvals.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import { ThemeProvider } from "styled-components"; import { Routes, Route } from "react-router-dom"; -import { getTheme } from "@anoma/utils"; +import { getTheme } from "@namada/utils"; import { AppContainer, @@ -32,7 +32,7 @@ export const Approvals: React.FC = () => { - Anoma Browser Extension + Namada Browser Extension void; diff --git a/apps/extension/src/background/index.ts b/apps/extension/src/background/index.ts index b34b5ca5dd..6f3c2ce0de 100644 --- a/apps/extension/src/background/index.ts +++ b/apps/extension/src/background/index.ts @@ -3,11 +3,11 @@ import { ExtensionKVStore, IndexedDBKVStore, MemoryKVStore, -} from "@anoma/storage"; -import { defaultChainId, chains } from "@anoma/chains"; -import { init as initCrypto } from "@anoma/crypto/src/init"; -import { init as initShared } from "@anoma/shared/src/init"; -import { Query, Sdk } from "@anoma/shared"; +} from "@namada/storage"; +import { defaultChainId, chains } from "@namada/chains"; +import { init as initCrypto } from "@namada/crypto/src/init"; +import { init as initShared } from "@namada/shared/src/init"; +import { Query, Sdk } from "@namada/shared"; import { ExtensionRouter, @@ -15,7 +15,7 @@ import { ContentScriptEnv, ExtensionMessenger, ExtensionRequester, - getAnomaRouterId, + getNamadaRouterId, } from "extension"; import { Ports, KVPrefix } from "router"; import { ApprovalsService, init as initApprovals } from "./approvals"; @@ -53,7 +53,7 @@ const { REACT_APP_NAMADA_URL = DEFAULT_URL } = process.env; await initShared(); - const routerId = await getAnomaRouterId(extensionStore); + const routerId = await getNamadaRouterId(extensionStore); const messenger = new ExtensionMessenger(); const requester = new ExtensionRequester(messenger, routerId); diff --git a/apps/extension/src/background/keyring/crypto.ts b/apps/extension/src/background/keyring/crypto.ts index ce8bc5c92c..28eb6e54a5 100644 --- a/apps/extension/src/background/keyring/crypto.ts +++ b/apps/extension/src/background/keyring/crypto.ts @@ -6,11 +6,11 @@ import { Rng, Salt, VecU8Pointer, -} from "@anoma/crypto"; -import { AccountType, Bip44Path } from "@anoma/types"; +} from "@namada/crypto"; +import { AccountType, Bip44Path } from "@namada/types"; import { Argon2Config } from "config"; import { CryptoRecord, KdfType, KeyStore } from "./types"; -import { readVecU8Pointer } from "@anoma/crypto/src/utils"; +import { readVecU8Pointer } from "@namada/crypto/src/utils"; type CryptoArgs = { alias: string; diff --git a/apps/extension/src/background/keyring/keyring.ts b/apps/extension/src/background/keyring/keyring.ts index 7de2295021..51db0b80b5 100644 --- a/apps/extension/src/background/keyring/keyring.ts +++ b/apps/extension/src/background/keyring/keyring.ts @@ -7,7 +7,7 @@ import { PhraseSize, ShieldedHDWallet, VecU8Pointer, -} from "@anoma/crypto"; +} from "@namada/crypto"; import { Account, Address, @@ -16,15 +16,15 @@ import { PaymentAddress, Sdk, Query, -} from "@anoma/shared"; -import { IStore, KVStore, Store } from "@anoma/storage"; +} from "@namada/shared"; +import { IStore, KVStore, Store } from "@namada/storage"; import { AccountType, Bip44Path, DerivedAccount, TransferMsgValue, -} from "@anoma/types"; -import { chains } from "@anoma/chains"; +} from "@namada/types"; +import { chains } from "@namada/chains"; import { Crypto } from "./crypto"; import { KeyRingStatus, @@ -37,8 +37,8 @@ import { import { readVecStringPointer, readStringPointer, -} from "@anoma/crypto/src/utils"; -import { Result } from "@anoma/utils"; +} from "@namada/crypto/src/utils"; +import { Result } from "@namada/utils"; import { deserialize } from "@dao-xyz/borsh"; // Generated UUID namespace for uuid v5 diff --git a/apps/extension/src/background/keyring/messages.ts b/apps/extension/src/background/keyring/messages.ts index c0bd0ed407..0e8758a3f1 100644 --- a/apps/extension/src/background/keyring/messages.ts +++ b/apps/extension/src/background/keyring/messages.ts @@ -1,9 +1,9 @@ -import { PhraseSize } from "@anoma/crypto"; -import { AccountType, Bip44Path, DerivedAccount } from "@anoma/types"; +import { PhraseSize } from "@namada/crypto"; +import { AccountType, Bip44Path, DerivedAccount } from "@namada/types"; import { Message } from "router"; import { ROUTE } from "./constants"; import { KeyRingStatus, ResetPasswordError, DeleteAccountError } from "./types"; -import { Result } from "@anoma/utils"; +import { Result } from "@namada/utils"; enum MessageType { CheckIsLocked = "check-is-locked", diff --git a/apps/extension/src/background/keyring/service.ts b/apps/extension/src/background/keyring/service.ts index 85278bddcb..1bf68f281b 100644 --- a/apps/extension/src/background/keyring/service.ts +++ b/apps/extension/src/background/keyring/service.ts @@ -1,10 +1,10 @@ import { fromBase64, toBase64 } from "@cosmjs/encoding"; -import { PhraseSize } from "@anoma/crypto"; -import { KVStore } from "@anoma/storage"; -import { AccountType, Bip44Path, DerivedAccount } from "@anoma/types"; -import { Query, Sdk } from "@anoma/shared"; -import { Result } from "@anoma/utils"; +import { PhraseSize } from "@namada/crypto"; +import { KVStore } from "@namada/storage"; +import { AccountType, Bip44Path, DerivedAccount } from "@namada/types"; +import { Query, Sdk } from "@namada/shared"; +import { Result } from "@namada/utils"; import { KeyRing } from "./keyring"; import { @@ -16,7 +16,7 @@ import { UtilityStore, } from "./types"; import { syncTabs, updateTabStorage } from "./utils"; -import { ExtensionRequester, getAnomaRouterId } from "extension"; +import { ExtensionRequester, getNamadaRouterId } from "extension"; import { Ports } from "router"; import { AccountChangedEventMsg, @@ -178,7 +178,7 @@ export class KeyRingService { xsk?: string ): Promise { const offscreenDocumentPath = "offscreen.html"; - const routerId = await getAnomaRouterId(this.extensionStore); + const routerId = await getNamadaRouterId(this.extensionStore); if (!(await hasOffscreenDocument(offscreenDocumentPath))) { await createOffscreenWithTxWorker(offscreenDocumentPath); diff --git a/apps/extension/src/background/keyring/types.ts b/apps/extension/src/background/keyring/types.ts index 42cf222ffe..318a55e6ce 100644 --- a/apps/extension/src/background/keyring/types.ts +++ b/apps/extension/src/background/keyring/types.ts @@ -1,4 +1,4 @@ -import { AccountType, Bip44Path, DerivedAccount } from "@anoma/types"; +import { AccountType, Bip44Path, DerivedAccount } from "@namada/types"; export enum KdfType { Argon2 = "argon2", diff --git a/apps/extension/src/background/keyring/utils.ts b/apps/extension/src/background/keyring/utils.ts index c35b6d642a..304fc6c258 100644 --- a/apps/extension/src/background/keyring/utils.ts +++ b/apps/extension/src/background/keyring/utils.ts @@ -1,4 +1,4 @@ -import { KVStore } from "@anoma/storage"; +import { KVStore } from "@namada/storage"; import { TabStore } from "./types"; import { ExtensionRequester } from "extension"; diff --git a/apps/extension/src/background/ledger/ledger.ts b/apps/extension/src/background/ledger/ledger.ts index 13fd0b08e9..f8a9b74329 100644 --- a/apps/extension/src/background/ledger/ledger.ts +++ b/apps/extension/src/background/ledger/ledger.ts @@ -8,7 +8,7 @@ import TransportUSB from "@ledgerhq/hw-transport-webusb"; import TransportHID from "@ledgerhq/hw-transport-webhid"; import Transport from "@ledgerhq/hw-transport"; -import { defaultChainId, chains } from "@anoma/chains"; +import { defaultChainId, chains } from "@namada/chains"; const namadaChain = chains[defaultChainId]; const bip44CoinType = namadaChain.bip44.coinType; diff --git a/apps/extension/src/background/offscreen/offscreen.html b/apps/extension/src/background/offscreen/offscreen.html index 4684887674..be7cc97bb1 100644 --- a/apps/extension/src/background/offscreen/offscreen.html +++ b/apps/extension/src/background/offscreen/offscreen.html @@ -1,2 +1,2 @@ - + diff --git a/apps/extension/src/background/offscreen/utils.ts b/apps/extension/src/background/offscreen/utils.ts index b9a951e5a2..a974e31b03 100644 --- a/apps/extension/src/background/offscreen/utils.ts +++ b/apps/extension/src/background/offscreen/utils.ts @@ -24,4 +24,4 @@ export const createOffscreenWithTxWorker = async ( }; export const SUBMIT_TRANSFER_MSG_TYPE = "submit-transfer-offscreen"; -export const OFFSCREEN_TARGET = "offscreen.anoma"; +export const OFFSCREEN_TARGET = "offscreen.namada"; diff --git a/apps/extension/src/background/web-workers/index.ts b/apps/extension/src/background/web-workers/index.ts index e1f54fe9f4..ff368d136d 100644 --- a/apps/extension/src/background/web-workers/index.ts +++ b/apps/extension/src/background/web-workers/index.ts @@ -14,7 +14,7 @@ export const init = ( payload?: string ) => Promise ): void => { - const w = new Worker("submit-transfer-web-worker.anoma.js"); + const w = new Worker("submit-transfer-web-worker.namada.js"); w.onmessage = (e: MessageEvent) => { const { msgName, payload } = e.data; diff --git a/apps/extension/src/background/web-workers/submit-transfer-web-worker.ts b/apps/extension/src/background/web-workers/submit-transfer-web-worker.ts index ac0293b17e..eeeb9a09c4 100644 --- a/apps/extension/src/background/web-workers/submit-transfer-web-worker.ts +++ b/apps/extension/src/background/web-workers/submit-transfer-web-worker.ts @@ -1,7 +1,7 @@ -import { defaultChainId, chains } from "@anoma/chains"; -import { Sdk } from "@anoma/shared"; -import { init as initShared } from "@anoma/shared/src/init"; -import { IndexedDBKVStore } from "@anoma/storage"; +import { defaultChainId, chains } from "@namada/chains"; +import { Sdk } from "@namada/shared"; +import { init as initShared } from "@namada/shared/src/init"; +import { IndexedDBKVStore } from "@namada/storage"; import { fromBase64 } from "@cosmjs/encoding"; import { KVPrefix } from "router"; import { diff --git a/apps/extension/src/content/events.ts b/apps/extension/src/content/events.ts index 0d98d5434f..afcbb94863 100644 --- a/apps/extension/src/content/events.ts +++ b/apps/extension/src/content/events.ts @@ -1,4 +1,4 @@ -import { Events } from "@anoma/types"; +import { Events } from "@namada/types"; import { Message, Router, Routes } from "../router"; diff --git a/apps/extension/src/content/index.ts b/apps/extension/src/content/index.ts index 1bbc56839a..76383ae697 100644 --- a/apps/extension/src/content/index.ts +++ b/apps/extension/src/content/index.ts @@ -1,28 +1,28 @@ import browser from "webextension-polyfill"; -import { Anoma, Proxy } from "provider"; +import { Namada, Proxy } from "provider"; import { ExtensionRouter, ExtensionRequester, ContentScriptEnv, ContentScriptGuards, ExtensionMessenger, - getAnomaRouterId, + getNamadaRouterId, } from "extension"; import { KVPrefix, Ports } from "router/types"; import { initEvents } from "./events"; import manifest from "manifest/_base.json"; -import { ExtensionKVStore } from "@anoma/storage"; +import { ExtensionKVStore } from "@namada/storage"; -// Start proxying messages from Anoma to InjectedAnoma +// Start proxying messages from Namada to InjectedNamada (async function init() { const extensionStore = new ExtensionKVStore(KVPrefix.LocalStorage, { get: browser.storage.local.get, set: browser.storage.local.set, }); - const routerId = await getAnomaRouterId(extensionStore); + const routerId = await getNamadaRouterId(extensionStore); const messenger = new ExtensionMessenger(); Proxy.start( - new Anoma(manifest.version, new ExtensionRequester(messenger, routerId)) + new Namada(manifest.version, new ExtensionRequester(messenger, routerId)) ); const router = new ExtensionRouter( @@ -38,7 +38,7 @@ import { ExtensionKVStore } from "@anoma/storage"; const container = document.head || document.documentElement; const scriptElement = document.createElement("script"); - scriptElement.src = browser.runtime.getURL("injected.anoma.js"); + scriptElement.src = browser.runtime.getURL("injected.namada.js"); scriptElement.type = "text/javascript"; container.insertBefore(scriptElement, container.children[0]); scriptElement.remove(); diff --git a/apps/extension/src/content/injected.ts b/apps/extension/src/content/injected.ts index 987d285daf..fc55bbb166 100644 --- a/apps/extension/src/content/injected.ts +++ b/apps/extension/src/content/injected.ts @@ -1,20 +1,20 @@ -import { InjectedAnoma } from "provider"; +import { InjectedNamada } from "provider"; import manifest from "manifest/_base.json"; declare global { // NOTE: var is required to extend globalThis // eslint-disable-next-line - var anoma: InjectedAnoma; + var namada: InjectedNamada; } -export function init(anoma: InjectedAnoma): void { +export function init(namada: InjectedNamada): void { if (process.env.NODE_ENV !== "production") { - if (!window.anoma) { - window.anoma = anoma; + if (!window.namada) { + window.namada = namada; } } else { - window.anoma = anoma; + window.namada = namada; } } -init(new InjectedAnoma(manifest.version)); +init(new InjectedNamada(manifest.version)); diff --git a/apps/extension/src/extension/ExtensionRouter.ts b/apps/extension/src/extension/ExtensionRouter.ts index 236f3e139c..6bd931ba2e 100644 --- a/apps/extension/src/extension/ExtensionRouter.ts +++ b/apps/extension/src/extension/ExtensionRouter.ts @@ -1,4 +1,4 @@ -import { getAnomaRouterId } from "./utils"; +import { getNamadaRouterId } from "./utils"; import { EnvProducer, MessageSender, @@ -6,7 +6,7 @@ import { RoutedMessage, Router, } from "router"; -import { KVStore } from "@anoma/storage"; +import { KVStore } from "@namada/storage"; import { Messenger } from "./ExtensionMessenger"; export class ExtensionRouter extends Router { @@ -43,7 +43,7 @@ export class ExtensionRouter extends Router { if ( message.msg?.meta?.routerId && - message.msg.meta.routerId !== (await getAnomaRouterId(this.store)) + message.msg.meta.routerId !== (await getNamadaRouterId(this.store)) ) { return; } diff --git a/apps/extension/src/extension/utils.ts b/apps/extension/src/extension/utils.ts index 200f6f8657..05df8d6703 100644 --- a/apps/extension/src/extension/utils.ts +++ b/apps/extension/src/extension/utils.ts @@ -1,11 +1,11 @@ import browser from "webextension-polyfill"; -import { KVStore } from "@anoma/storage"; +import { KVStore } from "@namada/storage"; import { Env, MessageSender } from "router/types"; -const ROUTER_ID_KEY = "anomaExtensionRouterId"; +const ROUTER_ID_KEY = "namadaExtensionRouterId"; const NO_TAB_ID = -2; -export const getAnomaRouterId = async ( +export const getNamadaRouterId = async ( store: KVStore ): Promise => { const storedId = await store.get(ROUTER_ID_KEY); diff --git a/apps/extension/src/manifest/_base.json b/apps/extension/src/manifest/_base.json index df80f3f9db..7fe3358a2b 100644 --- a/apps/extension/src/manifest/_base.json +++ b/apps/extension/src/manifest/_base.json @@ -1,5 +1,5 @@ { - "name": "Anoma Extension", - "description": "The Anoma Extension manages a user's wallet for the Anoma ecosystem.", + "name": "Namada Extension", + "description": "The Namada Extension manages a user's wallet for the Namada ecosystem.", "version": "0.1.0" } diff --git a/apps/extension/src/manifest/v2/_base.json b/apps/extension/src/manifest/v2/_base.json index b1b219bd90..c9a1ad2760 100644 --- a/apps/extension/src/manifest/v2/_base.json +++ b/apps/extension/src/manifest/v2/_base.json @@ -2,10 +2,10 @@ "manifest_version": 2, "browser_action": { "default_popup": "popup.html", - "default_title": "Anoma Extension" + "default_title": "Namada Extension" }, "background": { - "scripts": ["background.anoma.js"], + "scripts": ["background.namada.js"], "persistent": true }, "permissions": [ @@ -18,10 +18,10 @@ "content_scripts": [ { "matches": [""], - "js": ["content.anoma.js"], + "js": ["content.namada.js"], "run_at": "document_start", "all_frames": true } ], - "web_accessible_resources": ["injected.anoma.js", "assets/app.css"] + "web_accessible_resources": ["injected.namada.js", "assets/app.css"] } diff --git a/apps/extension/src/manifest/v3/_base.json b/apps/extension/src/manifest/v3/_base.json index 076dd8c96a..2f4b28a712 100644 --- a/apps/extension/src/manifest/v3/_base.json +++ b/apps/extension/src/manifest/v3/_base.json @@ -1,13 +1,13 @@ { "manifest_version": 3, "background": { - "service_worker": "background.anoma.js", + "service_worker": "background.namada.js", "type": "module" }, "content_scripts": [ { "matches": [""], - "js": ["content.anoma.js"] + "js": ["content.namada.js"] } ], "action": { @@ -19,7 +19,7 @@ }, "web_accessible_resources": [ { - "resources": ["injected.anoma.js", "assets/app.css"], + "resources": ["injected.namada.js", "assets/app.css"], "matches": [""] } ] diff --git a/apps/extension/src/provider/InjectedAnoma.ts b/apps/extension/src/provider/InjectedNamada.ts similarity index 96% rename from apps/extension/src/provider/InjectedAnoma.ts rename to apps/extension/src/provider/InjectedNamada.ts index 8b34a9a3dd..dc4acca6de 100644 --- a/apps/extension/src/provider/InjectedAnoma.ts +++ b/apps/extension/src/provider/InjectedNamada.ts @@ -1,13 +1,13 @@ import { - Anoma as IAnoma, + Namada as INamada, Chain, DerivedAccount, Signer as ISigner, -} from "@anoma/types"; +} from "@namada/types"; import { InjectedProxy } from "./InjectedProxy"; import { Signer } from "./Signer"; -export class InjectedAnoma implements IAnoma { +export class InjectedNamada implements INamada { constructor(private readonly _version: string) {} public async connect(chainId: string): Promise { diff --git a/apps/extension/src/provider/Anoma.test.ts b/apps/extension/src/provider/Namada.test.ts similarity index 86% rename from apps/extension/src/provider/Anoma.test.ts rename to apps/extension/src/provider/Namada.test.ts index d95ad519ad..a2a90bd329 100644 --- a/apps/extension/src/provider/Anoma.test.ts +++ b/apps/extension/src/provider/Namada.test.ts @@ -10,12 +10,12 @@ import { TransferMsgValue, TransferProps, Chain, - Anoma, -} from "@anoma/types"; + Namada, +} from "@namada/types"; import { KVKeys } from "router"; import { init, KVStoreMock } from "test/init"; -import { chains as defaultChains } from "@anoma/chains"; +import { chains as defaultChains } from "@namada/chains"; import { chain, keyStore, password, ACTIVE_ACCOUNT_ID } from "./data.mock"; import { KeyRing, @@ -25,21 +25,21 @@ import { PARENT_ACCOUNT_ID_KEY, UtilityStore, } from "background/keyring"; -import { Sdk } from "@anoma/shared"; +import { Sdk } from "@namada/shared"; import * as utils from "extension/utils"; // Needed for now as utils import webextension-polyfill directly jest.mock("webextension-polyfill", () => ({})); -describe("Anoma", () => { - let anoma: Anoma; +describe("Namada", () => { + let namada: Namada; let iDBStore: KVStoreMock; let utilityStore: KVStoreMock; let keyRingService: KeyRingService; beforeAll(async () => { - jest.spyOn(utils, "getAnomaRouterId").mockResolvedValue(1); - ({ anoma, iDBStore, utilityStore, keyRingService } = await init()); + jest.spyOn(utils, "getNamadaRouterId").mockResolvedValue(1); + ({ namada, iDBStore, utilityStore, keyRingService } = await init()); jest .spyOn(KeyRing.prototype, "checkPassword") @@ -54,14 +54,14 @@ describe("Anoma", () => { it("should return chain by chainId", async () => { iDBStore.set(KVKeys.Chains, [chain]); - const storedChain = await anoma.chain(chain.chainId); + const storedChain = await namada.chain(chain.chainId); expect(storedChain).toEqual(chain); }); it("should return all chains", async () => { iDBStore.set(KVKeys.Chains, [chain]); - const storedChains = await anoma.chains(); + const storedChains = await namada.chains(); expect(storedChains).toEqual([...Object.values(defaultChains), chain]); }); @@ -72,13 +72,13 @@ describe("Anoma", () => { const storedKeyStore = keyStore.map( ({ crypto: _crypto, owner: _owner, ...account }) => account ); - const storedAccounts = await anoma.accounts(chain.chainId); + const storedAccounts = await namada.accounts(chain.chainId); expect(storedAccounts).toEqual(storedKeyStore); }); it("should add a chain configuration", async () => { - await anoma.suggestChain(chain); + await namada.suggestChain(chain); const chains = await iDBStore.get("chains"); expect(chains?.pop()).toEqual(chain); @@ -108,7 +108,7 @@ describe("Anoma", () => { const serializedTransfer = transferMessage.encode(transferMsgValue); jest.spyOn(keyRingService, "submitTransfer"); - anoma.submitTransfer(toBase64(serializedTransfer)); + namada.submitTransfer(toBase64(serializedTransfer)); expect(keyRingService.submitTransfer).toBeCalled(); }); @@ -141,7 +141,7 @@ describe("Anoma", () => { const transferMessage = new Message(); const serializedTransfer = transferMessage.encode(transferMsgValue); - const res = anoma.submitIbcTransfer(toBase64(serializedTransfer)); + const res = namada.submitIbcTransfer(toBase64(serializedTransfer)); await expect(res).resolves.not.toBeDefined(); }); @@ -156,7 +156,7 @@ describe("Anoma", () => { const serialized = accountMessage.encode(accountMsgValue); await expect( - anoma.encodeInitAccount({ + namada.encodeInitAccount({ txMsg: toBase64(serialized), address: keyStore[0].address, }) diff --git a/apps/extension/src/provider/Anoma.ts b/apps/extension/src/provider/Namada.ts similarity index 96% rename from apps/extension/src/provider/Anoma.ts rename to apps/extension/src/provider/Namada.ts index 9599037f5a..7551af508f 100644 --- a/apps/extension/src/provider/Anoma.ts +++ b/apps/extension/src/provider/Namada.ts @@ -1,4 +1,4 @@ -import { Anoma as IAnoma, Chain, DerivedAccount } from "@anoma/types"; +import { Namada as INamada, Chain, DerivedAccount } from "@namada/types"; import { Ports, MessageRequester } from "router"; import { @@ -17,7 +17,7 @@ import { SubmitIbcTransferMsg, } from "./messages"; -export class Anoma implements IAnoma { +export class Namada implements INamada { constructor( private readonly _version: string, protected readonly requester?: MessageRequester diff --git a/apps/extension/src/provider/Proxy.ts b/apps/extension/src/provider/Proxy.ts index a6ad19d68c..7a0cf08720 100644 --- a/apps/extension/src/provider/Proxy.ts +++ b/apps/extension/src/provider/Proxy.ts @@ -1,8 +1,8 @@ -import { Anoma } from "./Anoma"; +import { Namada } from "./Namada"; import { ProxyRequest, ProxyRequestResponse, ProxyRequestTypes } from "./types"; export class Proxy { - static start(anoma: Anoma): void { + static start(namada: Namada): void { Proxy.addMessageListener(async (e) => { const message = e.data; @@ -13,11 +13,11 @@ export class Proxy { const { method, args } = message; try { - if (!anoma[method] || typeof anoma[method] !== "function") { + if (!namada[method] || typeof namada[method] !== "function") { throw new Error(`${message.method} not found!`); } - const result = await anoma[method](args); + const result = await namada[method](args); const proxyResponse: ProxyRequestResponse = { type: ProxyRequestTypes.Response, id: message.id, diff --git a/apps/extension/src/provider/Signer.ts b/apps/extension/src/provider/Signer.ts index 36c0f31324..42d2a45367 100644 --- a/apps/extension/src/provider/Signer.ts +++ b/apps/extension/src/provider/Signer.ts @@ -1,7 +1,7 @@ import { toBase64 } from "@cosmjs/encoding"; import { Account, - Anoma, + Namada, AccountMsgValue, IbcTransferMsgValue, IbcTransferProps, @@ -14,16 +14,16 @@ import { SubmitBondProps, SubmitBondMsgValue, SubmitUnbondMsgValue, -} from "@anoma/types"; +} from "@namada/types"; export class Signer implements ISigner { constructor( protected readonly chainId: string, - private readonly _anoma: Anoma + private readonly _namada: Namada ) {} public async accounts(): Promise { - return (await this._anoma.accounts(this.chainId))?.map( + return (await this._namada.accounts(this.chainId))?.map( ({ alias, address, chainId, type }) => ({ alias, address, @@ -42,7 +42,7 @@ export class Signer implements ISigner { const msg = new Message(); const encoded = msg.encode(msgValue); - return await this._anoma.submitBond(toBase64(encoded)); + return await this._namada.submitBond(toBase64(encoded)); } /** @@ -54,7 +54,7 @@ export class Signer implements ISigner { const msg = new Message(); const encoded = msg.encode(msgValue); - return await this._anoma.submitUnbond(toBase64(encoded)); + return await this._namada.submitUnbond(toBase64(encoded)); } /** @@ -65,7 +65,7 @@ export class Signer implements ISigner { const transferMessage = new Message(); const serializedTransfer = transferMessage.encode(transferMsgValue); - return await this._anoma.submitTransfer(toBase64(serializedTransfer)); + return await this._namada.submitTransfer(toBase64(serializedTransfer)); } /** @@ -77,7 +77,7 @@ export class Signer implements ISigner { const serializedIbcTransfer = ibcTransferMessage.encode(ibcTransferMsgValue); - return await this._anoma.submitIbcTransfer(toBase64(serializedIbcTransfer)); + return await this._namada.submitIbcTransfer(toBase64(serializedIbcTransfer)); } /** @@ -94,7 +94,7 @@ export class Signer implements ISigner { const accountMessage = new Message(); const serialized = accountMessage.encode(accountMsgValue); - return await this._anoma.encodeInitAccount({ + return await this._namada.encodeInitAccount({ txMsg: toBase64(serialized), address: signer, }); diff --git a/apps/extension/src/provider/data.mock.ts b/apps/extension/src/provider/data.mock.ts index f46ebdcabf..3461151385 100644 --- a/apps/extension/src/provider/data.mock.ts +++ b/apps/extension/src/provider/data.mock.ts @@ -1,4 +1,4 @@ -import { AccountType, BridgeType, Chain, Extensions } from "@anoma/types"; +import { AccountType, BridgeType, Chain, Extensions } from "@namada/types"; import { KdfType, KeyStore } from "background/keyring"; export const ACTIVE_ACCOUNT_ID = "324bfe0e-cb19-5f1a-9630-9daaaecadabe"; @@ -14,7 +14,7 @@ export const chain: Chain = { bridgeType: [BridgeType.IBC, BridgeType.Ethereum], rpc: "http://localhost:26657", chainId: "namada-75a7e12.69483d59a9fb174", - extension: Extensions["anoma"], + extension: Extensions["namada"], currency: { token: "Namada", symbol: "NAM", diff --git a/apps/extension/src/provider/index.ts b/apps/extension/src/provider/index.ts index 43ab80d427..b99fc501ff 100644 --- a/apps/extension/src/provider/index.ts +++ b/apps/extension/src/provider/index.ts @@ -1,5 +1,5 @@ -export * from "./Anoma"; -export * from "./InjectedAnoma"; +export * from "./Namada"; +export * from "./InjectedNamada"; export * from "./InjectedProxy"; export * from "./messages"; export * from "./Proxy"; diff --git a/apps/extension/src/provider/messages.ts b/apps/extension/src/provider/messages.ts index cb2df89272..85e53869b6 100644 --- a/apps/extension/src/provider/messages.ts +++ b/apps/extension/src/provider/messages.ts @@ -1,4 +1,4 @@ -import { Chain, DerivedAccount } from "@anoma/types"; +import { Chain, DerivedAccount } from "@namada/types"; import { Message } from "router"; /** diff --git a/apps/extension/src/provider/types.ts b/apps/extension/src/provider/types.ts index dedc134de8..196bff8948 100644 --- a/apps/extension/src/provider/types.ts +++ b/apps/extension/src/provider/types.ts @@ -1,11 +1,11 @@ -import { Anoma } from "./Anoma"; +import { Namada } from "./Namada"; import { Result } from "router/types"; -export type ProxyMethod = keyof Omit; +export type ProxyMethod = keyof Omit; export enum ProxyRequestTypes { - Request = "anoma-proxy-request", - Response = "anoma-proxy-request-response", + Request = "namada-proxy-request", + Response = "namada-proxy-request-response", } // TODO: Look into better generic typing for this: diff --git a/apps/extension/src/public/approvals.html b/apps/extension/src/public/approvals.html index a8fad1b55b..8676d00e59 100644 --- a/apps/extension/src/public/approvals.html +++ b/apps/extension/src/public/approvals.html @@ -4,8 +4,8 @@ - - Anoma Extension + + Namada Extension @@ -13,5 +13,5 @@
- + diff --git a/apps/extension/src/public/popup.html b/apps/extension/src/public/popup.html index 013cf5555b..97d5e91618 100644 --- a/apps/extension/src/public/popup.html +++ b/apps/extension/src/public/popup.html @@ -4,8 +4,8 @@ - - Anoma Extension + + Namada Extension @@ -13,5 +13,5 @@
- + diff --git a/apps/extension/src/public/setup.html b/apps/extension/src/public/setup.html index 3ba9db50d5..c6c6bce53d 100644 --- a/apps/extension/src/public/setup.html +++ b/apps/extension/src/public/setup.html @@ -4,8 +4,8 @@ - - Anoma Extension + + Namada Extension @@ -13,5 +13,5 @@
- + diff --git a/apps/extension/src/router/types/enums.ts b/apps/extension/src/router/types/enums.ts index 759428b8b6..6db902d0fb 100644 --- a/apps/extension/src/router/types/enums.ts +++ b/apps/extension/src/router/types/enums.ts @@ -5,21 +5,21 @@ export enum Ports { } export enum Events { - KeystoreChanged = "anoma-keystore-changed", - PushEventData = "anoma-push-event-data", + KeystoreChanged = "namada-keystore-changed", + PushEventData = "namada-push-event-data", } export enum Routes { - InteractionForeground = "anoma-interaction-foreground", + InteractionForeground = "namada-interaction-foreground", } export enum KVPrefix { - IndexedDB = "Anoma::IndexedDB", - LocalStorage = "Anoma::LocalStorage", - Memory = "Anoma::Memory", - SDK = "Anoma::SDK", - Utility = "Anoma::Utility", - ConnectedTabs = "Anoma::ConnectedTabs", + IndexedDB = "Namada::IndexedDB", + LocalStorage = "Namada::LocalStorage", + Memory = "Namada::Memory", + SDK = "Namada::SDK", + Utility = "Namada::Utility", + ConnectedTabs = "Namada::ConnectedTabs", } export enum KVKeys { diff --git a/apps/extension/src/services/requester.tsx b/apps/extension/src/services/requester.tsx index 250116c2b7..9f30db5c55 100644 --- a/apps/extension/src/services/requester.tsx +++ b/apps/extension/src/services/requester.tsx @@ -1,12 +1,12 @@ import browser from "webextension-polyfill"; import { createContext, useEffect, useState } from "react"; -import { ExtensionKVStore } from "@anoma/storage"; +import { ExtensionKVStore } from "@namada/storage"; import { KVPrefix } from "router"; import { ExtensionMessenger, ExtensionRequester, - getAnomaRouterId, + getNamadaRouterId, } from "extension"; const store = new ExtensionKVStore(KVPrefix.LocalStorage, { @@ -22,7 +22,7 @@ export const RequesterProvider: React.FC = ({ children }) => { useEffect(() => { const getRequester = async (): Promise => { - const routerId = await getAnomaRouterId(store); + const routerId = await getNamadaRouterId(store); const requester = new ExtensionRequester(messenger, routerId); setRequester(requester); }; diff --git a/apps/extension/src/test/init.ts b/apps/extension/src/test/init.ts index e1086a33a4..acfc57a26f 100644 --- a/apps/extension/src/test/init.ts +++ b/apps/extension/src/test/init.ts @@ -1,13 +1,13 @@ -import { KVStore } from "@anoma/storage"; +import { KVStore } from "@namada/storage"; import { ExtensionRouter, ExtensionMessengerMock, ExtensionRequester, - getAnomaRouterId, + getNamadaRouterId, } from "../extension"; import { Ports, KVPrefix } from "../router"; -import { chains } from "@anoma/chains"; +import { chains } from "@namada/chains"; import { ChainsService, init as initChains } from "../background/chains"; import { KeyRingService, @@ -22,13 +22,13 @@ import { init as initApprovals, } from "../background/approvals"; -import { Anoma } from "provider"; -import { Chain } from "@anoma/types"; -import { Query, Sdk } from "@anoma/shared"; +import { Namada } from "provider"; +import { Chain } from "@namada/types"; +import { Query, Sdk } from "@namada/shared"; // __wasm is not exported in crypto.d.ts so need to use require instead of import /* eslint-disable @typescript-eslint/no-var-requires */ -const cryptoMemory = require("@anoma/crypto").__wasm.memory; +const cryptoMemory = require("@namada/crypto").__wasm.memory; const chainId = "namada-75a7e12.69483d59a9fb174"; export class KVStoreMock implements KVStore { @@ -52,7 +52,7 @@ export class KVStoreMock implements KVStore { } export const init = async (): Promise<{ - anoma: Anoma; + namada: Namada; iDBStore: KVStoreMock; extStore: KVStoreMock; utilityStore: KVStoreMock; @@ -67,8 +67,8 @@ export const init = async (): Promise<{ const connectedTabsStore = new KVStoreMock( KVPrefix.ConnectedTabs ); - const anomaRouterId = await getAnomaRouterId(extStore); - const requester = new ExtensionRequester(messenger, anomaRouterId); + const namadaRouterId = await getNamadaRouterId(extStore); + const requester = new ExtensionRequester(messenger, namadaRouterId); const txStore = new KVStoreMock(KVPrefix.LocalStorage); const router = new ExtensionRouter( @@ -118,10 +118,10 @@ export const init = async (): Promise<{ router.listen(Ports.Background); const version = "0.1.0"; - const anoma = new Anoma(version, requester); + const namada = new Namada(version, requester); return { - anoma, + namada, iDBStore, extStore, utilityStore, diff --git a/apps/extension/webpack.config.js b/apps/extension/webpack.config.js index da008b650a..99b99fdbba 100644 --- a/apps/extension/webpack.config.js +++ b/apps/extension/webpack.config.js @@ -89,7 +89,7 @@ module.exports = { output: { publicPath: "", path: resolve(__dirname, `./build/${TARGET}`), - filename: "[name].anoma.js", + filename: "[name].namada.js", }, module: { rules: [ diff --git a/apps/namada-interface/README.md b/apps/namada-interface/README.md index fa3516799e..2aabc207e6 100644 --- a/apps/namada-interface/README.md +++ b/apps/namada-interface/README.md @@ -61,7 +61,7 @@ By default, running the wallet in local-development mode (`yarn dev:local`), wil the following options are available: ```bash -REACT_APP_LOCAL_LEDGER_CHAIN_ID=anoma-test.fd58c789bc11e6c6392 +REACT_APP_LOCAL_LEDGER_CHAIN_ID=local.3424d591c781bb2c788b9201 REACT_APP_LOCAL_LEDGER_URL=172.0.00.123 REACT_APP_LOCAL_LEDGER_PORT=27657 REACT_APP_LOCAL_FAUCET=atest1v4ehgw36gfprwdekgg6rsdesg3rry3pjx9prqv3exumrg3zzx3q5vv3nx4zr2v6yggurgwp4rzjk2v @@ -75,15 +75,15 @@ We can configure the app to work with two chains, both with IBC enabled (assumin ```bash # CHAIN A - Default Chain -REACT_APP_CHAIN_A_ALIAS=Anoma Fractal Instance - 1 # OPTIONAL - Defaults to "IBC - 1" -REACT_APP_CHAIN_A_ID=anoma-test.1e670ba91369ec891fc # REQUIRED +REACT_APP_CHAIN_A_ALIAS=Namada - 1 # OPTIONAL - Defaults to "IBC - 1" +REACT_APP_CHAIN_A_ID=local.3424d591c781bb2c788b9201 # REQUIRED REACT_APP_CHAIN_A_URL=10.0.1.123 # OPTIONAL - Defaults to 127.0.0.1 REACT_APP_CHAIN_A_PORT=27657 # OPTIONAL - Defaults to 27657 REACT_APP_CHAIN_A_FAUCET=atest1v4ehgw36gfprwdekgg6rsdesg3rry3pjx9prqv3exumrg3zzx3q5vv3nx4zr2v6yggurgwp4rzjk2v # CHAIN B -REACT_APP_CHAIN_B_ALIAS=Anoma Fractal Instance - 2 # OPTIONAL - Defaults to "IBC - 2" -REACT_APP_CHAIN_B_ID=anoma-test.89060614ce340f4baae # REQUIRED +REACT_APP_CHAIN_B_ALIAS=Namada - 2 # OPTIONAL - Defaults to "IBC - 2" +REACT_APP_CHAIN_B_ID=local.11350caf633557b1f9a22d44 # REQUIRED REACT_APP_CHAIN_B_URL=10.0.1.123 # OPTIONAL - Defaults to 127.0.0.1 REACT_APP_CHAIN_B_PORT=28657 # OPTIONAL - Defaults to 28657 REACT_APP_CHAIN_B_FAUCET=atest1v4ehgw36xscyvdpcxgenvdf3x5c523j98pqnz3fjgfq5yvp4xpqnvv69x5erzvjzgse5yd3suq5pd0 diff --git a/apps/namada-interface/package.json b/apps/namada-interface/package.json index 01ce7606a0..52a425f97f 100644 --- a/apps/namada-interface/package.json +++ b/apps/namada-interface/package.json @@ -1,16 +1,16 @@ { - "name": "@anoma/namada-interface", + "name": "@namada/namada-interface", "version": "0.1.0", - "description": "Anoma Browser Extension", + "description": "Namada Browser Extension", "repository": "https://github.com/anoma/namada-interface/", "author": "Heliax Dev ", "license": "MIT", "private": true, "dependencies": { - "@anoma/components": "0.1.0", - "@anoma/hooks": "0.1.0", - "@anoma/integrations": "0.1.0", - "@anoma/utils": "0.1.0", + "@namada/components": "0.1.0", + "@namada/hooks": "0.1.0", + "@namada/integrations": "0.1.0", + "@namada/utils": "0.1.0", "@reduxjs/toolkit": "^1.8.0", "bignumber.js": "^9.1.1", "buffer": "^6.0.3", diff --git a/apps/namada-interface/src/App/AccountOverview/AccountOverview.components.ts b/apps/namada-interface/src/App/AccountOverview/AccountOverview.components.ts index 2e33b5fc35..e63bb9d781 100644 --- a/apps/namada-interface/src/App/AccountOverview/AccountOverview.components.ts +++ b/apps/namada-interface/src/App/AccountOverview/AccountOverview.components.ts @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { DesignConfiguration, ColorMode } from "@anoma/utils"; +import { DesignConfiguration, ColorMode } from "@namada/utils"; enum ComponentColor { TabLabelActive, diff --git a/apps/namada-interface/src/App/AccountOverview/AccountOverview.tsx b/apps/namada-interface/src/App/AccountOverview/AccountOverview.tsx index 0025fd89e4..ca51c802f2 100644 --- a/apps/namada-interface/src/App/AccountOverview/AccountOverview.tsx +++ b/apps/namada-interface/src/App/AccountOverview/AccountOverview.tsx @@ -2,13 +2,13 @@ import { useState } from "react"; import { useNavigate } from "react-router-dom"; import BigNumber from "bignumber.js"; -import { chains } from "@anoma/chains"; +import { chains } from "@namada/chains"; import { useIntegrationConnection, useUntilIntegrationAttached, -} from "@anoma/hooks"; -import { Account, ExtensionKey, Extensions } from "@anoma/types"; -import { formatCurrency } from "@anoma/utils"; +} from "@namada/hooks"; +import { Account, ExtensionKey, Extensions } from "@namada/types"; +import { formatCurrency } from "@namada/utils"; import { useAppSelector, useAppDispatch } from "store"; import { AccountsState, addAccounts, fetchBalances } from "slices/accounts"; @@ -20,7 +20,7 @@ import { ButtonVariant, Heading, HeadingLevel, -} from "@anoma/components"; +} from "@namada/components"; import { AccountOverviewContainer, AccountOverviewContent, @@ -48,7 +48,7 @@ export const AccountOverview = (): JSX.Element => { const [isExtensionConnected, setIsExtensionConnected] = useState< Record >({ - anoma: false, + namada: false, keplr: false, metamask: false, }); diff --git a/apps/namada-interface/src/App/AccountOverview/DerivedAccounts/DerivedAccounts.components.ts b/apps/namada-interface/src/App/AccountOverview/DerivedAccounts/DerivedAccounts.components.ts index e0363cc547..ae4a62710a 100644 --- a/apps/namada-interface/src/App/AccountOverview/DerivedAccounts/DerivedAccounts.components.ts +++ b/apps/namada-interface/src/App/AccountOverview/DerivedAccounts/DerivedAccounts.components.ts @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { ColorMode, DesignConfiguration } from "@anoma/utils"; +import { ColorMode, DesignConfiguration } from "@namada/utils"; enum ComponentColor { ScrollbarThumb, diff --git a/apps/namada-interface/src/App/AccountOverview/DerivedAccounts/DerivedAccounts.tsx b/apps/namada-interface/src/App/AccountOverview/DerivedAccounts/DerivedAccounts.tsx index 9b284cc48a..d87cda15a4 100644 --- a/apps/namada-interface/src/App/AccountOverview/DerivedAccounts/DerivedAccounts.tsx +++ b/apps/namada-interface/src/App/AccountOverview/DerivedAccounts/DerivedAccounts.tsx @@ -3,12 +3,12 @@ import { ThemeContext } from "styled-components"; import { useNavigate } from "react-router-dom"; import BigNumber from "bignumber.js"; -import { chains } from "@anoma/chains"; +import { chains } from "@namada/chains"; import { useAppDispatch, useAppSelector } from "store"; import { AccountsState, Balance } from "slices/accounts"; import { SettingsState } from "slices/settings"; -import { TokenType } from "@anoma/types"; -import { formatCurrency, formatRoute } from "@anoma/utils"; +import { TokenType } from "@namada/types"; +import { formatCurrency, formatRoute } from "@namada/utils"; import { DerivedAccountsContainer, diff --git a/apps/namada-interface/src/App/App.components.ts b/apps/namada-interface/src/App/App.components.ts index 82464d96f9..cf749fc90e 100644 --- a/apps/namada-interface/src/App/App.components.ts +++ b/apps/namada-interface/src/App/App.components.ts @@ -1,7 +1,7 @@ import styled, { createGlobalStyle } from "styled-components"; import { motion } from "framer-motion"; -import { ColorMode, DesignConfiguration } from "@anoma/utils"; +import { ColorMode, DesignConfiguration } from "@namada/utils"; enum ComponentColor { BorderColor, diff --git a/apps/namada-interface/src/App/App.tsx b/apps/namada-interface/src/App/App.tsx index 866f542ada..d6e75a34d7 100644 --- a/apps/namada-interface/src/App/App.tsx +++ b/apps/namada-interface/src/App/App.tsx @@ -10,7 +10,7 @@ import { loadColorMode, storeColorMode, ColorMode, -} from "@anoma/utils"; +} from "@namada/utils"; import { TopNavigation } from "./TopNavigation"; import { @@ -25,11 +25,11 @@ import { import { persistor, store, useAppDispatch, useAppSelector } from "store"; import { Toasts } from "App/Toast"; import { SettingsState } from "slices/settings"; -import { chains } from "@anoma/chains"; -import { useIntegration, useUntilIntegrationAttached } from "@anoma/hooks"; +import { chains } from "@namada/chains"; +import { useIntegration, useUntilIntegrationAttached } from "@namada/hooks"; import { Outlet } from "react-router-dom"; import { addAccounts, fetchBalances } from "slices/accounts"; -import { Account } from "@anoma/types"; +import { Account } from "@namada/types"; export const history = createBrowserHistory({ window }); diff --git a/apps/namada-interface/src/App/Bridge/Bridge.tsx b/apps/namada-interface/src/App/Bridge/Bridge.tsx index e013a180c3..f7c3daf829 100644 --- a/apps/namada-interface/src/App/Bridge/Bridge.tsx +++ b/apps/namada-interface/src/App/Bridge/Bridge.tsx @@ -1,4 +1,4 @@ -import { Heading, HeadingLevel, NavigationContainer } from "@anoma/components"; +import { Heading, HeadingLevel, NavigationContainer } from "@namada/components"; import { BridgeContainer } from "./Bridge.components"; import IBCTransfer from "App/Token/IBCTransfer/IBCTransfer"; diff --git a/apps/namada-interface/src/App/Governance/Governance.tsx b/apps/namada-interface/src/App/Governance/Governance.tsx index af636c536d..3d7109af97 100644 --- a/apps/namada-interface/src/App/Governance/Governance.tsx +++ b/apps/namada-interface/src/App/Governance/Governance.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { MainContainerNavigation } from "App/StakingAndGovernance/MainContainerNavigation"; import { GovernanceContainer } from "./Governance.components"; -import { Button, ButtonVariant } from "@anoma/components"; +import { Button, ButtonVariant } from "@namada/components"; const initialTitle = "Governance"; export const Governance = (): JSX.Element => { diff --git a/apps/namada-interface/src/App/NotFound.tsx b/apps/namada-interface/src/App/NotFound.tsx index a323ef178d..5a41948e6e 100644 --- a/apps/namada-interface/src/App/NotFound.tsx +++ b/apps/namada-interface/src/App/NotFound.tsx @@ -7,7 +7,7 @@ import { Icon, IconName, NavigationContainer, -} from "@anoma/components"; +} from "@namada/components"; import { TopLevelRoute } from "./types"; import { diff --git a/apps/namada-interface/src/App/PublicGoodsFunding/PublicGoodsFunding.tsx b/apps/namada-interface/src/App/PublicGoodsFunding/PublicGoodsFunding.tsx index d321850316..2422c312f8 100644 --- a/apps/namada-interface/src/App/PublicGoodsFunding/PublicGoodsFunding.tsx +++ b/apps/namada-interface/src/App/PublicGoodsFunding/PublicGoodsFunding.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { MainContainerNavigation } from "App/StakingAndGovernance/MainContainerNavigation"; import { PublicGoodsFundingContainer } from "./PublicGoodsFunding.components"; -import { Button, ButtonVariant } from "@anoma/components"; +import { Button, ButtonVariant } from "@namada/components"; const initialTitle = "Public Goods Funding"; diff --git a/apps/namada-interface/src/App/Redirect.tsx b/apps/namada-interface/src/App/Redirect.tsx index 9c6da6b576..ae1065436b 100644 --- a/apps/namada-interface/src/App/Redirect.tsx +++ b/apps/namada-interface/src/App/Redirect.tsx @@ -1,7 +1,7 @@ import { useEffect } from "react"; import { useNavigate } from "react-router-dom"; import { TopLevelRoute } from "./types"; -import { useSanitizedLocation } from "@anoma/hooks"; +import { useSanitizedLocation } from "@namada/hooks"; type Props = { password?: string; diff --git a/apps/namada-interface/src/App/Settings/Settings.tsx b/apps/namada-interface/src/App/Settings/Settings.tsx index 37ce064860..22cbc4c3e2 100644 --- a/apps/namada-interface/src/App/Settings/Settings.tsx +++ b/apps/namada-interface/src/App/Settings/Settings.tsx @@ -10,7 +10,7 @@ import { Icon, IconName, NavigationContainer, -} from "@anoma/components"; +} from "@namada/components"; import { SettingsContainer, SettingsContent, diff --git a/apps/namada-interface/src/App/Settings/SettingsWalletSettings/SettingsWalletSettings.tsx b/apps/namada-interface/src/App/Settings/SettingsWalletSettings/SettingsWalletSettings.tsx index ddda9ecf46..5c2f303743 100644 --- a/apps/namada-interface/src/App/Settings/SettingsWalletSettings/SettingsWalletSettings.tsx +++ b/apps/namada-interface/src/App/Settings/SettingsWalletSettings/SettingsWalletSettings.tsx @@ -1,6 +1,6 @@ import { useNavigate } from "react-router-dom"; -import { chains } from "@anoma/chains"; -import { Chain } from "@anoma/types"; +import { chains } from "@namada/chains"; +import { Chain } from "@namada/types"; import { setFiatCurrency, setChainId, SettingsState } from "slices/settings"; import { useAppDispatch, useAppSelector } from "store"; @@ -16,7 +16,7 @@ import { IconName, Select, Option, -} from "@anoma/components"; +} from "@namada/components"; import { InputContainer } from "App/AccountOverview/AccountOverview.components"; import { BackButton } from "App/Token/TokenSend/TokenSendForm.components"; import { ButtonsContainer, SettingsContent } from "../Settings.components"; diff --git a/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.components.ts b/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.components.ts index 8925a7e1ee..2618bc5547 100644 --- a/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.components.ts +++ b/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.components.ts @@ -3,7 +3,7 @@ import { Select, Table, Props as TableProps, -} from "@anoma/components"; +} from "@namada/components"; import { FC } from "react"; import styled from "styled-components"; diff --git a/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.tsx b/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.tsx index 5f28de4a2a..87d8a71389 100644 --- a/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.tsx +++ b/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.tsx @@ -12,8 +12,8 @@ import { ButtonVariant, TableConfigurations, KeyValueData, -} from "@anoma/components"; -import { truncateInMiddle } from "@anoma/utils"; +} from "@namada/components"; +import { truncateInMiddle } from "@namada/utils"; import { StakingPosition, ChangeInStakingPosition, diff --git a/apps/namada-interface/src/App/Staking/Staking.tsx b/apps/namada-interface/src/App/Staking/Staking.tsx index 83f43c576b..351aa0e36e 100644 --- a/apps/namada-interface/src/App/Staking/Staking.tsx +++ b/apps/namada-interface/src/App/Staking/Staking.tsx @@ -1,8 +1,8 @@ import { useState, useEffect } from "react"; import { Routes, Route, useNavigate } from "react-router-dom"; -import { truncateInMiddle } from "@anoma/utils"; -import { Modal } from "@anoma/components"; +import { truncateInMiddle } from "@namada/utils"; +import { Modal } from "@namada/components"; import { MainContainerNavigation } from "App/StakingAndGovernance/MainContainerNavigation"; import { StakingContainer } from "./Staking.components"; @@ -18,7 +18,7 @@ import { import { NewBondingPosition } from "./NewBondingPosition"; import { UnbondPosition } from "./UnbondPosition"; import { Account } from "slices/accounts"; -import { useSanitizedLocation } from "@anoma/hooks"; +import { useSanitizedLocation } from "@namada/hooks"; const initialTitle = "Staking"; diff --git a/apps/namada-interface/src/App/Staking/StakingOverview/StakingOverview.tsx b/apps/namada-interface/src/App/Staking/StakingOverview/StakingOverview.tsx index 9f5daecba3..d1f6c1dfbf 100644 --- a/apps/namada-interface/src/App/Staking/StakingOverview/StakingOverview.tsx +++ b/apps/namada-interface/src/App/Staking/StakingOverview/StakingOverview.tsx @@ -1,5 +1,5 @@ import BigNumber from "bignumber.js"; -import { Table, TableLink, TableConfigurations } from "@anoma/components"; +import { Table, TableLink, TableConfigurations } from "@namada/components"; import { Account } from "slices/accounts"; import { Validator, MyValidators } from "slices/StakingAndGovernance"; import { diff --git a/apps/namada-interface/src/App/Staking/UnbondPosition/UnbondPosition.tsx b/apps/namada-interface/src/App/Staking/UnbondPosition/UnbondPosition.tsx index 606080e04e..5f1a7d05a2 100644 --- a/apps/namada-interface/src/App/Staking/UnbondPosition/UnbondPosition.tsx +++ b/apps/namada-interface/src/App/Staking/UnbondPosition/UnbondPosition.tsx @@ -6,14 +6,14 @@ import { Table, TableConfigurations, KeyValueData, -} from "@anoma/components"; +} from "@namada/components"; import { StakingPosition, ChangeInStakingPosition, } from "slices/StakingAndGovernance"; import { UnstakePositionContainer } from "./UnbondPosition.components"; -import { useSanitizedParams } from "@anoma/hooks"; +import { useSanitizedParams } from "@namada/hooks"; // keys for the table that we want to act upon in table configuration const AMOUNT_TO_UNBOND_KEY = "Amount to unbond"; diff --git a/apps/namada-interface/src/App/Staking/ValidatorDetails/ValidatorDetails.tsx b/apps/namada-interface/src/App/Staking/ValidatorDetails/ValidatorDetails.tsx index 38531ac1bb..fb064d2cf7 100644 --- a/apps/namada-interface/src/App/Staking/ValidatorDetails/ValidatorDetails.tsx +++ b/apps/namada-interface/src/App/Staking/ValidatorDetails/ValidatorDetails.tsx @@ -1,6 +1,6 @@ import { Outlet } from "react-router-dom"; -import { truncateInMiddle } from "@anoma/utils"; +import { truncateInMiddle } from "@namada/utils"; import { Button, ButtonVariant, @@ -8,7 +8,7 @@ import { TableConfigurations, KeyValueData, TableLink, -} from "@anoma/components"; +} from "@namada/components"; import { ValidatorDetailsContainer, diff --git a/apps/namada-interface/src/App/StakingAndGovernance/MainContainerNavigation/MainContainerNavigation.tsx b/apps/namada-interface/src/App/StakingAndGovernance/MainContainerNavigation/MainContainerNavigation.tsx index b146c036f3..8eed5e3ab4 100644 --- a/apps/namada-interface/src/App/StakingAndGovernance/MainContainerNavigation/MainContainerNavigation.tsx +++ b/apps/namada-interface/src/App/StakingAndGovernance/MainContainerNavigation/MainContainerNavigation.tsx @@ -1,4 +1,4 @@ -import { Icon, IconName } from "@anoma/components"; +import { Icon, IconName } from "@namada/components"; import { MainContainerNavigationContainer, BackButtonContainer, diff --git a/apps/namada-interface/src/App/StakingAndGovernance/StakingAndGovernance.tsx b/apps/namada-interface/src/App/StakingAndGovernance/StakingAndGovernance.tsx index 21aac1330f..50807ce744 100644 --- a/apps/namada-interface/src/App/StakingAndGovernance/StakingAndGovernance.tsx +++ b/apps/namada-interface/src/App/StakingAndGovernance/StakingAndGovernance.tsx @@ -2,7 +2,7 @@ import { useEffect } from "react"; import { useAppDispatch, useAppSelector, RootState } from "store"; import { Routes, Route, useNavigate } from "react-router-dom"; -import { useIntegrationConnection } from "@anoma/hooks"; +import { useIntegrationConnection } from "@namada/hooks"; import { Staking } from "App/Staking"; import { Governance } from "App/Governance"; import { PublicGoodsFunding } from "App/PublicGoodsFunding"; @@ -12,7 +12,7 @@ import { StakingAndGovernanceSubRoute, locationToStakingAndGovernanceSubRoute, } from "App/types"; -import { useSanitizedLocation } from "@anoma/hooks"; +import { useSanitizedLocation } from "@namada/hooks"; import { fetchValidators, diff --git a/apps/namada-interface/src/App/Toast/toast.tsx b/apps/namada-interface/src/App/Toast/toast.tsx index f80207fc3e..b64d4a5969 100644 --- a/apps/namada-interface/src/App/Toast/toast.tsx +++ b/apps/namada-interface/src/App/Toast/toast.tsx @@ -1,7 +1,7 @@ import { useEffect, useContext, useCallback } from "react"; import { AnimatePresence } from "framer-motion"; -import { Icon, IconName } from "@anoma/components"; +import { Icon, IconName } from "@namada/components"; import { useAppSelector, useAppDispatch } from "store"; import { ThemeContext } from "styled-components"; diff --git a/apps/namada-interface/src/App/Token/IBCTransfer/IBCTransfer.tsx b/apps/namada-interface/src/App/Token/IBCTransfer/IBCTransfer.tsx index a00beaeebb..403e4c6668 100644 --- a/apps/namada-interface/src/App/Token/IBCTransfer/IBCTransfer.tsx +++ b/apps/namada-interface/src/App/Token/IBCTransfer/IBCTransfer.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import BigNumber from "bignumber.js"; -import { chains } from "@anoma/chains"; +import { chains } from "@namada/chains"; import { Account as AccountType, BridgeType, @@ -10,7 +10,7 @@ import { Extensions, Tokens, TokenType, -} from "@anoma/types"; +} from "@namada/types"; import { Button, ButtonVariant, @@ -20,12 +20,12 @@ import { InputVariants, Option, Select, -} from "@anoma/components"; +} from "@namada/components"; import { useIntegrationConnection, useUntilIntegrationAttached, -} from "@anoma/hooks"; +} from "@namada/hooks"; import { useAppDispatch, useAppSelector } from "store"; import { Account, @@ -65,7 +65,7 @@ const IBCTransfer = (): JSX.Element => { const [isExtensionConnected, setIsExtensionConnected] = useState< Record >({ - anoma: false, + namada: false, keplr: false, metamask: false, }); diff --git a/apps/namada-interface/src/App/Token/TokenDetails.tsx b/apps/namada-interface/src/App/Token/TokenDetails.tsx index 39abefbec3..bf54edf85e 100644 --- a/apps/namada-interface/src/App/Token/TokenDetails.tsx +++ b/apps/namada-interface/src/App/Token/TokenDetails.tsx @@ -1,15 +1,15 @@ import { useNavigate } from "react-router-dom"; -import { chains } from "@anoma/chains"; -import { Chain, Tokens } from "@anoma/types"; -import { formatRoute, stringFromTimestamp } from "@anoma/utils"; +import { chains } from "@namada/chains"; +import { Chain, Tokens } from "@namada/types"; +import { formatRoute, stringFromTimestamp } from "@namada/utils"; import { Button, ButtonVariant, Heading, HeadingLevel, NavigationContainer, -} from "@anoma/components"; +} from "@namada/components"; import { TopLevelRoute } from "App/types"; import { AccountsState } from "slices/accounts"; @@ -23,7 +23,7 @@ import { TransactionListItem, AccountsDetailsNavContainer, } from "./TokenDetails.components"; -import { useSanitizedParams } from "@anoma/hooks"; +import { useSanitizedParams } from "@namada/hooks"; type TokenDetailsParams = { id: string; diff --git a/apps/namada-interface/src/App/Token/TokenReceive/TokenReceive.tsx b/apps/namada-interface/src/App/Token/TokenReceive/TokenReceive.tsx index c9f4c6f9d7..9bd8af8ba2 100644 --- a/apps/namada-interface/src/App/Token/TokenReceive/TokenReceive.tsx +++ b/apps/namada-interface/src/App/Token/TokenReceive/TokenReceive.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { useQRCode } from "next-qrcode"; -import { formatRoute } from "@anoma/utils"; +import { formatRoute } from "@namada/utils"; import { Heading, HeadingLevel, @@ -10,7 +10,7 @@ import { IconName, NavigationContainer, Select, -} from "@anoma/components"; +} from "@namada/components"; import { Address } from "../Transfers/TransferDetails.components"; import { diff --git a/apps/namada-interface/src/App/Token/TokenSend/TokenSend.components.ts b/apps/namada-interface/src/App/Token/TokenSend/TokenSend.components.ts index 413db2bfe9..93cb911574 100644 --- a/apps/namada-interface/src/App/Token/TokenSend/TokenSend.components.ts +++ b/apps/namada-interface/src/App/Token/TokenSend/TokenSend.components.ts @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { ColorMode, DesignConfiguration } from "@anoma/utils"; +import { ColorMode, DesignConfiguration } from "@namada/utils"; enum ComponentColor { TabBackgroundColorActive, diff --git a/apps/namada-interface/src/App/Token/TokenSend/TokenSend.tsx b/apps/namada-interface/src/App/Token/TokenSend/TokenSend.tsx index 5412704e61..30d070d598 100644 --- a/apps/namada-interface/src/App/Token/TokenSend/TokenSend.tsx +++ b/apps/namada-interface/src/App/Token/TokenSend/TokenSend.tsx @@ -5,16 +5,16 @@ import { SettingsState } from "slices/settings"; import { TransferType } from "slices/transfers"; import { useAppSelector } from "store"; -import { TokenType } from "@anoma/types"; +import { TokenType } from "@namada/types"; import { Heading, HeadingLevel, NavigationContainer, Select, Option, -} from "@anoma/components"; +} from "@namada/components"; import TokenSendForm from "./TokenSendForm"; -import { useSanitizedParams } from "@anoma/hooks"; +import { useSanitizedParams } from "@namada/hooks"; import { TokenSendContainer, @@ -28,7 +28,7 @@ import { ESTABLISHED_ADDRESS_LENGTH, ESTABLISHED_ADDRESS_PREFIX, } from "./types"; -import { chains } from "@anoma/chains"; +import { chains } from "@namada/chains"; export const parseTarget = (target: string): TransferType | undefined => { if ( diff --git a/apps/namada-interface/src/App/Token/TokenSend/TokenSendForm.tsx b/apps/namada-interface/src/App/Token/TokenSend/TokenSendForm.tsx index b764bb2b73..e92c58c81c 100644 --- a/apps/namada-interface/src/App/Token/TokenSend/TokenSendForm.tsx +++ b/apps/namada-interface/src/App/Token/TokenSend/TokenSendForm.tsx @@ -4,8 +4,8 @@ import { ThemeContext } from "styled-components"; import QrReader from "react-qr-reader"; import BigNumber from "bignumber.js"; -import { Tokens, TokenType } from "@anoma/types"; -import { ColorMode, DesignConfiguration } from "@anoma/utils"; +import { Tokens, TokenType } from "@namada/types"; +import { ColorMode, DesignConfiguration } from "@namada/utils"; import { Button, ButtonVariant, @@ -13,7 +13,7 @@ import { IconName, Input, InputVariants, -} from "@anoma/components"; +} from "@namada/components"; import { AccountsState } from "slices/accounts"; import { diff --git a/apps/namada-interface/src/App/Token/Transfers/TransferDetails.tsx b/apps/namada-interface/src/App/Token/Transfers/TransferDetails.tsx index a6134949d2..0e4ef9028b 100644 --- a/apps/namada-interface/src/App/Token/Transfers/TransferDetails.tsx +++ b/apps/namada-interface/src/App/Token/Transfers/TransferDetails.tsx @@ -1,22 +1,22 @@ import { useNavigate } from "react-router-dom"; -import { chains } from "@anoma/chains"; -import { Chain } from "@anoma/types"; -import { stringFromTimestamp } from "@anoma/utils"; +import { chains } from "@namada/chains"; +import { Chain } from "@namada/types"; +import { stringFromTimestamp } from "@namada/utils"; import { Heading, HeadingLevel, NavigationContainer, Icon, IconName, -} from "@anoma/components"; +} from "@namada/components"; import { TransfersState } from "slices/transfers"; import { useAppSelector } from "store"; import { Address, TransferDetailContainer } from "./TransferDetails.components"; import { BackButton } from "../TokenSend/TokenSendForm.components"; import { ButtonsContainer, TransfersContent } from "./Transfers.components"; -import { useSanitizedParams } from "@anoma/hooks"; +import { useSanitizedParams } from "@namada/hooks"; type TransferDetailsParams = { id: string; diff --git a/apps/namada-interface/src/App/Token/Transfers/Transfers.tsx b/apps/namada-interface/src/App/Token/Transfers/Transfers.tsx index 167d258244..1993d84fca 100644 --- a/apps/namada-interface/src/App/Token/Transfers/Transfers.tsx +++ b/apps/namada-interface/src/App/Token/Transfers/Transfers.tsx @@ -1,7 +1,7 @@ import { useNavigate } from "react-router-dom"; -import { TokenType } from "@anoma/types"; -import { formatRoute, stringFromTimestamp } from "@anoma/utils"; +import { TokenType } from "@namada/types"; +import { formatRoute, stringFromTimestamp } from "@namada/utils"; import { Button, ButtonVariant, @@ -10,7 +10,7 @@ import { Icon, IconName, NavigationContainer, -} from "@anoma/components"; +} from "@namada/components"; import { TopLevelRoute } from "App/types"; import { Account, AccountsState } from "slices/accounts"; @@ -26,7 +26,7 @@ import { TransfersContent, } from "./Transfers.components"; import { BackButton } from "../TokenSend/TokenSendForm.components"; -import { useSanitizedParams } from "@anoma/hooks"; +import { useSanitizedParams } from "@namada/hooks"; type TokenDetailsParams = { id: string; diff --git a/apps/namada-interface/src/App/TopNavigation/topNavigation.components.ts b/apps/namada-interface/src/App/TopNavigation/topNavigation.components.ts index 5943c22677..7b4e44e0ba 100644 --- a/apps/namada-interface/src/App/TopNavigation/topNavigation.components.ts +++ b/apps/namada-interface/src/App/TopNavigation/topNavigation.components.ts @@ -1,5 +1,5 @@ import styled, { css, FlattenSimpleInterpolation } from "styled-components"; -import { ColorMode, DesignConfiguration } from "@anoma/utils"; +import { ColorMode, DesignConfiguration } from "@namada/utils"; enum ComponentColor { Logo, diff --git a/apps/namada-interface/src/App/TopNavigation/topNavigation.tsx b/apps/namada-interface/src/App/TopNavigation/topNavigation.tsx index 3e5cb28657..a015417c74 100644 --- a/apps/namada-interface/src/App/TopNavigation/topNavigation.tsx +++ b/apps/namada-interface/src/App/TopNavigation/topNavigation.tsx @@ -6,9 +6,9 @@ import { Location, } from "react-router-dom"; -import { ColorMode } from "@anoma/utils"; -import { chains } from "@anoma/chains"; -import { Chain } from "@anoma/types"; +import { ColorMode } from "@namada/utils"; +import { chains } from "@namada/chains"; +import { Chain } from "@namada/types"; import { Icon, IconName, @@ -16,8 +16,8 @@ import { ImageName, Toggle, Select, -} from "@anoma/components"; -import { useSanitizedLocation } from "@anoma/hooks"; +} from "@namada/components"; +import { useSanitizedLocation } from "@namada/hooks"; import { useAppDispatch, useAppSelector } from "store"; import { AppStore } from "store/store"; diff --git a/apps/namada-interface/src/App/TopNavigation/topNavigationLoggedIn.components.ts b/apps/namada-interface/src/App/TopNavigation/topNavigationLoggedIn.components.ts index 93edfed470..272c00d06d 100644 --- a/apps/namada-interface/src/App/TopNavigation/topNavigationLoggedIn.components.ts +++ b/apps/namada-interface/src/App/TopNavigation/topNavigationLoggedIn.components.ts @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { ColorMode, DesignConfiguration } from "@anoma/utils"; +import { ColorMode, DesignConfiguration } from "@namada/utils"; enum ComponentColor { NavItem, diff --git a/apps/namada-interface/src/App/TopNavigation/topNavigationLoggedIn.tsx b/apps/namada-interface/src/App/TopNavigation/topNavigationLoggedIn.tsx index 007d6b4b05..b81e632f8a 100644 --- a/apps/namada-interface/src/App/TopNavigation/topNavigationLoggedIn.tsx +++ b/apps/namada-interface/src/App/TopNavigation/topNavigationLoggedIn.tsx @@ -1,7 +1,7 @@ import { useNavigate } from "react-router-dom"; -import { Icon, IconName, Toggle } from "@anoma/components"; -import { ColorMode } from "@anoma/utils"; +import { Icon, IconName, Toggle } from "@namada/components"; +import { ColorMode } from "@namada/utils"; import { TopLevelRoute } from "App/types"; import { ColorModeContainer, OnlyInMedium } from "./topNavigation.components"; diff --git a/apps/namada-interface/src/App/types.ts b/apps/namada-interface/src/App/types.ts index e88adeee1b..2eddd594aa 100644 --- a/apps/namada-interface/src/App/types.ts +++ b/apps/namada-interface/src/App/types.ts @@ -83,8 +83,8 @@ export const locationToStakingAndGovernanceSubRoute = ( }; export enum LocalStorageKeys { - MasterSeed = "com.anoma.network:seed", - Session = "com.anoma.network:session", - Persist = "com.anoma.network:state", - ColorMode = "com.anoma.color-mode", + MasterSeed = "com.namada.network:seed", + Session = "com.namada.network:session", + Persist = "com.namada.network:state", + ColorMode = "com.namada.color-mode", } diff --git a/apps/namada-interface/src/index.tsx b/apps/namada-interface/src/index.tsx index cb8fad0e74..edfef3edc1 100644 --- a/apps/namada-interface/src/index.tsx +++ b/apps/namada-interface/src/index.tsx @@ -2,7 +2,7 @@ import React from "react"; import ReactDOM from "react-dom"; import { RouterProvider } from "react-router-dom"; import reportWebVitals from "./reportWebVitals"; -import { init as initShared } from "@anoma/shared/src/init"; +import { init as initShared } from "@namada/shared/src/init"; import "./index.css"; import { store } from "store/store"; import { getRouter } from "./App/AppRoutes"; diff --git a/apps/namada-interface/src/services/extensionEvents/handlers/index.ts b/apps/namada-interface/src/services/extensionEvents/handlers/index.ts index b1ef3e6f16..2ffb72911f 100644 --- a/apps/namada-interface/src/services/extensionEvents/handlers/index.ts +++ b/apps/namada-interface/src/services/extensionEvents/handlers/index.ts @@ -1,3 +1,3 @@ -export * from "./anoma"; +export * from "./namada"; export * from "./keplr"; export * from "./metamask"; diff --git a/apps/namada-interface/src/services/extensionEvents/handlers/keplr.ts b/apps/namada-interface/src/services/extensionEvents/handlers/keplr.ts index 9eb06af33a..da1cd3d9f4 100644 --- a/apps/namada-interface/src/services/extensionEvents/handlers/keplr.ts +++ b/apps/namada-interface/src/services/extensionEvents/handlers/keplr.ts @@ -1,6 +1,6 @@ import { Dispatch } from "react"; -import { Keplr } from "@anoma/integrations"; +import { Keplr } from "@namada/integrations"; import { addAccounts, fetchBalances } from "slices/accounts"; diff --git a/apps/namada-interface/src/services/extensionEvents/handlers/metamask.ts b/apps/namada-interface/src/services/extensionEvents/handlers/metamask.ts index 7d60dae736..7809c0341f 100644 --- a/apps/namada-interface/src/services/extensionEvents/handlers/metamask.ts +++ b/apps/namada-interface/src/services/extensionEvents/handlers/metamask.ts @@ -1,5 +1,5 @@ import { Dispatch } from "react"; -import { Metamask } from "@anoma/integrations"; +import { Metamask } from "@namada/integrations"; import { addAccounts, fetchBalances } from "slices/accounts"; export const MetamaskAccountChangedHandler = diff --git a/apps/namada-interface/src/services/extensionEvents/handlers/anoma.ts b/apps/namada-interface/src/services/extensionEvents/handlers/namada.ts similarity index 76% rename from apps/namada-interface/src/services/extensionEvents/handlers/anoma.ts rename to apps/namada-interface/src/services/extensionEvents/handlers/namada.ts index 742361703f..d577e9f413 100644 --- a/apps/namada-interface/src/services/extensionEvents/handlers/anoma.ts +++ b/apps/namada-interface/src/services/extensionEvents/handlers/namada.ts @@ -1,19 +1,19 @@ import { Dispatch } from "react"; -import { chains } from "@anoma/chains"; -import { Anoma } from "@anoma/integrations"; +import { chains } from "@namada/chains"; +import { Namada } from "@namada/integrations"; import { addAccounts, fetchBalances } from "slices/accounts"; import { actions as notificationsActions } from "slices/notifications"; import { getToast, Toasts } from "slices/transfers"; -export const AnomaAccountChangedHandler = - (dispatch: Dispatch, integration: Anoma) => +export const NamadaAccountChangedHandler = + (dispatch: Dispatch, integration: Namada) => async (event: CustomEventInit) => { const chainId = event.detail?.chainId; const chain = chains[chainId]; - if (chain.extension.id === "anoma") { + if (chain.extension.id === "namada") { const accounts = (await integration.accounts()) || []; dispatch(addAccounts(accounts)); @@ -21,12 +21,12 @@ export const AnomaAccountChangedHandler = } }; -export const AnomaUpdatedBalancesHandler = +export const NamadaUpdatedBalancesHandler = (dispatch: Dispatch) => async () => { dispatch(fetchBalances()); }; -export const AnomaTransferStartedHandler = +export const NamadaTransferStartedHandler = (dispatch: Dispatch) => async (event: CustomEventInit) => { const { msgId } = event.detail; dispatch( @@ -39,7 +39,7 @@ export const AnomaTransferStartedHandler = ); }; -export const AnomaTransferCompletedHandler = +export const NamadaTransferCompletedHandler = (dispatch: Dispatch) => async (event: CustomEventInit) => { const { msgId, success } = event.detail; dispatch( diff --git a/apps/namada-interface/src/services/extensionEvents/provider.tsx b/apps/namada-interface/src/services/extensionEvents/provider.tsx index ff0e376873..77dac031bf 100644 --- a/apps/namada-interface/src/services/extensionEvents/provider.tsx +++ b/apps/namada-interface/src/services/extensionEvents/provider.tsx @@ -1,20 +1,20 @@ import { createContext } from "react"; -import { Events, KeplrEvents, MetamaskEvents } from "@anoma/types"; +import { Events, KeplrEvents, MetamaskEvents } from "@namada/types"; import { defaultChainId, defaultCosmosChainId, defaultEthereumChainId, -} from "@anoma/chains"; -import { Anoma, Keplr, Metamask } from "@anoma/integrations"; -import { useEventListenerOnce, useIntegration } from "@anoma/hooks"; +} from "@namada/chains"; +import { Namada, Keplr, Metamask } from "@namada/integrations"; +import { useEventListenerOnce, useIntegration } from "@namada/hooks"; import { useAppDispatch } from "store"; import { - AnomaAccountChangedHandler, - AnomaTransferCompletedHandler, - AnomaTransferStartedHandler, - AnomaUpdatedBalancesHandler, + NamadaAccountChangedHandler, + NamadaTransferCompletedHandler, + NamadaTransferStartedHandler, + NamadaUpdatedBalancesHandler, KeplrAccountChangedHandler, MetamaskAccountChangedHandler, } from "./handlers"; @@ -23,18 +23,18 @@ export const ExtensionEventsContext = createContext({}); export const ExtensionEventsProvider: React.FC = (props): JSX.Element => { const dispatch = useAppDispatch(); - const anomaIntegration = useIntegration(defaultChainId); + const namadaIntegration = useIntegration(defaultChainId); const keplrIntegration = useIntegration(defaultCosmosChainId); const metamaskIntegration = useIntegration(defaultEthereumChainId); // Instantiate handlers: - const anomaAccountChangedHandler = AnomaAccountChangedHandler( + const namadaAccountChangedHandler = NamadaAccountChangedHandler( dispatch, - anomaIntegration as Anoma + namadaIntegration as Namada ); - const anomaTransferStartedHandler = AnomaTransferStartedHandler(dispatch); - const anomaTransferCompletedHandler = AnomaTransferCompletedHandler(dispatch); - const anomaUpdatedBalancesHandler = AnomaUpdatedBalancesHandler(dispatch); + const namadaTransferStartedHandler = NamadaTransferStartedHandler(dispatch); + const namadaTransferCompletedHandler = NamadaTransferCompletedHandler(dispatch); + const namadaUpdatedBalancesHandler = NamadaUpdatedBalancesHandler(dispatch); // Keplr handlers const keplrAccountChangedHandler = KeplrAccountChangedHandler( @@ -49,10 +49,10 @@ export const ExtensionEventsProvider: React.FC = (props): JSX.Element => { ); // Register handlers: - useEventListenerOnce(Events.AccountChanged, anomaAccountChangedHandler); - useEventListenerOnce(Events.TransferStarted, anomaTransferStartedHandler); - useEventListenerOnce(Events.TransferCompleted, anomaTransferCompletedHandler); - useEventListenerOnce(Events.UpdatedBalances, anomaUpdatedBalancesHandler); + useEventListenerOnce(Events.AccountChanged, namadaAccountChangedHandler); + useEventListenerOnce(Events.TransferStarted, namadaTransferStartedHandler); + useEventListenerOnce(Events.TransferCompleted, namadaTransferCompletedHandler); + useEventListenerOnce(Events.UpdatedBalances, namadaUpdatedBalancesHandler); useEventListenerOnce(KeplrEvents.AccountChanged, keplrAccountChangedHandler); useEventListenerOnce( MetamaskEvents.AccountChanged, diff --git a/apps/namada-interface/src/services/integrations/provider.tsx b/apps/namada-interface/src/services/integrations/provider.tsx index 160a87b838..d867268594 100644 --- a/apps/namada-interface/src/services/integrations/provider.tsx +++ b/apps/namada-interface/src/services/integrations/provider.tsx @@ -1,4 +1,4 @@ -import { IntegrationsContext, integrations } from "@anoma/hooks"; +import { IntegrationsContext, integrations } from "@namada/hooks"; export const IntegrationsProvider: React.FC = (props): JSX.Element => { return ( diff --git a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts index 5e0a83e68e..12fb09c418 100644 --- a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts +++ b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts @@ -1,10 +1,10 @@ import { createAsyncThunk } from "@reduxjs/toolkit"; import BigNumber from "bignumber.js"; -import { Query } from "@anoma/shared"; -import { Signer, Tokens } from "@anoma/types"; -import { chains } from "@anoma/chains"; -import { getIntegration } from "@anoma/hooks"; +import { Query } from "@namada/shared"; +import { Signer, Tokens } from "@namada/types"; +import { chains } from "@namada/chains"; +import { getIntegration } from "@namada/hooks"; import { FETCH_VALIDATORS, diff --git a/apps/namada-interface/src/slices/accounts.ts b/apps/namada-interface/src/slices/accounts.ts index bfa58b0606..bbc32b4b74 100644 --- a/apps/namada-interface/src/slices/accounts.ts +++ b/apps/namada-interface/src/slices/accounts.ts @@ -1,9 +1,9 @@ import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit"; import BigNumber from "bignumber.js"; -import { Account as AccountDetails, TokenType } from "@anoma/types"; -import { chains } from "@anoma/chains"; -import { getIntegration } from "@anoma/hooks"; +import { Account as AccountDetails, TokenType } from "@namada/types"; +import { chains } from "@namada/chains"; +import { getIntegration } from "@namada/hooks"; import { RootState } from "store"; diff --git a/apps/namada-interface/src/slices/coins.ts b/apps/namada-interface/src/slices/coins.ts index 1acc455b5b..48bd48abb2 100644 --- a/apps/namada-interface/src/slices/coins.ts +++ b/apps/namada-interface/src/slices/coins.ts @@ -1,7 +1,7 @@ import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit"; -import { Symbols, Tokens } from "@anoma/types"; -import { getTimeStamp } from "@anoma/utils"; +import { Symbols, Tokens } from "@namada/types"; +import { getTimeStamp } from "@namada/utils"; import Config from "config"; import { Currencies } from "currencies"; diff --git a/apps/namada-interface/src/slices/settings.ts b/apps/namada-interface/src/slices/settings.ts index 741307b1a2..24b6e99e4f 100644 --- a/apps/namada-interface/src/slices/settings.ts +++ b/apps/namada-interface/src/slices/settings.ts @@ -1,5 +1,5 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit"; -import { defaultChainId } from "@anoma/chains"; +import { defaultChainId } from "@namada/chains"; const SETTINGS_ACTIONS_BASE = "settings"; diff --git a/apps/namada-interface/src/slices/transfers.ts b/apps/namada-interface/src/slices/transfers.ts index 75851a928c..5a311eb87d 100644 --- a/apps/namada-interface/src/slices/transfers.ts +++ b/apps/namada-interface/src/slices/transfers.ts @@ -1,8 +1,8 @@ import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; import BigNumber from "bignumber.js"; -import { Account, Tokens, TokenType, Signer } from "@anoma/types"; -import { getIntegration } from "@anoma/hooks"; +import { Account, Tokens, TokenType, Signer } from "@namada/types"; +import { getIntegration } from "@namada/hooks"; import { actions as notificationsActions, diff --git a/apps/namada-interface/src/store/mocks.ts b/apps/namada-interface/src/store/mocks.ts index 8e2861067b..73dca8884d 100644 --- a/apps/namada-interface/src/store/mocks.ts +++ b/apps/namada-interface/src/store/mocks.ts @@ -7,11 +7,11 @@ import { StakingOrUnstakingState } from "slices/StakingAndGovernance"; export const mockAppState: RootState = { accounts: { derived: { - "anoma-masp-1.5.32ccad5356012a7": { + "namada-masp-1.5.32ccad5356012a7": { atest1v4ehgw36xqcyz3zrxsenzd3kxsunsvzzxymyywpkg4zrjv2pxepyyd3cgse5gwzxgsm5x3zrkf2pwp: { details: { - chainId: "anoma-masp-1.5.32ccad5356012a7", + chainId: "namada-masp-1.5.32ccad5356012a7", alias: "Namada", address: "atest1v4ehgw36xqcyz3zrxsenzd3kxsunsvzzxymyywpkg4zrjv2pxepyyd3cgse5gwzxgsm5x3zrkf2pwp", @@ -24,10 +24,10 @@ export const mockAppState: RootState = { }, }, }, - "anoma-test.1e670ba91369ec891fc": { + "namada-test.1e670ba91369ec891fc": { "39UL18": { details: { - chainId: "anoma-test.1e670ba91369ec891fc", + chainId: "namada-test.1e670ba91369ec891fc", alias: "Namada", address: "atest1v4ehgw36xqcyz3zrxsenzd3kxsunsvzzxymyywpkg4zrjv2pxepyyd3cgse5gwzxgsm5x3zrkf2pwp", @@ -40,10 +40,10 @@ export const mockAppState: RootState = { }, }, }, - "anoma-test.89060614ce340f4baae": { + "namada-test.89060614ce340f4baae": { "2MLGVA": { details: { - chainId: "anoma-test.89060614ce340f4baae", + chainId: "namada-test.89060614ce340f4baae", alias: "Namada", address: "L1qDtV8TRwYLSHdMDW518hgRw9nWnRjFTenkcBYNJruyYoLjaj8F", isShielded: false, @@ -61,7 +61,7 @@ export const mockAppState: RootState = { transfers: { transactions: [ { - chainId: "anoma-masp-1.5.32ccad5356012a7", + chainId: "namada-masp-1.5.32ccad5356012a7", source: "atest1v4ehgw36gc6yxvpjxccyzvphxycrxw2xxsuyydesxgcnjs3cg9znwv3cxgmnj32yxy6rssf5tcqjm3", target: @@ -77,7 +77,7 @@ export const mockAppState: RootState = { type: TransferType.NonShielded, }, { - chainId: "anoma-masp-1.5.32ccad5356012a7", + chainId: "namada-masp-1.5.32ccad5356012a7", source: "atest1v4ehgw36gc6yxvpjxccyzvphxycrxw2xxsuyydesxgcnjs3cg9znwv3cxgmnj32yxy6rssf5tcqjm3", target: @@ -93,7 +93,7 @@ export const mockAppState: RootState = { type: TransferType.NonShielded, }, { - chainId: "anoma-masp-1.5.32ccad5356012a7", + chainId: "namada-masp-1.5.32ccad5356012a7", source: "atest1v4ehgw36gc6yxvpjxccyzvphxycrxw2xxsuyydesxgcnjs3cg9znwv3cxgmnj32yxy6rssf5tcqjm3", target: @@ -116,17 +116,17 @@ export const mockAppState: RootState = { }, channels: { channelsByChain: { - "anoma-test.1e670ba91369ec891fc": { - "anoma-test.89060614ce340f4baae": ["channel-0"], + "namada-test.1e670ba91369ec891fc": { + "namada-test.89060614ce340f4baae": ["channel-0"], }, - "anoma-test.89060614ce340f4baae": { - "anoma-test.1e670ba91369ec891fc": ["channel-0"], + "namada-test.89060614ce340f4baae": { + "namada-test.1e670ba91369ec891fc": ["channel-0"], }, }, }, settings: { fiatCurrency: "USD", - chainId: "anoma-masp-1.5.32ccad5356012a7", + chainId: "namada-masp-1.5.32ccad5356012a7", connectedChains: [], }, coins: { diff --git a/apps/namada-interface/src/store/store.ts b/apps/namada-interface/src/store/store.ts index db5d4dd73d..c7f0a38f57 100644 --- a/apps/namada-interface/src/store/store.ts +++ b/apps/namada-interface/src/store/store.ts @@ -15,7 +15,7 @@ import { import { LocalStorageKeys } from "App/types"; import { createTransform } from "redux-persist"; import { SettingsState } from "slices/settings"; -import { chains, defaultChainId } from "@anoma/chains"; +import { chains, defaultChainId } from "@namada/chains"; const { REACT_APP_LOCAL, NODE_ENV } = process.env; const POSTFIX = diff --git a/apps/namada-interface/src/styled.d.ts b/apps/namada-interface/src/styled.d.ts index f758193beb..a75432c212 100644 --- a/apps/namada-interface/src/styled.d.ts +++ b/apps/namada-interface/src/styled.d.ts @@ -1,5 +1,5 @@ import "styled-components"; -import { DesignConfiguration } from "@anoma/utils"; +import { DesignConfiguration } from "@namada/utils"; interface IPalette { main: string; contrastText: string; diff --git a/package.json b/package.json index f871845567..1d0a578239 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "anoma", + "name": "namada", "version": "0.1.0", "private": true, "workspaces": [ diff --git a/packages/chains/package.json b/packages/chains/package.json index 11abd18f5f..6269f19740 100644 --- a/packages/chains/package.json +++ b/packages/chains/package.json @@ -1,5 +1,5 @@ { - "name": "@anoma/chains", + "name": "@namada/chains", "version": "0.1.0", "description": "Chain configurations for Namada", "main": "src/index.ts", @@ -9,7 +9,7 @@ "private": false, "dependencies": { "typescript": "^5.1.3", - "@anoma/types": "0.1.0" + "@namada/types": "0.1.0" }, "devDependencies": { "eslint": "^8.27.0", diff --git a/packages/chains/src/chains/cosmos.ts b/packages/chains/src/chains/cosmos.ts index 743a1d239b..9757638e59 100644 --- a/packages/chains/src/chains/cosmos.ts +++ b/packages/chains/src/chains/cosmos.ts @@ -1,4 +1,4 @@ -import { BridgeType, Chain, Extensions } from "@anoma/types"; +import { BridgeType, Chain, Extensions } from "@namada/types"; const DEFAULT_ALIAS = "Cosmos Hub"; const DEFAULT_CHAIN_ID = "cosmoshub-4"; diff --git a/packages/chains/src/chains/ethereum.ts b/packages/chains/src/chains/ethereum.ts index d64f9c392e..48917d51b3 100644 --- a/packages/chains/src/chains/ethereum.ts +++ b/packages/chains/src/chains/ethereum.ts @@ -1,4 +1,4 @@ -import { BridgeType, Chain, Extensions } from "@anoma/types"; +import { BridgeType, Chain, Extensions } from "@namada/types"; const DEFAULT_ALIAS = "Goerli Testnet"; const DEFAULT_CHAIN_ID = "0x5"; diff --git a/packages/chains/src/chains/namada.ts b/packages/chains/src/chains/namada.ts index eb9e36e961..0c4ce3cb86 100644 --- a/packages/chains/src/chains/namada.ts +++ b/packages/chains/src/chains/namada.ts @@ -1,4 +1,4 @@ -import { BridgeType, Chain, Extensions } from "@anoma/types"; +import { BridgeType, Chain, Extensions } from "@namada/types"; const DEFAULT_ALIAS = "Namada Testnet"; const DEFAULT_CHAIN_ID = "qc-testnet-5.1.025a61165acd05e"; @@ -28,7 +28,7 @@ const namada: Chain = { symbol: "NAM", gasPriceStep: { low: 0.01, average: 0.025, high: 0.03 }, }, - extension: Extensions["anoma"], + extension: Extensions["namada"], ibc: { portId: "transfer", }, diff --git a/packages/components/package.json b/packages/components/package.json index 45decd36f6..d5c6c81926 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,7 +1,7 @@ { - "name": "@anoma/components", + "name": "@namada/components", "version": "0.1.0", - "description": "A collection of components for use with the Anoma ecosystem", + "description": "A collection of components for use with the Namada ecosystem", "main": "src/index.ts", "repository": "https://github.com/anoma/namada-interface", "author": "Heliax Dev ", @@ -13,7 +13,7 @@ "lint:ci": "yarn lint --max-warnings 0" }, "dependencies": { - "@anoma/utils": "0.1.0", + "@namada/utils": "0.1.0", "react": "^17.0.2", "styled-components": "^5.3.5", "typescript": "^5.1.3" diff --git a/packages/components/src/Button/button.components.ts b/packages/components/src/Button/button.components.ts index 892b6fd9d8..8edf9660c4 100644 --- a/packages/components/src/Button/button.components.ts +++ b/packages/components/src/Button/button.components.ts @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { DesignConfiguration, ColorMode } from "@anoma/utils"; +import { DesignConfiguration, ColorMode } from "@namada/utils"; enum ComponentColor { ButtonBackground, diff --git a/packages/components/src/Input/input.components.ts b/packages/components/src/Input/input.components.ts index efd4792255..a8d62a3b84 100644 --- a/packages/components/src/Input/input.components.ts +++ b/packages/components/src/Input/input.components.ts @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { ColorMode, DesignConfiguration } from "@anoma/utils"; +import { ColorMode, DesignConfiguration } from "@namada/utils"; enum ComponentColor { BorderColor, diff --git a/packages/components/src/Select/Select.components.ts b/packages/components/src/Select/Select.components.ts index 4db4a73d04..3de816dc7a 100644 --- a/packages/components/src/Select/Select.components.ts +++ b/packages/components/src/Select/Select.components.ts @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { ColorMode, DesignConfiguration } from "@anoma/utils"; +import { ColorMode, DesignConfiguration } from "@namada/utils"; enum ComponentColor { Arrow, diff --git a/packages/components/src/Toggle/toggle.components.ts b/packages/components/src/Toggle/toggle.components.ts index 3014f75db5..91396b0837 100644 --- a/packages/components/src/Toggle/toggle.components.ts +++ b/packages/components/src/Toggle/toggle.components.ts @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { ColorMode, DesignConfiguration } from "@anoma/utils"; +import { ColorMode, DesignConfiguration } from "@namada/utils"; const COMPONENT_WIDTH_PIXELS = 46; const CIRCLE_DIAMETER_PIXELS = 20; diff --git a/packages/crypto/README.md b/packages/crypto/README.md index 94098f536f..81a9db9444 100644 --- a/packages/crypto/README.md +++ b/packages/crypto/README.md @@ -1,6 +1,6 @@ # crypto -The `@anoma/crypto` package is to provide cryptography functionality with Rust via WebAssembly. +The `@namada/crypto` package is to provide cryptography functionality with Rust via WebAssembly. The Rust source code lives in `lib/`, and currently provides the following crates: diff --git a/packages/crypto/lib/Cargo.toml b/packages/crypto/lib/Cargo.toml index c98f49f670..75e065cc28 100644 --- a/packages/crypto/lib/Cargo.toml +++ b/packages/crypto/lib/Cargo.toml @@ -4,7 +4,7 @@ authors = ["Heliax AG "] version = "0.1.0" edition = "2021" repository = "https://github.com/anoma/namada-interface/" -description = "Cryptographic functions for Anoma apps" +description = "Cryptographic functions for Namada apps" license = "MIT" [lib] diff --git a/packages/crypto/lib/src/lib.rs b/packages/crypto/lib/src/lib.rs index 2cf767d209..45743fede2 100644 --- a/packages/crypto/lib/src/lib.rs +++ b/packages/crypto/lib/src/lib.rs @@ -1,5 +1,5 @@ //! # crypto //! -//! A library of cryptographic functions for use in the Anoma ecosystem +//! A library of cryptographic functions for use in the Namada ecosystem pub mod crypto; diff --git a/packages/crypto/package.json b/packages/crypto/package.json index 97dc374a8f..2acc83321d 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -1,7 +1,7 @@ { - "name": "@anoma/crypto", + "name": "@namada/crypto", "version": "0.1.0", - "description": "Crypto functions related to Anoma", + "description": "Crypto functions related to Namada", "main": "src/index.ts", "repository": "https://github.com/anoma/namada-interface/", "author": "Heliax Dev ", diff --git a/packages/hooks/README.md b/packages/hooks/README.md index 6f8d283fa9..4b14fa7809 100644 --- a/packages/hooks/README.md +++ b/packages/hooks/README.md @@ -1,6 +1,6 @@ # hooks -The `@anoma/hooks` package contains re-usable React hooks that may be of use to both the `extension` and `namada-interface` apps, +The `@namada/hooks` package contains re-usable React hooks that may be of use to both the `extension` and `namada-interface` apps, as well as for third-party integrations. Currently, the following hooks are defined: diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 6c9dd079ac..d7d9b0338e 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,5 +1,5 @@ { - "name": "@anoma/hooks", + "name": "@namada/hooks", "version": "0.1.0", "description": "A collection of React hooks", "main": "src/index.ts", @@ -13,10 +13,10 @@ "lint:ci": "yarn lint --max-warnings 0" }, "dependencies": { - "@anoma/chains": "0.1.0", - "@anoma/integrations": "0.1.0", - "@anoma/types": "0.1.0", - "@anoma/utils": "0.1.0", + "@namada/chains": "0.1.0", + "@namada/integrations": "0.1.0", + "@namada/types": "0.1.0", + "@namada/utils": "0.1.0", "react": "^17.0.2", "typescript": "^5.1.3" }, diff --git a/packages/hooks/src/useIntegration.ts b/packages/hooks/src/useIntegration.ts index 91ff55d6e9..fa2f6af41b 100644 --- a/packages/hooks/src/useIntegration.ts +++ b/packages/hooks/src/useIntegration.ts @@ -6,12 +6,12 @@ import { useState, } from "react"; -import { chains } from "@anoma/chains"; -import { Anoma, Keplr, Metamask } from "@anoma/integrations"; -import { Chain, ExtensionKey } from "@anoma/types"; -import { useUntil } from "@anoma/hooks"; +import { chains } from "@namada/chains"; +import { Namada, Keplr, Metamask } from "@namada/integrations"; +import { Chain, ExtensionKey } from "@namada/types"; +import { useUntil } from "@namada/hooks"; -type Integration = typeof Anoma | typeof Keplr | typeof Metamask; +type Integration = typeof Namada | typeof Keplr | typeof Metamask; type ChainId = string; type IntegrationsMap = Record; export type Integrations = Record>; @@ -21,7 +21,7 @@ type ExtensionConnection = ( ) => Promise; const extensionMap: IntegrationsMap = { - anoma: Anoma, + namada: Namada, keplr: Keplr, metamask: Metamask, }; @@ -106,7 +106,7 @@ export const useUntilIntegrationAttached = (chain: Chain): AttachStatusMap => { const integration = useIntegration(chainId); const [attachStatusMap, setAttachStatus] = useState({ - anoma: "pending", + namada: "pending", keplr: "pending", metamask: "pending", }); diff --git a/packages/hooks/src/useUntil.ts b/packages/hooks/src/useUntil.ts index 3c81f8caeb..1929a71e89 100644 --- a/packages/hooks/src/useUntil.ts +++ b/packages/hooks/src/useUntil.ts @@ -1,6 +1,6 @@ import { useEffect } from "react"; -import { executeUntil, Config } from "@anoma/utils"; +import { executeUntil, Config } from "@namada/utils"; type Options = { predFn: () => Promise; diff --git a/packages/integrations/README.md b/packages/integrations/README.md index 9edeb78214..9ffbf5d460 100644 --- a/packages/integrations/README.md +++ b/packages/integrations/README.md @@ -1,6 +1,6 @@ # integrations -Anoma Wallet third-party integrations. +Namada Wallet third-party integrations. - Keplr Wallet - Metamask Wallet diff --git a/packages/integrations/package.json b/packages/integrations/package.json index cf5c6d3279..51eecdda47 100644 --- a/packages/integrations/package.json +++ b/packages/integrations/package.json @@ -1,7 +1,7 @@ { - "name": "@anoma/integrations", + "name": "@namada/integrations", "version": "0.1.0", - "description": "Anoma Wallet third-party integrations", + "description": "Namada Wallet third-party integrations", "main": "src/index.ts", "repository": "https://github.com/anoma/namada-interface", "author": "Heliax Dev ", @@ -30,8 +30,8 @@ "ts-node": "^10.9.1" }, "dependencies": { - "@anoma/types": "0.1.0", - "@anoma/utils": "0.1.0", + "@namada/types": "0.1.0", + "@namada/utils": "0.1.0", "@cosmjs/launchpad": "^0.27.1", "@cosmjs/proto-signing": "^0.27.1", "@cosmjs/stargate": "^0.29.5", diff --git a/packages/integrations/src/Keplr.test.ts b/packages/integrations/src/Keplr.test.ts index dd3f924a06..c325179464 100644 --- a/packages/integrations/src/Keplr.test.ts +++ b/packages/integrations/src/Keplr.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { mock } from "jest-mock-extended"; -import { Chain } from "@anoma/types"; +import { Chain } from "@namada/types"; import { Key, Keplr as IKeplr } from "@keplr-wallet/types"; import Keplr from "./Keplr"; diff --git a/packages/integrations/src/Keplr.ts b/packages/integrations/src/Keplr.ts index 667d39fab5..53f9d76383 100644 --- a/packages/integrations/src/Keplr.ts +++ b/packages/integrations/src/Keplr.ts @@ -12,8 +12,8 @@ import { import { Coin } from "@cosmjs/launchpad"; import Long from "long"; -import { Account, Chain, CosmosTokens, TokenBalance } from "@anoma/types"; -import { shortenAddress } from "@anoma/utils"; +import { Account, Chain, CosmosTokens, TokenBalance } from "@namada/types"; +import { shortenAddress } from "@namada/utils"; import { BridgeProps, Integration } from "./types/Integration"; const KEPLR_NOT_FOUND = "Keplr extension not found!"; diff --git a/packages/integrations/src/Metamask.ts b/packages/integrations/src/Metamask.ts index ef75ec36e2..08a0e4c368 100644 --- a/packages/integrations/src/Metamask.ts +++ b/packages/integrations/src/Metamask.ts @@ -1,8 +1,8 @@ import { type MetaMaskInpageProvider } from "@metamask/providers"; import MetaMaskSDK from "@metamask/sdk"; -import { Account, Chain, TokenBalance } from "@anoma/types"; -import { shortenAddress } from "@anoma/utils"; +import { Account, Chain, TokenBalance } from "@namada/types"; +import { shortenAddress } from "@namada/utils"; import { BridgeProps, Integration } from "./types/Integration"; const MULTIPLE_WALLETS = "Multiple wallets installed!"; diff --git a/packages/integrations/src/Anoma.ts b/packages/integrations/src/Namada.ts similarity index 75% rename from packages/integrations/src/Anoma.ts rename to packages/integrations/src/Namada.ts index aff6e0bba3..f68be24ce3 100644 --- a/packages/integrations/src/Anoma.ts +++ b/packages/integrations/src/Namada.ts @@ -1,50 +1,50 @@ import { Account, - Anoma as IAnoma, + Namada as INamada, Chain, Signer, Tokens, TokenType, TokenBalance, - WindowWithAnoma, -} from "@anoma/types"; + WindowWithNamada, +} from "@namada/types"; import BigNumber from "bignumber.js"; import { BridgeProps, Integration } from "./types/Integration"; -export default class Anoma implements Integration { - private _anoma: WindowWithAnoma["anoma"] | undefined; +export default class Namada implements Integration { + private _namada: WindowWithNamada["namada"] | undefined; constructor(public readonly chain: Chain) {} - public get instance(): IAnoma | undefined { - return this._anoma; + public get instance(): INamada | undefined { + return this._namada; } private _init(): void { - if (!this._anoma) { - this._anoma = (window)?.anoma; + if (!this._namada) { + this._namada = (window)?.namada; } } public detect(): boolean { this._init(); - return !!this._anoma; + return !!this._namada; } public async connect(): Promise { this._init(); - await this._anoma?.connect(this.chain.chainId); + await this._namada?.connect(this.chain.chainId); } public async accounts(): Promise { await this.connect(); - const signer = this._anoma?.getSigner(this.chain.chainId); + const signer = this._namada?.getSigner(this.chain.chainId); return await signer?.accounts(); } public signer(): Signer | undefined { - return this._anoma?.getSigner(this.chain.chainId); + return this._namada?.getSigner(this.chain.chainId); } public async submitBridgeTransfer(props: BridgeProps): Promise { @@ -52,7 +52,7 @@ export default class Anoma implements Integration { const { source, receiver, channelId, portId, amount, token } = props.ibcProps; const tokenAddress = Tokens[token as TokenType]?.address; - const signer = this._anoma?.getSigner(this.chain.chainId); + const signer = this._namada?.getSigner(this.chain.chainId); return await signer?.submitIbcTransfer({ tx: { @@ -77,7 +77,7 @@ export default class Anoma implements Integration { } public async queryBalances(owner: string): Promise { - const balance = (await this._anoma?.balances(owner)) || []; + const balance = (await this._namada?.balances(owner)) || []; const tokenBalances = Object.keys(Tokens).map((tokenType: string) => { const { address: tokenAddress = "" } = Tokens[tokenType as TokenType]; const amount = diff --git a/packages/integrations/src/index.ts b/packages/integrations/src/index.ts index 695e8a5c6c..95402873c6 100644 --- a/packages/integrations/src/index.ts +++ b/packages/integrations/src/index.ts @@ -1,5 +1,5 @@ -import Anoma from "./Anoma"; +import Namada from "./Namada"; import Keplr from "./Keplr"; import Metamask from "./Metamask"; -export { Anoma, Keplr, Metamask }; +export { Namada, Keplr, Metamask }; diff --git a/packages/integrations/src/types/Integration.ts b/packages/integrations/src/types/Integration.ts index b156d1e648..74f77d4c5c 100644 --- a/packages/integrations/src/types/Integration.ts +++ b/packages/integrations/src/types/Integration.ts @@ -2,7 +2,7 @@ import { BridgeTransferProps, IbcTransferProps, TokenBalance, -} from "@anoma/types"; +} from "@namada/types"; export type BridgeProps = { ibcProps?: IbcTransferProps; diff --git a/packages/shared/README.md b/packages/shared/README.md index 56bb45a9d1..7353c5844a 100644 --- a/packages/shared/README.md +++ b/packages/shared/README.md @@ -1,6 +1,6 @@ # shared -Anoma shared library functionality, providing wasm-compability for features in `namada/shared`. +Namada shared library functionality, providing wasm-compability for features in `namada/shared`. ## Usage diff --git a/packages/shared/lib/Cargo.toml b/packages/shared/lib/Cargo.toml index d470ea419c..8c39026cee 100644 --- a/packages/shared/lib/Cargo.toml +++ b/packages/shared/lib/Cargo.toml @@ -4,7 +4,7 @@ authors = ["Heliax AG "] version = "0.1.0" edition = "2021" repository = "https://github.com/anoma/namada-interface/" -description = "Shared functionality from Anoma protocol" +description = "Shared functionality from Namada protocol" license = "MIT" [lib] diff --git a/packages/shared/lib/src/lib.rs b/packages/shared/lib/src/lib.rs index dfe3766464..6054948cd1 100644 --- a/packages/shared/lib/src/lib.rs +++ b/packages/shared/lib/src/lib.rs @@ -1,6 +1,6 @@ //! # shared //! -//! A library of functions to integrate shared functionality from the Anoma ecosystem +//! A library of functions to integrate shared functionality from the Namada ecosystem pub mod account; pub mod query; diff --git a/packages/shared/lib/src/sdk/mod.js b/packages/shared/lib/src/sdk/mod.js index 94f1fea187..3cbefade7a 100644 --- a/packages/shared/lib/src/sdk/mod.js +++ b/packages/shared/lib/src/sdk/mod.js @@ -1,4 +1,4 @@ -export const PREFIX = "Anoma::SDK"; +export const PREFIX = "Namada::SDK"; export async function hasMaspParams() { return ( diff --git a/packages/shared/lib/src/types/masp.rs b/packages/shared/lib/src/types/masp.rs index 5f86a5f40e..117358d33f 100644 --- a/packages/shared/lib/src/types/masp.rs +++ b/packages/shared/lib/src/types/masp.rs @@ -1,5 +1,5 @@ //! PaymentAddress - Provide wasm_bindgen bindings for shielded addresses -//! See @anoma/crypto for zip32 HD wallet functionality. +//! See @namada/crypto for zip32 HD wallet functionality. use borsh::BorshDeserialize; use masp_primitives::{sapling, zip32}; use namada::types::masp; @@ -105,7 +105,7 @@ mod tests { #[test] fn can_deserialize_an_extended_spending_key() { - // BorshSerialize'd slice, generated from @anoma/crypto - zip32 + // BorshSerialize'd slice, generated from @namada/crypto - zip32 let encoded_xsk: &[u8] = &[ 1, 233, 222, 184, 155, 1, 0, 0, 0, 232, 94, 130, 41, 9, 58, 197, 35, 245, 249, 232, 225, 222, 38, 148, 105, 204, 14, 230, 30, 241, 22, 214, 38, 221, 49, 17, 147, 255, 136, @@ -135,7 +135,7 @@ mod tests { #[test] fn can_deserialize_an_extended_viewing_key() { - // BorshSerialize'd slice, generated from @anoma/crypto - zip32 + // BorshSerialize'd slice, generated from @namada/crypto - zip32 let encoded_xfvk: &[u8] = &[ 1, 233, 222, 184, 155, 1, 0, 0, 0, 232, 94, 130, 41, 9, 58, 197, 35, 245, 249, 232, 225, 222, 38, 148, 105, 204, 14, 230, 30, 241, 22, 214, 38, 221, 49, 17, 147, 255, 136, @@ -164,7 +164,7 @@ mod tests { #[test] fn can_deserialize_a_payment_address() { - // BorshSerialize'd slice, generated from @anoma/crypto - zip32 + // BorshSerialize'd slice, generated from @namada/crypto - zip32 let encoded_payment_address: &[u8] = &[ 100, 199, 34, 96, 93, 67, 18, 95, 86, 139, 123, 213, 141, 228, 147, 169, 218, 247, 75, 83, 195, 72, 73, 44, 65, 232, 243, 229, 209, 63, 183, 1, 87, 87, 203, 40, 180, 242, diff --git a/packages/shared/package.json b/packages/shared/package.json index 9b6330bf16..9a0dc9a052 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,7 +1,7 @@ { - "name": "@anoma/shared", + "name": "@namada/shared", "version": "0.1.0", - "description": "Anoma shared functionality", + "description": "Namada shared functionality", "main": "src/index.ts", "repository": "https://github.com/anoma/namada-interface/", "author": "Heliax Dev ", diff --git a/packages/storage/package.json b/packages/storage/package.json index 36729e5071..47300417e5 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -1,7 +1,7 @@ { - "name": "@anoma/storage", + "name": "@namada/storage", "version": "0.1.0", - "description": "Browser storage for Anoma apps", + "description": "Browser storage for Namada apps", "main": "src/index.ts", "repository": "https://github.com/anoma/namada-interface", "author": "Heliax Dev ", diff --git a/packages/storage/src/store/Store.ts b/packages/storage/src/store/Store.ts index 9115c6b5b4..343d9f2de8 100644 --- a/packages/storage/src/store/Store.ts +++ b/packages/storage/src/store/Store.ts @@ -1,4 +1,4 @@ -import { KVStore } from "@anoma/storage"; +import { KVStore } from "@namada/storage"; // StoredRecords in storage should have a unique identifier export type StoredRecord = { id: string }; diff --git a/packages/types/README.md b/packages/types/README.md index a11da08978..c060f506a4 100644 --- a/packages/types/README.md +++ b/packages/types/README.md @@ -1,21 +1,21 @@ # types -This package is to provide types shared between applications in the Anoma ecosystem, primarily that of +This package is to provide types shared between applications in the Namada ecosystem, primarily that of the `namada-interface` and `extension` apps. Some types from `@keplr-wallet/types` have been aliased and re-exported, as we may want to support a more custom configuration for chain and currency configurations. These have been added to reduce the work necessary to refactor against a custom type definition. -The exported `Anoma` and `WindowWithAnoma` types serve as a public interface allowing other applications to +The exported `Namada` and `WindowWithNamada` types serve as a public interface allowing other applications to integrate with the APIs provided by the extension using TypeScript. ## Borsh schemas In `src/tx`, we have several schemas for handling Borsh serialization and deserialization when submitting transaction data. As transaction data from the user needs to move between an external application and the extension, this allow greater -privacy using with the `postMessage` API. These directly correllate to Rust `struct`s defined in the `@anoma/shared` package, -but exist here as to decouple them from the wasm dependency in the build pipeline. Including `@anoma/shared` would imply +privacy using with the `postMessage` API. These directly correllate to Rust `struct`s defined in the `@namada/shared` package, +but exist here as to decouple them from the wasm dependency in the build pipeline. Including `@namada/shared` would imply that you're willing to deliver compiled wasm in your final bundle, but that shouldn't be the case when you're merely interacting with the extension. @@ -27,7 +27,7 @@ from the user and passing into the extension where the associated private keys c An application can serialize transaction data using these schemas as follows: ```ts -import { Message, TransferMsgSchema, TransferMsgValue } from "@anoma/types"; +import { Message, TransferMsgSchema, TransferMsgValue } from "@namada/types"; // The user's data for transfer: const source = diff --git a/packages/types/package.json b/packages/types/package.json index 344369cc67..be30c64bbb 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,7 +1,7 @@ { - "name": "@anoma/types", + "name": "@namada/types", "version": "0.1.0", - "description": "Types related to the Anoma Extension", + "description": "Types related to the Namada Extension", "main": "src/index.ts", "repository": "https://github.com/anoma/namada-interface/", "author": "Heliax AG ", diff --git a/packages/types/src/chain.ts b/packages/types/src/chain.ts index b0a1c62fd9..3403fce3eb 100644 --- a/packages/types/src/chain.ts +++ b/packages/types/src/chain.ts @@ -16,7 +16,7 @@ export enum BridgeType { } // Define keys for supported extensions -export type ExtensionKey = "anoma" | "keplr" | "metamask"; +export type ExtensionKey = "namada" | "keplr" | "metamask"; export type ExtensionInfo = { alias: string; @@ -26,9 +26,9 @@ export type ExtensionInfo = { // Define constant with extension properties export const Extensions: Record = { - anoma: { - alias: "Anoma", - id: "anoma", + namada: { + alias: "Namada", + id: "namada", url: "https://namada.me/", }, keplr: { diff --git a/packages/types/src/events.ts b/packages/types/src/events.ts index 5fecc6e843..482c6ff477 100644 --- a/packages/types/src/events.ts +++ b/packages/types/src/events.ts @@ -1,11 +1,11 @@ // Constants defining events which may be subscribed to -// Anoma extension events +// Namada extension events export enum Events { - AccountChanged = "anoma-account-changed", - TransferStarted = "anoma-transfer-started", - TransferCompleted = "anoma-transfer-completed", - UpdatedBalances = "anoma-updated-balances", + AccountChanged = "namada-account-changed", + TransferStarted = "namada-transfer-started", + TransferCompleted = "namada-transfer-completed", + UpdatedBalances = "namada-updated-balances", } // Keplr extension events diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index c052e0e043..f702338d00 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -1,5 +1,5 @@ export * from "./account"; -export * from "./anoma"; +export * from "./namada"; export * from "./chain"; export * from "./events"; export * from "./signer"; diff --git a/packages/types/src/anoma.ts b/packages/types/src/namada.ts similarity index 90% rename from packages/types/src/anoma.ts rename to packages/types/src/namada.ts index e0335a5fb9..db47aaf323 100644 --- a/packages/types/src/anoma.ts +++ b/packages/types/src/namada.ts @@ -2,7 +2,7 @@ import { DerivedAccount } from "./account"; import { Chain } from "./chain"; import { Signer } from "./signer"; -export interface Anoma { +export interface Namada { connect(chainId: string): Promise; accounts(chainId: string): Promise; balances( @@ -22,9 +22,9 @@ export interface Anoma { version: () => string; } -export type WindowWithAnoma = Window & +export type WindowWithNamada = Window & typeof globalThis & { - anoma: Anoma & { + namada: Namada & { getSigner: (chainId: string) => Signer; }; }; diff --git a/packages/utils/README.md b/packages/utils/README.md index c87e0164b1..a9946e25f0 100644 --- a/packages/utils/README.md +++ b/packages/utils/README.md @@ -1,5 +1,5 @@ # util -Anoma Wallet utility library +Namada Wallet utility library _TBD_ diff --git a/packages/utils/package.json b/packages/utils/package.json index 83b9cebd13..d394222bba 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,7 +1,7 @@ { - "name": "@anoma/utils", + "name": "@namada/utils", "version": "0.1.0", - "description": "Anoma Wallet Utilities", + "description": "Namada Wallet Utilities", "main": "src/index.ts", "repository": "https://github.com/anoma/namada-interface/", "author": "Heliax Dev ", diff --git a/packages/utils/src/helpers/index.ts b/packages/utils/src/helpers/index.ts index e7d9a9fd26..e6ea41efa3 100644 --- a/packages/utils/src/helpers/index.ts +++ b/packages/utils/src/helpers/index.ts @@ -1,6 +1,6 @@ import { JsonRpcRequest } from "@cosmjs/json-rpc"; import { DateTime } from "luxon"; -import { JsonCompatibleArray, JsonCompatibleDictionary } from "@anoma/types"; +import { JsonCompatibleArray, JsonCompatibleDictionary } from "@namada/types"; import BigNumber from "bignumber.js"; const MICRO_FACTOR = 1000000; // 1,000,000 diff --git a/packages/utils/src/theme/theme.ts b/packages/utils/src/theme/theme.ts index 5c8212b82a..6420b72564 100644 --- a/packages/utils/src/theme/theme.ts +++ b/packages/utils/src/theme/theme.ts @@ -2,7 +2,7 @@ // our Figma, which is considered to be the source of truth. // https://www.figma.com/file/aiWZpaXjPLW6fDjE7dpFaU/Projects-2021?node-id=9102%3A8806 -const ColorModeStorageKey = "com.anoma.color-mode"; +const ColorModeStorageKey = "com.namada.color-mode"; type Colors = { primary: { diff --git a/specs/browser-extension/integration.md b/specs/browser-extension/integration.md index b8ad5d5731..92750c5290 100644 --- a/specs/browser-extension/integration.md +++ b/specs/browser-extension/integration.md @@ -9,7 +9,7 @@ The extension is able to be integrated with in a similar fasion to Keplr and Met If the extension is installed, and the domain is enabled (currently, all domains are enabled by the extension), detection can be achieved simply by doing the following: ```typescript= -const isExtensionInstalled = typeof window.anoma === 'object'; +const isExtensionInstalled = typeof window.namada === 'object'; ``` ## 2. Connecting to the extension @@ -18,7 +18,7 @@ To connect your application to the extension, you can invoke the following, prov ```typescript= const chainId = 'namada-test.XXXXXXXXXX'; -await anoma.connect(chainId); +await namada.connect(chainId); ``` Soon, this will prompt the user to either `Accept` or `Reject` a connection, but this isn't currently implemented. @@ -28,7 +28,7 @@ Soon, this will prompt the user to either `Accept` or `Reject` a connection, but To query available accounts in the extension, we first instantiate a signing client: ```typescript= -const client = await anoma.getSigner(chainId); +const client = await namada.getSigner(chainId); const accounts = await client.accounts(); @@ -49,7 +49,7 @@ const accounts = await client.accounts(); There are two types that can be imported from `namada-interface`: ```typescript= -import { TxProps, TransferProps } from "@anoma/types"; +import { TxProps, TransferProps } from "@namada/types"; ``` Where the following is defined (for reference - these are the properties we will need to provide to the signing client): @@ -76,7 +76,7 @@ export type TransferProps = { We will need to import a pre-built `tx-transfer` wasm file to provide to `TxProps`. There is a utility (see the following) that handles fetching these: ```typescript= -import { fetchWasmCode } from "@anoma/utils"; +import { fetchWasmCode } from "@namada/utils"; (async () { const txCode = await fetchWasmCode('./path/to/tx-transfer.wasm'); @@ -87,7 +87,7 @@ import { fetchWasmCode } from "@anoma/utils"; ### 4.2 Encoding a transfer tx ```typescript= -const client = anoma.getSigner("namada-test.XXXXXXXXXXX"); +const client = namada.getSigner("namada-test.XXXXXXXXXXX"); const address = "atest1v4ehgw368ycryv2z8qcnxv3cxgmrgvjpxs6yg333gym5vv2zxepnj334g4rryvj9xucrgve4x3xvr4"; // NOTE: Transfer amount is converted to micro-units diff --git a/specs/browser-extension/security.md b/specs/browser-extension/security.md index db34606006..50fcf4bf3d 100644 --- a/specs/browser-extension/security.md +++ b/specs/browser-extension/security.md @@ -19,7 +19,7 @@ when communicating between the web client and the content scripts. This requires ## Routing -When the extension is installed, the content and background scripts establish a shared state variable, `anomaExtensionRouterId`, stored in the extension's `localStorage`, which allows +When the extension is installed, the content and background scripts establish a shared state variable, `namadaExtensionRouterId`, stored in the extension's `localStorage`, which allows us to validate messages between the two before performing any actions in the background scripts. ## Handling sensitive data in WASM memory diff --git a/specs/interface/shielded-transfers.md b/specs/interface/shielded-transfers.md index f3d03a073e..95c80e93d2 100644 --- a/specs/interface/shielded-transfers.md +++ b/specs/interface/shielded-transfers.md @@ -2,12 +2,12 @@ **NOTE**: The following documentation is outdated, but included below while updated functionality which incorporates the Namada SDK is being integrated: -Shielded transfers are based on [MASP](https://github.com/anoma/masp) and allows users of Anoma to performs transactions where only the recipient, sender and a holder of a viewing key can see the transactions details. It is based on the specifications defined at [Shielded execution](../../ledger/shielded-execution/masp.md). +Shielded transfers are based on [MASP](https://github.com/anoma/masp) and allows users of Namada to performs transactions where only the recipient, sender and a holder of a viewing key can see the transactions details. It is based on the specifications defined at [Shielded execution](../../ledger/shielded-execution/masp.md). - [Shielded Transfers In Web Client](#shielded-transfers-in-web-client) - [Codebase](#codebase) - [High level data flow in the client](#high-level-data-flow-in-the-client) - - [Relation to MASP/Anoma CLI](#relation-to-maspanoma-cli) + - [Relation to MASP/Namada CLI](#relation-to-maspnamada-cli) - [The API](#the-api) - [`getMaspWeb`](#getmaspweb) - [`MaspWeb`](#maspweb) @@ -26,7 +26,7 @@ Shielded transfers are based on [MASP](https://github.com/anoma/masp) and allows The code for interacting with the shielded transfers is split in 2 places: -- `anoma-wallet` (TypeScript) +- `namada-wallet` (TypeScript) - capturing the user interactions - providing user feedback - fetching the existing MASP transactions from the ledger @@ -38,7 +38,7 @@ The code for interacting with the shielded transfers is split in 2 places: ``` packages │ ├── masp-web # MASP specific Rust code -│ ├── anoma-wallet # anoma web wallet +│ ├── namada-wallet # namada web wallet ``` ## High level data flow in the client @@ -47,10 +47,10 @@ In the current implementation whenever a user start to perform a new action rela This process can be further optimized: -- Anoma CLI already does caching of fetched transfers, so that logic can be ru-used by providing virtual filesystem (for example [memfs](https://github.com/streamich/memfs#readme)) implementation to Rust: +- Namada CLI already does caching of fetched transfers, so that logic can be ru-used by providing virtual filesystem (for example [memfs](https://github.com/streamich/memfs#readme)) implementation to Rust: - Likely the scanning can already start parallel while the fetching is running and if a sufficient amount of notes are found in scanning the fetching could be terminated. -## Relation to MASP/Anoma CLI +## Relation to MASP/Namada CLI The feature set and logic between the CLI and the web client should be the same. There are however a few differences in how they work, they are listed here: diff --git a/specs/interface/transparent-transactions.md b/specs/interface/transparent-transactions.md index 5f6ea82a72..fb81aeae54 100644 --- a/specs/interface/transparent-transactions.md +++ b/specs/interface/transparent-transactions.md @@ -77,7 +77,7 @@ let data = transfer ``` _In namada CLI:_ -https://github.com/namada/namada/blob/f6e78278608aaef253617885bb7ef95a50057268/apps/src/lib/client/tx.rs#L406-L411 +https://github.com/anoma/namada/blob/f6e78278608aaef253617885bb7ef95a50057268/apps/src/lib/client/tx.rs#L406-L411 #### Creating and signing the `proto::Tx` struct @@ -100,7 +100,7 @@ impl Tx { **NOTE** Here we provide a work around to an issue with `proto::Tx::new()` in wasm - instead of calling the method directly on `Tx`, we create a new implementation that returns a `proto::Tx`, with the timestamp being set using `js_sys` in order to make this wasm-compatible. _In namada CLI:_ -https://github.com/namada/namada/blob/f6e78278608aaef253617885bb7ef95a50057268/apps/src/lib/client/tx.rs#L417-L419 +https://github.com/anoma/namada/blob/f6e78278608aaef253617885bb7ef95a50057268/apps/src/lib/client/tx.rs#L417-L419 ### 1.2 - Creating the `namada::types::transaction::WrapperTx` struct @@ -133,7 +133,7 @@ transaction::WrapperTx::new( **NOTE** Here we can directly invoke `WrapperTx::new`, so we only need to concern ourselves with convering the JavaScript-provided values into the appropriate types. _In namada CLI:_ -https://github.com/namada/namada/blob/f6e78278608aaef253617885bb7ef95a50057268/apps/src/lib/client/tx.rs#L687-L696 +https://github.com/anoma/namada/blob/f6e78278608aaef253617885bb7ef95a50057268/apps/src/lib/client/tx.rs#L687-L696 #### 1.3 - Create a new `Tx` with `WrapperTx` and sign it @@ -186,7 +186,7 @@ Ok(Transaction { ``` _In namada CLI:_ -https://github.com/namada/namada/blob/f6e78278608aaef253617885bb7ef95a50057268/apps/src/lib/client/tx.rs#L810-L814 +https://github.com/anoma/namada/blob/f6e78278608aaef253617885bb7ef95a50057268/apps/src/lib/client/tx.rs#L810-L814 ## Part 2 - Initialize Account Transaction diff --git a/specs/packages/overview.md b/specs/packages/overview.md index 6cd79550ef..3d5bca6f5f 100644 --- a/specs/packages/overview.md +++ b/specs/packages/overview.md @@ -39,7 +39,7 @@ Aside from `wasm-bindgen` bindings for Rust crypography libraries, this package ## integrations This package introduces an `Intergration` interface, which wraps the APIs of various extensions to expose a -single API to the interface. Currently, this supports integrations with Keplr, Metamask, and the Anoma browser extension. +single API to the interface. Currently, this supports integrations with Keplr, Metamask, and the Namada browser extension. ## rpc diff --git a/specs/packages/sdk.md b/specs/packages/sdk.md index 826cfa07e4..62661e3f98 100644 --- a/specs/packages/sdk.md +++ b/specs/packages/sdk.md @@ -34,7 +34,7 @@ Contains the logic for: ### Why we are not using key generation functions from the Namada Shared? -Currently, the Anoma extension derives keys based on a mnemonic, while Namada derives keys based on a source of randomness (`OsRng`). As such, we have introduced functions that allow us to add keys derived within the extension into Sdk's wallet storage. This will most likely change in future after Namada introduces support for mnemonics into the Sdk. +Currently, the Namada extension derives keys based on a mnemonic, while Namada derives keys based on a source of randomness (`OsRng`). As such, we have introduced functions that allow us to add keys derived within the extension into Sdk's wallet storage. This will most likely change in future after Namada introduces support for mnemonics into the Sdk. ## sdk @@ -42,5 +42,5 @@ Sdk struct wraps logic from the other modules, creating public API using `wasm_b ## About wallet storage -At the moment, the client of the Sdk is responsible for keeping storage in sync with the Sdk's wallet instance. What does that mean? The Anoma extension has its own key storage, which is modified by user actions. Every time the extension storage changes (for example, when a new address is derived), we must manually sync the extension and Sdk wallet storage +At the moment, the client of the Sdk is responsible for keeping storage in sync with the Sdk's wallet instance. What does that mean? The Namada extension has its own key storage, which is modified by user actions. Every time the extension storage changes (for example, when a new address is derived), we must manually sync the extension and Sdk wallet storage using functions provided by `wallet` module. This is something that will most likely change in the future. From 6d82708bfce0e81e0ea799df658821af435495b0 Mon Sep 17 00:00:00 2001 From: "Justin R. Evans" <330911+jurevans@users.noreply.github.com> Date: Thu, 20 Jul 2023 06:25:56 -0400 Subject: [PATCH 2/2] feat/253 Implement ledger service in Extension (#295) * Implement Ledger service with transfer functionality Re-enable test Fix failing test feat/335 - Approve Bond Tx, Sign bond with Ledger (#336) * Hook up bond approval and Ledger signing * Clean up, fix naming * Add query for public_key * Hooking up Reveal PK tx to extension * Put public_key into explicit schema type * Fix schema order * Refactor submit calls to include signing * Fix error on submit public key reveal, clean up logs * Begin hooking up staking update events * Fix issue with Reveal PK tx * Fix Cargo.lock * Addressing PR feedback --- apps/extension/package.json | 2 +- .../src/App/Accounts/AccountListing.tsx | 22 +- apps/extension/src/App/App.tsx | 8 +- .../Settings/ExtraSettings/ExtraSettings.tsx | 49 +- .../ResetPassword/ResetPassword.tsx | 42 +- .../src/App/Settings/ExtraSettings/types.ts | 4 +- apps/extension/src/App/Settings/Settings.tsx | 78 +- .../src/Approvals/Approvals.components.tsx | 44 +- apps/extension/src/Approvals/Approvals.tsx | 36 +- .../src/Approvals/ApproveBond/ApproveBond.tsx | 94 ++ .../src/Approvals/ApproveBond/ConfirmBond.tsx | 109 ++ .../ApproveBond/ConfirmLedgerBond.tsx | 196 +++ .../src/Approvals/ApproveBond/index.ts | 3 + .../ApproveConnection.components.tsx | 6 - .../ApproveTransfer.components.ts | 6 - .../ApproveTransfer/ApproveTransfer.tsx | 13 +- .../ApproveTransfer/ConfirmLedgerTransfer.tsx | 103 ++ .../ConfirmTransfer.components.ts | 43 - .../ApproveTransfer/ConfirmTransfer.tsx | 8 +- .../src/Approvals/ApproveTransfer/index.ts | 1 + apps/extension/src/Approvals/types.ts | 14 +- apps/extension/src/Setup/Ledger/Ledger.tsx | 110 +- .../src/Setup/Ledger/LedgerConfirmation.tsx | 89 ++ apps/extension/src/Setup/Setup.tsx | 13 +- apps/extension/src/Setup/types.ts | 1 + .../src/background/approvals/handler.ts | 79 +- .../src/background/approvals/init.ts | 14 +- .../src/background/approvals/messages.ts | 87 +- .../src/background/approvals/service.ts | 151 +- apps/extension/src/background/index.ts | 21 +- .../src/background/keyring/handler.ts | 42 +- apps/extension/src/background/keyring/init.ts | 6 +- .../src/background/keyring/keyring.ts | 152 +- .../src/background/keyring/messages.ts | 47 +- .../src/background/keyring/service.ts | 79 +- .../extension/src/background/keyring/types.ts | 25 +- .../src/background/ledger/constants.ts | 1 + .../src/background/ledger/handler.ts | 117 ++ apps/extension/src/background/ledger/index.ts | 3 + apps/extension/src/background/ledger/init.ts | 27 + .../extension/src/background/ledger/ledger.ts | 124 +- .../src/background/ledger/messages.ts | 293 ++++ .../src/background/ledger/service.ts | 331 ++++ .../web-workers/submit-transfer-web-worker.ts | 7 +- apps/extension/src/content/events.ts | 28 + apps/extension/src/provider/InjectedNamada.ts | 38 +- apps/extension/src/provider/Namada.test.ts | 12 +- apps/extension/src/provider/Namada.ts | 32 +- apps/extension/src/provider/Signer.ts | 29 +- apps/extension/src/provider/data.mock.ts | 16 +- apps/extension/src/provider/messages.ts | 54 +- apps/extension/src/test/init.ts | 30 +- apps/extension/src/utils/index.ts | 42 +- .../NewBondingPosition/NewBondingPosition.tsx | 7 +- .../extensionEvents/handlers/namada.ts | 6 + .../src/services/extensionEvents/provider.tsx | 11 +- .../slices/StakingAndGovernance/actions.ts | 38 +- apps/namada-interface/src/slices/accounts.ts | 5 +- apps/namada-interface/src/slices/transfers.ts | 26 +- apps/namada-interface/src/store/mocks.ts | 30 +- packages/integrations/src/Keplr.test.ts | 3 +- packages/integrations/src/Keplr.ts | 11 +- packages/integrations/src/Metamask.ts | 5 +- packages/ledger-namada/LICENSE | 201 +++ packages/ledger-namada/README.md | 12 + packages/ledger-namada/dist/common.d.ts | 90 ++ packages/ledger-namada/dist/common.js | 158 ++ packages/ledger-namada/dist/common.js.map | 1 + packages/ledger-namada/dist/config.d.ts | 30 + packages/ledger-namada/dist/config.js | 34 + packages/ledger-namada/dist/config.js.map | 1 + packages/ledger-namada/dist/index.d.ts | 16 + packages/ledger-namada/dist/index.js | 33 + packages/ledger-namada/dist/index.js.map | 1 + packages/ledger-namada/dist/namadaApp.d.ts | 34 + packages/ledger-namada/dist/namadaApp.js | 194 +++ packages/ledger-namada/dist/namadaApp.js.map | 1 + .../ledger-namada/dist/processResponses.d.ts | 24 + .../ledger-namada/dist/processResponses.js | 133 ++ .../dist/processResponses.js.map | 1 + packages/ledger-namada/dist/types.d.ts | 68 + packages/ledger-namada/dist/types.js | 25 + packages/ledger-namada/dist/types.js.map | 1 + packages/ledger-namada/package.json | 78 + packages/shared/lib/src/query.rs | 24 +- packages/shared/lib/src/sdk/mod.rs | 165 +- packages/shared/lib/src/sdk/tx.rs | 29 + packages/shared/src/index.ts | 24 +- packages/types/src/account.ts | 9 +- packages/types/src/events.ts | 1 + packages/types/src/namada.ts | 13 +- packages/types/src/signer.ts | 10 +- packages/types/src/tx/schema/index.ts | 5 +- packages/types/src/tx/schema/revealPK.ts | 17 + packages/types/src/tx/types.ts | 5 + packages/utils/src/helpers/index.ts | 51 +- yarn.lock | 1354 ++++++++++++++++- 97 files changed, 5285 insertions(+), 681 deletions(-) create mode 100644 apps/extension/src/Approvals/ApproveBond/ApproveBond.tsx create mode 100644 apps/extension/src/Approvals/ApproveBond/ConfirmBond.tsx create mode 100644 apps/extension/src/Approvals/ApproveBond/ConfirmLedgerBond.tsx create mode 100644 apps/extension/src/Approvals/ApproveBond/index.ts delete mode 100644 apps/extension/src/Approvals/ApproveConnection/ApproveConnection.components.tsx delete mode 100644 apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.components.ts create mode 100644 apps/extension/src/Approvals/ApproveTransfer/ConfirmLedgerTransfer.tsx delete mode 100644 apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.components.ts create mode 100644 apps/extension/src/Setup/Ledger/LedgerConfirmation.tsx create mode 100644 apps/extension/src/background/ledger/constants.ts create mode 100644 apps/extension/src/background/ledger/handler.ts create mode 100644 apps/extension/src/background/ledger/init.ts create mode 100644 apps/extension/src/background/ledger/messages.ts create mode 100644 apps/extension/src/background/ledger/service.ts create mode 100644 packages/ledger-namada/LICENSE create mode 100644 packages/ledger-namada/README.md create mode 100644 packages/ledger-namada/dist/common.d.ts create mode 100644 packages/ledger-namada/dist/common.js create mode 100644 packages/ledger-namada/dist/common.js.map create mode 100644 packages/ledger-namada/dist/config.d.ts create mode 100644 packages/ledger-namada/dist/config.js create mode 100644 packages/ledger-namada/dist/config.js.map create mode 100644 packages/ledger-namada/dist/index.d.ts create mode 100644 packages/ledger-namada/dist/index.js create mode 100644 packages/ledger-namada/dist/index.js.map create mode 100644 packages/ledger-namada/dist/namadaApp.d.ts create mode 100644 packages/ledger-namada/dist/namadaApp.js create mode 100644 packages/ledger-namada/dist/namadaApp.js.map create mode 100644 packages/ledger-namada/dist/processResponses.d.ts create mode 100644 packages/ledger-namada/dist/processResponses.js create mode 100644 packages/ledger-namada/dist/processResponses.js.map create mode 100644 packages/ledger-namada/dist/types.d.ts create mode 100644 packages/ledger-namada/dist/types.js create mode 100644 packages/ledger-namada/dist/types.js.map create mode 100644 packages/ledger-namada/package.json create mode 100644 packages/types/src/tx/schema/revealPK.ts diff --git a/apps/extension/package.json b/apps/extension/package.json index a9b975be3e..fad22ce1d2 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -33,11 +33,11 @@ "@namada/storage": "0.1.0", "@namada/types": "0.1.0", "@namada/utils": "0.1.0", + "@namada/ledger-namada": "0.0.1", "@cosmjs/encoding": "^0.29.0", "@ledgerhq/hw-transport": "^6.28.3", "@ledgerhq/hw-transport-webhid": "^6.27.14", "@ledgerhq/hw-transport-webusb": "^6.27.14", - "@zondax/ledger-namada": "^0.0.2", "bignumber.js": "^9.1.1", "@dao-xyz/borsh": "^5.1.5", "buffer": "^6.0.3", diff --git a/apps/extension/src/App/Accounts/AccountListing.tsx b/apps/extension/src/App/Accounts/AccountListing.tsx index a061517e10..5704d0d475 100644 --- a/apps/extension/src/App/Accounts/AccountListing.tsx +++ b/apps/extension/src/App/Accounts/AccountListing.tsx @@ -29,6 +29,24 @@ const textToClipboard = (content: string): void => { navigator.clipboard.writeText(content); }; +const isChild = (type: AccountType, path: Bip44Path): boolean => { + // All PrivateKey accounts are child accounts + if (type === AccountType.PrivateKey) { + return true; + } + + if (type === AccountType.Ledger) { + // If this is a Ledger account, a child account is any account + // with a path that isn't the default path (/0'/0/0). This is for display + // purposes only. If the sum of the path components is greater than + // zero, it is a child. + const { account, change, index = 0 } = path; + return account + change + index > 0; + } + + return false; +}; + const formatDerivationPath = ( isChildAccount: boolean, { account, change, index = 0 }: Bip44Path, @@ -36,14 +54,14 @@ const formatDerivationPath = ( ): string => isChildAccount ? `/${account}'/${ - type === AccountType.PrivateKey ? `${change}/` : "" + type !== AccountType.Mnemonic ? `${change}/` : "" }${index}` : ""; const AccountListing = ({ account, parentAlias }: Props): JSX.Element => { const { address, alias, path, type } = account; const navigate = useNavigate(); - const isChildAccount = type !== AccountType.Mnemonic; + const isChildAccount = isChild(type, path); return ( diff --git a/apps/extension/src/App/App.tsx b/apps/extension/src/App/App.tsx index e669253b88..eaed3f07ae 100644 --- a/apps/extension/src/App/App.tsx +++ b/apps/extension/src/App/App.tsx @@ -78,11 +78,13 @@ export const App: React.FC = () => { setStatus(Status.Pending); try { - const parentId = await requester.sendMessage( + const parent = await requester.sendMessage( Ports.Background, new GetActiveAccountMsg() ); - const parentAccount = accounts.find((account) => account.id === parentId); + const parentAccount = accounts.find( + (account) => account.id === parent?.id + ); setParentAccount(parentAccount); } catch (e) { console.error(e); @@ -115,7 +117,7 @@ export const App: React.FC = () => { }, onFail: () => { setError("An error occurred connecting to extension"); - setStatus(Status.Failed); + setStatus(Status.Completed); }, }, { tries: 10, ms: 100 }, diff --git a/apps/extension/src/App/Settings/ExtraSettings/ExtraSettings.tsx b/apps/extension/src/App/Settings/ExtraSettings/ExtraSettings.tsx index 04ded376b0..765a4ce129 100644 --- a/apps/extension/src/App/Settings/ExtraSettings/ExtraSettings.tsx +++ b/apps/extension/src/App/Settings/ExtraSettings/ExtraSettings.tsx @@ -4,10 +4,7 @@ import { ExtensionRequester } from "extension"; import { Mode, ExtraSetting } from "./types"; import { ResetPassword } from "./ResetPassword"; import { DeleteAccount } from "./DeleteAccount"; -import { - ExtraSettingsContainer, - CloseLink -} from "./ExtraSettings.components"; +import { ExtraSettingsContainer, CloseLink } from "./ExtraSettings.components"; /** * Container for additional settings forms such as the reset password form. @@ -17,37 +14,27 @@ const ExtraSettings: React.FC<{ requester: ExtensionRequester; onClose: () => void; onDeleteAccount: (id: string) => void; -}> = ({ - extraSetting, - requester, - onClose, - onDeleteAccount, -}) => { +}> = ({ extraSetting, requester, onClose, onDeleteAccount }) => { return ( - {extraSetting && - - Close - } - - { - extraSetting === null ? "" : - - extraSetting.mode === Mode.ResetPassword ? - : - - extraSetting.mode === Mode.DeleteAccount ? - : + {extraSetting && Close} + {extraSetting === null ? ( + "" + ) : extraSetting.mode === Mode.ResetPassword ? ( + + ) : extraSetting.mode === Mode.DeleteAccount ? ( + + ) : ( assertNever(extraSetting.mode) - } + )} ); }; diff --git a/apps/extension/src/App/Settings/ExtraSettings/ResetPassword/ResetPassword.tsx b/apps/extension/src/App/Settings/ExtraSettings/ResetPassword/ResetPassword.tsx index 1134aabc46..192fae1036 100644 --- a/apps/extension/src/App/Settings/ExtraSettings/ResetPassword/ResetPassword.tsx +++ b/apps/extension/src/App/Settings/ExtraSettings/ResetPassword/ResetPassword.tsx @@ -23,12 +23,12 @@ enum Status { Unsubmitted, Pending, Complete, - Failed -}; + Failed, +} export type Props = { - accountId: string, - requester: ExtensionRequester + accountId: string; + requester: ExtensionRequester; }; const ResetPassword: React.FC = ({ accountId, requester }) => { @@ -42,8 +42,8 @@ const ResetPassword: React.FC = ({ accountId, requester }) => { const match = newPassword === confirmNewPassword; const { feedback } = zxcvbn(newPassword); - const hasFeedback = feedback.warning !== "" || - feedback.suggestions.length > 0; + const hasFeedback = + feedback.warning !== "" || feedback.suggestions.length > 0; const shouldDisableSubmit = status === Status.Pending || @@ -52,7 +52,7 @@ const ResetPassword: React.FC = ({ accountId, requester }) => { !match || (process.env.NODE_ENV !== "development" && hasFeedback); - const handleSubmit = async () => { + const handleSubmit = async (): Promise => { setStatus(Status.Pending); const result = await requester.sendMessage( @@ -87,7 +87,7 @@ const ResetPassword: React.FC = ({ accountId, requester }) => { setCurrentPassword(e.target.value)} + onChange={(e) => setCurrentPassword(e.target.value)} /> @@ -96,16 +96,16 @@ const ResetPassword: React.FC = ({ accountId, requester }) => { setNewPassword(e.target.value)} + onChange={(e) => setNewPassword(e.target.value)} /> {feedback.warning} - {feedback.suggestions.map((suggestion, i) => + {feedback.suggestions.map((suggestion, i) => ( {suggestion} - )} + ))} @@ -113,35 +113,27 @@ const ResetPassword: React.FC = ({ accountId, requester }) => { setConfirmNewPassword(e.target.value)} + onChange={(e) => setConfirmNewPassword(e.target.value)} /> - {!match && ( - Passwords do not match - )} + {!match && Passwords do not match} - {errorMessage && ( - {errorMessage} - )} + {errorMessage && {errorMessage}} )} - {status === Status.Complete && ( -

Complete!

- )} + {status === Status.Complete &&

Complete!

} ); -} +}; export default ResetPassword; diff --git a/apps/extension/src/App/Settings/ExtraSettings/types.ts b/apps/extension/src/App/Settings/ExtraSettings/types.ts index a41b62d343..f7254a1263 100644 --- a/apps/extension/src/App/Settings/ExtraSettings/types.ts +++ b/apps/extension/src/App/Settings/ExtraSettings/types.ts @@ -2,9 +2,9 @@ export enum Mode { ResetPassword = "Reset password", DeleteAccount = "Delete account", -}; +} export type ExtraSetting = { mode: Mode; accountId: string; -} +}; diff --git a/apps/extension/src/App/Settings/Settings.tsx b/apps/extension/src/App/Settings/Settings.tsx index 3e8d9bb438..00d2bed12a 100644 --- a/apps/extension/src/App/Settings/Settings.tsx +++ b/apps/extension/src/App/Settings/Settings.tsx @@ -12,6 +12,7 @@ import { LockKeyRingMsg, SetActiveAccountMsg, QueryParentAccountsMsg, + ParentAccount, } from "background/keyring"; import { SettingsContainer, @@ -29,10 +30,6 @@ import { } from "../Accounts/Accounts.components"; import { TopLevelRoute } from "../types"; import { Status } from "../App"; -import { - ResetPassword, - Props as ResetPasswordProps -} from "./ExtraSettings/ResetPassword" import { ExtraSettings } from "./ExtraSettings"; import { Mode, ExtraSetting } from "./ExtraSettings/types"; @@ -43,11 +40,7 @@ const Settings: React.FC<{ activeAccountId: string; requester: ExtensionRequester; onSelectAccount: (account: DerivedAccount) => void; -}> = ({ - activeAccountId, - requester, - onSelectAccount, -}) => { +}> = ({ activeAccountId, requester, onSelectAccount }) => { const [extraSetting, setExtraSetting] = useState(null); const [status, setStatus] = useState(Status.Pending); const [error, setError] = useState(""); @@ -75,19 +68,21 @@ const Settings: React.FC<{ fetchParentAccounts(); }, []); - const handleSelectAccount = async (account: DerivedAccount): Promise => { - const { id } = account; + const handleSelectAccount = async ( + account: DerivedAccount + ): Promise => { + const { id, type } = account; try { await requester.sendMessage( Ports.Background, - new SetActiveAccountMsg(id) + new SetActiveAccountMsg(id, type as ParentAccount) ); // Lock current wallet keyring: await requester.sendMessage(Ports.Background, new LockKeyRingMsg()); // Fetch accounts for selected parent account - await onSelectAccount(account); + onSelectAccount(account); } catch (e) { console.error(e); setError(`An error occurred while setting active account: ${e}`); @@ -95,7 +90,9 @@ const Settings: React.FC<{ } }; - const handleDeleteAccount = async (deletedAccountId: string): Promise => { + const handleDeleteAccount = async ( + deletedAccountId: string + ): Promise => { await fetchParentAccounts(); }; @@ -122,25 +119,26 @@ const Settings: React.FC<{ - {status === Status.Failed && (

Error communicating with extension background!

)}

{error ? error : "Select account:"}

- {parentAccounts.map((account, i) => + {parentAccounts.map((account, i) => ( handleSelectAccount(account)} - onSelectMode={(mode) => setExtraSetting({ - mode, - accountId: account.id - })} + onSelectMode={(mode) => + setExtraSetting({ + mode, + accountId: account.id, + }) + } /> - )} + ))} @@ -168,7 +166,6 @@ const Settings: React.FC<{ onClose={() => setExtraSetting(null)} onDeleteAccount={handleDeleteAccount} /> -
@@ -183,37 +180,28 @@ const AccountListItem: React.FC<{ activeAccountId: string; onSelectAccount: () => void; onSelectMode: (mode: Mode) => void; -}> = ({ - account, - activeAccountId, - onSelectAccount, - onSelectMode, -}) => { +}> = ({ account, activeAccountId, onSelectAccount, onSelectMode }) => { const [expanded, setExpanded] = useState(false); return ( <> - + {account.alias} {activeAccountId === account.id && (selected)} - setExpanded(!expanded)} - /> + setExpanded(!expanded)} /> - {expanded && + {expanded && ( { setExpanded(false); onSelectMode(mode); }} /> - } + )} ); }; @@ -223,24 +211,16 @@ const AccountListItem: React.FC<{ */ const ModeSelect: React.FC<{ onSelectMode: (mode: Mode) => void; -}> = ({ - onSelectMode, -}) => { - const modes = [ - Mode.ResetPassword, - Mode.DeleteAccount, - ]; +}> = ({ onSelectMode }) => { + const modes = [Mode.ResetPassword, Mode.DeleteAccount]; return ( - {modes.map((mode, i) => - onSelectMode(mode)} - > + {modes.map((mode, i) => ( + onSelectMode(mode)}> {mode} - )} + ))} ); }; diff --git a/apps/extension/src/Approvals/Approvals.components.tsx b/apps/extension/src/Approvals/Approvals.components.tsx index 84940937ab..89c38be9a6 100644 --- a/apps/extension/src/Approvals/Approvals.components.tsx +++ b/apps/extension/src/Approvals/Approvals.components.tsx @@ -1,4 +1,4 @@ -import styled, { createGlobalStyle } from "styled-components"; +import styled, { createGlobalStyle, css } from "styled-components"; export const GlobalStyles = createGlobalStyle` html, body { @@ -93,3 +93,45 @@ export const ButtonContainer = styled.div` display: flex; flex-direction: row; `; + +export const Spinner = css` + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-top-color: ${(props) => props.theme.colors.primary.main}; + border-radius: 50%; + animation: button-loading-spinner 1s ease infinite; + + @keyframes button-loading-spinner { + from { + transform: rotate(0turn); + } + + to { + transform: rotate(1turn); + } + } + } +`; + +export const InfoHeader = styled.div` + display: flex; + align-items: center; + gap: 10px; +`; + +export const InfoLoader = styled.div` + position: relative; + width: 20px; + height: 20px; + + &::after { + width: 16px; + height: 16px; + border: 2px solid transparent; + ${Spinner} + } +`; diff --git a/apps/extension/src/Approvals/Approvals.tsx b/apps/extension/src/Approvals/Approvals.tsx index d689ad1f31..c39210bded 100644 --- a/apps/extension/src/Approvals/Approvals.tsx +++ b/apps/extension/src/Approvals/Approvals.tsx @@ -14,6 +14,8 @@ import { import { ApproveTransfer, ConfirmTransfer } from "./ApproveTransfer"; import { ApproveConnection } from "./ApproveConnection"; import { TopLevelRoute } from "Approvals/types"; +import { ConfirmLedgerTransfer } from "./ApproveTransfer/ConfirmLedgerTransfer"; +import { ApproveBond, ConfirmBond, ConfirmLedgerBond } from "./ApproveBond"; export enum Status { Completed, @@ -25,6 +27,7 @@ export const Approvals: React.FC = () => { const theme = getTheme("dark"); const [msgId, setMsgId] = useState(""); const [address, setAddress] = useState(""); + const [publicKey, setPublicKey] = useState(""); return ( @@ -36,15 +39,44 @@ export const Approvals: React.FC = () => {
} /> } /> + } + /> + + } + /> + } + /> + + } + /> + } diff --git a/apps/extension/src/Approvals/ApproveBond/ApproveBond.tsx b/apps/extension/src/Approvals/ApproveBond/ApproveBond.tsx new file mode 100644 index 0000000000..d7dd0c9e8c --- /dev/null +++ b/apps/extension/src/Approvals/ApproveBond/ApproveBond.tsx @@ -0,0 +1,94 @@ +import { useNavigate } from "react-router-dom"; +import { useCallback, useEffect } from "react"; + +import { Button, ButtonVariant } from "@namada/components"; +import { shortenAddress } from "@namada/utils"; +import { AccountType, Tokens } from "@namada/types"; + +import { useQuery } from "hooks"; +import { Address } from "App/Accounts/AccountListing.components"; +import { + ApprovalContainer, + ButtonContainer, +} from "Approvals/Approvals.components"; +import { TopLevelRoute } from "Approvals/types"; +import { Ports } from "router"; +import { RejectTxMsg } from "background/approvals"; +import { useRequester } from "hooks/useRequester"; +import { closeCurrentTab } from "utils"; + +type Props = { + setAddress: (address: string) => void; + setMsgId: (msgId: string) => void; + setPublicKey: (publicKey: string) => void; +}; + +export const ApproveBond: React.FC = ({ + setAddress, + setMsgId, + setPublicKey, +}) => { + const navigate = useNavigate(); + const requester = useRequester(); + + const query = useQuery(); + const type = query.get("type") || ""; + const id = query.get("id") || ""; + const amount = query.get("amount") || ""; + const source = query.get("source") || ""; + const tokenAddress = query.get("token") || ""; + const tokenType = + Object.values(Tokens).find((token) => token.address === tokenAddress) + ?.symbol || ""; + const publicKey = query.get("publicKey") || ""; + + useEffect(() => { + if (source) { + setAddress(source); + } + if (publicKey) { + setPublicKey(publicKey); + } + }, [source, publicKey]); + + const handleApproveClick = (): void => { + setMsgId(id); + if (type === AccountType.Ledger) { + return navigate(`${TopLevelRoute.ConfirmLedgerBond}`); + } + navigate(TopLevelRoute.ConfirmBond); + }; + + const handleReject = useCallback(async (): Promise => { + try { + // TODO: use executeUntil here! + await requester.sendMessage(Ports.Background, new RejectTxMsg(id)); + + // Close tab + await closeCurrentTab(); + } catch (e) { + console.warn(e); + } + return; + }, [id]); + + return ( + +

Approve this Bond?

+

Source: 

+
{shortenAddress(source)}
+

+ Amount: {amount} {tokenType} +

+ + + + + +
+ ); +}; diff --git a/apps/extension/src/Approvals/ApproveBond/ConfirmBond.tsx b/apps/extension/src/Approvals/ApproveBond/ConfirmBond.tsx new file mode 100644 index 0000000000..88b44713e3 --- /dev/null +++ b/apps/extension/src/Approvals/ApproveBond/ConfirmBond.tsx @@ -0,0 +1,109 @@ +import { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; + +import { + Button, + ButtonVariant, + Input, + InputVariants, +} from "@namada/components"; +import { shortenAddress } from "@namada/utils"; + +import { Status } from "Approvals/Approvals"; +import { + ApprovalContainer, + ButtonContainer, + InfoHeader, + InfoLoader, +} from "Approvals/Approvals.components"; +import { Ports } from "router"; +import { useRequester } from "hooks/useRequester"; +import { SubmitApprovedBondMsg } from "background/approvals"; +import { Address } from "App/Accounts/AccountListing.components"; +import { closeCurrentTab } from "utils"; + +type Props = { + msgId: string; + address: string; +}; + +export const ConfirmBond: React.FC = ({ msgId, address }) => { + const navigate = useNavigate(); + const requester = useRequester(); + const [password, setPassword] = useState(""); + const [error, setError] = useState(); + const [status, setStatus] = useState(); + const [statusInfo, setStatusInfo] = useState(""); + + const handleApproveBond = async (): Promise => { + setStatus(Status.Pending); + try { + // TODO: use executeUntil here! + setStatusInfo("Decrypting keys and submitting transfer..."); + await requester.sendMessage( + Ports.Background, + new SubmitApprovedBondMsg(msgId, address, password) + ); + setStatus(Status.Completed); + } catch (e) { + setError("Unable to authenticate Tx!"); + setStatus(Status.Failed); + } + setStatusInfo(""); + setStatus(Status.Completed); + return; + }; + + useEffect(() => { + (async () => { + if (status === Status.Completed) { + await closeCurrentTab(); + } + })(); + }, [status]); + + return ( + + {status === Status.Pending && ( + + +

{statusInfo}

+
+ )} + {status === Status.Failed && ( +

+ {error} +
+ Try again +

+ )} + {status !== (Status.Pending || Status.Completed) && ( + <> +
+ Decrypt keys for
{shortenAddress(address)}
+
+ setPassword(e.target.value)} + /> + + + + + + )} +
+ ); +}; diff --git a/apps/extension/src/Approvals/ApproveBond/ConfirmLedgerBond.tsx b/apps/extension/src/Approvals/ApproveBond/ConfirmLedgerBond.tsx new file mode 100644 index 0000000000..d1581f7147 --- /dev/null +++ b/apps/extension/src/Approvals/ApproveBond/ConfirmLedgerBond.tsx @@ -0,0 +1,196 @@ +import { useCallback, useState } from "react"; +import { toBase64 } from "@cosmjs/encoding"; +import BigNumber from "bignumber.js"; + +import { LedgerError } from "@namada/ledger-namada"; +import { Button, ButtonVariant } from "@namada/components"; +import { defaultChainId as chainId } from "@namada/chains"; + +import { Ledger } from "background/ledger"; +import { + GetBondBytesMsg, + GetRevealPKBytesMsg, + SubmitSignedBondMsg, + SubmitSignedRevealPKMsg, +} from "background/ledger/messages"; +import { Ports } from "router"; +import { closeCurrentTab } from "utils"; +import { useRequester } from "hooks/useRequester"; +import { Status } from "Approvals/Approvals"; +import { + ApprovalContainer, + ButtonContainer, +} from "Approvals/Approvals.components"; +import { InfoHeader, InfoLoader } from "Approvals/Approvals.components"; +import { + Message, + RevealPKProps, + SubmitRevealPKMsgValue, + Tokens, +} from "@namada/types"; +import { QueryPublicKeyMsg } from "background/keyring"; + +type Props = { + address: string; + msgId: string; + publicKey: string; +}; + +export const ConfirmLedgerBond: React.FC = ({ + address, + msgId, + publicKey, +}) => { + const requester = useRequester(); + const [error, setError] = useState(); + const [status, setStatus] = useState(); + const [statusInfo, setStatusInfo] = useState(""); + + const revealPk = async (publicKey: string): Promise => { + const revealPKArgs: RevealPKProps = { + tx: { + token: Tokens.NAM.address || "", + feeAmount: new BigNumber(0), + gasLimit: new BigNumber(0), + chainId, + publicKey, + }, + publicKey, + }; + + const msgValue = new SubmitRevealPKMsgValue(revealPKArgs); + const msg = new Message(); + const encoded = msg.encode(msgValue); + + // Open Ledger transport + const ledger = await Ledger.init(); + + try { + const { bytes, path } = await requester.sendMessage( + Ports.Background, + new GetRevealPKBytesMsg(toBase64(encoded)) + ); + + // Sign with Ledgeg + const signatures = await ledger.sign(bytes, path); + + // Submit signatures for tx + setStatusInfo("Submitting reveal pk tx..."); + await requester.sendMessage( + Ports.Background, + new SubmitSignedRevealPKMsg( + toBase64(encoded), + toBase64(bytes), + signatures + ) + ); + } catch (e) { + console.warn("An error occured: ", e); + throw new Error(`${e}`); + } finally { + await ledger.closeTransport(); + } + }; + + const queryPublicKey = async ( + address: string + ): Promise => { + return await requester.sendMessage( + Ports.Background, + new QueryPublicKeyMsg(address) + ); + }; + + const submitBond = async (): Promise => { + setStatus(Status.Pending); + setStatusInfo("Querying for public key on chain..."); + + const pk = await queryPublicKey(address); + + if (!pk) { + setStatusInfo( + "Public key not found! Review and approve reveal pk on your Ledger" + ); + await revealPk(publicKey); + } + + // Open ledger transport + const ledger = await Ledger.init(); + + try { + // Constuct tx bytes from SDK + const { bytes, path } = await requester.sendMessage( + Ports.Background, + new GetBondBytesMsg(msgId) + ); + + setStatusInfo("Review and approve bond transaction on your Ledger"); + // Sign with Ledger + const signatures = await ledger.sign(bytes, path); + const { errorMessage, returnCode } = signatures; + + if (returnCode !== LedgerError.NoErrors) { + console.warn("Bond sign errors encountered, exiting: ", { + returnCode, + errorMessage, + }); + setError(errorMessage); + return setStatus(Status.Failed); + } + + // Submit signatures for tx + setStatusInfo("Submitting bond transaction..."); + await requester.sendMessage( + Ports.Background, + new SubmitSignedBondMsg(msgId, toBase64(bytes), signatures) + ); + setStatus(Status.Completed); + } catch (e) { + console.warn(e); + setStatus(Status.Failed); + await ledger.closeTransport(); + } + }; + + const handleCloseTab = useCallback(async (): Promise => { + await closeCurrentTab(); + }, []); + + return ( + + {status === Status.Failed && ( +

+ {error} +
+ Try again +

+ )} + {status === Status.Pending && ( + + + {statusInfo} + + )} + {status !== Status.Pending && status !== Status.Completed && ( + <> +

Make sure your Ledger is unlocked, and click "Submit"

+ + + + + )} + {status === Status.Completed && ( + <> +

Success! You may close this window.

+ + + + + )} +
+ ); +}; diff --git a/apps/extension/src/Approvals/ApproveBond/index.ts b/apps/extension/src/Approvals/ApproveBond/index.ts new file mode 100644 index 0000000000..e25c4c1552 --- /dev/null +++ b/apps/extension/src/Approvals/ApproveBond/index.ts @@ -0,0 +1,3 @@ +export * from "./ApproveBond"; +export * from "./ConfirmBond"; +export * from "./ConfirmLedgerBond"; diff --git a/apps/extension/src/Approvals/ApproveConnection/ApproveConnection.components.tsx b/apps/extension/src/Approvals/ApproveConnection/ApproveConnection.components.tsx deleted file mode 100644 index 08cf720e5d..0000000000 --- a/apps/extension/src/Approvals/ApproveConnection/ApproveConnection.components.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import styled from "styled-components"; - -export const ApproveConnectionContainer = styled.div` - display: flex; - flex-direction: column; -`; diff --git a/apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.components.ts b/apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.components.ts deleted file mode 100644 index 4b17bbbe0e..0000000000 --- a/apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.components.ts +++ /dev/null @@ -1,6 +0,0 @@ -import styled from "styled-components"; - -export const ApproveTxContainer = styled.div` - display: flex; - flex-direction: column; -`; diff --git a/apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.tsx b/apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.tsx index 5d738591af..792fe5492a 100644 --- a/apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.tsx +++ b/apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.tsx @@ -3,7 +3,7 @@ import { useEffect } from "react"; import { Button, ButtonVariant } from "@namada/components"; import { shortenAddress } from "@namada/utils"; -import { Tokens } from "@namada/types"; +import { AccountType, Tokens } from "@namada/types"; import { useQuery } from "hooks"; import { Address } from "App/Accounts/AccountListing.components"; @@ -13,7 +13,7 @@ import { } from "Approvals/Approvals.components"; import { TopLevelRoute } from "Approvals/types"; import { Ports } from "router"; -import { RejectTransferMsg } from "background/approvals"; +import { RejectTxMsg } from "background/approvals"; import { useRequester } from "hooks/useRequester"; import { closeCurrentTab } from "utils"; @@ -28,6 +28,7 @@ export const ApproveTransfer: React.FC = ({ setAddress, setMsgId }) => { const query = useQuery(); // TODO: Get current parent account alias to display to user + const type = query.get("type") || ""; const id = query.get("id") || ""; const amount = query.get("amount") || ""; const source = query.get("source") || ""; @@ -45,13 +46,16 @@ export const ApproveTransfer: React.FC = ({ setAddress, setMsgId }) => { const handleApproveClick = (): void => { setMsgId(id); - navigate(TopLevelRoute.ConfirmTx); + if (type === AccountType.Ledger) { + return navigate(`${TopLevelRoute.ConfirmLedgerTransfer}`); + } + navigate(TopLevelRoute.ConfirmTransfer); }; const handleReject = async (): Promise => { try { // TODO: use executeUntil here! - await requester.sendMessage(Ports.Background, new RejectTransferMsg(id)); + await requester.sendMessage(Ports.Background, new RejectTxMsg(id)); // Close tab await closeCurrentTab(); @@ -64,7 +68,6 @@ export const ApproveTransfer: React.FC = ({ setAddress, setMsgId }) => { return (

Approve this Transaction?

-

ID: {id}

Target: 

{shortenAddress(target)}

Source: 

diff --git a/apps/extension/src/Approvals/ApproveTransfer/ConfirmLedgerTransfer.tsx b/apps/extension/src/Approvals/ApproveTransfer/ConfirmLedgerTransfer.tsx new file mode 100644 index 0000000000..9877b3f309 --- /dev/null +++ b/apps/extension/src/Approvals/ApproveTransfer/ConfirmLedgerTransfer.tsx @@ -0,0 +1,103 @@ +import { useCallback, useState } from "react"; +import { LedgerError } from "@namada/ledger-namada"; +import { toBase64 } from "@cosmjs/encoding"; + +import { Button, ButtonVariant } from "@namada/components"; + +import { Ledger } from "background/ledger"; +import { + GetTransferBytesMsg, + SubmitSignedTransferMsg, +} from "background/ledger/messages"; +import { Ports } from "router"; +import { closeCurrentTab } from "utils"; +import { useRequester } from "hooks/useRequester"; +import { Status } from "Approvals/Approvals"; +import { + ApprovalContainer, + ButtonContainer, +} from "Approvals/Approvals.components"; + +type Props = { + msgId: string; +}; + +export const ConfirmLedgerTransfer: React.FC = ({ msgId }) => { + const requester = useRequester(); + const [error, setError] = useState(); + const [status, setStatus] = useState(); + + const submitTransfer = async (): Promise => { + setStatus(Status.Pending); + const ledger = await Ledger.init(); + + try { + // Constuct tx bytes from SDK + const { bytes, path } = await requester.sendMessage( + Ports.Background, + new GetTransferBytesMsg(msgId) + ); + + // Sign with Ledger + const signatures = await ledger.sign(bytes, path); + const { errorMessage, returnCode } = signatures; + + // Close transport so that it may be re-opened on a subsequent attempt (due to error) + await ledger.closeTransport(); + + if (returnCode !== LedgerError.NoErrors) { + setError(errorMessage); + return setStatus(Status.Failed); + } + + // Submit signatures for tx + await requester.sendMessage( + Ports.Background, + new SubmitSignedTransferMsg(msgId, toBase64(bytes), signatures) + ); + setStatus(Status.Completed); + } catch (e) { + console.warn(e); + const ledgerErrors = await ledger.queryErrors(); + setError(ledgerErrors); + setStatus(Status.Failed); + } + }; + + const handleCloseTab = useCallback(async (): Promise => { + await closeCurrentTab(); + }, []); + + return ( + + {status === Status.Failed && ( +

+ {error} +
+ Try again +

+ )} + {status === Status.Pending &&

Submitting transfer...

} + {status !== Status.Pending && status !== Status.Completed && ( + <> +

Make sure your Ledger is unlocked, and click "Submit"

+ + + + + )} + {status === Status.Completed && ( + <> +

Success! You may close this window.

+ + + + + )} +
+ ); +}; diff --git a/apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.components.ts b/apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.components.ts deleted file mode 100644 index 9e5a44b80f..0000000000 --- a/apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.components.ts +++ /dev/null @@ -1,43 +0,0 @@ -import styled, { css } from "styled-components"; - -export const Spinner = css` - content: ""; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - border-top-color: ${(props) => props.theme.colors.primary.main}; - border-radius: 50%; - animation: button-loading-spinner 1s ease infinite; - - @keyframes button-loading-spinner { - from { - transform: rotate(0turn); - } - - to { - transform: rotate(1turn); - } - } - } -`; - -export const InfoHeader = styled.div` - display: flex; - align-items: center; - gap: 10px; -`; - -export const InfoLoader = styled.div` - position: relative; - width: 20px; - height: 20px; - - &::after { - width: 16px; - height: 16px; - border: 2px solid transparent; - ${Spinner} - } -`; diff --git a/apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.tsx b/apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.tsx index 7cc31f8365..ca9c92de1d 100644 --- a/apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.tsx +++ b/apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.tsx @@ -8,6 +8,8 @@ import { Status } from "Approvals/Approvals"; import { ApprovalContainer, ButtonContainer, + InfoHeader, + InfoLoader, } from "Approvals/Approvals.components"; import { Ports } from "router"; import { useRequester } from "hooks/useRequester"; @@ -15,7 +17,6 @@ import { SubmitApprovedTransferMsg } from "background/approvals"; import { Address } from "App/Accounts/AccountListing.components"; import { closeCurrentTab } from "utils"; import { FetchAndStoreMaspParamsMsg, HasMaspParamsMsg } from "provider"; -import { InfoHeader, InfoLoader } from "./ConfirmTransfer.components"; type Props = { msgId: string; @@ -30,7 +31,7 @@ export const ConfirmTransfer: React.FC = ({ msgId, address }) => { const [status, setStatus] = useState(); const [statusInfo, setStatusInfo] = useState(""); - const handleApprove = async (): Promise => { + const handleApproveTransfer = async (): Promise => { setStatus(Status.Pending); const hasMaspParams = await requester.sendMessage( Ports.Background, @@ -56,6 +57,7 @@ export const ConfirmTransfer: React.FC = ({ msgId, address }) => { Ports.Background, new SubmitApprovedTransferMsg(msgId, address, password) ); + setStatus(Status.Completed); } catch (e) { setError("Unable to authenticate Tx!"); setStatus(Status.Failed); @@ -100,7 +102,7 @@ export const ConfirmTransfer: React.FC = ({ msgId, address }) => { /> - - - - )} + + setAlias(e.target.value)} + variant={InputVariants.Text} + /> + + + + + ); }; diff --git a/apps/extension/src/Setup/Ledger/LedgerConfirmation.tsx b/apps/extension/src/Setup/Ledger/LedgerConfirmation.tsx new file mode 100644 index 0000000000..d631a28407 --- /dev/null +++ b/apps/extension/src/Setup/Ledger/LedgerConfirmation.tsx @@ -0,0 +1,89 @@ +import React, { useCallback, useContext, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { ThemeContext } from "styled-components"; + +import { + Button, + ButtonVariant, + Icon, + IconName, + IconSize, +} from "@namada/components"; +import { shortenAddress } from "@namada/utils"; +import { useSanitizedParams } from "@namada/hooks"; + +import { useRequester } from "hooks/useRequester"; +import { LedgerError } from "./Ledger.components"; +import { + TopSection, + TopSectionHeaderContainer, + TopSectionButtonContainer, + ButtonsContainer, + SubViewContainer, + UpperContentContainer, + Header1, + BodyText, +} from "Setup/Setup.components"; +import { Ports } from "router"; +import { AddLedgerAccountMsg } from "background/ledger/messages"; +import { closeCurrentTab } from "utils"; + +const LedgerConfirmation: React.FC = () => { + const navigate = useNavigate(); + const requester = useRequester(); + const themeContext = useContext(ThemeContext); + const { alias = "", address = "", publicKey = "" } = useSanitizedParams(); + const [error, setError] = useState(); + + const handleSubmitClick = useCallback(async (): Promise => { + try { + await requester.sendMessage( + Ports.Background, + new AddLedgerAccountMsg(alias, address, publicKey, { + account: 0, + change: 0, + index: 0, + }) + ); + closeCurrentTab(); + } catch (e) { + console.warn(e); + setError(`${e}`); + } + }, []); + + return ( + + + + navigate(-1)} style={{ cursor: "pointer" }}> + + + + + + + + Confirm Ledger Connection + + + {error && {error}} + + Connection successful for "{alias}"! + + Address: {address && shortenAddress(address)} + Add this address to your wallet? + + + + + ); +}; + +export default LedgerConfirmation; diff --git a/apps/extension/src/Setup/Setup.tsx b/apps/extension/src/Setup/Setup.tsx index 7b3554a088..23120a6117 100644 --- a/apps/extension/src/Setup/Setup.tsx +++ b/apps/extension/src/Setup/Setup.tsx @@ -28,6 +28,7 @@ import { ImportAccount } from "./ImportAccount"; import { useRequester } from "hooks/useRequester"; import { SeedPhraseImport } from "./ImportAccount/Steps"; import { Completion, Password } from "./Common"; +import LedgerConfirmation from "./Ledger/LedgerConfirmation"; type AnimatedTransitionProps = { elementKey: string; @@ -259,7 +260,17 @@ export const Setup: React.FC = () => { path={`/${TopLevelRoute.Ledger}`} element={ - + + + } + /> + + } /> diff --git a/apps/extension/src/Setup/types.ts b/apps/extension/src/Setup/types.ts index fc06a99d2e..ec902b93c1 100644 --- a/apps/extension/src/Setup/types.ts +++ b/apps/extension/src/Setup/types.ts @@ -3,6 +3,7 @@ export enum TopLevelRoute { AccountCreation = "account-creation", ImportAccount = "restore-account", Ledger = "ledger", + LedgerConfirmation = "ledger-confirmation", } export enum AccountCreationRoute { diff --git a/apps/extension/src/background/approvals/handler.ts b/apps/extension/src/background/approvals/handler.ts index b8fb368eac..653d92b815 100644 --- a/apps/extension/src/background/approvals/handler.ts +++ b/apps/extension/src/background/approvals/handler.ts @@ -1,46 +1,101 @@ import { Handler, Env, Message, InternalHandler } from "router"; import { ApprovalsService } from "./service"; -import { ApproveTransferMsg } from "provider"; -import { RejectTransferMsg, SubmitApprovedTransferMsg } from "./messages"; +import { ApproveBondMsg, ApproveUnbondMsg, ApproveTransferMsg } from "provider"; +import { + RejectTxMsg, + SubmitApprovedTransferMsg, + SubmitApprovedBondMsg, + SubmitApprovedUnbondMsg, +} from "./messages"; export const getHandler: (service: ApprovalsService) => Handler = (service) => { return (env: Env, msg: Message) => { switch (msg.constructor) { case ApproveTransferMsg: - return handleApproveTxMsg(service)(env, msg as ApproveTransferMsg); - case RejectTransferMsg: - return handleRejectTxMsg(service)(env, msg as RejectTransferMsg); + return handleApproveTransferMsg(service)( + env, + msg as ApproveTransferMsg + ); + case ApproveBondMsg: + return handleApproveBondMsg(service)(env, msg as ApproveBondMsg); + case ApproveUnbondMsg: + return handleApproveUnbondMsg(service)(env, msg as ApproveUnbondMsg); + case RejectTxMsg: + return handleRejectTxMsg(service)(env, msg as RejectTxMsg); case SubmitApprovedTransferMsg: - return handleSubmitApprovedTxMsg(service)( + return handleSubmitApprovedTransferMsg(service)( env, msg as SubmitApprovedTransferMsg ); + case SubmitApprovedBondMsg: + return handleSubmitApprovedBondMsg(service)( + env, + msg as SubmitApprovedBondMsg + ); + case SubmitApprovedUnbondMsg: + return handleSubmitApprovedUnbondMsg(service)( + env, + msg as SubmitApprovedUnbondMsg + ); + default: throw new Error("Unknown msg type"); } }; }; -const handleApproveTxMsg: ( +const handleApproveTransferMsg: ( service: ApprovalsService ) => InternalHandler = (service) => { - return async (_, { txMsg }) => { - return await service.approveTransfer(txMsg); + return async (_, { txMsg, accountType }) => { + return await service.approveTransfer(txMsg, accountType); }; }; const handleRejectTxMsg: ( service: ApprovalsService -) => InternalHandler = (service) => { +) => InternalHandler = (service) => { return async (_, { msgId }) => { - return await service.rejectTransfer(msgId); + return await service.rejectTx(msgId); }; }; -const handleSubmitApprovedTxMsg: ( +const handleSubmitApprovedTransferMsg: ( service: ApprovalsService ) => InternalHandler = (service) => { return async (_, { msgId, password }) => { return await service.submitTransfer(msgId, password); }; }; + +const handleApproveBondMsg: ( + service: ApprovalsService +) => InternalHandler = (service) => { + return async (_, { txMsg, accountType, publicKey }) => { + return await service.approveBond(txMsg, accountType, publicKey); + }; +}; + +const handleApproveUnbondMsg: ( + service: ApprovalsService +) => InternalHandler = (service) => { + return async (_, { txMsg, accountType }) => { + return await service.approveUnbond(txMsg, accountType); + }; +}; + +const handleSubmitApprovedBondMsg: ( + service: ApprovalsService +) => InternalHandler = (service) => { + return async (_, { msgId, password }) => { + return await service.submitBond(msgId, password); + }; +}; + +const handleSubmitApprovedUnbondMsg: ( + service: ApprovalsService +) => InternalHandler = (service) => { + return async (_, { msgId, password }) => { + return await service.submitUnbond(msgId, password); + }; +}; diff --git a/apps/extension/src/background/approvals/init.ts b/apps/extension/src/background/approvals/init.ts index e0d4a060fe..60bc02c6a5 100644 --- a/apps/extension/src/background/approvals/init.ts +++ b/apps/extension/src/background/approvals/init.ts @@ -1,14 +1,22 @@ import { Router } from "router"; -import { ApproveTransferMsg } from "provider"; -import { RejectTransferMsg, SubmitApprovedTransferMsg } from "./messages"; +import { ApproveBondMsg, ApproveTransferMsg } from "provider"; +import { + RejectTxMsg, + SubmitApprovedBondMsg, + SubmitApprovedUnbondMsg, + SubmitApprovedTransferMsg, +} from "./messages"; import { ROUTE } from "./constants"; import { ApprovalsService } from "./service"; import { getHandler } from "./handler"; export function init(router: Router, service: ApprovalsService): void { + router.registerMessage(ApproveBondMsg); router.registerMessage(ApproveTransferMsg); - router.registerMessage(RejectTransferMsg); + router.registerMessage(RejectTxMsg); + router.registerMessage(SubmitApprovedBondMsg); + router.registerMessage(SubmitApprovedUnbondMsg); router.registerMessage(SubmitApprovedTransferMsg); router.addHandler(ROUTE, getHandler(service)); diff --git a/apps/extension/src/background/approvals/messages.ts b/apps/extension/src/background/approvals/messages.ts index a1ee99967e..43549e9b40 100644 --- a/apps/extension/src/background/approvals/messages.ts +++ b/apps/extension/src/background/approvals/messages.ts @@ -2,13 +2,15 @@ import { Message } from "router"; import { ROUTE } from "./constants"; enum MessageType { - RejectTransfer = "reject-transfer", + RejectTx = "reject-tx", SubmitApprovedTransfer = "submit-approved-transfer", + SubmitApprovedBond = "submit-approved-bond", + SubmitApprovedUnbond = "submit-approved-unbond", } -export class RejectTransferMsg extends Message { +export class RejectTxMsg extends Message { public static type(): MessageType { - return MessageType.RejectTransfer; + return MessageType.RejectTx; } constructor(public readonly msgId: string) { @@ -27,7 +29,7 @@ export class RejectTransferMsg extends Message { } type(): string { - return RejectTransferMsg.type(); + return RejectTxMsg.type(); } } @@ -52,8 +54,11 @@ export class SubmitApprovedTransferMsg extends Message { throw new Error("address must not be empty!"); } if (!this.password) { - throw new Error("Password is required to submitTx!"); + throw new Error( + "Password is required to submitTx for this type of account!" + ); } + return; } @@ -65,3 +70,75 @@ export class SubmitApprovedTransferMsg extends Message { return SubmitApprovedTransferMsg.type(); } } + +export class SubmitApprovedBondMsg extends Message { + public static type(): MessageType { + return MessageType.SubmitApprovedBond; + } + + constructor( + public readonly msgId: string, + public readonly address: string, + public readonly password: string + ) { + super(); + } + + validate(): void { + if (!this.msgId) { + throw new Error("msgId must not be empty!"); + } + if (!this.address) { + throw new Error("address must not be empty!"); + } + if (!this.password) { + throw new Error("Password is required to submit bond tx!"); + } + + return; + } + + route(): string { + return ROUTE; + } + + type(): string { + return SubmitApprovedBondMsg.type(); + } +} + +export class SubmitApprovedUnbondMsg extends Message { + public static type(): MessageType { + return MessageType.SubmitApprovedUnbond; + } + + constructor( + public readonly msgId: string, + public readonly address: string, + public readonly password: string + ) { + super(); + } + + validate(): void { + if (!this.msgId) { + throw new Error("msgId must not be empty!"); + } + if (!this.address) { + throw new Error("address must not be empty!"); + } + if (!this.password) { + throw new Error("Password is required to submit unbond tx!"); + } + + return; + } + + route(): string { + return ROUTE; + } + + type(): string { + return SubmitApprovedUnbondMsg.type(); + } +} diff --git a/apps/extension/src/background/approvals/service.ts b/apps/extension/src/background/approvals/service.ts index 1a65d95d67..43d1050ca1 100644 --- a/apps/extension/src/background/approvals/service.ts +++ b/apps/extension/src/background/approvals/service.ts @@ -2,74 +2,171 @@ import browser from "webextension-polyfill"; import { fromBase64 } from "@cosmjs/encoding"; import { v4 as uuid } from "uuid"; import BigNumber from "bignumber.js"; +import { deserialize } from "@dao-xyz/borsh"; -import { TransferMsgValue } from "@namada/types"; +import { + AccountType, + SubmitBondMsgValue, + TransferMsgValue, +} from "@namada/types"; import { KVStore } from "@namada/storage"; -import { ExtensionRequester } from "extension"; -import { KeyRingService } from "background/keyring"; -import { TabStore } from "background/keyring"; -import { deserialize } from "@dao-xyz/borsh"; +import { KeyRingService, TabStore } from "background/keyring"; +import { LedgerService } from "background/ledger"; +import { paramsToUrl } from "@namada/utils"; export class ApprovalsService { constructor( protected readonly txStore: KVStore, protected readonly connectedTabsStore: KVStore, protected readonly keyRingService: KeyRingService, - protected readonly chainId: string, - protected readonly requester: ExtensionRequester - ) {} + protected readonly ledgerService: LedgerService + ) { } // Deserialize transfer details and prompt user - async approveTransfer(txMsg: string): Promise { + async approveTransfer(txMsg: string, type?: AccountType): Promise { const txMsgBuffer = Buffer.from(fromBase64(txMsg)); const id = uuid(); - this.txStore.set(id, txMsg); + await this.txStore.set(id, txMsg); // Decode tx details and launch approval screen const txDetails = deserialize(txMsgBuffer, TransferMsgValue); const { source, target, token, amount: amountBN } = txDetails; const amount = new BigNumber(amountBN.toString()); - const url = `${browser.runtime.getURL( + const baseUrl = `${browser.runtime.getURL( "approvals.html" - )}#/tx?id=${id}&source=${source}&target=${target}&token=${token}&amount=${amount}`; + )}#/approve-transfer`; - browser.windows.create({ - url, - width: 415, - height: 510, - type: "popup", + const url = paramsToUrl(baseUrl, { + id, + source, + target, + token, + amount: amount.toString(), + type: type as string, + }); + + this._launchApprovalWindow(url); + } + + // Deserialize bond details and prompt user + async approveBond( + txMsg: string, + type: AccountType, + publicKey?: string + ): Promise { + const txMsgBuffer = Buffer.from(fromBase64(txMsg)); + const id = uuid(); + await this.txStore.set(id, txMsg); + + // Decode tx details and launch approval screen + const txDetails = deserialize(txMsgBuffer, SubmitBondMsgValue); + + const { source, nativeToken: token, amount: amountBN } = txDetails; + const amount = new BigNumber(amountBN.toString()); + const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-bond`; + + const url = paramsToUrl(baseUrl, { + id, + source, + token, + amount: amount.toString(), + publicKey: publicKey || "", + type: type as string, + }); + + this._launchApprovalWindow(url); + } + + // Deserialize bond details and prompt user + // TODO: Finish implementing! + async approveUnbond(txMsg: string, type?: AccountType): Promise { + const txMsgBuffer = Buffer.from(fromBase64(txMsg)); + const id = uuid(); + await this.txStore.set(id, txMsg); + + // Decode tx details and launch approval screen + const txDetails = deserialize(txMsgBuffer, SubmitBondMsgValue); + + const { source, nativeToken, amount: amountBN } = txDetails; + const amount = new BigNumber(amountBN.toString()); + // TODO: This query should include perhaps a "type" indicating whether it's a bond or unbond tx: + const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-bond`; + + const url = paramsToUrl(baseUrl, { + id, + source, + token: nativeToken, + amount: amount.toString(), + type: type as string, }); - return; + this._launchApprovalWindow(url); } // Remove pending transaction from storage - async rejectTransfer(msgId: string): Promise { + async rejectTx(msgId: string): Promise { await this._clearPendingTx(msgId); } - // Authenticate keyring, submit approved transaction from storage + // Authenticate keyring and submit approved transfer transaction from storage async submitTransfer(msgId: string, password: string): Promise { - // TODO: Use executeUntil here: - try { - await this.keyRingService.unlock(password); - } catch (e) { - throw new Error(`${e}`); - } + await this.keyRingService.unlock(password); + // Fetch pending transfer tx const tx = await this.txStore.get(msgId); if (tx) { await this.keyRingService.submitTransfer(tx, msgId); - // Clean up storage + return await this._clearPendingTx(msgId); } throw new Error("Pending transfer not found!"); } + // Authenticate keyring and submit approved bond transaction from storage + async submitBond(msgId: string, password: string): Promise { + await this.keyRingService.unlock(password); + + // Fetch pending bond tx + const tx = await this.txStore.get(msgId); + + if (tx) { + await this.keyRingService.submitBond(tx, msgId); + await this.ledgerService.broadcastUpdateStaking(); + + return await this._clearPendingTx(msgId); + } + + throw new Error("Pending bond not found!"); + } + + async submitUnbond(msgId: string, password: string): Promise { + await this.keyRingService.unlock(password); + + // Fetch pending bond tx + const tx = await this.txStore.get(msgId); + + if (tx) { + await this.keyRingService.submitUnbond(tx, msgId); + + return await this._clearPendingTx(msgId); + } + + throw new Error("Pending bond not found!"); + } + private async _clearPendingTx(msgId: string): Promise { return await this.txStore.set(msgId, null); } + + private _launchApprovalWindow = (url: string): void => { + browser.windows.create({ + url, + width: 415, + height: 510, + type: "popup", + }); + }; } diff --git a/apps/extension/src/background/index.ts b/apps/extension/src/background/index.ts index 6f3c2ce0de..440ba4ebcc 100644 --- a/apps/extension/src/background/index.ts +++ b/apps/extension/src/background/index.ts @@ -26,7 +26,9 @@ import { SDK_KEY, PARENT_ACCOUNT_ID_KEY, UtilityStore, + ActiveAccountStore, } from "./keyring"; +import { LedgerService, init as initLedger } from "./ledger"; const store = new IndexedDBKVStore(KVPrefix.IndexedDB); @@ -72,10 +74,12 @@ const { REACT_APP_NAMADA_URL = DEFAULT_URL } = process.env; const sdkData: Record | undefined = await sdkStore.get( SDK_KEY ); - const activeAccount = await utilityStore.get(PARENT_ACCOUNT_ID_KEY); + const activeAccount = await utilityStore.get( + PARENT_ACCOUNT_ID_KEY + ); if (sdkData && activeAccount) { - const data = new TextEncoder().encode(sdkData[activeAccount]); + const data = new TextEncoder().encode(sdkData[activeAccount.id]); sdk.decode(data); } @@ -92,18 +96,27 @@ const { REACT_APP_NAMADA_URL = DEFAULT_URL } = process.env; cryptoMemory, requester ); + const ledgerService = new LedgerService( + keyRingService, + store, + connectedTabsStore, + txStore, + defaultChainId, + sdk, + requester + ); const approvalsService = new ApprovalsService( txStore, connectedTabsStore, keyRingService, - defaultChainId, - requester + ledgerService ); // Initialize messages and handlers initApprovals(router, approvalsService); initChains(router, chainsService); initKeyRing(router, keyRingService); + initLedger(router, ledgerService); router.listen(Ports.Background); })(); diff --git a/apps/extension/src/background/keyring/handler.ts b/apps/extension/src/background/keyring/handler.ts index 3705a68d1b..6394934175 100644 --- a/apps/extension/src/background/keyring/handler.ts +++ b/apps/extension/src/background/keyring/handler.ts @@ -3,6 +3,7 @@ import { KeyRingService } from "./service"; import { CheckIsLockedMsg, CheckPasswordMsg, + QueryPublicKeyMsg, CloseOffscreenDocumentMsg, ResetPasswordMsg, DeriveAccountMsg, @@ -23,8 +24,6 @@ import { EncodeInitAccountMsg, QueryAccountsMsg, QueryBalancesMsg, - SubmitBondMsg, - SubmitUnbondMsg, SubmitIbcTransferMsg, FetchAndStoreMaspParamsMsg, HasMaspParamsMsg, @@ -46,6 +45,8 @@ export const getHandler: (service: KeyRingService) => Handler = (service) => { return handleUnlockKeyRingMsg(service)(env, msg as UnlockKeyRingMsg); case CheckPasswordMsg: return handleCheckPasswordMsg(service)(env, msg as CheckPasswordMsg); + case QueryPublicKeyMsg: + return handleQueryPublicKey(service)(env, msg as QueryPublicKeyMsg); case ResetPasswordMsg: return handleResetPasswordMsg(service)(env, msg as ResetPasswordMsg); case GenerateMnemonicMsg: @@ -83,10 +84,6 @@ export const getHandler: (service: KeyRingService) => Handler = (service) => { env, msg as QueryParentAccountsMsg ); - case SubmitBondMsg: - return handleSubmitBondMsg(service)(env, msg as SubmitBondMsg); - case SubmitUnbondMsg: - return handleSubmitUnbondMsg(service)(env, msg as SubmitUnbondMsg); case SubmitIbcTransferMsg: return handleSubmitIbcTransferMsg(service)( env, @@ -162,6 +159,15 @@ const handleCheckPasswordMsg: ( }; }; +const handleQueryPublicKey: ( + service: KeyRingService +) => InternalHandler = (service) => { + return async (_, msg) => { + const { address } = msg; + return await service.queryPublicKey(address); + }; +}; + const handleResetPasswordMsg: ( service: KeyRingService ) => InternalHandler = (service) => { @@ -243,24 +249,6 @@ const handleQueryParentAccountsMsg: ( }; }; -const handleSubmitBondMsg: ( - service: KeyRingService -) => InternalHandler = (service) => { - return async (_, msg) => { - const { txMsg } = msg; - return await service.submitBond(txMsg); - }; -}; - -const handleSubmitUnbondMsg: ( - service: KeyRingService -) => InternalHandler = (service) => { - return async (_, msg) => { - const { txMsg } = msg; - return await service.submitUnbond(txMsg); - }; -}; - const handleSubmitIbcTransferMsg: ( service: KeyRingService ) => InternalHandler = (service) => { @@ -283,8 +271,8 @@ const handleSetActiveAccountMsg: ( service: KeyRingService ) => InternalHandler = (service) => { return async (_, msg) => { - const { accountId } = msg; - return await service.setActiveAccountId(accountId); + const { accountId, accountType } = msg; + return await service.setActiveAccount(accountId, accountType); }; }; @@ -292,7 +280,7 @@ const handleGetActiveAccountMsg: ( service: KeyRingService ) => InternalHandler = (service) => { return async (_, _msg) => { - return await service.getActiveAccountId(); + return await service.getActiveAccount(); }; }; diff --git a/apps/extension/src/background/keyring/init.ts b/apps/extension/src/background/keyring/init.ts index ac2dfb430d..101294a17a 100644 --- a/apps/extension/src/background/keyring/init.ts +++ b/apps/extension/src/background/keyring/init.ts @@ -5,6 +5,7 @@ import { LockKeyRingMsg, UnlockKeyRingMsg, CheckPasswordMsg, + QueryPublicKeyMsg, ResetPasswordMsg, GenerateMnemonicMsg, SaveMnemonicMsg, @@ -23,8 +24,6 @@ import { QueryAccountsMsg, QueryBalancesMsg, EncodeRevealPkMsg, - SubmitBondMsg, - SubmitUnbondMsg, SubmitIbcTransferMsg, FetchAndStoreMaspParamsMsg, HasMaspParamsMsg, @@ -36,6 +35,7 @@ import { KeyRingService } from "./service"; export function init(router: Router, service: KeyRingService): void { router.registerMessage(CheckIsLockedMsg); router.registerMessage(CheckPasswordMsg); + router.registerMessage(QueryPublicKeyMsg); router.registerMessage(CloseOffscreenDocumentMsg); router.registerMessage(ConnectInterfaceMsg); router.registerMessage(DeriveAccountMsg); @@ -51,9 +51,7 @@ export function init(router: Router, service: KeyRingService): void { router.registerMessage(SaveMnemonicMsg); router.registerMessage(ScanAccountsMsg); router.registerMessage(SetActiveAccountMsg); - router.registerMessage(SubmitBondMsg); router.registerMessage(SubmitIbcTransferMsg); - router.registerMessage(SubmitUnbondMsg); router.registerMessage(TransferCompletedEvent); router.registerMessage(UnlockKeyRingMsg); router.registerMessage(DeleteAccountMsg); diff --git a/apps/extension/src/background/keyring/keyring.ts b/apps/extension/src/background/keyring/keyring.ts index 51db0b80b5..79591d1ac9 100644 --- a/apps/extension/src/background/keyring/keyring.ts +++ b/apps/extension/src/background/keyring/keyring.ts @@ -1,6 +1,8 @@ import BigNumber from "bignumber.js"; -import { v5 as uuid, v4 as uuidV4 } from "uuid"; +import { v4 as uuidV4 } from "uuid"; +import { deserialize } from "@dao-xyz/borsh"; +import { chains } from "@namada/chains"; import { HDWallet, Mnemonic, @@ -24,9 +26,8 @@ import { DerivedAccount, TransferMsgValue, } from "@namada/types"; -import { chains } from "@namada/chains"; -import { Crypto } from "./crypto"; import { + ActiveAccountStore, KeyRingStatus, KeyStore, ResetPasswordError, @@ -38,27 +39,14 @@ import { readVecStringPointer, readStringPointer, } from "@namada/crypto/src/utils"; -import { Result } from "@namada/utils"; -import { deserialize } from "@dao-xyz/borsh"; +import { makeBip44Path, Result } from "@namada/utils"; + +import { Crypto } from "./crypto"; +import { getAccountValuesFromStore, generateId } from "utils"; // Generated UUID namespace for uuid v5 const UUID_NAMESPACE = "9bfceade-37fe-11ed-acc0-a3da3461b38c"; -// Construct unique uuid, passing in an arbitray number of arguments. -// This could be a unique parameter of the object receiving the id, -// or an index based on the number of existing objects in a hierarchy. -const getId = (name: string, ...args: (number | string)[]): string => { - // Ensure a unique UUID - let uuidName = name; - - // Concatenate any number of args onto the name parameter - args.forEach((arg) => { - uuidName = `${uuidName}::${arg}`; - }); - - return uuid(uuidName, UUID_NAMESPACE); -}; - export const KEYSTORE_KEY = "key-store"; export const SDK_KEY = "sdk-store"; export const PARENT_ACCOUNT_ID_KEY = "parent-account-id"; @@ -116,17 +104,19 @@ export class KeyRing { } } - public async getActiveAccountId(): Promise { + public async getActiveAccount(): Promise { return await this.utilityStore.get(PARENT_ACCOUNT_ID_KEY); } - public async setActiveAccountId(parentId: string): Promise { - await this.utilityStore.set(PARENT_ACCOUNT_ID_KEY, parentId); - + public async setActiveAccount( + id: string, + type: AccountType.Mnemonic | AccountType.Ledger + ): Promise { + await this.utilityStore.set(PARENT_ACCOUNT_ID_KEY, { id, type }); // To sync sdk wallet with DB const sdkData = await this.sdkStore.get(SDK_KEY); if (sdkData) { - this.sdk.decode(new TextEncoder().encode(sdkData[parentId])); + this.sdk.decode(new TextEncoder().encode(sdkData[id])); } } @@ -135,7 +125,7 @@ export class KeyRing { accountId?: string ): Promise { // default to active account if no account provided - const idToCheck = accountId ?? (await this.getActiveAccountId()); + const idToCheck = accountId ?? (await this.getActiveAccount())?.id; if (!idToCheck) { throw new Error("No account to check password against"); } @@ -191,7 +181,7 @@ export class KeyRing { } // change password held locally if active account password changed - if (accountId === (await this.getActiveAccountId())) { + if (accountId === (await this.getActiveAccount())?.id) { this._password = newPassword; } } catch (error) { @@ -238,19 +228,24 @@ export class KeyRing { const mnemonic = Mnemonic.from_phrase(phrase); const seed = mnemonic.to_seed(); const { coinType } = chains[this.chainId].bip44; - const path = `m/44'/${coinType}'/0'/0`; - const bip44 = new HDWallet(seed); - const account = bip44.derive(path); + const path = { account: 0, change: 0 }; + const bip44Path = makeBip44Path(coinType, path); + const hdWallet = new HDWallet(seed); + const account = hdWallet.derive(bip44Path); const stringPointer = account.private().to_hex(); const sk = readStringPointer(stringPointer, this._cryptoMemory); const address = new Address(sk).implicit(); const { chainId } = this; // Generate unique ID for new parent account: - const id = getId(phrase, (await this._keyStore.get()).length); + const id = generateId( + UUID_NAMESPACE, + phrase, + (await this._keyStore.get()).length + ); mnemonic.free(); - bip44.free(); + hdWallet.free(); account.free(); stringPointer.free(); @@ -261,10 +256,7 @@ export class KeyRing { owner: address, chainId, password, - path: { - account: 0, - change: 0, - }, + path, text: phrase, type: AccountType.Mnemonic, }); @@ -275,7 +267,7 @@ export class KeyRing { // to prevent adding top level secret key to existing keys this.sdk.clear_storage(); await this.addSecretKey(sk, password, alias, id); - await this.setActiveAccountId(id); + await this.setActiveAccount(id, AccountType.Mnemonic); this._password = password; return true; @@ -305,26 +297,26 @@ export class KeyRing { path: Bip44Path, parentId: string ): DerivedAccountInfo { - const { account, change, index = 0 } = path; - const root = "m/44'"; const { coinType } = chains[this.chainId].bip44; - const derivationPath = [ - root, - `${coinType}'`, - `${account}`, - change, - index, - ].join("/"); - const bip44 = new HDWallet(seed); - const derivedAccount = bip44.derive(derivationPath); - + const derivationPath = makeBip44Path(coinType, path); + const hdWallet = new HDWallet(seed); + const derivedAccount = hdWallet.derive(derivationPath); const privateKey = derivedAccount.private(); const hex = privateKey.to_hex(); const text = readStringPointer(hex, this.cryptoMemory); const address = new Address(text).implicit(); - const id = getId("account", parentId, account, change, index); - bip44.free(); + const { account, change, index = 0 } = path; + const id = generateId( + UUID_NAMESPACE, + "account", + parentId, + account, + change, + index + ); + + hdWallet.free(); derivedAccount.free(); privateKey.free(); hex.free(); @@ -343,7 +335,7 @@ export class KeyRing { parentId: string ): DerivedAccountInfo { const { index = 0 } = path; - const id = getId("shielded-account", parentId, index); + const id = generateId("shielded-account", parentId, index); const zip32 = new ShieldedHDWallet(seed); const account = zip32.derive_to_serialized_keys(index); @@ -475,9 +467,10 @@ export class KeyRing { parentId: string; seed: VecU8Pointer; }> { + const activeAccount = await this.getActiveAccount(); const storedMnemonic = await this._keyStore.getRecord( "id", - await this.getActiveAccountId() + activeAccount?.id ); if (!storedMnemonic) { @@ -575,28 +568,18 @@ export class KeyRing { /** * Query accounts from storage (active parent account + associated derived child accounts) */ - public async queryAccounts(): Promise { - const activeAccountId = await this.getActiveAccountId(); + public async queryAccounts( + activeAccountId: string + ): Promise { const parentAccount = await this._keyStore.getRecord("id", activeAccountId); + const derivedAccounts = (await this._keyStore.getRecords("parentId", activeAccountId)) || []; if (parentAccount) { const accounts = [parentAccount, ...derivedAccounts]; - // Return only non-encrypted data - - return accounts.map( - ({ address, alias, chainId, path, parentId, id, type }) => ({ - address, - alias, - chainId, - id, - parentId, - path, - type, - }) - ); + return getAccountValuesFromStore(accounts); } return []; } @@ -605,22 +588,10 @@ export class KeyRing { * Query all top-level parent accounts (mnemonic accounts) */ public async queryParentAccounts(): Promise { - const accounts = await this._keyStore.getRecords( - "type", - AccountType.Mnemonic - ); + const accounts = + (await this._keyStore.getRecords("type", AccountType.Mnemonic)) || []; // Return only non-encrypted data - return (accounts || []).map( - ({ address, alias, chainId, path, parentId, id, type }) => ({ - address, - alias, - chainId, - id, - parentId, - path, - type, - }) - ); + return getAccountValuesFromStore(accounts); } async encodeInitAccount( @@ -738,7 +709,7 @@ export class KeyRing { } // remove password held locally if active account deleted - if (accountId === (await this.getActiveAccountId())) { + if (accountId === (await this.getActiveAccount())?.id) { this._password = undefined; } @@ -753,15 +724,10 @@ export class KeyRing { } async queryBalances( - address: string + owner: string ): Promise<{ token: string; amount: string }[]> { - const account = await this._keyStore.getRecord("address", address); - if (!account) { - throw new Error(`Account not found.`); - } - try { - return (await this.query.query_balance(account.owner)).map( + return (await this.query.query_balance(owner)).map( ([token, amount]: [string, string]) => { return { token, @@ -782,6 +748,10 @@ export class KeyRing { activeAccountId: string ): Promise { this.sdk.add_key(secretKey, password, alias); + await this.initSdkStore(activeAccountId); + } + + public async initSdkStore(activeAccountId: string): Promise { const store = (await this.sdkStore.get(SDK_KEY)) || {}; this.sdkStore.set(SDK_KEY, { diff --git a/apps/extension/src/background/keyring/messages.ts b/apps/extension/src/background/keyring/messages.ts index 0e8758a3f1..f773f196ed 100644 --- a/apps/extension/src/background/keyring/messages.ts +++ b/apps/extension/src/background/keyring/messages.ts @@ -2,12 +2,18 @@ import { PhraseSize } from "@namada/crypto"; import { AccountType, Bip44Path, DerivedAccount } from "@namada/types"; import { Message } from "router"; import { ROUTE } from "./constants"; -import { KeyRingStatus, ResetPasswordError, DeleteAccountError } from "./types"; +import { + KeyRingStatus, + ResetPasswordError, + DeleteAccountError, + ParentAccount, +} from "./types"; import { Result } from "@namada/utils"; enum MessageType { CheckIsLocked = "check-is-locked", CheckPassword = "check-password", + QueryPublicKey = "query-public-key", CloseOffscreenDocument = "close-offscreen-document", DeriveAccount = "derive-account", DeriveShieldedAccount = "derive-shielded-account", @@ -117,6 +123,30 @@ export class CheckPasswordMsg extends Message { } } +export class QueryPublicKeyMsg extends Message { + public static type(): MessageType { + return MessageType.QueryPublicKey; + } + + constructor(public readonly address: string) { + super(); + } + + validate(): void { + if (!this.address) { + throw new Error("address not set"); + } + } + + route(): string { + return ROUTE; + } + + type(): string { + return QueryPublicKeyMsg.type(); + } +} + export class ResetPasswordMsg extends Message< Result > { @@ -237,7 +267,7 @@ export class ScanAccountsMsg extends Message { } // eslint-disable-next-line @typescript-eslint/no-empty-function - validate(): void {} + validate(): void { } route(): string { return ROUTE; @@ -294,7 +324,10 @@ export class SetActiveAccountMsg extends Message { return MessageType.SetActiveAccount; } - constructor(public readonly accountId: string) { + constructor( + public readonly accountId: string, + public readonly accountType: ParentAccount + ) { super(); } @@ -302,6 +335,10 @@ export class SetActiveAccountMsg extends Message { if (!this.accountId) { throw new Error("Account ID is not set!"); } + + if (!this.accountType) { + throw new Error("Account Type is required!"); + } } route(): string { @@ -313,7 +350,9 @@ export class SetActiveAccountMsg extends Message { } } -export class GetActiveAccountMsg extends Message { +export class GetActiveAccountMsg extends Message< + { id: string; type: ParentAccount } | undefined +> { public static type(): MessageType { return MessageType.GetActiveAccount; } diff --git a/apps/extension/src/background/keyring/service.ts b/apps/extension/src/background/keyring/service.ts index 1bf68f281b..18a92d44b4 100644 --- a/apps/extension/src/background/keyring/service.ts +++ b/apps/extension/src/background/keyring/service.ts @@ -1,19 +1,22 @@ import { fromBase64, toBase64 } from "@cosmjs/encoding"; import { PhraseSize } from "@namada/crypto"; -import { KVStore } from "@namada/storage"; +import { KVStore, Store } from "@namada/storage"; import { AccountType, Bip44Path, DerivedAccount } from "@namada/types"; import { Query, Sdk } from "@namada/shared"; import { Result } from "@namada/utils"; -import { KeyRing } from "./keyring"; +import { KeyRing, KEYSTORE_KEY } from "./keyring"; import { + AccountStore, KeyRingStatus, KeyStore, TabStore, ResetPasswordError, DeleteAccountError, UtilityStore, + ParentAccount, + ActiveAccountStore, } from "./types"; import { syncTabs, updateTabStorage } from "./utils"; import { ExtensionRequester, getNamadaRouterId } from "extension"; @@ -31,9 +34,13 @@ import { SUBMIT_TRANSFER_MSG_TYPE, } from "background/offscreen"; import { init as initSubmitTransferWebWorker } from "background/web-workers"; +import { LEDGERSTORE_KEY } from "background/ledger"; +import { getAccountValuesFromStore } from "utils"; export class KeyRingService { private _keyRing: KeyRing; + private _keyRingStore: Store; + private _ledgerStore: Store; constructor( protected readonly kvStore: KVStore, @@ -57,6 +64,8 @@ export class KeyRingService { query, cryptoMemory ); + this._ledgerStore = new Store(LEDGERSTORE_KEY, kvStore); + this._keyRingStore = new Store(KEYSTORE_KEY, kvStore); } lock(): { status: KeyRingStatus } { @@ -146,14 +155,40 @@ export class KeyRingService { } async queryAccounts(): Promise { - return await this._keyRing.queryAccounts(); + const { id, type } = (await this.getActiveAccount()) || {}; + + if (type !== AccountType.Ledger && id) { + // Query KeyRing accounts + return await this._keyRing.queryAccounts(id); + } + + // Query Ledger accounts + const parent = await this._ledgerStore.getRecord("id", id); + + if (parent) { + const accounts = [ + parent, + ...((await this._ledgerStore.getRecords("parentId", id)) || []), + ]; + + return getAccountValuesFromStore(accounts); + } + + throw new Error(`No accounts found for ${id} ${type}`); } async queryParentAccounts(): Promise { - return await this._keyRing.queryParentAccounts(); + const ledgerAccounts = + (await this._ledgerStore.getRecords("parentId", undefined)) || []; + + return [ + ...(await this._keyRing.queryParentAccounts()), + ...getAccountValuesFromStore(ledgerAccounts), + ]; } - async submitBond(txMsg: string): Promise { + async submitBond(txMsg: string, msgId: string): Promise { + console.log(`TODO: Broadcast notification for ${msgId}`); try { await this._keyRing.submitBond(fromBase64(txMsg)); } catch (e) { @@ -162,7 +197,8 @@ export class KeyRingService { } } - async submitUnbond(txMsg: string): Promise { + async submitUnbond(txMsg: string, msgId: string): Promise { + console.log(`TODO: Broadcast notification for ${msgId}`); try { await this._keyRing.submitUnbond(fromBase64(txMsg)); } catch (e) { @@ -283,14 +319,13 @@ export class KeyRingService { return toBase64(tx_data); } - async setActiveAccountId(accountId: string): Promise { - await this._keyRing.setActiveAccountId(accountId); - + async setActiveAccount(id: string, type: ParentAccount): Promise { + await this._keyRing.setActiveAccount(id, type); await this.broadcastAccountsChanged(); } - async getActiveAccountId(): Promise { - return await this._keyRing.getActiveAccountId(); + async getActiveAccount(): Promise { + return await this._keyRing.getActiveAccount(); } async handleTransferCompleted( @@ -369,7 +404,7 @@ export class KeyRingService { return Sdk.has_masp_params(); } - private async broadcastUpdateBalance(): Promise { + async broadcastUpdateBalance(): Promise { const tabs = await syncTabs( this.connectedTabsStore, this.requester, @@ -391,8 +426,24 @@ export class KeyRingService { } async queryBalances( - owner: string + address: string ): Promise<{ token: string; amount: string }[]> { - return this._keyRing.queryBalances(owner); + // Validate account + const account = + (await this._keyRingStore.getRecord("address", address)) || + (await this._ledgerStore.getRecord("address", address)); + + if (!account) { + throw new Error("Account not found!"); + } + return this._keyRing.queryBalances(account.owner); + } + + async initSdkStore(activeAccountId: string): Promise { + return await this._keyRing.initSdkStore(activeAccountId); + } + + async queryPublicKey(address: string): Promise { + return await this.query.query_public_key(address); } } diff --git a/apps/extension/src/background/keyring/types.ts b/apps/extension/src/background/keyring/types.ts index 318a55e6ce..f93466e2c8 100644 --- a/apps/extension/src/background/keyring/types.ts +++ b/apps/extension/src/background/keyring/types.ts @@ -1,3 +1,4 @@ +import { StoredRecord } from "@namada/storage"; import { AccountType, Bip44Path, DerivedAccount } from "@namada/types"; export enum KdfType { @@ -34,19 +35,22 @@ export type CryptoRecord = { }; }; -export interface KeyStore { - id: string; +export interface AccountStore extends StoredRecord { alias: string; address: string; owner: string; chainId: string; + publicKey?: string; + path: Bip44Path; + parentId?: string; + type: AccountType; +} + +export interface KeyStore extends AccountStore { crypto: CryptoRecord; meta?: { [key: string]: string; }; - path: Bip44Path; - parentId?: string; - type: AccountType; } export type AccountState = DerivedAccount & { @@ -67,13 +71,20 @@ export type TabStore = { timestamp: number; }; -export type UtilityStore = string | { [id: string]: CryptoRecord }; - export enum ResetPasswordError { BadPassword, KeyStoreError, } +export type ParentAccount = AccountType.Mnemonic | AccountType.Ledger; + +export type ActiveAccountStore = { + id: string; + type: ParentAccount; +}; + +export type UtilityStore = ActiveAccountStore | { [id: string]: CryptoRecord }; + export enum DeleteAccountError { BadPassword, KeyStoreError, diff --git a/apps/extension/src/background/ledger/constants.ts b/apps/extension/src/background/ledger/constants.ts new file mode 100644 index 0000000000..57854a916f --- /dev/null +++ b/apps/extension/src/background/ledger/constants.ts @@ -0,0 +1 @@ +export const ROUTE = "ledger-route"; diff --git a/apps/extension/src/background/ledger/handler.ts b/apps/extension/src/background/ledger/handler.ts new file mode 100644 index 0000000000..75d1535220 --- /dev/null +++ b/apps/extension/src/background/ledger/handler.ts @@ -0,0 +1,117 @@ +import { Handler, Env, Message, InternalHandler } from "router"; +import { LedgerService } from "./service"; +import { + AddLedgerAccountMsg, + GetBondBytesMsg, + GetRevealPKBytesMsg, + GetTransferBytesMsg, + SubmitSignedTransferMsg, + SubmitSignedBondMsg, + SubmitSignedRevealPKMsg, +} from "./messages"; + +export const getHandler: (service: LedgerService) => Handler = (service) => { + return (env: Env, msg: Message) => { + switch (msg.constructor) { + case AddLedgerAccountMsg: + return handleAddLedgerAccountMsg(service)( + env, + msg as AddLedgerAccountMsg + ); + case GetRevealPKBytesMsg: + return handleGetRevealPKBytesMsg(service)( + env, + msg as GetRevealPKBytesMsg + ); + + case GetTransferBytesMsg: + return handleGetTransferBytesMsg(service)( + env, + msg as GetTransferBytesMsg + ); + case SubmitSignedRevealPKMsg: + return handleSubmitSignedRevealPKMsg(service)( + env, + msg as SubmitSignedRevealPKMsg + ); + case SubmitSignedTransferMsg: + return handleSubmitSignedTransferMsg(service)( + env, + msg as SubmitSignedTransferMsg + ); + case GetBondBytesMsg: + return handleGetBondBytesMsg(service)(env, msg as GetTransferBytesMsg); + case SubmitSignedBondMsg: + return handleSubmitSignedBondMsg(service)( + env, + msg as SubmitSignedBondMsg + ); + + default: + throw new Error("Unknown msg type"); + } + }; +}; + +const handleAddLedgerAccountMsg: ( + service: LedgerService +) => InternalHandler = (service) => { + return async (_, msg) => { + const { alias, address, publicKey, bip44Path } = msg; + return await service.addAccount(alias, address, publicKey, bip44Path); + }; +}; + +const handleGetTransferBytesMsg: ( + service: LedgerService +) => InternalHandler = (service) => { + return async (_, msg) => { + const { msgId } = msg; + return await service.getTransferBytes(msgId); + }; +}; + +const handleSubmitSignedTransferMsg: ( + service: LedgerService +) => InternalHandler = (service) => { + return async (_, msg) => { + const { bytes, msgId, signatures } = msg; + return await service.submitTransfer(msgId, bytes, signatures); + }; +}; + +const handleGetBondBytesMsg: ( + service: LedgerService +) => InternalHandler = (service) => { + return async (_, msg) => { + const { msgId } = msg; + return await service.getBondBytes(msgId); + }; +}; + +const handleSubmitSignedBondMsg: ( + service: LedgerService +) => InternalHandler = (service) => { + return async (_, msg) => { + const { bytes, msgId, signatures } = msg; + return await service.submitBond(msgId, bytes, signatures); + }; +}; + +const handleGetRevealPKBytesMsg: ( + service: LedgerService +) => InternalHandler = (service) => { + return async (_, msg) => { + const { txMsg } = msg; + return await service.getRevealPKBytes(txMsg); + }; +}; + +const handleSubmitSignedRevealPKMsg: ( + service: LedgerService +) => InternalHandler = (service) => { + return async (_, msg) => { + const { txMsg, bytes, signatures } = msg; + return await service.submitRevealPk(txMsg, bytes, signatures); + }; +}; diff --git a/apps/extension/src/background/ledger/index.ts b/apps/extension/src/background/ledger/index.ts index d1cd2cc47a..f2a87c7999 100644 --- a/apps/extension/src/background/ledger/index.ts +++ b/apps/extension/src/background/ledger/index.ts @@ -1 +1,4 @@ +export * from "./constants"; +export * from "./init"; export * from "./ledger"; +export * from "./service"; diff --git a/apps/extension/src/background/ledger/init.ts b/apps/extension/src/background/ledger/init.ts new file mode 100644 index 0000000000..12eaba6f22 --- /dev/null +++ b/apps/extension/src/background/ledger/init.ts @@ -0,0 +1,27 @@ +import { Router } from "router"; +import { ROUTE } from "./constants"; +import { + AddLedgerAccountMsg, + GetBondBytesMsg, + GetRevealPKBytesMsg, + GetTransferBytesMsg, + SubmitSignedBondMsg, + SubmitSignedRevealPKMsg, + SubmitSignedUnbondMsg, + SubmitSignedTransferMsg, +} from "./messages"; +import { getHandler } from "./handler"; +import { LedgerService } from "./service"; + +export function init(router: Router, service: LedgerService): void { + router.registerMessage(AddLedgerAccountMsg); + router.registerMessage(GetBondBytesMsg); + router.registerMessage(GetRevealPKBytesMsg); + router.registerMessage(GetTransferBytesMsg); + router.registerMessage(SubmitSignedBondMsg); + router.registerMessage(SubmitSignedRevealPKMsg); + router.registerMessage(SubmitSignedUnbondMsg); + router.registerMessage(SubmitSignedTransferMsg); + + router.addHandler(ROUTE, getHandler(service)); +} diff --git a/apps/extension/src/background/ledger/ledger.ts b/apps/extension/src/background/ledger/ledger.ts index f8a9b74329..ce78477aaf 100644 --- a/apps/extension/src/background/ledger/ledger.ts +++ b/apps/extension/src/background/ledger/ledger.ts @@ -1,17 +1,19 @@ +import TransportUSB from "@ledgerhq/hw-transport-webusb"; +import TransportHID from "@ledgerhq/hw-transport-webhid"; +import Transport from "@ledgerhq/hw-transport"; + import { NamadaApp, ResponseAppInfo, ResponseSign, ResponseVersion, -} from "@zondax/ledger-namada"; -import TransportUSB from "@ledgerhq/hw-transport-webusb"; -import TransportHID from "@ledgerhq/hw-transport-webhid"; -import Transport from "@ledgerhq/hw-transport"; - + LedgerError, +} from "@namada/ledger-namada"; import { defaultChainId, chains } from "@namada/chains"; +import { makeBip44Path } from "@namada/utils"; const namadaChain = chains[defaultChainId]; -const bip44CoinType = namadaChain.bip44.coinType; +const { coinType } = namadaChain.bip44; export const initLedgerUSBTransport = async (): Promise => { return await TransportHID.create(); @@ -21,13 +23,14 @@ export const initLedgerHIDTransport = async (): Promise => { return await TransportUSB.create(); }; -export const DEFAULT_LEDGER_BIP44_PATH = `m/44'/${bip44CoinType}'/0'/0/0`; +export const DEFAULT_LEDGER_BIP44_PATH = makeBip44Path(coinType, { + account: 0, + change: 0, + index: 0, +}); export class Ledger { - public version: ResponseVersion | undefined; - public info: ResponseAppInfo | undefined; - - constructor(public readonly namadaApp: NamadaApp | undefined = undefined) {} + constructor(public readonly namadaApp: NamadaApp | undefined = undefined) { } /** * Returns an initialized Ledger class instance with initialized Transport @@ -38,79 +41,92 @@ export class Ledger { const namadaApp = new NamadaApp(initializedTransport); const ledger = new Ledger(namadaApp); - ledger.version = await namadaApp.getVersion(); - ledger.info = await namadaApp.getAppInfo(); - return ledger; } /** * Return status and version info of initialized NamadaApp */ - public status(): { - appName: string; - appVersion: string; - errorMessage: string; - returnCode: number; - deviceLocked: boolean; - major: number; - minor: number; - patch: number; - targetId: string; - testMode: boolean; - } { - if (!this.version || !this.info) { + public async status(): Promise<{ + version: ResponseVersion; + info: ResponseAppInfo; + }> { + if (!this.namadaApp) { throw new Error("NamadaApp is not initialized!"); } - - const { appName, appVersion, errorMessage, returnCode } = this.info; - const { - major, - minor, - patch, - targetId, - deviceLocked = false, - testMode, - } = this.version; + const version = await this.namadaApp.getVersion(); + const info = await this.namadaApp.getAppInfo(); return { - appName, - appVersion, - errorMessage, - returnCode, - deviceLocked, - major, - minor, - patch, - targetId, - testMode, + version, + info, }; } /** - * Get public key associated with optional path, otherwise, use default path + * Get address and public key associated with optional path, otherwise, use default path */ - public async getPublicKey(bip44Path?: string): Promise { + public async getAddressAndPublicKey( + bip44Path?: string + ): Promise<{ address: string; publicKey: string }> { if (!this.namadaApp) { throw new Error("NamadaApp is not initialized!"); } const path = bip44Path || DEFAULT_LEDGER_BIP44_PATH; - const { publicKey } = await this.namadaApp.getAddressAndPubKey(path); + const { address, publicKey } = await this.namadaApp.getAddressAndPubKey( + path + ); - return publicKey.toString("hex"); + return { + // Return address as bech32-encoded string + address: address.toString(), + // Return public key as hex-encoded string + publicKey: publicKey.toString("hex"), + }; } /** * Sign tx bytes with the key associated with provided (or default) path + * + * @async + * @param {Uint8Array} tx - tx data blob to sign + * @param {string} bip44Path (optional) - Bip44 path for signing account + * + * @returns {ResponseSign} */ - public async sign(tx: ArrayBuffer, bip44Path: string): Promise { + public async sign(tx: Uint8Array, bip44Path?: string): Promise { if (!this.namadaApp) { throw new Error("NamadaApp is not initialized!"); } - + const buffer = Buffer.from(tx); const path = bip44Path || DEFAULT_LEDGER_BIP44_PATH; - return await this.namadaApp.sign(path, Buffer.from(tx)); + return await this.namadaApp.sign(path, buffer); + } + + /** + * Query status to determine if device has thrown an error + */ + public async queryErrors(): Promise { + const { + info: { returnCode, errorMessage }, + } = await this.status(); + + if (returnCode !== LedgerError.NoErrors) { + return errorMessage; + } + return ""; + } + + /** + * Close the initialized transport, which may be needed if Ledger needs to be reinitialized due to error state + */ + public async closeTransport(): Promise { + if (!this.namadaApp) { + throw new Error("NamadaApp is not initialized!"); + } + + return await this.namadaApp.transport.close(); } } diff --git a/apps/extension/src/background/ledger/messages.ts b/apps/extension/src/background/ledger/messages.ts new file mode 100644 index 0000000000..7b485755b2 --- /dev/null +++ b/apps/extension/src/background/ledger/messages.ts @@ -0,0 +1,293 @@ +import { ResponseSign } from "@namada/ledger-namada"; +import { Bip44Path } from "@namada/types"; + +import { Message } from "router"; +import { ROUTE } from "./constants"; + +enum MessageType { + AddLedgerAccount = "add-ledger-account", + + // Reveal PK + GetRevealPKBytes = "get-reveal-pk-bytes", + SubmitSignedRevealPK = "submit-signed-reveal-pk", + + // Transfers + GetTransferBytes = "get-transfer-bytes", + SubmitSignedTransfer = "submit-signed-transfer", + + // Bonds + GetBondBytes = "get-bond-bytes", + SubmitSignedBond = "submit-signed-bond", + SubmitSignedUnbond = "submit-signed-unbond", +} + +export class AddLedgerAccountMsg extends Message { + public static type(): MessageType { + return MessageType.AddLedgerAccount; + } + + constructor( + public readonly alias: string, + public readonly address: string, + public readonly publicKey: string, + public readonly bip44Path: Bip44Path + ) { + super(); + } + + validate(): void { + if (!this.alias) { + throw new Error("Alias must not be empty!"); + } + + if (!this.address) { + throw new Error("Address was not provided!"); + } + + if (!this.publicKey) { + throw new Error("Public key was not provided!"); + } + + if (!this.bip44Path) { + throw new Error("BIP44 Path was not provided!"); + } + } + + route(): string { + return ROUTE; + } + + type(): string { + return AddLedgerAccountMsg.type(); + } +} + +export class GetRevealPKBytesMsg extends Message<{ + bytes: Uint8Array; + path: string; +}> { + public static type(): MessageType { + return MessageType.GetRevealPKBytes; + } + + constructor(public readonly txMsg: string) { + super(); + } + + validate(): void { + if (!this.txMsg) { + throw new Error("txMsg was not provided!"); + } + } + + route(): string { + return ROUTE; + } + + type(): string { + return GetRevealPKBytesMsg.type(); + } +} + +export class GetTransferBytesMsg extends Message<{ + bytes: Uint8Array; + path: string; +}> { + public static type(): MessageType { + return MessageType.GetTransferBytes; + } + + constructor(public readonly msgId: string) { + super(); + } + + validate(): void { + if (!this.msgId) { + throw new Error("Transfer Tx msgId was not provided!"); + } + } + + route(): string { + return ROUTE; + } + + type(): string { + return GetTransferBytesMsg.type(); + } +} + +export class GetBondBytesMsg extends Message<{ + bytes: Uint8Array; + path: string; +}> { + public static type(): MessageType { + return MessageType.GetBondBytes; + } + + constructor(public readonly msgId: string) { + super(); + } + + validate(): void { + if (!this.msgId) { + throw new Error("Bond Tx msgId was not provided!"); + } + } + + route(): string { + return ROUTE; + } + + type(): string { + return GetBondBytesMsg.type(); + } +} + +export class SubmitSignedRevealPKMsg extends Message { + public static type(): MessageType { + return MessageType.SubmitSignedRevealPK; + } + + constructor( + public readonly txMsg: string, + public readonly bytes: string, + public readonly signatures: ResponseSign + ) { + super(); + } + + validate(): void { + if (!this.txMsg) { + throw new Error("txMsg was not provided!"); + } + + if (!this.bytes) { + throw new Error("bytes were not provided!"); + } + + if (!this.signatures) { + throw new Error("No signatures were provided!"); + } + } + + route(): string { + return ROUTE; + } + + type(): string { + return SubmitSignedRevealPKMsg.type(); + } +} + +export class SubmitSignedTransferMsg extends Message { + public static type(): MessageType { + return MessageType.SubmitSignedTransfer; + } + + constructor( + public readonly msgId: string, + public readonly bytes: string, + public readonly signatures: ResponseSign + ) { + super(); + } + + validate(): void { + if (!this.msgId) { + throw new Error("msgId was not provided!"); + } + + if (!this.bytes) { + throw new Error("bytes were not provided!"); + } + + if (!this.signatures) { + throw new Error("No signatures were provided!"); + } + } + + route(): string { + return ROUTE; + } + + type(): string { + return SubmitSignedTransferMsg.type(); + } +} + +export class SubmitSignedBondMsg extends Message { + public static type(): MessageType { + return MessageType.SubmitSignedBond; + } + + constructor( + public readonly msgId: string, + public readonly bytes: string, + public readonly signatures: ResponseSign + ) { + super(); + } + + validate(): void { + if (!this.msgId) { + throw new Error("msgId was not provided!"); + } + + if (!this.bytes) { + throw new Error("bytes were not provided!"); + } + + if (!this.signatures) { + throw new Error("No signatures were provided!"); + } + } + + route(): string { + return ROUTE; + } + + type(): string { + return SubmitSignedBondMsg.type(); + } +} + +export class SubmitSignedUnbondMsg extends Message { + public static type(): MessageType { + return MessageType.SubmitSignedUnbond; + } + + constructor( + public readonly msgId: string, + public readonly bytes: string, + public readonly signatures: ResponseSign, + public readonly publicKey: string + ) { + super(); + } + + validate(): void { + if (!this.msgId) { + throw new Error("msgId was not provided!"); + } + + if (!this.bytes) { + throw new Error("bytes were not provided!"); + } + + if (!this.signatures) { + throw new Error("No signatures were provided!"); + } + + if (!this.publicKey) { + throw new Error("No publicKey provided!"); + } + } + + route(): string { + return ROUTE; + } + + type(): string { + return SubmitSignedUnbondMsg.type(); + } +} diff --git a/apps/extension/src/background/ledger/service.ts b/apps/extension/src/background/ledger/service.ts new file mode 100644 index 0000000000..5471108126 --- /dev/null +++ b/apps/extension/src/background/ledger/service.ts @@ -0,0 +1,331 @@ +import { fromBase64 } from "@cosmjs/encoding"; +import { deserialize } from "@dao-xyz/borsh"; + +import { + AccountType, + Bip44Path, + SubmitBondMsgValue, + SubmitRevealPKMsgValue, + TransferMsgValue, +} from "@namada/types"; +import { ResponseSign } from "@namada/ledger-namada"; +import { Sdk } from "@namada/shared"; +import { IStore, KVStore, Store } from "@namada/storage"; +import { chains } from "@namada/chains"; +import { makeBip44Path } from "@namada/utils"; + +import { + AccountStore, + KeyRingService, + TabStore, + syncTabs, +} from "background/keyring"; +import { generateId } from "utils"; +import { ExtensionRequester } from "extension"; +import { Ports } from "router"; +import { UpdatedStakingEventMsg } from "content/events"; + +export const LEDGERSTORE_KEY = "ledger-store"; +const UUID_NAMESPACE = "be9fdaee-ffa2-11ed-8ef1-325096b39f47"; + +export class LedgerService { + private _ledgerStore: IStore; + + constructor( + protected readonly keyring: KeyRingService, + protected readonly kvStore: KVStore, + protected readonly connectedTabsStore: KVStore, + protected readonly txStore: KVStore, + protected readonly chainId: string, + protected readonly sdk: Sdk, + protected readonly requester: ExtensionRequester + ) { + this._ledgerStore = new Store(LEDGERSTORE_KEY, kvStore); + } + + async getRevealPKBytes( + txMsg: string + ): Promise<{ bytes: Uint8Array; path: string }> { + const { coinType } = chains[this.chainId].bip44; + + try { + // Deserialize txMsg to retrieve source + const { publicKey } = deserialize( + Buffer.from(fromBase64(txMsg)), + SubmitRevealPKMsgValue + ); + + // Query account from Ledger storage to determine path for signer + const account = await this._ledgerStore.getRecord("publicKey", publicKey); + + if (!account) { + throw new Error(`Ledger account not found for ${publicKey}`); + } + + const bytes = await this.sdk.build_reveal_pk(fromBase64(txMsg)); + const path = makeBip44Path(coinType, account.path); + + return { bytes, path }; + } catch (e) { + console.warn(e); + throw new Error(`${e}`); + } + } + + async submitRevealPk( + txMsg: string, + bytes: string, + signatures: ResponseSign + ): Promise { + const { + wrapperSignature: { + raw: { data: wrapperSig }, + }, + rawSignature: { + raw: { data: rawSig }, + }, + // TODO: We need the correct type updated in ResponseSign + } = signatures as any; // eslint-disable-line + + if (!wrapperSig) { + throw new Error("No wrapper signature was produced!"); + } + + if (!rawSig) { + throw new Error("No raw signature was produced!"); + } + + try { + await this.sdk.submit_signed_reveal_pk( + fromBase64(txMsg), + fromBase64(bytes), + new Uint8Array(wrapperSig), + new Uint8Array(rawSig) + ); + } catch (e) { + console.warn(e); + } + } + + async getTransferBytes( + msgId: string + ): Promise<{ bytes: Uint8Array; path: string }> { + const txMsg = await this.txStore.get(msgId); + const { coinType } = chains[this.chainId].bip44; + + if (!txMsg) { + throw new Error(`Transaction ${msgId} not found!`); + } + + try { + // Deserialize txMsg to retrieve source + const { source } = deserialize( + Buffer.from(fromBase64(txMsg)), + TransferMsgValue + ); + + // Query account from Ledger storage to determine path for signer + const account = await this._ledgerStore.getRecord("address", source); + + if (!account) { + throw new Error(`Ledger account not found for ${source}`); + } + + const bytes = await this.sdk.build_transfer(fromBase64(txMsg)); + const path = makeBip44Path(coinType, account.path); + + return { bytes, path }; + } catch (e) { + console.warn(e); + throw new Error(`${e}`); + } + } + + async submitTransfer( + msgId: string, + bytes: string, + signatures: ResponseSign + ): Promise { + const txMsg = await this.txStore.get(msgId); + + if (!txMsg) { + throw new Error(`Transaction ${msgId} not found!`); + } + + const { + wrapperSignature: { + raw: { data: wrapperSig }, + }, + rawSignature: { + raw: { data: rawSig }, + }, + // TODO: We need the correct type updated in ResponseSign + } = signatures as any; // eslint-disable-line + + if (!wrapperSig) { + throw new Error("No wrapper signature was produced!"); + } + + if (!rawSig) { + throw new Error("No raw signature was produced!"); + } + + try { + await this.sdk.submit_signed_transfer( + fromBase64(txMsg), + fromBase64(bytes), + new Uint8Array(wrapperSig), + new Uint8Array(rawSig) + ); + + // Clear pending tx if successful + await this.txStore.set(msgId, null); + } catch (e) { + console.warn(e); + } + } + + async getBondBytes( + msgId: string + ): Promise<{ bytes: Uint8Array; path: string }> { + const txMsg = await this.txStore.get(msgId); + + if (!txMsg) { + console.warn(`txMsg not found for msgId: ${msgId}`); + throw new Error(`Transfer Transaction ${msgId} not found!`); + } + + const { coinType } = chains[this.chainId].bip44; + + try { + // Deserialize txMsg to retrieve source + const { source } = deserialize( + Buffer.from(fromBase64(txMsg)), + SubmitBondMsgValue + ); + + // Query account from Ledger storage to determine path for signer + const account = await this._ledgerStore.getRecord("address", source); + + if (!account) { + throw new Error(`Ledger account not found for ${source}`); + } + + const bytes = await this.sdk.build_bond(fromBase64(txMsg)); + const path = makeBip44Path(coinType, account.path); + + return { bytes, path }; + } catch (e) { + console.warn(e); + throw new Error(`${e}`); + } + } + + /* Submit a bond with provided signatures */ + async submitBond( + msgId: string, + bytes: string, + signatures: ResponseSign + ): Promise { + const txMsg = await this.txStore.get(msgId); + + if (!txMsg) { + throw new Error(`Bond Transaction ${msgId} not found!`); + } + + const { + wrapperSignature: { + raw: { data: wrapperSig }, + }, + rawSignature: { + raw: { data: rawSig }, + }, + // TODO: We need the correct type updated in ResponseSign + } = signatures as any; // eslint-disable-line + + if (!wrapperSig) { + throw new Error("No wrapper signature was produced!"); + } + + if (!rawSig) { + throw new Error("No raw signature was produced!"); + } + + try { + await this.sdk.submit_signed_bond( + fromBase64(txMsg), + fromBase64(bytes), + new Uint8Array(wrapperSig), + new Uint8Array(rawSig) + ); + + await this.broadcastUpdateStaking(); + + // Clear pending tx if successful + await this.txStore.set(msgId, null); + } catch (e) { + console.warn(e); + } + + await this.keyring.broadcastUpdateBalance(); + } + + /** + * Append a new address record for use with Ledger + */ + async addAccount( + alias: string, + address: string, + publicKey: string, + bip44Path: Bip44Path + ): Promise { + // Check if account exists in storage, return if so: + const record = await this._ledgerStore.getRecord("address", address); + if (record) { + return; + } + + // Generate a UUID v5 unique id from alias & path + const id = generateId(UUID_NAMESPACE, alias, address); + + const account = { + id, + alias, + address, + publicKey, + owner: address, + chainId: this.chainId, + path: bip44Path, + type: AccountType.Ledger, + }; + await this._ledgerStore.append(account); + + // Prepare SDK store + this.sdk.clear_storage(); + await this.keyring.initSdkStore(id); + + // Set active account ID + await this.keyring.setActiveAccount(id, AccountType.Ledger); + } + + async broadcastUpdateStaking(): Promise { + const tabs = await syncTabs( + this.connectedTabsStore, + this.requester, + this.chainId + ); + try { + tabs?.forEach(({ tabId }: TabStore) => { + this.requester.sendMessageToTab( + tabId, + Ports.WebBrowser, + new UpdatedStakingEventMsg(this.chainId) + ); + }); + } catch (e) { + console.warn(e); + } + + return; + } +} diff --git a/apps/extension/src/background/web-workers/submit-transfer-web-worker.ts b/apps/extension/src/background/web-workers/submit-transfer-web-worker.ts index eeeb9a09c4..8975e095bd 100644 --- a/apps/extension/src/background/web-workers/submit-transfer-web-worker.ts +++ b/apps/extension/src/background/web-workers/submit-transfer-web-worker.ts @@ -10,6 +10,7 @@ import { TRANSFER_FAILED_MSG, TRANSFER_SUCCESSFUL_MSG, } from "./types"; +import { ActiveAccountStore } from "background/keyring"; (async function init() { await initShared(); @@ -22,10 +23,12 @@ import { const sdkData: Record | undefined = await sdkStore.get( "sdk-store" ); - const activeAccount = await utilityStore.get("parent-account-id"); + const activeAccount = await utilityStore.get( + "parent-account-id" + ); if (sdkData && activeAccount) { - const data = new TextEncoder().encode(sdkData[activeAccount]); + const data = new TextEncoder().encode(sdkData[activeAccount.id]); sdk.decode(data); } diff --git a/apps/extension/src/content/events.ts b/apps/extension/src/content/events.ts index afcbb94863..6fe26c4ae3 100644 --- a/apps/extension/src/content/events.ts +++ b/apps/extension/src/content/events.ts @@ -102,11 +102,36 @@ export class UpdatedBalancesEventMsg extends Message { } } +export class UpdatedStakingEventMsg extends Message { + public static type(): Events { + return Events.UpdatedStaking; + } + + constructor(public readonly chainId: string) { + super(); + } + + validate(): void { + if (!this.chainId) { + throw new Error("chainId must not be empty"); + } + } + + route(): string { + return Routes.InteractionForeground; + } + + type(): string { + return UpdatedBalancesEventMsg.type(); + } +} + export function initEvents(router: Router): void { router.registerMessage(AccountChangedEventMsg); router.registerMessage(TransferStartedEvent); router.registerMessage(TransferCompletedEvent); router.registerMessage(UpdatedBalancesEventMsg); + router.registerMessage(UpdatedStakingEventMsg); router.addHandler(Routes.InteractionForeground, (_, msg) => { const clonedMsg = @@ -135,6 +160,9 @@ export function initEvents(router: Router): void { case UpdatedBalancesEventMsg: window.dispatchEvent(new CustomEvent(Events.UpdatedBalances)); break; + case UpdatedStakingEventMsg: + window.dispatchEvent(new CustomEvent(Events.UpdatedStaking)); + break; default: throw new Error("Unknown msg type"); } diff --git a/apps/extension/src/provider/InjectedNamada.ts b/apps/extension/src/provider/InjectedNamada.ts index dc4acca6de..9536c5b75e 100644 --- a/apps/extension/src/provider/InjectedNamada.ts +++ b/apps/extension/src/provider/InjectedNamada.ts @@ -1,14 +1,15 @@ import { - Namada as INamada, + AccountType, Chain, DerivedAccount, + Namada as INamada, Signer as ISigner, } from "@namada/types"; import { InjectedProxy } from "./InjectedProxy"; import { Signer } from "./Signer"; export class InjectedNamada implements INamada { - constructor(private readonly _version: string) {} + constructor(private readonly _version: string) { } public async connect(chainId: string): Promise { return await InjectedProxy.requestMethod("connect", chainId); @@ -49,8 +50,20 @@ export class InjectedNamada implements INamada { return new Signer(chainId, this); } - public async submitBond(txMsg: string): Promise { - return await InjectedProxy.requestMethod("submitBond", txMsg); + public async submitBond(props: { + txMsg: string; + type: AccountType; + publicKey?: string; + }): Promise { + const { txMsg, type, publicKey } = props; + return await InjectedProxy.requestMethod< + { txMsg: string; type: AccountType; publicKey?: string }, + void + >("submitBond", { + txMsg, + type, + publicKey, + }); } public async submitUnbond(txMsg: string): Promise { @@ -60,11 +73,18 @@ export class InjectedNamada implements INamada { ); } - public async submitTransfer(txMsg: string): Promise { - return await InjectedProxy.requestMethod( - "submitTransfer", - txMsg - ); + public async submitTransfer(props: { + txMsg: string; + type: AccountType; + }): Promise { + const { txMsg, type } = props; + return await InjectedProxy.requestMethod< + { txMsg: string; type: AccountType }, + void + >("submitTransfer", { + txMsg, + type, + }); } public async submitIbcTransfer(txMsg: string): Promise { diff --git a/apps/extension/src/provider/Namada.test.ts b/apps/extension/src/provider/Namada.test.ts index a2a90bd329..cc035f321e 100644 --- a/apps/extension/src/provider/Namada.test.ts +++ b/apps/extension/src/provider/Namada.test.ts @@ -4,6 +4,7 @@ import BigNumber from "bignumber.js"; import { AccountMsgValue, + AccountType, IbcTransferMsgValue, IbcTransferProps, Message, @@ -16,7 +17,7 @@ import { import { KVKeys } from "router"; import { init, KVStoreMock } from "test/init"; import { chains as defaultChains } from "@namada/chains"; -import { chain, keyStore, password, ACTIVE_ACCOUNT_ID } from "./data.mock"; +import { chain, keyStore, password, ACTIVE_ACCOUNT } from "./data.mock"; import { KeyRing, KeyRingService, @@ -68,9 +69,9 @@ describe("Namada", () => { it("should return all accounts", async () => { iDBStore.set(KEYSTORE_KEY, keyStore); - utilityStore.set(PARENT_ACCOUNT_ID_KEY, ACTIVE_ACCOUNT_ID); + utilityStore.set(PARENT_ACCOUNT_ID_KEY, ACTIVE_ACCOUNT); const storedKeyStore = keyStore.map( - ({ crypto: _crypto, owner: _owner, ...account }) => account + ({ crypto: _crypto, ...account }) => account ); const storedAccounts = await namada.accounts(chain.chainId); @@ -108,7 +109,10 @@ describe("Namada", () => { const serializedTransfer = transferMessage.encode(transferMsgValue); jest.spyOn(keyRingService, "submitTransfer"); - namada.submitTransfer(toBase64(serializedTransfer)); + namada.submitTransfer({ + txMsg: toBase64(serializedTransfer), + type: AccountType.PrivateKey, + }); expect(keyRingService.submitTransfer).toBeCalled(); }); diff --git a/apps/extension/src/provider/Namada.ts b/apps/extension/src/provider/Namada.ts index 7551af508f..13b9211d6a 100644 --- a/apps/extension/src/provider/Namada.ts +++ b/apps/extension/src/provider/Namada.ts @@ -1,8 +1,15 @@ -import { Namada as INamada, Chain, DerivedAccount } from "@namada/types"; +import { + AccountType, + Namada as INamada, + Chain, + DerivedAccount, +} from "@namada/types"; import { Ports, MessageRequester } from "router"; import { ApproveTransferMsg, + ApproveBondMsg, + ApproveUnbondMsg, ConnectInterfaceMsg, GetChainMsg, GetChainsMsg, @@ -12,8 +19,6 @@ import { FetchAndStoreMaspParamsMsg, HasMaspParamsMsg, QueryBalancesMsg, - SubmitBondMsg, - SubmitUnbondMsg, SubmitIbcTransferMsg, } from "./messages"; @@ -21,7 +26,7 @@ export class Namada implements INamada { constructor( private readonly _version: string, protected readonly requester?: MessageRequester - ) {} + ) { } public async connect(chainId: string): Promise { return await this.requester?.sendMessage( @@ -83,24 +88,33 @@ export class Namada implements INamada { ); } - public async submitBond(txMsg: string): Promise { + public async submitBond(props: { + txMsg: string; + type: AccountType; + publicKey?: string; + }): Promise { + const { txMsg, type, publicKey } = props; return await this.requester?.sendMessage( Ports.Background, - new SubmitBondMsg(txMsg) + new ApproveBondMsg(txMsg, type, publicKey) ); } public async submitUnbond(txMsg: string): Promise { return await this.requester?.sendMessage( Ports.Background, - new SubmitUnbondMsg(txMsg) + new ApproveUnbondMsg(txMsg) ); } - public async submitTransfer(txMsg: string): Promise { + public async submitTransfer(props: { + txMsg: string; + type?: AccountType; + }): Promise { + const { txMsg, type } = props; return await this.requester?.sendMessage( Ports.Background, - new ApproveTransferMsg(txMsg) + new ApproveTransferMsg(txMsg, type) ); } diff --git a/apps/extension/src/provider/Signer.ts b/apps/extension/src/provider/Signer.ts index 42d2a45367..9dbd48d277 100644 --- a/apps/extension/src/provider/Signer.ts +++ b/apps/extension/src/provider/Signer.ts @@ -20,14 +20,16 @@ export class Signer implements ISigner { constructor( protected readonly chainId: string, private readonly _namada: Namada - ) {} + ) { } public async accounts(): Promise { return (await this._namada.accounts(this.chainId))?.map( - ({ alias, address, chainId, type }) => ({ + ({ alias, address, chainId, type, publicKey }) => ({ alias, address, chainId, + type, + publicKey, isShielded: type === AccountType.ShieldedKeys, }) ); @@ -36,13 +38,20 @@ export class Signer implements ISigner { /** * Submit bond transaction */ - public async submitBond(args: SubmitBondProps): Promise { + public async submitBond( + args: SubmitBondProps, + type: AccountType, + publicKey?: string + ): Promise { const msgValue = new SubmitBondMsgValue(args); - const msg = new Message(); const encoded = msg.encode(msgValue); - return await this._namada.submitBond(toBase64(encoded)); + return await this._namada.submitBond({ + txMsg: toBase64(encoded), + type, + publicKey, + }); } /** @@ -60,12 +69,18 @@ export class Signer implements ISigner { /** * Submit a transfer */ - public async submitTransfer(args: TransferProps): Promise { + public async submitTransfer( + args: TransferProps, + type: AccountType + ): Promise { const transferMsgValue = new TransferMsgValue(args); const transferMessage = new Message(); const serializedTransfer = transferMessage.encode(transferMsgValue); - return await this._namada.submitTransfer(toBase64(serializedTransfer)); + return await this._namada.submitTransfer({ + txMsg: toBase64(serializedTransfer), + type, + }); } /** diff --git a/apps/extension/src/provider/data.mock.ts b/apps/extension/src/provider/data.mock.ts index 3461151385..adf92f5e1e 100644 --- a/apps/extension/src/provider/data.mock.ts +++ b/apps/extension/src/provider/data.mock.ts @@ -1,7 +1,10 @@ import { AccountType, BridgeType, Chain, Extensions } from "@namada/types"; -import { KdfType, KeyStore } from "background/keyring"; +import { ActiveAccountStore, KdfType, KeyStore } from "background/keyring"; -export const ACTIVE_ACCOUNT_ID = "324bfe0e-cb19-5f1a-9630-9daaaecadabe"; +export const ACTIVE_ACCOUNT: ActiveAccountStore = { + id: "324bfe0e-cb19-5f1a-9630-9daaaecadabe", + type: AccountType.Mnemonic, +}; export const chain: Chain = { alias: "Namada Testnet", @@ -30,7 +33,8 @@ export const keyStore: KeyStore[] = [ owner: "atest1d9khqw36gvurxv6yxcmyvv6pgdzyxwp3g9z5gv6px5cyxs348yenjd6ygse5y32xxapy2dph26clnv", chainId: "namada-75a7e12.69483d59a9fb174", - id: ACTIVE_ACCOUNT_ID, + id: ACTIVE_ACCOUNT.id, + parentId: undefined, path: { account: 0, change: 0, @@ -60,7 +64,8 @@ export const keyStore: KeyStore[] = [ }, }, }, - type: AccountType.Mnemonic, + publicKey: undefined, + type: ACTIVE_ACCOUNT.type, }, { alias: "Derived Account", @@ -70,7 +75,7 @@ export const keyStore: KeyStore[] = [ "atest1d9khqw36geprgd2yxgcyy3fnxymnzwf4xpprgdzxgccryvp489qn2wzyxcmrgd2xxdznvv2p8akmfs", chainId: "namada-75a7e12.69483d59a9fb174", id: "123e4567-e89b-12d3-a456-426614174000", - parentId: ACTIVE_ACCOUNT_ID, + parentId: ACTIVE_ACCOUNT.id, path: { account: 0, change: 0, @@ -101,6 +106,7 @@ export const keyStore: KeyStore[] = [ }, }, }, + publicKey: undefined, type: AccountType.PrivateKey, }, ]; diff --git a/apps/extension/src/provider/messages.ts b/apps/extension/src/provider/messages.ts index 85e53869b6..556f706df0 100644 --- a/apps/extension/src/provider/messages.ts +++ b/apps/extension/src/provider/messages.ts @@ -1,4 +1,4 @@ -import { Chain, DerivedAccount } from "@namada/types"; +import { AccountType, Chain, DerivedAccount } from "@namada/types"; import { Message } from "router"; /** @@ -16,16 +16,17 @@ enum Route { enum MessageType { ConnectInterface = "connect-interface", QueryAccounts = "query-accounts", - ApproveTransfer = "approve-tx", + ApproveTransfer = "approve-transfer", + ApproveBond = "approve-bond", + ApproveUnbond = "approve-unbond", QueryBalances = "query-balances", SubmitIbcTransfer = "submit-ibc-transfer", + SubmitLedgerTransfer = "submit-ledger-transfer", EncodeInitAccount = "encode-init-account", EncodeRevealPublicKey = "encode-reveal-public-key", GetChain = "get-chain", GetChains = "get-chains", SuggestChain = "suggest-chain", - SubmitBond = "submit-bond", - SubmitUnbond = "submit-unbond", FetchAndStoreMaspParams = "fetch-and-store-masp-params", HasMaspParams = "has-masp-params", } @@ -258,62 +259,75 @@ export class EncodeRevealPkMsg extends Message { } } -export class SubmitBondMsg extends Message { +export class ApproveTransferMsg extends Message { public static type(): MessageType { - return MessageType.SubmitBond; + return MessageType.ApproveTransfer; } - constructor(public readonly txMsg: string) { + constructor( + public readonly txMsg: string, + public readonly accountType?: AccountType + ) { super(); } validate(): void { if (!this.txMsg) { - throw new Error("An encoded txMsg is required!"); + throw new Error("txMsg was not provided!"); } return; } route(): string { - return Route.KeyRing; + return Route.Approvals; } type(): string { - return SubmitBondMsg.type(); + return ApproveTransferMsg.type(); } } -export class SubmitUnbondMsg extends Message { +export class ApproveBondMsg extends Message { public static type(): MessageType { - return MessageType.SubmitUnbond; + return MessageType.ApproveBond; } - constructor(public readonly txMsg: string) { + constructor( + public readonly txMsg: string, + public readonly accountType: AccountType, + public readonly publicKey?: string + ) { super(); } validate(): void { if (!this.txMsg) { - throw new Error("An encoded txMsg is required!"); + throw new Error("txMsg was not provided!"); + } + if (!this.accountType) { + throw new Error("accountType was not provided!"); } return; } route(): string { - return Route.KeyRing; + return Route.Approvals; } type(): string { - return SubmitUnbondMsg.type(); + return ApproveBondMsg.type(); } } -export class ApproveTransferMsg extends Message { +export class ApproveUnbondMsg extends Message { public static type(): MessageType { - return MessageType.ApproveTransfer; + return MessageType.ApproveUnbond; } - constructor(public readonly txMsg: string) { + constructor( + public readonly txMsg: string, + public readonly accountType?: AccountType + ) { super(); } @@ -329,7 +343,7 @@ export class ApproveTransferMsg extends Message { } type(): string { - return ApproveTransferMsg.type(); + return ApproveUnbondMsg.type(); } } diff --git a/apps/extension/src/test/init.ts b/apps/extension/src/test/init.ts index acfc57a26f..c8c71493b1 100644 --- a/apps/extension/src/test/init.ts +++ b/apps/extension/src/test/init.ts @@ -1,20 +1,23 @@ +import { chains } from "@namada/chains"; +import { Query, Sdk } from "@namada/shared"; import { KVStore } from "@namada/storage"; +import { Chain } from "@namada/types"; import { ExtensionRouter, ExtensionMessengerMock, ExtensionRequester, getNamadaRouterId, -} from "../extension"; -import { Ports, KVPrefix } from "../router"; -import { chains } from "@namada/chains"; -import { ChainsService, init as initChains } from "../background/chains"; +} from "extension"; +import { Ports, KVPrefix } from "router"; +import { ChainsService, init as initChains } from "background/chains"; import { KeyRingService, init as initKeyRing, KeyStore, TabStore, UtilityStore, + AccountStore, } from "../background/keyring"; import { @@ -23,8 +26,7 @@ import { } from "../background/approvals"; import { Namada } from "provider"; -import { Chain } from "@namada/types"; -import { Query, Sdk } from "@namada/shared"; +import { LedgerService } from "background/ledger"; // __wasm is not exported in crypto.d.ts so need to use require instead of import /* eslint-disable @typescript-eslint/no-var-requires */ @@ -34,7 +36,7 @@ const chainId = "namada-75a7e12.69483d59a9fb174"; export class KVStoreMock implements KVStore { private storage: { [key: string]: T | null } = {}; - constructor(readonly _prefix: string) {} + constructor(readonly _prefix: string) { } get(key: string): Promise { return new Promise((resolve) => { @@ -102,12 +104,22 @@ export const init = async (): Promise<{ cryptoMemory, requester ); + + const ledgerService = new LedgerService( + keyRingService, + iDBStore as KVStore, + connectedTabsStore, + txStore, + chainId, + sdk, + requester + ); + const approvalsService = new ApprovalsService( txStore, connectedTabsStore, keyRingService, - chainId, - requester + ledgerService ); // Initialize messages and handlers diff --git a/apps/extension/src/utils/index.ts b/apps/extension/src/utils/index.ts index 4f9c874c4a..e907fd4c4e 100644 --- a/apps/extension/src/utils/index.ts +++ b/apps/extension/src/utils/index.ts @@ -1,12 +1,50 @@ import browser from "webextension-polyfill"; +import { v5 as uuid } from "uuid"; + +import { DerivedAccount } from "@namada/types"; +import { pick } from "@namada/utils"; +import { AccountStore } from "background/keyring"; /** - * Extension-specific utilities + * Query the current extension tab and close it */ - export const closeCurrentTab = async (): Promise => { const tab = await browser.tabs.getCurrent(); if (tab.id) { browser.tabs.remove(tab.id); } }; + +/** + * Return all unencrypted values from key store + */ +export const getAccountValuesFromStore = ( + accounts: AccountStore[] +): DerivedAccount[] => { + return accounts.map((account) => + pick( + account, + "address", + "alias", + "chainId", + "id", + "owner", + "parentId", + "publicKey", + "path", + "type" + ) + ); +}; + +/** + * Construct unique uuid (v5), passing in an arbitray number of arguments. + * This could be a unique parameter of the object receiving the id, + * or an index based on the number of existing objects in a hierarchy. + */ +export const generateId = ( + namespace: string, + ...args: (number | string)[] +): string => { + return uuid(args.join(":"), namespace); +}; diff --git a/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.tsx b/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.tsx index 87d8a71389..cb352b9b28 100644 --- a/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.tsx +++ b/apps/namada-interface/src/App/Staking/NewBondingPosition/NewBondingPosition.tsx @@ -68,8 +68,11 @@ export const NewBondingPosition = (props: Props): JSX.Element => { const currentBondingPosition = currentBondingPositions.find( (pos) => pos.owner === currentAccount?.details.address ); - const stakedAmount: BigNumber = new BigNumber(currentBondingPosition?.stakedAmount || "0"); - const currentNAMBalance: BigNumber = currentAccount.balance["NAM"] || new BigNumber(0); + const stakedAmount: BigNumber = new BigNumber( + currentBondingPosition?.stakedAmount || "0" + ); + const currentNAMBalance: BigNumber = + currentAccount.balance["NAM"] || new BigNumber(0); const handleAddressChange = ( e: React.ChangeEvent diff --git a/apps/namada-interface/src/services/extensionEvents/handlers/namada.ts b/apps/namada-interface/src/services/extensionEvents/handlers/namada.ts index d577e9f413..c624490aac 100644 --- a/apps/namada-interface/src/services/extensionEvents/handlers/namada.ts +++ b/apps/namada-interface/src/services/extensionEvents/handlers/namada.ts @@ -6,6 +6,7 @@ import { Namada } from "@namada/integrations"; import { addAccounts, fetchBalances } from "slices/accounts"; import { actions as notificationsActions } from "slices/notifications"; import { getToast, Toasts } from "slices/transfers"; +import { fetchValidators } from "slices/StakingAndGovernance/actions"; export const NamadaAccountChangedHandler = (dispatch: Dispatch, integration: Namada) => @@ -26,6 +27,11 @@ export const NamadaUpdatedBalancesHandler = dispatch(fetchBalances()); }; +export const NamadaUpdatedStakingHandler = + (dispatch: Dispatch) => async () => { + dispatch(fetchValidators()); + }; + export const NamadaTransferStartedHandler = (dispatch: Dispatch) => async (event: CustomEventInit) => { const { msgId } = event.detail; diff --git a/apps/namada-interface/src/services/extensionEvents/provider.tsx b/apps/namada-interface/src/services/extensionEvents/provider.tsx index 77dac031bf..54b762d8fc 100644 --- a/apps/namada-interface/src/services/extensionEvents/provider.tsx +++ b/apps/namada-interface/src/services/extensionEvents/provider.tsx @@ -15,6 +15,7 @@ import { NamadaTransferCompletedHandler, NamadaTransferStartedHandler, NamadaUpdatedBalancesHandler, + NamadaUpdatedStakingHandler, KeplrAccountChangedHandler, MetamaskAccountChangedHandler, } from "./handlers"; @@ -33,8 +34,10 @@ export const ExtensionEventsProvider: React.FC = (props): JSX.Element => { namadaIntegration as Namada ); const namadaTransferStartedHandler = NamadaTransferStartedHandler(dispatch); - const namadaTransferCompletedHandler = NamadaTransferCompletedHandler(dispatch); + const namadaTransferCompletedHandler = + NamadaTransferCompletedHandler(dispatch); const namadaUpdatedBalancesHandler = NamadaUpdatedBalancesHandler(dispatch); + const namadaUpdatedStakingHandler = NamadaUpdatedStakingHandler(dispatch); // Keplr handlers const keplrAccountChangedHandler = KeplrAccountChangedHandler( @@ -51,8 +54,12 @@ export const ExtensionEventsProvider: React.FC = (props): JSX.Element => { // Register handlers: useEventListenerOnce(Events.AccountChanged, namadaAccountChangedHandler); useEventListenerOnce(Events.TransferStarted, namadaTransferStartedHandler); - useEventListenerOnce(Events.TransferCompleted, namadaTransferCompletedHandler); + useEventListenerOnce( + Events.TransferCompleted, + namadaTransferCompletedHandler + ); useEventListenerOnce(Events.UpdatedBalances, namadaUpdatedBalancesHandler); + useEventListenerOnce(Events.UpdatedStaking, namadaUpdatedStakingHandler); useEventListenerOnce(KeplrEvents.AccountChanged, keplrAccountChangedHandler); useEventListenerOnce( MetamaskEvents.AccountChanged, diff --git a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts index 12fb09c418..32835a6f58 100644 --- a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts +++ b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts @@ -44,9 +44,9 @@ const toMyValidators = ( index == -1 ? (arr: MyValidators[]) => arr : (arr: MyValidators[], idx: number) => [ - ...arr.slice(0, idx), - ...arr.slice(idx + 1), - ]; + ...arr.slice(0, idx), + ...arr.slice(idx + 1), + ]; const stakedAmount = new BigNumber(stake) .plus(new BigNumber(v?.stakedAmount || 0)) @@ -159,20 +159,30 @@ export const postNewBonding = createAsyncThunk< { state: RootState } >(POST_NEW_STAKING, async (change, thunkApi) => { const { chainId } = thunkApi.getState().settings; + const { derived } = thunkApi.getState().accounts; const integration = getIntegration(chainId); const signer = integration.signer() as Signer; - await signer.submitBond({ - source: change.owner, - validator: change.validatorId, - amount: new BigNumber(change.amount), - nativeToken: Tokens.NAM.address || "", - tx: { - token: Tokens.NAM.address || "", - feeAmount: new BigNumber(0), - gasLimit: new BigNumber(0), - chainId, + const { owner, validatorId, amount } = change; + const account = derived[chainId][owner]; + const { type, publicKey } = account.details; + + await signer.submitBond( + { + source: owner, + validator: validatorId, + amount: new BigNumber(amount), + nativeToken: Tokens.NAM.address || "", + tx: { + token: Tokens.NAM.address || "", + feeAmount: new BigNumber(0), + gasLimit: new BigNumber(0), + chainId, + publicKey, + }, }, - }); + type, + publicKey + ); }); // we post an unstake transaction diff --git a/apps/namada-interface/src/slices/accounts.ts b/apps/namada-interface/src/slices/accounts.ts index bbc32b4b74..21e8c3dff8 100644 --- a/apps/namada-interface/src/slices/accounts.ts +++ b/apps/namada-interface/src/slices/accounts.ts @@ -80,7 +80,8 @@ const accountsSlice = createSlice({ state.derived[accounts[0].chainId] = {}; accounts.forEach((account) => { - const { address, alias, isShielded, chainId } = account; + const { address, alias, isShielded, chainId, type, publicKey } = + account; const currencySymbol = chains[chainId].currency.symbol; if (!state.derived[chainId]) { state.derived[chainId] = {}; @@ -91,6 +92,8 @@ const accountsSlice = createSlice({ address, alias, chainId, + type, + publicKey, isShielded, }, balance: { diff --git a/apps/namada-interface/src/slices/transfers.ts b/apps/namada-interface/src/slices/transfers.ts index 5a311eb87d..f932540524 100644 --- a/apps/namada-interface/src/slices/transfers.ts +++ b/apps/namada-interface/src/slices/transfers.ts @@ -155,19 +155,23 @@ export const submitTransferTransaction = createAsyncThunk< const integration = getIntegration(chainId); const signer = integration.signer() as Signer; - await signer.submitTransfer({ - tx: { + await signer.submitTransfer( + { + tx: { + token: Tokens.NAM.address || "", + feeAmount: new BigNumber(0), + gasLimit: new BigNumber(0), + chainId, + publicKey: txTransferArgs.account.publicKey, + }, + source: txTransferArgs.account.address, + target: txTransferArgs.target, token: Tokens.NAM.address || "", - feeAmount: new BigNumber(0), - gasLimit: new BigNumber(0), - chainId, + amount: txTransferArgs.amount, + nativeToken: Tokens.NAM.address || "", }, - source: txTransferArgs.account.address, - target: txTransferArgs.target, - token: Tokens.NAM.address || "", - amount: txTransferArgs.amount, - nativeToken: Tokens.NAM.address || "", - }); + txTransferArgs.account.type + ); } ); diff --git a/apps/namada-interface/src/store/mocks.ts b/apps/namada-interface/src/store/mocks.ts index 73dca8884d..a7b8acc4bb 100644 --- a/apps/namada-interface/src/store/mocks.ts +++ b/apps/namada-interface/src/store/mocks.ts @@ -1,5 +1,6 @@ import BigNumber from "bignumber.js"; +import { AccountType } from "@namada/types"; import { RootState } from "./store"; import { TransferType } from "slices/transfers"; import { StakingOrUnstakingState } from "slices/StakingAndGovernance"; @@ -9,20 +10,21 @@ export const mockAppState: RootState = { derived: { "namada-masp-1.5.32ccad5356012a7": { atest1v4ehgw36xqcyz3zrxsenzd3kxsunsvzzxymyywpkg4zrjv2pxepyyd3cgse5gwzxgsm5x3zrkf2pwp: - { - details: { - chainId: "namada-masp-1.5.32ccad5356012a7", - alias: "Namada", - address: - "atest1v4ehgw36xqcyz3zrxsenzd3kxsunsvzzxymyywpkg4zrjv2pxepyyd3cgse5gwzxgsm5x3zrkf2pwp", - isShielded: false, - }, - balance: { - NAM: new BigNumber(1000), - ATOM: new BigNumber(1000), - ETH: new BigNumber(1000), - }, + { + details: { + chainId: "namada-masp-1.5.32ccad5356012a7", + alias: "Namada", + address: + "atest1v4ehgw36xqcyz3zrxsenzd3kxsunsvzzxymyywpkg4zrjv2pxepyyd3cgse5gwzxgsm5x3zrkf2pwp", + isShielded: false, + type: AccountType.PrivateKey, }, + balance: { + NAM: new BigNumber(1000), + ATOM: new BigNumber(1000), + ETH: new BigNumber(1000), + }, + }, }, "namada-test.1e670ba91369ec891fc": { "39UL18": { @@ -31,6 +33,7 @@ export const mockAppState: RootState = { alias: "Namada", address: "atest1v4ehgw36xqcyz3zrxsenzd3kxsunsvzzxymyywpkg4zrjv2pxepyyd3cgse5gwzxgsm5x3zrkf2pwp", + type: AccountType.PrivateKey, isShielded: false, }, balance: { @@ -46,6 +49,7 @@ export const mockAppState: RootState = { chainId: "namada-test.89060614ce340f4baae", alias: "Namada", address: "L1qDtV8TRwYLSHdMDW518hgRw9nWnRjFTenkcBYNJruyYoLjaj8F", + type: AccountType.PrivateKey, isShielded: false, }, diff --git a/packages/integrations/src/Keplr.test.ts b/packages/integrations/src/Keplr.test.ts index c325179464..cfc0760a2f 100644 --- a/packages/integrations/src/Keplr.test.ts +++ b/packages/integrations/src/Keplr.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { mock } from "jest-mock-extended"; -import { Chain } from "@namada/types"; +import { AccountType, Chain } from "@namada/types"; import { Key, Keplr as IKeplr } from "@keplr-wallet/types"; import Keplr from "./Keplr"; @@ -131,6 +131,7 @@ describe("Keplr class", () => { alias: `${a}...${a}`, chainId: mockChain.chainId, address: a, + type: AccountType.PrivateKey, isShielded: false, })) ); diff --git a/packages/integrations/src/Keplr.ts b/packages/integrations/src/Keplr.ts index 53f9d76383..c2f5d740ba 100644 --- a/packages/integrations/src/Keplr.ts +++ b/packages/integrations/src/Keplr.ts @@ -12,7 +12,13 @@ import { import { Coin } from "@cosmjs/launchpad"; import Long from "long"; -import { Account, Chain, CosmosTokens, TokenBalance } from "@namada/types"; +import { + Account, + AccountType, + Chain, + CosmosTokens, + TokenBalance, +} from "@namada/types"; import { shortenAddress } from "@namada/utils"; import { BridgeProps, Integration } from "./types/Integration"; @@ -35,7 +41,7 @@ class Keplr implements Integration { * override keplr instance for testing * @param chain */ - constructor(public readonly chain: Chain) {} + constructor(public readonly chain: Chain) { } private init(): void { if (!this._keplr) { @@ -116,6 +122,7 @@ class Keplr implements Integration { alias: shortenAddress(account.address, 16), chainId: this.chain.chainId, address: account.address, + type: AccountType.PrivateKey, isShielded: false, }) ); diff --git a/packages/integrations/src/Metamask.ts b/packages/integrations/src/Metamask.ts index 08a0e4c368..24b31ca159 100644 --- a/packages/integrations/src/Metamask.ts +++ b/packages/integrations/src/Metamask.ts @@ -1,7 +1,7 @@ import { type MetaMaskInpageProvider } from "@metamask/providers"; import MetaMaskSDK from "@metamask/sdk"; -import { Account, Chain, TokenBalance } from "@namada/types"; +import { Account, AccountType, Chain, TokenBalance } from "@namada/types"; import { shortenAddress } from "@namada/utils"; import { BridgeProps, Integration } from "./types/Integration"; @@ -15,7 +15,7 @@ type MetamaskWindow = Window & class Metamask implements Integration { private _ethereum: MetaMaskInpageProvider | undefined; - constructor(public readonly chain: Chain) {} + constructor(public readonly chain: Chain) { } private init(): void { if ((window).ethereum) { @@ -48,6 +48,7 @@ class Metamask implements Integration { address, alias: shortenAddress(address, 16), chainId: this.chain.chainId, + type: AccountType.PrivateKey, isShielded: false, })); diff --git a/packages/ledger-namada/LICENSE b/packages/ledger-namada/LICENSE new file mode 100644 index 0000000000..9259c4d1e9 --- /dev/null +++ b/packages/ledger-namada/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018 - 2022 Zondax AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/ledger-namada/README.md b/packages/ledger-namada/README.md new file mode 100644 index 0000000000..4171ca0725 --- /dev/null +++ b/packages/ledger-namada/README.md @@ -0,0 +1,12 @@ +# @zondax/ledger-namada + +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![npm version](https://badge.fury.io/js/%40zondax%2Fledger-namada.svg)](https://badge.fury.io/js/%40zondax%2Fledger-namada) + +This package provides a basic client library to communicate with the Namada App running in a Ledger Nano S/X + +We recommend using the npmjs package in order to receive updates/fixes. + +## Notes + +Use `yarn install` to avoid issues. diff --git a/packages/ledger-namada/dist/common.d.ts b/packages/ledger-namada/dist/common.d.ts new file mode 100644 index 0000000000..8c9bc01661 --- /dev/null +++ b/packages/ledger-namada/dist/common.d.ts @@ -0,0 +1,90 @@ +/// +/** ****************************************************************************** + * (c) 2018 - 2023 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +export declare const CHUNK_SIZE = 250; +export declare const PAYLOAD_TYPE: { + INIT: number; + ADD: number; + LAST: number; +}; +export declare const P1_VALUES: { + ONLY_RETRIEVE: number; + SHOW_ADDRESS_IN_DEVICE: number; +}; +export declare const P2_VALUES: { + DEFAULT: number; +}; +export declare const SIGN_VALUES_P2: { + DEFAULT: number; +}; +export declare const ERROR_CODE: { + NoError: number; +}; +export declare const enum SignatureType { + WrapperSignature = 0, + RawSignature = 1 +} +export declare enum LedgerError { + U2FUnknown = 1, + U2FBadRequest = 2, + U2FConfigurationUnsupported = 3, + U2FDeviceIneligible = 4, + U2FTimeout = 5, + Timeout = 14, + NoErrors = 36864, + DeviceIsBusy = 36865, + ErrorDerivingKeys = 26626, + ExecutionError = 25600, + WrongLength = 26368, + EmptyBuffer = 27010, + OutputBufferTooSmall = 27011, + DataIsInvalid = 27012, + ConditionsNotSatisfied = 27013, + TransactionRejected = 27014, + BadKeyHandle = 27264, + InvalidP1P2 = 27392, + InstructionNotSupported = 27904, + AppDoesNotSeemToBeOpen = 28161, + UnknownError = 28416, + SignVerifyError = 28417 +} +export declare const ERROR_DESCRIPTION: { + 1: string; + 2: string; + 3: string; + 4: string; + 5: string; + 14: string; + 36864: string; + 36865: string; + 26626: string; + 25600: string; + 26368: string; + 27010: string; + 27011: string; + 27012: string; + 27013: string; + 27014: string; + 27264: string; + 27392: string; + 27904: string; + 28161: string; + 28416: string; + 28417: string; +}; +export declare function errorCodeToString(statusCode: LedgerError): string; +export declare function processErrorResponse(response: any): any; +export declare function serializePath(path: string): Buffer; diff --git a/packages/ledger-namada/dist/common.js b/packages/ledger-namada/dist/common.js new file mode 100644 index 0000000000..1e9a7a5eca --- /dev/null +++ b/packages/ledger-namada/dist/common.js @@ -0,0 +1,158 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.serializePath = exports.processErrorResponse = exports.errorCodeToString = exports.ERROR_DESCRIPTION = exports.LedgerError = exports.ERROR_CODE = exports.SIGN_VALUES_P2 = exports.P2_VALUES = exports.P1_VALUES = exports.PAYLOAD_TYPE = exports.CHUNK_SIZE = void 0; +/** ****************************************************************************** + * (c) 2018 - 2023 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +exports.CHUNK_SIZE = 250; +exports.PAYLOAD_TYPE = { + INIT: 0x00, + ADD: 0x01, + LAST: 0x02, +}; +exports.P1_VALUES = { + ONLY_RETRIEVE: 0x00, + SHOW_ADDRESS_IN_DEVICE: 0x01, +}; +exports.P2_VALUES = { + DEFAULT: 0x00, +}; +// noinspection JSUnusedGlobalSymbols +exports.SIGN_VALUES_P2 = { + DEFAULT: 0x00, +}; +exports.ERROR_CODE = { + NoError: 0x9000, +}; +var LedgerError; +(function (LedgerError) { + LedgerError[LedgerError["U2FUnknown"] = 1] = "U2FUnknown"; + LedgerError[LedgerError["U2FBadRequest"] = 2] = "U2FBadRequest"; + LedgerError[LedgerError["U2FConfigurationUnsupported"] = 3] = "U2FConfigurationUnsupported"; + LedgerError[LedgerError["U2FDeviceIneligible"] = 4] = "U2FDeviceIneligible"; + LedgerError[LedgerError["U2FTimeout"] = 5] = "U2FTimeout"; + LedgerError[LedgerError["Timeout"] = 14] = "Timeout"; + LedgerError[LedgerError["NoErrors"] = 36864] = "NoErrors"; + LedgerError[LedgerError["DeviceIsBusy"] = 36865] = "DeviceIsBusy"; + LedgerError[LedgerError["ErrorDerivingKeys"] = 26626] = "ErrorDerivingKeys"; + LedgerError[LedgerError["ExecutionError"] = 25600] = "ExecutionError"; + LedgerError[LedgerError["WrongLength"] = 26368] = "WrongLength"; + LedgerError[LedgerError["EmptyBuffer"] = 27010] = "EmptyBuffer"; + LedgerError[LedgerError["OutputBufferTooSmall"] = 27011] = "OutputBufferTooSmall"; + LedgerError[LedgerError["DataIsInvalid"] = 27012] = "DataIsInvalid"; + LedgerError[LedgerError["ConditionsNotSatisfied"] = 27013] = "ConditionsNotSatisfied"; + LedgerError[LedgerError["TransactionRejected"] = 27014] = "TransactionRejected"; + LedgerError[LedgerError["BadKeyHandle"] = 27264] = "BadKeyHandle"; + LedgerError[LedgerError["InvalidP1P2"] = 27392] = "InvalidP1P2"; + LedgerError[LedgerError["InstructionNotSupported"] = 27904] = "InstructionNotSupported"; + LedgerError[LedgerError["AppDoesNotSeemToBeOpen"] = 28161] = "AppDoesNotSeemToBeOpen"; + LedgerError[LedgerError["UnknownError"] = 28416] = "UnknownError"; + LedgerError[LedgerError["SignVerifyError"] = 28417] = "SignVerifyError"; +})(LedgerError || (exports.LedgerError = LedgerError = {})); +exports.ERROR_DESCRIPTION = { + [LedgerError.U2FUnknown]: 'U2F: Unknown', + [LedgerError.U2FBadRequest]: 'U2F: Bad request', + [LedgerError.U2FConfigurationUnsupported]: 'U2F: Configuration unsupported', + [LedgerError.U2FDeviceIneligible]: 'U2F: Device Ineligible', + [LedgerError.U2FTimeout]: 'U2F: Timeout', + [LedgerError.Timeout]: 'Timeout', + [LedgerError.NoErrors]: 'No errors', + [LedgerError.DeviceIsBusy]: 'Device is busy', + [LedgerError.ErrorDerivingKeys]: 'Error deriving keys', + [LedgerError.ExecutionError]: 'Execution Error', + [LedgerError.WrongLength]: 'Wrong Length', + [LedgerError.EmptyBuffer]: 'Empty Buffer', + [LedgerError.OutputBufferTooSmall]: 'Output buffer too small', + [LedgerError.DataIsInvalid]: 'Data is invalid', + [LedgerError.ConditionsNotSatisfied]: 'Conditions not satisfied', + [LedgerError.TransactionRejected]: 'Transaction rejected', + [LedgerError.BadKeyHandle]: 'Bad key handle', + [LedgerError.InvalidP1P2]: 'Invalid P1/P2', + [LedgerError.InstructionNotSupported]: 'Instruction not supported', + [LedgerError.AppDoesNotSeemToBeOpen]: 'App does not seem to be open', + [LedgerError.UnknownError]: 'Unknown error', + [LedgerError.SignVerifyError]: 'Sign/verify error', +}; +function errorCodeToString(statusCode) { + if (statusCode in exports.ERROR_DESCRIPTION) + return exports.ERROR_DESCRIPTION[statusCode]; + return `Unknown Status Code: ${statusCode}`; +} +exports.errorCodeToString = errorCodeToString; +function isDict(v) { + return typeof v === 'object' && v !== null && !(v instanceof Array) && !(v instanceof Date); +} +function processErrorResponse(response) { + if (response) { + if (isDict(response)) { + if (Object.prototype.hasOwnProperty.call(response, 'statusCode')) { + return { + returnCode: response.statusCode, + errorMessage: errorCodeToString(response.statusCode), + }; + } + if (Object.prototype.hasOwnProperty.call(response, 'returnCode') && Object.prototype.hasOwnProperty.call(response, 'errorMessage')) { + return response; + } + } + return { + returnCode: 0xffff, + errorMessage: response.toString(), + }; + } + return { + returnCode: 0xffff, + errorMessage: response.toString(), + }; +} +exports.processErrorResponse = processErrorResponse; +const HARDENED = 0x80000000; +const DEFAULT_DER_PATH_LEN = 6; +const IDENTITY_DER_PATH_LEN = 4; // m/888'/0'/ +function serializePath(path) { + if (!path.startsWith('m')) { + throw new Error(`Path should start with "m" (e.g "m/44'/5757'/5'/0/3")`); + } + const pathArray = path.split('/'); + let allocSize = 0; + if (pathArray.length === DEFAULT_DER_PATH_LEN || pathArray.length === IDENTITY_DER_PATH_LEN) { + allocSize = (pathArray.length - 1) * 4 + 1; + } + else { + throw new Error(`Invalid path. (e.g "m/44'/134'/0/0/0"`); + } + const buf = Buffer.alloc(allocSize); + buf.writeUInt8(pathArray.length - 1, 0); + for (let i = 1; i < pathArray.length; i += 1) { + let value = 0; + let child = pathArray[i]; + if (child.endsWith("'")) { + value += HARDENED; + child = child.slice(0, -1); + } + const childNumber = Number(child); + if (Number.isNaN(childNumber)) { + throw new Error(`Invalid path : ${child} is not a number. (e.g "m/44'/461'/5'/0/3")`); + } + if (childNumber >= HARDENED) { + throw new Error('Incorrect child value (bigger or equal to 0x80000000)'); + } + value += childNumber; + buf.writeUInt32LE(value, 4 * (i - 1) + 1); + } + return buf; +} +exports.serializePath = serializePath; +//# sourceMappingURL=common.js.map \ No newline at end of file diff --git a/packages/ledger-namada/dist/common.js.map b/packages/ledger-namada/dist/common.js.map new file mode 100644 index 0000000000..236b499b04 --- /dev/null +++ b/packages/ledger-namada/dist/common.js.map @@ -0,0 +1 @@ +{"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;mFAcmF;AACtE,QAAA,UAAU,GAAG,GAAG,CAAA;AAEhB,QAAA,YAAY,GAAG;IAC1B,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,IAAI;IACT,IAAI,EAAE,IAAI;CACX,CAAA;AAEY,QAAA,SAAS,GAAG;IACvB,aAAa,EAAE,IAAI;IACnB,sBAAsB,EAAE,IAAI;CAC7B,CAAA;AAEY,QAAA,SAAS,GAAG;IACvB,OAAO,EAAE,IAAI;CACd,CAAA;AAED,qCAAqC;AACxB,QAAA,cAAc,GAAG;IAC5B,OAAO,EAAE,IAAI;CACd,CAAA;AAEY,QAAA,UAAU,GAAG;IACxB,OAAO,EAAE,MAAM;CAChB,CAAA;AAOD,IAAY,WAuBX;AAvBD,WAAY,WAAW;IACrB,yDAAc,CAAA;IACd,+DAAiB,CAAA;IACjB,2FAA+B,CAAA;IAC/B,2EAAuB,CAAA;IACvB,yDAAc,CAAA;IACd,oDAAY,CAAA;IACZ,yDAAiB,CAAA;IACjB,iEAAqB,CAAA;IACrB,2EAA0B,CAAA;IAC1B,qEAAuB,CAAA;IACvB,+DAAoB,CAAA;IACpB,+DAAoB,CAAA;IACpB,iFAA6B,CAAA;IAC7B,mEAAsB,CAAA;IACtB,qFAA+B,CAAA;IAC/B,+EAA4B,CAAA;IAC5B,iEAAqB,CAAA;IACrB,+DAAoB,CAAA;IACpB,uFAAgC,CAAA;IAChC,qFAA+B,CAAA;IAC/B,iEAAqB,CAAA;IACrB,uEAAwB,CAAA;AAC1B,CAAC,EAvBW,WAAW,2BAAX,WAAW,QAuBtB;AAEY,QAAA,iBAAiB,GAAG;IAC/B,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,cAAc;IACxC,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,kBAAkB;IAC/C,CAAC,WAAW,CAAC,2BAA2B,CAAC,EAAE,gCAAgC;IAC3E,CAAC,WAAW,CAAC,mBAAmB,CAAC,EAAE,wBAAwB;IAC3D,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,cAAc;IACxC,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS;IAChC,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,WAAW;IACnC,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,gBAAgB;IAC5C,CAAC,WAAW,CAAC,iBAAiB,CAAC,EAAE,qBAAqB;IACtD,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,iBAAiB;IAC/C,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,cAAc;IACzC,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,cAAc;IACzC,CAAC,WAAW,CAAC,oBAAoB,CAAC,EAAE,yBAAyB;IAC7D,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,iBAAiB;IAC9C,CAAC,WAAW,CAAC,sBAAsB,CAAC,EAAE,0BAA0B;IAChE,CAAC,WAAW,CAAC,mBAAmB,CAAC,EAAE,sBAAsB;IACzD,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,gBAAgB;IAC5C,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,eAAe;IAC1C,CAAC,WAAW,CAAC,uBAAuB,CAAC,EAAE,2BAA2B;IAClE,CAAC,WAAW,CAAC,sBAAsB,CAAC,EAAE,8BAA8B;IACpE,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,eAAe;IAC3C,CAAC,WAAW,CAAC,eAAe,CAAC,EAAE,mBAAmB;CACnD,CAAA;AAED,SAAgB,iBAAiB,CAAC,UAAuB;IACvD,IAAI,UAAU,IAAI,yBAAiB;QAAE,OAAO,yBAAiB,CAAC,UAAU,CAAC,CAAA;IACzE,OAAO,wBAAwB,UAAU,EAAE,CAAA;AAC7C,CAAC;AAHD,8CAGC;AAED,SAAS,MAAM,CAAC,CAAM;IACpB,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAA;AAC7F,CAAC;AAED,SAAgB,oBAAoB,CAAC,QAAa;IAChD,IAAI,QAAQ,EAAE;QACZ,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE;YACpB,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE;gBAChE,OAAO;oBACL,UAAU,EAAE,QAAQ,CAAC,UAAU;oBAC/B,YAAY,EAAE,iBAAiB,CAAC,QAAQ,CAAC,UAAU,CAAC;iBACrD,CAAA;aACF;YAED,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE;gBAClI,OAAO,QAAQ,CAAA;aAChB;SACF;QACD,OAAO;YACL,UAAU,EAAE,MAAM;YAClB,YAAY,EAAE,QAAQ,CAAC,QAAQ,EAAE;SAClC,CAAA;KACF;IAED,OAAO;QACL,UAAU,EAAE,MAAM;QAClB,YAAY,EAAE,QAAQ,CAAC,QAAQ,EAAE;KAClC,CAAA;AACH,CAAC;AAxBD,oDAwBC;AAED,MAAM,QAAQ,GAAG,UAAU,CAAA;AAC3B,MAAM,oBAAoB,GAAG,CAAC,CAAA;AAC9B,MAAM,qBAAqB,GAAG,CAAC,CAAA,CAAC,sBAAsB;AAEtD,SAAgB,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QACzB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAA;KACzE;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAEjC,IAAI,SAAS,GAAG,CAAC,CAAA;IAEjB,IAAI,SAAS,CAAC,MAAM,KAAK,oBAAoB,IAAI,SAAS,CAAC,MAAM,KAAK,qBAAqB,EAAE;QAC3F,SAAS,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;KAC3C;SAAM;QACL,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAA;KACzD;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACnC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE;QAC5C,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,IAAI,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;QACxB,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YACvB,KAAK,IAAI,QAAQ,CAAA;YACjB,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;SAC3B;QAED,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAEjC,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;YAC7B,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,6CAA6C,CAAC,CAAA;SACtF;QAED,IAAI,WAAW,IAAI,QAAQ,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAA;SACzE;QAED,KAAK,IAAI,WAAW,CAAA;QAEpB,GAAG,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;KAC1C;IAED,OAAO,GAAG,CAAA;AACZ,CAAC;AA1CD,sCA0CC","sourcesContent":["/** ******************************************************************************\n * (c) 2018 - 2023 Zondax AG\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n ******************************************************************************* */\nexport const CHUNK_SIZE = 250\n\nexport const PAYLOAD_TYPE = {\n INIT: 0x00,\n ADD: 0x01,\n LAST: 0x02,\n}\n\nexport const P1_VALUES = {\n ONLY_RETRIEVE: 0x00,\n SHOW_ADDRESS_IN_DEVICE: 0x01,\n}\n\nexport const P2_VALUES = {\n DEFAULT: 0x00,\n}\n\n// noinspection JSUnusedGlobalSymbols\nexport const SIGN_VALUES_P2 = {\n DEFAULT: 0x00,\n}\n\nexport const ERROR_CODE = {\n NoError: 0x9000,\n}\n\nexport const enum SignatureType {\n WrapperSignature = 0,\n RawSignature = 1,\n}\n\nexport enum LedgerError {\n U2FUnknown = 1,\n U2FBadRequest = 2,\n U2FConfigurationUnsupported = 3,\n U2FDeviceIneligible = 4,\n U2FTimeout = 5,\n Timeout = 14,\n NoErrors = 0x9000,\n DeviceIsBusy = 0x9001,\n ErrorDerivingKeys = 0x6802,\n ExecutionError = 0x6400,\n WrongLength = 0x6700,\n EmptyBuffer = 0x6982,\n OutputBufferTooSmall = 0x6983,\n DataIsInvalid = 0x6984,\n ConditionsNotSatisfied = 0x6985,\n TransactionRejected = 0x6986,\n BadKeyHandle = 0x6a80,\n InvalidP1P2 = 0x6b00,\n InstructionNotSupported = 0x6d00,\n AppDoesNotSeemToBeOpen = 0x6e01,\n UnknownError = 0x6f00,\n SignVerifyError = 0x6f01,\n}\n\nexport const ERROR_DESCRIPTION = {\n [LedgerError.U2FUnknown]: 'U2F: Unknown',\n [LedgerError.U2FBadRequest]: 'U2F: Bad request',\n [LedgerError.U2FConfigurationUnsupported]: 'U2F: Configuration unsupported',\n [LedgerError.U2FDeviceIneligible]: 'U2F: Device Ineligible',\n [LedgerError.U2FTimeout]: 'U2F: Timeout',\n [LedgerError.Timeout]: 'Timeout',\n [LedgerError.NoErrors]: 'No errors',\n [LedgerError.DeviceIsBusy]: 'Device is busy',\n [LedgerError.ErrorDerivingKeys]: 'Error deriving keys',\n [LedgerError.ExecutionError]: 'Execution Error',\n [LedgerError.WrongLength]: 'Wrong Length',\n [LedgerError.EmptyBuffer]: 'Empty Buffer',\n [LedgerError.OutputBufferTooSmall]: 'Output buffer too small',\n [LedgerError.DataIsInvalid]: 'Data is invalid',\n [LedgerError.ConditionsNotSatisfied]: 'Conditions not satisfied',\n [LedgerError.TransactionRejected]: 'Transaction rejected',\n [LedgerError.BadKeyHandle]: 'Bad key handle',\n [LedgerError.InvalidP1P2]: 'Invalid P1/P2',\n [LedgerError.InstructionNotSupported]: 'Instruction not supported',\n [LedgerError.AppDoesNotSeemToBeOpen]: 'App does not seem to be open',\n [LedgerError.UnknownError]: 'Unknown error',\n [LedgerError.SignVerifyError]: 'Sign/verify error',\n}\n\nexport function errorCodeToString(statusCode: LedgerError) {\n if (statusCode in ERROR_DESCRIPTION) return ERROR_DESCRIPTION[statusCode]\n return `Unknown Status Code: ${statusCode}`\n}\n\nfunction isDict(v: any) {\n return typeof v === 'object' && v !== null && !(v instanceof Array) && !(v instanceof Date)\n}\n\nexport function processErrorResponse(response: any) {\n if (response) {\n if (isDict(response)) {\n if (Object.prototype.hasOwnProperty.call(response, 'statusCode')) {\n return {\n returnCode: response.statusCode,\n errorMessage: errorCodeToString(response.statusCode),\n }\n }\n\n if (Object.prototype.hasOwnProperty.call(response, 'returnCode') && Object.prototype.hasOwnProperty.call(response, 'errorMessage')) {\n return response\n }\n }\n return {\n returnCode: 0xffff,\n errorMessage: response.toString(),\n }\n }\n\n return {\n returnCode: 0xffff,\n errorMessage: response.toString(),\n }\n}\n\nconst HARDENED = 0x80000000\nconst DEFAULT_DER_PATH_LEN = 6\nconst IDENTITY_DER_PATH_LEN = 4 // m/888'/0'/\n\nexport function serializePath(path: string) {\n if (!path.startsWith('m')) {\n throw new Error(`Path should start with \"m\" (e.g \"m/44'/5757'/5'/0/3\")`)\n }\n\n const pathArray = path.split('/')\n\n let allocSize = 0\n\n if (pathArray.length === DEFAULT_DER_PATH_LEN || pathArray.length === IDENTITY_DER_PATH_LEN) {\n allocSize = (pathArray.length - 1) * 4 + 1\n } else {\n throw new Error(`Invalid path. (e.g \"m/44'/134'/0/0/0\"`)\n }\n\n const buf = Buffer.alloc(allocSize)\n buf.writeUInt8(pathArray.length - 1, 0)\n\n for (let i = 1; i < pathArray.length; i += 1) {\n let value = 0\n let child = pathArray[i]\n if (child.endsWith(\"'\")) {\n value += HARDENED\n child = child.slice(0, -1)\n }\n\n const childNumber = Number(child)\n\n if (Number.isNaN(childNumber)) {\n throw new Error(`Invalid path : ${child} is not a number. (e.g \"m/44'/461'/5'/0/3\")`)\n }\n\n if (childNumber >= HARDENED) {\n throw new Error('Incorrect child value (bigger or equal to 0x80000000)')\n }\n\n value += childNumber\n\n buf.writeUInt32LE(value, 4 * (i - 1) + 1)\n }\n\n return buf\n}\n"]} \ No newline at end of file diff --git a/packages/ledger-namada/dist/config.d.ts b/packages/ledger-namada/dist/config.d.ts new file mode 100644 index 0000000000..5f81c2aa7b --- /dev/null +++ b/packages/ledger-namada/dist/config.d.ts @@ -0,0 +1,30 @@ +/** ****************************************************************************** + * (c) 2018 - 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +export declare const CLA = 87; +export declare const INS: { + GET_VERSION: number; + GET_PUBLIC_KEY: number; + SIGN: number; + GET_MASP_ADDRESS: number; + GET_IVK: number; + GET_OVK: number; + GET_NF: number; + GET_SIGNATURE: number; +}; +export declare const SALT_LEN = 8; +export declare const HASH_LEN = 32; +export declare const PK_LEN_25519 = 32; +export declare const ED25519_SIGNATURE_LEN = 64; diff --git a/packages/ledger-namada/dist/config.js b/packages/ledger-namada/dist/config.js new file mode 100644 index 0000000000..3f52e80b84 --- /dev/null +++ b/packages/ledger-namada/dist/config.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ED25519_SIGNATURE_LEN = exports.PK_LEN_25519 = exports.HASH_LEN = exports.SALT_LEN = exports.INS = exports.CLA = void 0; +/** ****************************************************************************** + * (c) 2018 - 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +exports.CLA = 0x57; +exports.INS = { + GET_VERSION: 0x00, + GET_PUBLIC_KEY: 0x01, + SIGN: 0x02, + GET_MASP_ADDRESS: 0x03, + GET_IVK: 0x04, + GET_OVK: 0x05, + GET_NF: 0x06, + GET_SIGNATURE: 0x0a, +}; +exports.SALT_LEN = 8; +exports.HASH_LEN = 32; +exports.PK_LEN_25519 = 32; +exports.ED25519_SIGNATURE_LEN = 64; +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/packages/ledger-namada/dist/config.js.map b/packages/ledger-namada/dist/config.js.map new file mode 100644 index 0000000000..f97b947a42 --- /dev/null +++ b/packages/ledger-namada/dist/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;mFAcmF;AACtE,QAAA,GAAG,GAAG,IAAI,CAAA;AACV,QAAA,GAAG,GAAG;IACjB,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,IAAI;IACpB,IAAI,EAAE,IAAI;IAEV,gBAAgB,EAAE,IAAI;IACtB,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,IAAI;IACb,MAAM,EAAE,IAAI;IAEZ,aAAa,EAAE,IAAI;CACpB,CAAA;AACY,QAAA,QAAQ,GAAG,CAAC,CAAA;AACZ,QAAA,QAAQ,GAAG,EAAE,CAAA;AACb,QAAA,YAAY,GAAG,EAAE,CAAA;AACjB,QAAA,qBAAqB,GAAG,EAAE,CAAA","sourcesContent":["/** ******************************************************************************\n * (c) 2018 - 2022 Zondax AG\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n ******************************************************************************* */\nexport const CLA = 0x57\nexport const INS = {\n GET_VERSION: 0x00,\n GET_PUBLIC_KEY: 0x01,\n SIGN: 0x02,\n\n GET_MASP_ADDRESS: 0x03,\n GET_IVK: 0x04,\n GET_OVK: 0x05,\n GET_NF: 0x06,\n\n GET_SIGNATURE: 0x0a,\n}\nexport const SALT_LEN = 8\nexport const HASH_LEN = 32\nexport const PK_LEN_25519 = 32\nexport const ED25519_SIGNATURE_LEN = 64\n"]} \ No newline at end of file diff --git a/packages/ledger-namada/dist/index.d.ts b/packages/ledger-namada/dist/index.d.ts new file mode 100644 index 0000000000..59072a32be --- /dev/null +++ b/packages/ledger-namada/dist/index.d.ts @@ -0,0 +1,16 @@ +/** ****************************************************************************** + * (c) 2018 - 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +export * from './namadaApp'; diff --git a/packages/ledger-namada/dist/index.js b/packages/ledger-namada/dist/index.js new file mode 100644 index 0000000000..a4a6c9409c --- /dev/null +++ b/packages/ledger-namada/dist/index.js @@ -0,0 +1,33 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +/** ****************************************************************************** + * (c) 2018 - 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +__exportStar(require("./namadaApp"), exports); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/ledger-namada/dist/index.js.map b/packages/ledger-namada/dist/index.js.map new file mode 100644 index 0000000000..d79968f77f --- /dev/null +++ b/packages/ledger-namada/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;mFAcmF;AACnF,8CAA2B","sourcesContent":["/** ******************************************************************************\n * (c) 2018 - 2022 Zondax AG\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n ******************************************************************************* */\nexport * from './namadaApp'\n"]} \ No newline at end of file diff --git a/packages/ledger-namada/dist/namadaApp.d.ts b/packages/ledger-namada/dist/namadaApp.d.ts new file mode 100644 index 0000000000..43de16128a --- /dev/null +++ b/packages/ledger-namada/dist/namadaApp.d.ts @@ -0,0 +1,34 @@ +/// +/** ****************************************************************************** + * (c) 2018 - 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +import Transport from '@ledgerhq/hw-transport'; +import { ResponseAddress, ResponseAppInfo, ResponseBase, ResponseSign, ResponseVersion } from './types'; +import { LedgerError, SignatureType } from './common'; +export { LedgerError }; +export * from './types'; +export declare class NamadaApp { + transport: Transport; + constructor(transport: Transport); + prepareChunks(serializedPath: Buffer, message: Buffer): Promise; + getVersion(): Promise; + getAppInfo(): Promise; + getAddressAndPubKey(path: string): Promise; + showAddressAndPubKey(path: string): Promise; + signSendChunk(chunkIdx: number, chunkNum: number, chunk: Buffer, ins: number): Promise; + getSignature(signatureType: SignatureType): Promise; + _sign(path: string, message: Buffer): Promise; + sign(path: string, message: Buffer): Promise; +} diff --git a/packages/ledger-namada/dist/namadaApp.js b/packages/ledger-namada/dist/namadaApp.js new file mode 100644 index 0000000000..cb384cecd0 --- /dev/null +++ b/packages/ledger-namada/dist/namadaApp.js @@ -0,0 +1,194 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NamadaApp = exports.LedgerError = void 0; +const types_1 = require("./types"); +const common_1 = require("./common"); +Object.defineProperty(exports, "LedgerError", { enumerable: true, get: function () { return common_1.LedgerError; } }); +const config_1 = require("./config"); +const processResponses_1 = require("./processResponses"); +__exportStar(require("./types"), exports); +class NamadaApp { + constructor(transport) { + if (!transport) { + throw new Error('Transport has not been defined'); + } + this.transport = transport; + } + async prepareChunks(serializedPath, message) { + const chunks = []; + chunks.push(serializedPath); + for (let i = 0; i < message.length; i += common_1.CHUNK_SIZE) { + let end = i + common_1.CHUNK_SIZE; + if (i > message.length) { + end = message.length; + } + chunks.push(message.subarray(i, end)); + } + return chunks; + } + async getVersion() { + return this.transport.send(config_1.CLA, config_1.INS.GET_VERSION, 0, 0).then((response) => { + const errorCodeData = response.slice(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + let targetId = 0; + if (response.length >= 9) { + /* eslint-disable no-bitwise */ + targetId = (response[5] << 24) + (response[6] << 16) + (response[7] << 8) + (response[8] << 0); + /* eslint-enable no-bitwise */ + } + return { + returnCode: returnCode, + errorMessage: (0, common_1.errorCodeToString)(returnCode), + // /// + testMode: response[0] !== 0, + major: response[1], + minor: response[2], + patch: response[3], + deviceLocked: response[4] === 1, + targetId: targetId.toString(16), + }; + }, common_1.processErrorResponse); + } + async getAppInfo() { + return this.transport.send(0xb0, 0x01, 0, 0).then(response => { + const errorCodeData = response.slice(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + const result = {}; + let appName = 'err'; + let appVersion = 'err'; + let flagLen = 0; + let flagsValue = 0; + if (response[0] !== 1) { + // Ledger responds with format ID 1. There is no spec for any format != 1 + result.errorMessage = 'response format ID not recognized'; + result.returnCode = common_1.LedgerError.DeviceIsBusy; + } + else { + const appNameLen = response[1]; + appName = response.slice(2, 2 + appNameLen).toString('ascii'); + let idx = 2 + appNameLen; + const appVersionLen = response[idx]; + idx += 1; + appVersion = response.slice(idx, idx + appVersionLen).toString('ascii'); + idx += appVersionLen; + const appFlagsLen = response[idx]; + idx += 1; + flagLen = appFlagsLen; + flagsValue = response[idx]; + } + return { + returnCode, + errorMessage: (0, common_1.errorCodeToString)(returnCode), + // + appName, + appVersion, + flagLen, + flagsValue, + flagRecovery: (flagsValue & 1) !== 0, + // eslint-disable-next-line no-bitwise + flagSignedMcuCode: (flagsValue & 2) !== 0, + // eslint-disable-next-line no-bitwise + flagOnboarded: (flagsValue & 4) !== 0, + // eslint-disable-next-line no-bitwise + flagPINValidated: (flagsValue & 128) !== 0, + }; + }, common_1.processErrorResponse); + } + async getAddressAndPubKey(path) { + const serializedPath = (0, common_1.serializePath)(path); + return this.transport + .send(config_1.CLA, config_1.INS.GET_PUBLIC_KEY, common_1.P1_VALUES.ONLY_RETRIEVE, 0, serializedPath, [common_1.LedgerError.NoErrors]) + .then(processResponses_1.processGetAddrResponse, common_1.processErrorResponse); + } + async showAddressAndPubKey(path) { + const serializedPath = (0, common_1.serializePath)(path); + return this.transport + .send(config_1.CLA, config_1.INS.GET_PUBLIC_KEY, common_1.P1_VALUES.SHOW_ADDRESS_IN_DEVICE, 0, serializedPath, [common_1.LedgerError.NoErrors]) + .then(processResponses_1.processGetAddrResponse, common_1.processErrorResponse); + } + async signSendChunk(chunkIdx, chunkNum, chunk, ins) { + let payloadType = common_1.PAYLOAD_TYPE.ADD; + const p2 = 0; + if (chunkIdx === 1) { + payloadType = common_1.PAYLOAD_TYPE.INIT; + } + if (chunkIdx === chunkNum) { + payloadType = common_1.PAYLOAD_TYPE.LAST; + } + return this.transport + .send(config_1.CLA, ins, payloadType, p2, chunk, [ + common_1.LedgerError.NoErrors, + common_1.LedgerError.DataIsInvalid, + common_1.LedgerError.BadKeyHandle, + common_1.LedgerError.SignVerifyError, + ]) + .then((response) => { + const errorCodeData = response.subarray(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + let errorMessage = (0, common_1.errorCodeToString)(returnCode); + if (returnCode === common_1.LedgerError.BadKeyHandle || + returnCode === common_1.LedgerError.DataIsInvalid || + returnCode === common_1.LedgerError.SignVerifyError) { + errorMessage = `${errorMessage} : ${response.subarray(0, response.length - 2).toString('ascii')}`; + } + return { + returnCode: returnCode, + errorMessage: errorMessage, + }; + }, common_1.processErrorResponse); + } + async getSignature(signatureType) { + return this.transport + .send(config_1.CLA, config_1.INS.GET_SIGNATURE, common_1.P1_VALUES.ONLY_RETRIEVE, signatureType, Buffer.from([]), [common_1.LedgerError.NoErrors]) + .then(processResponses_1.processGetSignatureResponse, common_1.processErrorResponse); + } + async _sign(path, message) { + const serializedPath = (0, common_1.serializePath)(path); + return this.prepareChunks(serializedPath, message).then(chunks => { + return this.signSendChunk(1, chunks.length, chunks[0], config_1.INS.SIGN).then(async (response) => { + let result = { + returnCode: response.returnCode, + errorMessage: response.errorMessage, + }; + for (let i = 1; i < chunks.length; i++) { + result = await this.signSendChunk(1 + i, chunks.length, chunks[i], config_1.INS.SIGN); + if (result.returnCode !== common_1.LedgerError.NoErrors) { + break; + } + } + return result; + }, common_1.processErrorResponse); + }, common_1.processErrorResponse); + } + async sign(path, message) { + const signCommand = await this._sign(path, message); + const result = { + returnCode: signCommand.returnCode, + errorMessage: signCommand.errorMessage, + wrapperSignature: new types_1.Signature(), + rawSignature: new types_1.Signature(), + }; + if (signCommand.returnCode !== common_1.LedgerError.NoErrors) { + return result; + } + result.wrapperSignature = new types_1.Signature(await this.getSignature(0 /* SignatureType.WrapperSignature */)); + result.rawSignature = new types_1.Signature(await this.getSignature(1 /* SignatureType.RawSignature */)); + return result; + } +} +exports.NamadaApp = NamadaApp; +//# sourceMappingURL=namadaApp.js.map \ No newline at end of file diff --git a/packages/ledger-namada/dist/namadaApp.js.map b/packages/ledger-namada/dist/namadaApp.js.map new file mode 100644 index 0000000000..6b89fc8780 --- /dev/null +++ b/packages/ledger-namada/dist/namadaApp.js.map @@ -0,0 +1 @@ +{"version":3,"file":"namadaApp.js","sourceRoot":"","sources":["../src/namadaApp.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAgBA,mCAAkH;AAElH,qCASiB;AAKR,4FAXP,oBAAW,OAWO;AAHpB,qCAAmC;AACnC,yDAAwF;AAGxF,0CAAuB;AAEvB,MAAa,SAAS;IAGpB,YAAY,SAAoB;QAC9B,IAAI,CAAC,SAAS,EAAE;YACd,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;SAClD;QAED,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,cAAsB,EAAE,OAAe;QACzD,MAAM,MAAM,GAAG,EAAE,CAAA;QAEjB,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,mBAAU,EAAE;YACnD,IAAI,GAAG,GAAG,CAAC,GAAG,mBAAU,CAAA;YACxB,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE;gBACtB,GAAG,GAAG,OAAO,CAAC,MAAM,CAAA;aACrB;YACD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;SACtC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAG,EAAE,YAAG,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,QAAa,EAAE,EAAE;YAC5E,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;YACxC,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;YAE5D,IAAI,QAAQ,GAAG,CAAC,CAAA;YAChB,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,EAAE;gBACxB,+BAA+B;gBAC/B,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;gBAC9F,8BAA8B;aAC/B;YAED,OAAO;gBACL,UAAU,EAAE,UAAU;gBACtB,YAAY,EAAE,IAAA,0BAAiB,EAAC,UAAU,CAAC;gBAC3C,MAAM;gBACN,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;gBAC3B,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;gBAClB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;gBAClB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;gBAClB,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;gBAC/B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;aAChC,CAAA;QACH,CAAC,EAAE,6BAAoB,CAAC,CAAA;IAC1B,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;YAC3D,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;YACxC,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;YAE5D,MAAM,MAAM,GAAwD,EAAE,CAAA;YAEtE,IAAI,OAAO,GAAG,KAAK,CAAA;YACnB,IAAI,UAAU,GAAG,KAAK,CAAA;YACtB,IAAI,OAAO,GAAG,CAAC,CAAA;YACf,IAAI,UAAU,GAAG,CAAC,CAAA;YAElB,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;gBACrB,yEAAyE;gBACzE,MAAM,CAAC,YAAY,GAAG,mCAAmC,CAAA;gBACzD,MAAM,CAAC,UAAU,GAAG,oBAAW,CAAC,YAAY,CAAA;aAC7C;iBAAM;gBACL,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;gBAC9B,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;gBAC7D,IAAI,GAAG,GAAG,CAAC,GAAG,UAAU,CAAA;gBACxB,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;gBACnC,GAAG,IAAI,CAAC,CAAA;gBACR,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,aAAa,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;gBACvE,GAAG,IAAI,aAAa,CAAA;gBACpB,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;gBACjC,GAAG,IAAI,CAAC,CAAA;gBACR,OAAO,GAAG,WAAW,CAAA;gBACrB,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;aAC3B;YAED,OAAO;gBACL,UAAU;gBACV,YAAY,EAAE,IAAA,0BAAiB,EAAC,UAAU,CAAC;gBAC3C,EAAE;gBACF,OAAO;gBACP,UAAU;gBACV,OAAO;gBACP,UAAU;gBACV,YAAY,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC;gBACpC,sCAAsC;gBACtC,iBAAiB,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC;gBACzC,sCAAsC;gBACtC,aAAa,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC;gBACrC,sCAAsC;gBACtC,gBAAgB,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC;aAC3C,CAAA;QACH,CAAC,EAAE,6BAAoB,CAAC,CAAA;IAC1B,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,IAAY;QACpC,MAAM,cAAc,GAAG,IAAA,sBAAa,EAAC,IAAI,CAAC,CAAA;QAC1C,OAAO,IAAI,CAAC,SAAS;aAClB,IAAI,CAAC,YAAG,EAAE,YAAG,CAAC,cAAc,EAAE,kBAAS,CAAC,aAAa,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,oBAAW,CAAC,QAAQ,CAAC,CAAC;aACjG,IAAI,CAAC,yCAAsB,EAAE,6BAAoB,CAAC,CAAA;IACvD,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,IAAY;QACrC,MAAM,cAAc,GAAG,IAAA,sBAAa,EAAC,IAAI,CAAC,CAAA;QAC1C,OAAO,IAAI,CAAC,SAAS;aAClB,IAAI,CAAC,YAAG,EAAE,YAAG,CAAC,cAAc,EAAE,kBAAS,CAAC,sBAAsB,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,oBAAW,CAAC,QAAQ,CAAC,CAAC;aAC1G,IAAI,CAAC,yCAAsB,EAAE,6BAAoB,CAAC,CAAA;IACvD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAgB,EAAE,QAAgB,EAAE,KAAa,EAAE,GAAW;QAChF,IAAI,WAAW,GAAG,qBAAY,CAAC,GAAG,CAAA;QAClC,MAAM,EAAE,GAAG,CAAC,CAAA;QACZ,IAAI,QAAQ,KAAK,CAAC,EAAE;YAClB,WAAW,GAAG,qBAAY,CAAC,IAAI,CAAA;SAChC;QACD,IAAI,QAAQ,KAAK,QAAQ,EAAE;YACzB,WAAW,GAAG,qBAAY,CAAC,IAAI,CAAA;SAChC;QAED,OAAO,IAAI,CAAC,SAAS;aAClB,IAAI,CAAC,YAAG,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,KAAK,EAAE;YACtC,oBAAW,CAAC,QAAQ;YACpB,oBAAW,CAAC,aAAa;YACzB,oBAAW,CAAC,YAAY;YACxB,oBAAW,CAAC,eAAe;SAC5B,CAAC;aACD,IAAI,CAAC,CAAC,QAAgB,EAAE,EAAE;YACzB,MAAM,aAAa,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;YAC3C,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;YAC5D,IAAI,YAAY,GAAG,IAAA,0BAAiB,EAAC,UAAU,CAAC,CAAA;YAEhD,IACE,UAAU,KAAK,oBAAW,CAAC,YAAY;gBACvC,UAAU,KAAK,oBAAW,CAAC,aAAa;gBACxC,UAAU,KAAK,oBAAW,CAAC,eAAe,EAC1C;gBACA,YAAY,GAAG,GAAG,YAAY,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAA;aAClG;YAED,OAAO;gBACL,UAAU,EAAE,UAAU;gBACtB,YAAY,EAAE,YAAY;aACX,CAAA;QACnB,CAAC,EAAE,6BAAoB,CAAC,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,aAA4B;QAC7C,OAAO,IAAI,CAAC,SAAS;aAClB,IAAI,CAAC,YAAG,EAAE,YAAG,CAAC,aAAa,EAAE,kBAAS,CAAC,aAAa,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAW,CAAC,QAAQ,CAAC,CAAC;aAC7G,IAAI,CAAC,8CAA2B,EAAE,6BAAoB,CAAC,CAAA;IAC5D,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAY,EAAE,OAAe;QACvC,MAAM,cAAc,GAAG,IAAA,sBAAa,EAAC,IAAI,CAAC,CAAA;QAE1C,OAAO,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;YAC/D,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,YAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,EAAC,QAAQ,EAAC,EAAE;gBACrF,IAAI,MAAM,GAAG;oBACX,UAAU,EAAE,QAAQ,CAAC,UAAU;oBAC/B,YAAY,EAAE,QAAQ,CAAC,YAAY;iBACpC,CAAA;gBAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBACtC,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,YAAG,CAAC,IAAI,CAAC,CAAA;oBAC5E,IAAI,MAAM,CAAC,UAAU,KAAK,oBAAW,CAAC,QAAQ,EAAE;wBAC9C,MAAK;qBACN;iBACF;gBACD,OAAO,MAAM,CAAA;YACf,CAAC,EAAE,6BAAoB,CAAC,CAAA;QAC1B,CAAC,EAAE,6BAAoB,CAAC,CAAA;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,OAAe;QACtC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAEnD,MAAM,MAAM,GAAiB;YAC3B,UAAU,EAAE,WAAW,CAAC,UAAU;YAClC,YAAY,EAAE,WAAW,CAAC,YAAY;YACtC,gBAAgB,EAAE,IAAI,iBAAS,EAAE;YACjC,YAAY,EAAE,IAAI,iBAAS,EAAE;SAC9B,CAAA;QAED,IAAI,WAAW,CAAC,UAAU,KAAK,oBAAW,CAAC,QAAQ,EAAE;YACnD,OAAO,MAAM,CAAA;SACd;QAED,MAAM,CAAC,gBAAgB,GAAG,IAAI,iBAAS,CAAC,MAAM,IAAI,CAAC,YAAY,wCAAgC,CAAC,CAAA;QAChG,MAAM,CAAC,YAAY,GAAG,IAAI,iBAAS,CAAC,MAAM,IAAI,CAAC,YAAY,oCAA4B,CAAC,CAAA;QAExF,OAAO,MAAM,CAAA;IACf,CAAC;CAyCF;AA9OD,8BA8OC","sourcesContent":["/** ******************************************************************************\n * (c) 2018 - 2022 Zondax AG\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n ******************************************************************************* */\nimport Transport from '@ledgerhq/hw-transport'\nimport { ResponseAddress, ResponseAppInfo, ResponseBase, ResponseSign, ResponseVersion, Signature } from './types'\n\nimport {\n CHUNK_SIZE,\n errorCodeToString,\n LedgerError,\n P1_VALUES,\n PAYLOAD_TYPE,\n processErrorResponse,\n serializePath,\n SignatureType,\n} from './common'\n\nimport { CLA, INS } from './config'\nimport { processGetAddrResponse, processGetSignatureResponse } from './processResponses'\n\nexport { LedgerError }\nexport * from './types'\n\nexport class NamadaApp {\n transport: Transport\n\n constructor(transport: Transport) {\n if (!transport) {\n throw new Error('Transport has not been defined')\n }\n\n this.transport = transport\n }\n\n async prepareChunks(serializedPath: Buffer, message: Buffer) {\n const chunks = []\n\n chunks.push(serializedPath)\n for (let i = 0; i < message.length; i += CHUNK_SIZE) {\n let end = i + CHUNK_SIZE\n if (i > message.length) {\n end = message.length\n }\n chunks.push(message.subarray(i, end))\n }\n\n return chunks\n }\n\n async getVersion(): Promise {\n return this.transport.send(CLA, INS.GET_VERSION, 0, 0).then((response: any) => {\n const errorCodeData = response.slice(-2)\n const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n let targetId = 0\n if (response.length >= 9) {\n /* eslint-disable no-bitwise */\n targetId = (response[5] << 24) + (response[6] << 16) + (response[7] << 8) + (response[8] << 0)\n /* eslint-enable no-bitwise */\n }\n\n return {\n returnCode: returnCode,\n errorMessage: errorCodeToString(returnCode),\n // ///\n testMode: response[0] !== 0,\n major: response[1],\n minor: response[2],\n patch: response[3],\n deviceLocked: response[4] === 1,\n targetId: targetId.toString(16),\n }\n }, processErrorResponse)\n }\n\n async getAppInfo(): Promise {\n return this.transport.send(0xb0, 0x01, 0, 0).then(response => {\n const errorCodeData = response.slice(-2)\n const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n const result: { errorMessage?: string; returnCode?: LedgerError } = {}\n\n let appName = 'err'\n let appVersion = 'err'\n let flagLen = 0\n let flagsValue = 0\n\n if (response[0] !== 1) {\n // Ledger responds with format ID 1. There is no spec for any format != 1\n result.errorMessage = 'response format ID not recognized'\n result.returnCode = LedgerError.DeviceIsBusy\n } else {\n const appNameLen = response[1]\n appName = response.slice(2, 2 + appNameLen).toString('ascii')\n let idx = 2 + appNameLen\n const appVersionLen = response[idx]\n idx += 1\n appVersion = response.slice(idx, idx + appVersionLen).toString('ascii')\n idx += appVersionLen\n const appFlagsLen = response[idx]\n idx += 1\n flagLen = appFlagsLen\n flagsValue = response[idx]\n }\n\n return {\n returnCode,\n errorMessage: errorCodeToString(returnCode),\n //\n appName,\n appVersion,\n flagLen,\n flagsValue,\n flagRecovery: (flagsValue & 1) !== 0,\n // eslint-disable-next-line no-bitwise\n flagSignedMcuCode: (flagsValue & 2) !== 0,\n // eslint-disable-next-line no-bitwise\n flagOnboarded: (flagsValue & 4) !== 0,\n // eslint-disable-next-line no-bitwise\n flagPINValidated: (flagsValue & 128) !== 0,\n }\n }, processErrorResponse)\n }\n\n async getAddressAndPubKey(path: string): Promise {\n const serializedPath = serializePath(path)\n return this.transport\n .send(CLA, INS.GET_PUBLIC_KEY, P1_VALUES.ONLY_RETRIEVE, 0, serializedPath, [LedgerError.NoErrors])\n .then(processGetAddrResponse, processErrorResponse)\n }\n\n async showAddressAndPubKey(path: string): Promise {\n const serializedPath = serializePath(path)\n return this.transport\n .send(CLA, INS.GET_PUBLIC_KEY, P1_VALUES.SHOW_ADDRESS_IN_DEVICE, 0, serializedPath, [LedgerError.NoErrors])\n .then(processGetAddrResponse, processErrorResponse)\n }\n\n async signSendChunk(chunkIdx: number, chunkNum: number, chunk: Buffer, ins: number): Promise {\n let payloadType = PAYLOAD_TYPE.ADD\n const p2 = 0\n if (chunkIdx === 1) {\n payloadType = PAYLOAD_TYPE.INIT\n }\n if (chunkIdx === chunkNum) {\n payloadType = PAYLOAD_TYPE.LAST\n }\n\n return this.transport\n .send(CLA, ins, payloadType, p2, chunk, [\n LedgerError.NoErrors,\n LedgerError.DataIsInvalid,\n LedgerError.BadKeyHandle,\n LedgerError.SignVerifyError,\n ])\n .then((response: Buffer) => {\n const errorCodeData = response.subarray(-2)\n const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n let errorMessage = errorCodeToString(returnCode)\n\n if (\n returnCode === LedgerError.BadKeyHandle ||\n returnCode === LedgerError.DataIsInvalid ||\n returnCode === LedgerError.SignVerifyError\n ) {\n errorMessage = `${errorMessage} : ${response.subarray(0, response.length - 2).toString('ascii')}`\n }\n\n return {\n returnCode: returnCode,\n errorMessage: errorMessage,\n } as ResponseSign\n }, processErrorResponse)\n }\n\n async getSignature(signatureType: SignatureType) {\n return this.transport\n .send(CLA, INS.GET_SIGNATURE, P1_VALUES.ONLY_RETRIEVE, signatureType, Buffer.from([]), [LedgerError.NoErrors])\n .then(processGetSignatureResponse, processErrorResponse)\n }\n\n async _sign(path: string, message: Buffer) {\n const serializedPath = serializePath(path)\n\n return this.prepareChunks(serializedPath, message).then(chunks => {\n return this.signSendChunk(1, chunks.length, chunks[0], INS.SIGN).then(async response => {\n let result = {\n returnCode: response.returnCode,\n errorMessage: response.errorMessage,\n }\n\n for (let i = 1; i < chunks.length; i++) {\n result = await this.signSendChunk(1 + i, chunks.length, chunks[i], INS.SIGN)\n if (result.returnCode !== LedgerError.NoErrors) {\n break\n }\n }\n return result\n }, processErrorResponse)\n }, processErrorResponse)\n }\n\n async sign(path: string, message: Buffer) {\n const signCommand = await this._sign(path, message)\n\n const result: ResponseSign = {\n returnCode: signCommand.returnCode,\n errorMessage: signCommand.errorMessage,\n wrapperSignature: new Signature(),\n rawSignature: new Signature(),\n }\n\n if (signCommand.returnCode !== LedgerError.NoErrors) {\n return result\n }\n\n result.wrapperSignature = new Signature(await this.getSignature(SignatureType.WrapperSignature))\n result.rawSignature = new Signature(await this.getSignature(SignatureType.RawSignature))\n\n return result\n }\n\n /* Not implemented yet\n async getShieldedAddressAndPubKey(path: number, div: Buffer): Promise {\n const buf = Buffer.alloc(4);\n buf.writeUInt32LE(path, 0);\n return this.transport\n .send(CLA, INS.GET_MASP_ADDRESS, P1_VALUES.ONLY_RETRIEVE, 0, Buffer.concat([buf, div]), [LedgerError.NoErrors])\n .then(processGetShieldedAddrResponse, processErrorResponse)\n }\n\n async showShieldedAddressAndPubKey(path: number, div: Buffer): Promise {\n const buf = Buffer.alloc(4);\n buf.writeUInt32LE(path, 0);\n return this.transport\n .send(CLA, INS.GET_MASP_ADDRESS, P1_VALUES.SHOW_ADDRESS_IN_DEVICE, 0, Buffer.concat([buf, div]), [LedgerError.NoErrors])\n .then(processGetShieldedAddrResponse, processErrorResponse)\n }\n\n async getIncomingViewingKey(path: number): Promise {\n const buf = Buffer.alloc(4);\n buf.writeUInt32LE(path, 0);\n return this.transport\n .send(CLA, INS.GET_IVK, P1_VALUES.SHOW_ADDRESS_IN_DEVICE, 0, buf, [LedgerError.NoErrors])\n .then(processIncomingViewingKeyResponse, processErrorResponse)\n }\n\n async getOutgoingViewingKey(path: number): Promise {\n const buf = Buffer.alloc(4);\n buf.writeUInt32LE(path, 0);\n return this.transport\n .send(CLA, INS.GET_OVK, P1_VALUES.SHOW_ADDRESS_IN_DEVICE, 0, buf, [LedgerError.NoErrors])\n .then(processOutgoingViewingKeyResponse, processErrorResponse)\n }\n\n async getNullifier(pos: Uint8Array, cm: Buffer): Promise {\n return this.transport\n .send(CLA, INS.GET_NF, P1_VALUES.ONLY_RETRIEVE, 0, Buffer.concat([pos, cm]), [LedgerError.NoErrors])\n .then(processNullifierResponse, processErrorResponse)\n }\n */\n}\n"]} \ No newline at end of file diff --git a/packages/ledger-namada/dist/processResponses.d.ts b/packages/ledger-namada/dist/processResponses.d.ts new file mode 100644 index 0000000000..e3ebe096a2 --- /dev/null +++ b/packages/ledger-namada/dist/processResponses.d.ts @@ -0,0 +1,24 @@ +/** ****************************************************************************** + * (c) 2018 - 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +/// +import { ISignature } from './types'; +export declare function processGetSignatureResponse(response: Buffer): ISignature; +export declare function processGetAddrResponse(response: Buffer): { + publicKey: Buffer; + address: Buffer; + returnCode: number; + errorMessage: string; +}; diff --git a/packages/ledger-namada/dist/processResponses.js b/packages/ledger-namada/dist/processResponses.js new file mode 100644 index 0000000000..32d6357dea --- /dev/null +++ b/packages/ledger-namada/dist/processResponses.js @@ -0,0 +1,133 @@ +"use strict"; +/** ****************************************************************************** + * (c) 2018 - 2022 Zondax AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.processGetAddrResponse = exports.processGetSignatureResponse = void 0; +const common_1 = require("./common"); +const config_1 = require("./config"); +function processGetSignatureResponse(response) { + console.log('Processing get signature response'); + let offset = 0; + const salt = Buffer.from(response.subarray(offset, offset + config_1.SALT_LEN)); + offset += config_1.SALT_LEN; + const hashesLen = response[offset] + response[offset + 1] * 0x100 + response[offset + 2] * 0x10000 + response[offset + 3] * 0x1000000; + offset += 4; + const hashes = []; + for (let i = 0; i < hashesLen; i++) { + hashes.push(Buffer.from(response.subarray(offset, offset + config_1.HASH_LEN))); + offset += config_1.HASH_LEN; + } + const pubkey = Buffer.from(response.subarray(offset, offset + config_1.PK_LEN_25519 + 1)); + offset += config_1.PK_LEN_25519 + 1; + const hasSignature = response[offset]; + offset += 1; + let signature = null; + if (hasSignature) { + signature = Buffer.from(response.subarray(offset, offset + 65)); + offset += 65; + } + const raw = Buffer.from(response.subarray(0, offset)); + return { + salt, + hashes, + pubkey, + signature, + raw, + }; +} +exports.processGetSignatureResponse = processGetSignatureResponse; +function processGetAddrResponse(response) { + console.log('Processing get address response'); + let partialResponse = response; + const errorCodeData = partialResponse.subarray(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + //get public key len (variable) + const publicKey = Buffer.from(partialResponse.slice(0, config_1.PK_LEN_25519)); + //"advance" buffer + partialResponse = partialResponse.slice(config_1.PK_LEN_25519); + // get the implicit address corresponding to the public key + const address = Buffer.from(partialResponse.slice(0, -2)); + return { + publicKey, + address, + returnCode, + errorMessage: (0, common_1.errorCodeToString)(returnCode), + }; +} +exports.processGetAddrResponse = processGetAddrResponse; +// Not used yet +// function processGetShieldedAddrResponse(response: Buffer) { +// console.log("Processing get address response") +// let partialResponse = response +// const errorCodeData = partialResponse.slice(-2) +// const returnCode = errorCodeData[0] * 256 + errorCodeData[1] +// //get public key len (variable) +// const raw_pkd = Buffer.from(partialResponse.slice(0, 32)) +// //"advance" buffer +// partialResponse = partialResponse.slice(32) +// // get the length of the bech32m address +// const bech32m_len = partialResponse[0] +// //"advance" buffer +// partialResponse = partialResponse.slice(1) +// // get the bech32m encoding of the shielded address +// const bech32m_addr = Buffer.from(partialResponse.slice(0, bech32m_len)) +// return { +// raw_pkd, +// bech32m_len, +// bech32m_addr, +// returnCode, +// errorMessage: errorCodeToString(returnCode), +// } +// } +// function processIncomingViewingKeyResponse(response: Buffer) { +// console.log("Processing get IVK response") +// const partialResponse = response +// const errorCodeData = partialResponse.slice(-2) +// const returnCode = errorCodeData[0] * 256 + errorCodeData[1] +// //get public key len (variable) +// const raw_ivk = Buffer.from(partialResponse.slice(0, 32)) +// return { +// raw_ivk, +// returnCode, +// errorMessage: errorCodeToString(returnCode), +// } +// } +// function processNullifierResponse(response: Buffer) { +// console.log("Processing get nullifier response") +// const partialResponse = response +// const errorCodeData = partialResponse.slice(-2) +// const returnCode = errorCodeData[0] * 256 + errorCodeData[1] +// const raw_nf = Buffer.from(partialResponse.slice(0, 32)) +// return { +// raw_nf, +// returnCode, +// errorMessage: errorCodeToString(returnCode), +// } +// } +// function processOutgoingViewingKeyResponse(response: Buffer) { +// console.log("Processing get OVK response") +// const partialResponse = response +// const errorCodeData = partialResponse.slice(-2) +// const returnCode = errorCodeData[0] * 256 + errorCodeData[1] +// //get public key len (variable) +// const raw_ovk = Buffer.from(partialResponse.slice(0, 32)) +// return { +// raw_ovk, +// returnCode, +// errorMessage: errorCodeToString(returnCode), +// } +// } +//# sourceMappingURL=processResponses.js.map \ No newline at end of file diff --git a/packages/ledger-namada/dist/processResponses.js.map b/packages/ledger-namada/dist/processResponses.js.map new file mode 100644 index 0000000000..352dc18da3 --- /dev/null +++ b/packages/ledger-namada/dist/processResponses.js.map @@ -0,0 +1 @@ +{"version":3,"file":"processResponses.js","sourceRoot":"","sources":["../src/processResponses.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;mFAcmF;;;AAEnF,qCAA4C;AAC5C,qCAA2D;AAG3D,SAAgB,2BAA2B,CAAC,QAAgB;IAC1D,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAA;IAEhD,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAC,iBAAQ,CAAC,CAAC,CAAA;IACpE,MAAM,IAAI,iBAAQ,CAAA;IAClB,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAC,CAAC,CAAC,GAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAC,CAAC,CAAC,GAAC,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAC,CAAC,CAAC,GAAC,SAAS,CAAA;IACzH,MAAM,IAAI,CAAC,CAAA;IACX,MAAM,MAAM,GAAG,EAAE,CAAA;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAG,EAAE;QACnC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAC,iBAAQ,CAAC,CAAC,CAAC,CAAA;QACpE,MAAM,IAAI,iBAAQ,CAAA;KACnB;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAY,GAAC,CAAC,CAAC,CAAC,CAAA;IAC9E,MAAM,IAAI,qBAAY,GAAC,CAAC,CAAA;IACxB,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IACrC,MAAM,IAAI,CAAC,CAAA;IACX,IAAI,SAAS,GAAG,IAAI,CAAA;IACpB,IAAG,YAAY,EAAE;QACf,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,CAAA;QAC/D,MAAM,IAAI,EAAE,CAAA;KACb;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;IAErD,OAAO;QACL,IAAI;QACJ,MAAM;QACN,MAAM;QACN,SAAS;QACT,GAAG;KACJ,CAAA;AACH,CAAC;AA/BD,kEA+BC;AAED,SAAgB,sBAAsB,CAAC,QAAgB;IACrD,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAA;IAE9C,IAAI,eAAe,GAAG,QAAQ,CAAA;IAE9B,MAAM,aAAa,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAClD,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;IAE5D,+BAA+B;IAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAY,CAAC,CAAC,CAAA;IAErE,kBAAkB;IAClB,eAAe,GAAG,eAAe,CAAC,KAAK,CAAC,qBAAY,CAAC,CAAA;IAErD,2DAA2D;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAEzD,OAAO;QACL,SAAS;QACT,OAAO;QACP,UAAU;QACV,YAAY,EAAE,IAAA,0BAAiB,EAAC,UAAU,CAAC;KAC5C,CAAA;AACH,CAAC;AAvBD,wDAuBC;AAED,eAAe;AACf,8DAA8D;AAC9D,mDAAmD;AAEnD,mCAAmC;AAEnC,oDAAoD;AACpD,iEAAiE;AAEjE,oCAAoC;AACpC,8DAA8D;AAE9D,uBAAuB;AACvB,gDAAgD;AAEhD,6CAA6C;AAC7C,2CAA2C;AAE3C,uBAAuB;AACvB,+CAA+C;AAE/C,wDAAwD;AACxD,4EAA4E;AAE5E,aAAa;AACb,eAAe;AACf,mBAAmB;AACnB,oBAAoB;AACpB,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI;AAEJ,iEAAiE;AACjE,+CAA+C;AAE/C,qCAAqC;AAErC,oDAAoD;AACpD,iEAAiE;AAEjE,oCAAoC;AACpC,8DAA8D;AAE9D,aAAa;AACb,eAAe;AACf,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI;AAEJ,wDAAwD;AACxD,qDAAqD;AAErD,qCAAqC;AAErC,oDAAoD;AACpD,iEAAiE;AAEjE,6DAA6D;AAE7D,aAAa;AACb,cAAc;AACd,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI;AAEJ,iEAAiE;AACjE,+CAA+C;AAE/C,qCAAqC;AAErC,oDAAoD;AACpD,iEAAiE;AAEjE,oCAAoC;AACpC,8DAA8D;AAE9D,aAAa;AACb,eAAe;AACf,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI","sourcesContent":["/** ******************************************************************************\n * (c) 2018 - 2022 Zondax AG\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n ******************************************************************************* */\n\nimport { errorCodeToString } from './common'\nimport { HASH_LEN, PK_LEN_25519, SALT_LEN } from './config'\nimport { ISignature } from './types'\n\nexport function processGetSignatureResponse(response: Buffer): ISignature {\n console.log('Processing get signature response')\n\n let offset = 0\n const salt = Buffer.from(response.subarray(offset, offset+SALT_LEN))\n offset += SALT_LEN\n const hashesLen = response[offset] + response[offset+1]*0x100 + response[offset+2]*0x10000 + response[offset+3]*0x1000000\n offset += 4\n const hashes = []\n for (let i = 0; i < hashesLen; i ++) {\n hashes.push(Buffer.from(response.subarray(offset, offset+HASH_LEN)))\n offset += HASH_LEN\n }\n const pubkey = Buffer.from(response.subarray(offset, offset + PK_LEN_25519+1))\n offset += PK_LEN_25519+1\n const hasSignature = response[offset]\n offset += 1\n let signature = null\n if(hasSignature) {\n signature = Buffer.from(response.subarray(offset, offset + 65))\n offset += 65\n }\n const raw = Buffer.from(response.subarray(0, offset))\n\n return {\n salt,\n hashes,\n pubkey,\n signature,\n raw,\n }\n}\n\nexport function processGetAddrResponse(response: Buffer) {\n console.log('Processing get address response')\n\n let partialResponse = response\n\n const errorCodeData = partialResponse.subarray(-2)\n const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n //get public key len (variable)\n const publicKey = Buffer.from(partialResponse.slice(0, PK_LEN_25519))\n\n //\"advance\" buffer\n partialResponse = partialResponse.slice(PK_LEN_25519)\n\n // get the implicit address corresponding to the public key\n const address = Buffer.from(partialResponse.slice(0, -2))\n\n return {\n publicKey,\n address,\n returnCode,\n errorMessage: errorCodeToString(returnCode),\n }\n}\n\n// Not used yet\n// function processGetShieldedAddrResponse(response: Buffer) {\n// console.log(\"Processing get address response\")\n\n// let partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// //get public key len (variable)\n// const raw_pkd = Buffer.from(partialResponse.slice(0, 32))\n\n// //\"advance\" buffer\n// partialResponse = partialResponse.slice(32)\n\n// // get the length of the bech32m address\n// const bech32m_len = partialResponse[0]\n\n// //\"advance\" buffer\n// partialResponse = partialResponse.slice(1)\n\n// // get the bech32m encoding of the shielded address\n// const bech32m_addr = Buffer.from(partialResponse.slice(0, bech32m_len))\n\n// return {\n// raw_pkd,\n// bech32m_len,\n// bech32m_addr,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n\n// function processIncomingViewingKeyResponse(response: Buffer) {\n// console.log(\"Processing get IVK response\")\n\n// const partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// //get public key len (variable)\n// const raw_ivk = Buffer.from(partialResponse.slice(0, 32))\n\n// return {\n// raw_ivk,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n\n// function processNullifierResponse(response: Buffer) {\n// console.log(\"Processing get nullifier response\")\n\n// const partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// const raw_nf = Buffer.from(partialResponse.slice(0, 32))\n\n// return {\n// raw_nf,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n\n// function processOutgoingViewingKeyResponse(response: Buffer) {\n// console.log(\"Processing get OVK response\")\n\n// const partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// //get public key len (variable)\n// const raw_ovk = Buffer.from(partialResponse.slice(0, 32))\n\n// return {\n// raw_ovk,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n"]} \ No newline at end of file diff --git a/packages/ledger-namada/dist/types.d.ts b/packages/ledger-namada/dist/types.d.ts new file mode 100644 index 0000000000..aab75bd60f --- /dev/null +++ b/packages/ledger-namada/dist/types.d.ts @@ -0,0 +1,68 @@ +/// +import { LedgerError } from './common'; +export interface ResponseBase { + errorMessage: string; + returnCode: LedgerError; +} +export interface ResponseAddress extends ResponseBase { + publicKey: Buffer; + address: Buffer; +} +export interface ResponseVersion extends ResponseBase { + testMode: boolean; + major: number; + minor: number; + patch: number; + deviceLocked: boolean; + targetId: string; +} +export interface ResponseAppInfo extends ResponseBase { + appName: string; + appVersion: string; + flagLen: number; + flagsValue: number; + flagRecovery: boolean; + flagSignedMcuCode: boolean; + flagOnboarded: boolean; + flagPINValidated: boolean; +} +export interface ResponseDeviceInfo extends ResponseBase { + targetId: string; + seVersion: string; + flag: string; + mcuVersion: string; +} +export interface ResponseShieldedAddress extends ResponseBase { + raw_pkd: Buffer; + bech32m_len: number; + bech32m_addr: Buffer; +} +export interface ResponseIncomingViewingKey extends ResponseBase { + raw_ivk: Buffer; +} +export interface ResponseOutgoingViewingKey extends ResponseBase { + raw_ovk: Buffer; +} +export interface ResponseNullifier extends ResponseBase { + raw_nf: Buffer; +} +export interface ISignature { + raw: Buffer; + salt: Buffer; + hashes: Buffer[]; + pubkey: Buffer; + signature: Buffer | null; +} +export declare class Signature implements ISignature { + raw: Buffer; + salt: Buffer; + hashes: Buffer[]; + pubkey: Buffer; + signature: Buffer | null; + isFilled: boolean; + constructor(signature?: ISignature); +} +export interface ResponseSign extends ResponseBase { + wrapperSignature: Signature; + rawSignature: Signature; +} diff --git a/packages/ledger-namada/dist/types.js b/packages/ledger-namada/dist/types.js new file mode 100644 index 0000000000..e5d79875b4 --- /dev/null +++ b/packages/ledger-namada/dist/types.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Signature = void 0; +class Signature { + constructor(signature) { + if (signature == null) { + this.raw = Buffer.from([]); + this.isFilled = false; + this.salt = Buffer.from([]); + this.hashes = []; + this.pubkey = Buffer.from([]); + this.signature = null; + } + else { + this.isFilled = true; + this.raw = signature.raw; + this.salt = signature.salt; + this.hashes = signature.hashes; + this.pubkey = signature.pubkey; + this.signature = signature.signature; + } + } +} +exports.Signature = Signature; +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/packages/ledger-namada/dist/types.js.map b/packages/ledger-namada/dist/types.js.map new file mode 100644 index 0000000000..4e62f9cad1 --- /dev/null +++ b/packages/ledger-namada/dist/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAgEA,MAAa,SAAS;IASpB,YAAY,SAAsB;QAChC,IAAI,SAAS,IAAI,IAAI,EAAE;YACrB,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC1B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;YACrB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC3B,IAAI,CAAC,MAAM,GAAG,EAAE,CAAA;YAChB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;SACtB;aAAM;YACL,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;YACpB,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,CAAA;YACxB,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAA;YAC1B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAA;YAC9B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAA;YAC9B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAA;SACrC;IACH,CAAC;CACF;AA1BD,8BA0BC","sourcesContent":["import { LedgerError } from './common'\n\nexport interface ResponseBase {\n errorMessage: string\n returnCode: LedgerError\n}\n\nexport interface ResponseAddress extends ResponseBase {\n publicKey: Buffer\n address: Buffer\n}\n\nexport interface ResponseVersion extends ResponseBase {\n testMode: boolean\n major: number\n minor: number\n patch: number\n deviceLocked: boolean\n targetId: string\n}\n\nexport interface ResponseAppInfo extends ResponseBase {\n appName: string\n appVersion: string\n flagLen: number\n flagsValue: number\n flagRecovery: boolean\n flagSignedMcuCode: boolean\n flagOnboarded: boolean\n flagPINValidated: boolean\n}\n\nexport interface ResponseDeviceInfo extends ResponseBase {\n targetId: string\n seVersion: string\n flag: string\n mcuVersion: string\n}\n\nexport interface ResponseShieldedAddress extends ResponseBase {\n raw_pkd: Buffer\n bech32m_len: number\n bech32m_addr: Buffer\n}\n\nexport interface ResponseIncomingViewingKey extends ResponseBase {\n raw_ivk: Buffer\n}\n\nexport interface ResponseOutgoingViewingKey extends ResponseBase {\n raw_ovk: Buffer\n}\n\nexport interface ResponseNullifier extends ResponseBase {\n raw_nf: Buffer\n}\n\nexport interface ISignature {\n raw: Buffer\n salt: Buffer\n hashes: Buffer[]\n pubkey: Buffer\n signature: Buffer | null\n}\nexport class Signature implements ISignature {\n raw: Buffer\n salt: Buffer\n hashes: Buffer[]\n pubkey: Buffer\n signature: Buffer | null\n\n isFilled: boolean\n\n constructor(signature?: ISignature) {\n if (signature == null) {\n this.raw = Buffer.from([])\n this.isFilled = false\n this.salt = Buffer.from([])\n this.hashes = []\n this.pubkey = Buffer.from([])\n this.signature = null\n } else {\n this.isFilled = true\n this.raw = signature.raw\n this.salt = signature.salt\n this.hashes = signature.hashes\n this.pubkey = signature.pubkey\n this.signature = signature.signature\n }\n }\n}\n\nexport interface ResponseSign extends ResponseBase {\n wrapperSignature: Signature\n rawSignature: Signature\n}\n"]} \ No newline at end of file diff --git a/packages/ledger-namada/package.json b/packages/ledger-namada/package.json new file mode 100644 index 0000000000..b55ea7ac97 --- /dev/null +++ b/packages/ledger-namada/package.json @@ -0,0 +1,78 @@ +{ + "name": "@namada/ledger-namada", + "author": "Zondax AG", + "license": "Apache-2.0", + "version": "0.0.1", + "description": "Node API for the Namada App (Ledger Nano S/X/S+)", + "main": "./dist/index.js", + "private": false, + "typings": "./dist/index.d.ts", + "types": "./dist/index.d.ts", + "homepage": "https://github.com/zondax/ledger-namada", + "repository": { + "type": "git", + "url": "git+https://github.com/zondax/ledger-namada.git" + }, + "keywords": [ + "Zondax", + "Ledger", + "Javascript", + "Namada" + ], + "scripts": { + "build": "tsc", + "copy-files": "copyfiles -u 0 src/**/*.proto dist/", + "test:integration": "yarn build && jest -t 'Integration'", + "test:key-derivation": "yarn build && jest -t 'KeyDerivation'", + "supported": "ts-node src/cmd/cli.ts supported", + "linter": "eslint --max-warnings 0 .", + "linter:fix": "yarn linter --fix", + "format": "prettier -w ." + }, + "bugs": { + "url": "https://github.com/zondax/ledger-namada/issues" + }, + "dependencies": { + "@ledgerhq/hw-transport": "^6.28.2" + }, + "devDependencies": { + "@types/ledgerhq__hw-transport": "^4.21.4", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "bip32": "^4.0.0", + "bip39": "^3.1.0", + "core-js": "^3.30.1", + "crypto-js": "4.1.1", + "eslint": "^8.40.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jest": "^27.2.1", + "eslint-plugin-prettier": "^4.0.0", + "jest": "^29.5.0", + "leb128": "^0.0.5", + "prettier": "^2.8.8", + "secp256k1": "^5.0.0", + "typescript": "^5.0.4" + }, + "moduleDirectories": [ + "node_modules", + "dist" + ], + "postcss": { + "plugins": { + "autoprefixer": {} + } + }, + "browserslist": [ + "> 1%", + "last 2 versions" + ], + "files": [ + "dist/*", + "LICENSE", + "yarn.lock" + ], + "publishConfig": { + "access": "public" + } +} diff --git a/packages/shared/lib/src/query.rs b/packages/shared/lib/src/query.rs index 33bc13187a..111f4d3a01 100644 --- a/packages/shared/lib/src/query.rs +++ b/packages/shared/lib/src/query.rs @@ -1,11 +1,13 @@ use masp_primitives::{transaction::components::Amount, zip32::ExtendedFullViewingKey}; use namada::ledger::masp::ShieldedContext; use namada::ledger::queries::RPC; -use namada::ledger::rpc::get_token_balance; -use namada::types::address::Address; -use namada::types::masp::ExtendedViewingKey; -use namada::types::token::{self, TokenAddress}; -use namada::types::uint::I256; +use namada::ledger::rpc::{get_public_key, get_token_balance}; +use namada::types::{ + address::Address, + masp::ExtendedViewingKey, + token::{self, TokenAddress}, + uint::I256, +}; use std::collections::{HashMap, HashSet}; use std::str::FromStr; use wasm_bindgen::prelude::*; @@ -212,4 +214,16 @@ impl Query { to_js_result(result) } + + pub async fn query_public_key(&self, address: &str) -> Result { + let addr = Address::from_str(address).map_err(JsError::from)?; + let pk = get_public_key(&self.client, &addr).await; + + let result = match pk { + Some(v) => Some(v.to_string()), + None => None, + }; + + to_js_result(result) + } } diff --git a/packages/shared/lib/src/sdk/mod.rs b/packages/shared/lib/src/sdk/mod.rs index e1ee893674..f970e7c904 100644 --- a/packages/shared/lib/src/sdk/mod.rs +++ b/packages/shared/lib/src/sdk/mod.rs @@ -4,7 +4,7 @@ use crate::{ sdk::masp::WebShieldedUtils, utils::{set_panic_hook, to_bytes}, }; -use borsh::BorshSerialize; +use borsh::{BorshDeserialize, BorshSerialize}; use namada::{ ledger::{ args, @@ -13,15 +13,22 @@ use namada::{ wallet::{Store, Wallet}, }, proto::{Section, Signature, Tx}, - types::{key::common::PublicKey, key::common::SecretKey as SK, key::ed25519::SecretKey}, + types::key::common::PublicKey, }; -use std::str::FromStr; use wasm_bindgen::{prelude::wasm_bindgen, JsError, JsValue}; pub mod masp; mod tx; mod wallet; +// Require that a public key is present +fn validate_pk(pk: Option) -> Result { + match pk { + Some(v) => Ok(v), + None => Err(JsError::new("No public key was provided!")), + } +} + /// Represents the Sdk public API. #[wasm_bindgen] pub struct Sdk { @@ -113,7 +120,7 @@ impl Sdk { .await?; // Sign and submit reveal pk - if let Some((mut rtx, _, pk)) = reveal_pk { + if let Some((mut rtx, _, _)) = reveal_pk { // Sign the reveal public key transaction with the fee payer signing::sign_tx(&mut self.wallet, &mut rtx, &args, &pk).await?; // Submit the reveal public key transaction first @@ -149,6 +156,46 @@ impl Sdk { Ok(()) } + /// Contruct reveal pk data for external signers, returns byte array + pub async fn build_reveal_pk(&mut self, tx_msg: &[u8]) -> Result { + let args = tx::reveal_pk_tx_args(tx_msg)?; + + let reveal_pk = namada::ledger::tx::build_reveal_pk( + &self.client, + &mut self.wallet, + args::RevealPk { + tx: args.tx.clone(), + public_key: args.public_key.clone(), + }, + ) + .await?; + + let bytes = match reveal_pk { + Some(v) => v.0.try_to_vec().map_err(JsError::from)?, + None => vec![], + }; + + to_js_result(bytes) + } + + /// Submit signed reveal pk tx + pub async fn submit_signed_reveal_pk( + &mut self, + tx_msg: &[u8], + tx_bytes: &[u8], + wrapper_sig_bytes: &[u8], + raw_sig_bytes: &[u8], + ) -> Result<(), JsError> { + let reveal_pk_tx = self.sign_tx(tx_bytes, wrapper_sig_bytes, raw_sig_bytes)?; + let args = tx::reveal_pk_tx_args(tx_msg).map_err(JsError::from)?; + + namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, reveal_pk_tx) + .await + .map_err(JsError::from)?; + + Ok(()) + } + /// Contruct transfer data for external signers, returns byte array pub async fn build_transfer(&mut self, tx_msg: &[u8]) -> Result { let args = tx::transfer_tx_args(tx_msg, None, None)?; @@ -167,45 +214,63 @@ impl Sdk { to_js_result(bytes) } + /// Contruct bond data for external signers, returns byte array + pub async fn build_bond(&mut self, tx_msg: &[u8]) -> Result { + let args = tx::bond_tx_args(tx_msg, None)?; + + let bond = namada::ledger::tx::build_bond(&self.client, &mut self.wallet, args.clone()) + .await + .map_err(JsError::from)?; + + let bytes = bond.0.try_to_vec().map_err(JsError::from)?; + + to_js_result(bytes) + } + + /// Contruct unbond data for external signers, returns byte array + pub async fn build_unbond(&mut self, tx_msg: &[u8]) -> Result { + let args = tx::unbond_tx_args(tx_msg, None)?; + + let unbond = namada::ledger::tx::build_unbond(&self.client, &mut self.wallet, args.clone()) + .await + .map_err(JsError::from)?; + + let bytes = unbond.0.try_to_vec().map_err(JsError::from)?; + + to_js_result(bytes) + } + // Append signatures and return tx bytes - pub fn sign_tx( + fn sign_tx( &self, tx_bytes: &[u8], - data_key: String, - header_key: String, - ) -> Result { - let mut tx: Tx = Tx::try_from(tx_bytes).map_err(JsError::from)?; - let data_secret = SecretKey::from_str(&data_key).map_err(JsError::from)?; - let header_secret = SecretKey::from_str(&header_key).map_err(JsError::from)?; - - // Sign over the transaction data - tx.add_section(Section::Signature(Signature::new( - vec![*tx.data_sechash(), *tx.code_sechash()], - &SK::Ed25519(data_secret), - ))); + wrapper_sig_bytes: &[u8], + raw_sig_bytes: &[u8], + ) -> Result { + let mut tx: Tx = Tx::try_from_slice(tx_bytes).map_err(JsError::from)?; - tx.protocol_filter(); + let wrapper_sig = Signature::try_from_slice(wrapper_sig_bytes).map_err(JsError::from)?; + let raw_sig = Signature::try_from_slice(raw_sig_bytes).map_err(JsError::from)?; - // Then sign over the bound wrapper - tx.add_section(Section::Signature(Signature::new( - tx.sechashes(), - &SK::Ed25519(header_secret), - ))); + tx.add_section(Section::Signature(raw_sig)); + tx.protocol_filter(); + tx.add_section(Section::Signature(wrapper_sig)); - let bytes = tx.try_to_vec().map_err(|e| JsError::from(e))?; - to_js_result(Vec::from(bytes)) + Ok(tx) } /// Submit signed transfer tx pub async fn submit_signed_transfer( &mut self, - pk: String, tx_msg: &[u8], tx_bytes: &[u8], + wrapper_sig_bytes: &[u8], + raw_sig_bytes: &[u8], ) -> Result<(), JsError> { - let transfer_tx = Tx::try_from(tx_bytes).map_err(|e| JsError::from(e))?; - let args = tx::transfer_tx_args(tx_msg, None, None).map_err(|e| JsError::from(e))?; - let pk = PublicKey::from_str(&pk).map_err(JsError::from)?; + let transfer_tx = self.sign_tx(tx_bytes, wrapper_sig_bytes, raw_sig_bytes)?; + let args = tx::transfer_tx_args(tx_msg, None, None).map_err(JsError::from)?; + let verification_key = args.tx.verification_key.clone(); + let pk = validate_pk(verification_key)?; self.submit_reveal_pk(&args.tx, transfer_tx.clone(), &pk) .await?; @@ -272,6 +337,25 @@ impl Sdk { Ok(()) } + /// Submit signed bond + pub async fn submit_signed_bond( + &mut self, + tx_msg: &[u8], + tx_bytes: &[u8], + wrapper_sig_bytes: &[u8], + raw_sig_bytes: &[u8], + ) -> Result<(), JsError> { + let bond_tx = self.sign_tx(tx_bytes, wrapper_sig_bytes, raw_sig_bytes)?; + let args = tx::bond_tx_args(tx_msg, None).map_err(JsError::from)?; + + namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, bond_tx) + .await + .map_err(JsError::from)?; + + Ok(()) + } + + /// Submit unbond pub async fn submit_unbond( &mut self, tx_msg: &[u8], @@ -288,6 +372,29 @@ impl Sdk { Ok(()) } + + /// Submit signed unbond tx + pub async fn submit_signed_unbond( + &mut self, + tx_msg: &[u8], + tx_bytes: &[u8], + wrapper_sig_bytes: &[u8], + raw_sig_bytes: &[u8], + ) -> Result<(), JsError> { + let bond_tx = self.sign_tx(tx_bytes, wrapper_sig_bytes, raw_sig_bytes)?; + let args = tx::unbond_tx_args(tx_msg, None).map_err(JsError::from)?; + let verification_key = args.tx.verification_key.clone(); + let pk = validate_pk(verification_key)?; + + self.submit_reveal_pk(&args.tx, bond_tx.clone(), &pk) + .await?; + + namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, bond_tx) + .await + .map_err(JsError::from)?; + + Ok(()) + } } #[wasm_bindgen(module = "/src/sdk/mod.js")] diff --git a/packages/shared/lib/src/sdk/tx.rs b/packages/shared/lib/src/sdk/tx.rs index 935d0e91d0..e887aaf799 100644 --- a/packages/shared/lib/src/sdk/tx.rs +++ b/packages/shared/lib/src/sdk/tx.rs @@ -34,6 +34,35 @@ pub struct SubmitBondMsg { tx: TxMsg, } +#[derive(BorshSerialize, BorshDeserialize)] +pub struct SubmitRevealPKMsg { + tx: TxMsg, + public_key: String, +} + +/// Maps serialized tx_msg into RevealPk args +/// +/// # Arguments +/// +/// * `tx_msg` - Borsh serialized tx_msg. +/// +/// # Errors +/// +/// Returns JsError if the tx_msg can't be deserialized or +/// Rust structs can't be created. +pub fn reveal_pk_tx_args(tx_msg: &[u8]) -> Result { + let tx_msg = SubmitRevealPKMsg::try_from_slice(tx_msg)?; + let SubmitRevealPKMsg { tx, public_key } = tx_msg; + let public_key = PK::Ed25519(PublicKey::from_str(&public_key).map_err(JsError::from)?); + + let args = args::RevealPk { + tx: tx_msg_into_args(tx, None)?, + public_key, + }; + + Ok(args) +} + /// Maps serialized tx_msg into BondTx args. /// /// # Arguments diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index af68f75bf1..9e1f4f0eba 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -8,7 +8,7 @@ type TimeoutOpts = { error?: string; }; -const DEFAULT_TIMEOUT = 5000; +const DEFAULT_TIMEOUT = 60000; const DEFAULT_OPTS: TimeoutOpts = { timeout: DEFAULT_TIMEOUT, @@ -23,19 +23,19 @@ const promiseWithTimeout = fn: (...args: U) => Promise, opts?: TimeoutOpts ) => - (...args: U): Promise => { - const { timeout, error } = { ...DEFAULT_OPTS, ...opts }; + (...args: U): Promise => { + const { timeout, error } = { ...DEFAULT_OPTS, ...opts }; - return new Promise(async (resolve, reject) => { - const t = setTimeout(() => { - reject(error); - }, timeout); + return new Promise(async (resolve, reject) => { + const t = setTimeout(() => { + reject(error); + }, timeout); - const res = await fn(...args); - clearTimeout(t); - resolve(res); - }); - }; + const res = await fn(...args); + clearTimeout(t); + resolve(res); + }); + }; export class Query extends RustQuery { query_balance = promiseWithTimeout(super.query_balance.bind(this), { diff --git a/packages/types/src/account.ts b/packages/types/src/account.ts index 223e6cd121..23628284d3 100644 --- a/packages/types/src/account.ts +++ b/packages/types/src/account.ts @@ -12,18 +12,25 @@ export enum AccountType { PrivateKey = "private-key", // Stored, stringified spending and viewing keys ShieldedKeys = "shielded-keys", + // Ledger account + Ledger = "ledger", } export type DerivedAccount = { id: string; chainId: string; address: string; + owner?: string; + publicKey?: string; alias: string; parentId?: string; path: Bip44Path; type: AccountType; }; -export type Account = Pick & { +export type Account = Pick< + DerivedAccount, + "address" | "alias" | "chainId" | "type" | "publicKey" +> & { isShielded: boolean; }; diff --git a/packages/types/src/events.ts b/packages/types/src/events.ts index 482c6ff477..2ebc3ffae3 100644 --- a/packages/types/src/events.ts +++ b/packages/types/src/events.ts @@ -6,6 +6,7 @@ export enum Events { TransferStarted = "namada-transfer-started", TransferCompleted = "namada-transfer-completed", UpdatedBalances = "namada-updated-balances", + UpdatedStaking = "namada-updated-staking", } // Keplr extension events diff --git a/packages/types/src/namada.ts b/packages/types/src/namada.ts index db47aaf323..e36c3cbd0d 100644 --- a/packages/types/src/namada.ts +++ b/packages/types/src/namada.ts @@ -1,4 +1,4 @@ -import { DerivedAccount } from "./account"; +import { AccountType, DerivedAccount } from "./account"; import { Chain } from "./chain"; import { Signer } from "./signer"; @@ -11,9 +11,16 @@ export interface Namada { suggestChain(chainConfig: Chain): Promise; chain: (chainId: string) => Promise; chains: () => Promise; - submitBond: (txMsg: string) => Promise; + submitBond: (props: { + txMsg: string; + type: AccountType; + publicKey?: string; + }) => Promise; submitUnbond: (txMsg: string) => Promise; - submitTransfer: (txMsg: string) => Promise; + submitTransfer: (props: { + txMsg: string; + type: AccountType; + }) => Promise; submitIbcTransfer: (txMsg: string) => Promise; encodeInitAccount: (props: { txMsg: string; diff --git a/packages/types/src/signer.ts b/packages/types/src/signer.ts index 163061072f..90f5b21037 100644 --- a/packages/types/src/signer.ts +++ b/packages/types/src/signer.ts @@ -1,4 +1,4 @@ -import { Account } from "./account"; +import { Account, AccountType } from "./account"; import { IbcTransferProps, InitAccountProps, @@ -9,9 +9,13 @@ import { export interface Signer { accounts: () => Promise; - submitBond(args: SubmitBondProps): Promise; + submitBond( + args: SubmitBondProps, + type: AccountType, + publicKey?: string + ): Promise; submitUnbond(args: SubmitUnbondProps): Promise; - submitTransfer(args: TransferProps): Promise; + submitTransfer(args: TransferProps, type: AccountType): Promise; submitIbcTransfer(args: IbcTransferProps): Promise; encodeInitAccount( args: InitAccountProps, diff --git a/packages/types/src/tx/schema/index.ts b/packages/types/src/tx/schema/index.ts index 65c1b1bf35..d66a77dc67 100644 --- a/packages/types/src/tx/schema/index.ts +++ b/packages/types/src/tx/schema/index.ts @@ -2,6 +2,7 @@ export * from "./account"; export * from "./ibcTransfer"; export * from "./transfer"; export * from "./bond"; +export * from "./revealPK"; export * from "./unbond"; import { AccountMsgValue } from "./account"; @@ -9,10 +10,12 @@ import { IbcTransferMsgValue } from "./ibcTransfer"; import { TransferMsgValue } from "./transfer"; import { SubmitBondMsgValue } from "./bond"; import { SubmitUnbondMsgValue } from "./unbond"; +import { SubmitRevealPKMsgValue } from "./revealPK"; export type Schema = | AccountMsgValue | IbcTransferMsgValue | TransferMsgValue | SubmitBondMsgValue - | SubmitUnbondMsgValue; + | SubmitUnbondMsgValue + | SubmitRevealPKMsgValue; diff --git a/packages/types/src/tx/schema/revealPK.ts b/packages/types/src/tx/schema/revealPK.ts new file mode 100644 index 0000000000..902d9b7c06 --- /dev/null +++ b/packages/types/src/tx/schema/revealPK.ts @@ -0,0 +1,17 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { field } from "@dao-xyz/borsh"; +import { TxMsgValue } from "./tx"; +import { RevealPKProps } from "../types"; + +export class SubmitRevealPKMsgValue { + @field({ type: TxMsgValue }) + tx!: InstanceType; + + @field({ type: "string" }) + publicKey!: string; + + constructor(data: RevealPKProps) { + Object.assign(this, data); + this.tx = new TxMsgValue(data.tx); + } +} diff --git a/packages/types/src/tx/types.ts b/packages/types/src/tx/types.ts index a97304db1a..1312c3d29c 100644 --- a/packages/types/src/tx/types.ts +++ b/packages/types/src/tx/types.ts @@ -23,6 +23,11 @@ export type TxProps = { publicKey?: string; }; +export type RevealPKProps = { + publicKey: string; + tx: TxProps; +}; + export type TransferProps = { tx: TxProps; source: string; diff --git a/packages/utils/src/helpers/index.ts b/packages/utils/src/helpers/index.ts index e6ea41efa3..2bb3cf8c90 100644 --- a/packages/utils/src/helpers/index.ts +++ b/packages/utils/src/helpers/index.ts @@ -1,7 +1,11 @@ import { JsonRpcRequest } from "@cosmjs/json-rpc"; import { DateTime } from "luxon"; -import { JsonCompatibleArray, JsonCompatibleDictionary } from "@namada/types"; import BigNumber from "bignumber.js"; +import { + Bip44Path, + JsonCompatibleArray, + JsonCompatibleDictionary, +} from "@namada/types"; const MICRO_FACTOR = 1000000; // 1,000,000 @@ -172,3 +176,48 @@ export const Result = { return { ok: false as const, error }; }, }; + +/** + * Return a properly formatted BIP-044 path + * + * @param {number} coinType - SLIP-044 Coin designation + * @param {Bip44Path} bip44Path - path object + * @returns {string} + */ +export const makeBip44Path = ( + coinType: number, + bip44Path: Bip44Path +): string => { + const { account, change, index } = bip44Path; + const basePath = `m/44'/${coinType}'/${account}'/${change}`; + + return typeof index === "number" ? `${basePath}/${index}` : basePath; +}; + +/** + * Pick object parameters + */ +export function pick(obj: T, ...keys: K[]): Pick { + return keys.reduce((acc, val) => { + return (acc[val] = obj[val]), acc; + }, {} as Pick); +} + +/** + * Format url with query string params using an object + * + * @param {string} url + * @param {object} params + * @returns {string} + */ +export function paramsToUrl( + url: string, + params: Record +): string { + const queryString = new URLSearchParams(params).toString(); + + if (queryString) { + return `${url}?${queryString}`; + } + return url; +} diff --git a/yarn.lock b/yarn.lock index 878344e589..edabf01f2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + "@ampproject/remapping@^2.1.0": version "2.1.2" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" @@ -2866,6 +2871,18 @@ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924" integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw== +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" + integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== + "@eslint/eslintrc@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.1.tgz#8b5e1c49f4077235516bc9ec7d41378c0f69b8c6" @@ -2941,6 +2958,26 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@eslint/eslintrc@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.0.tgz#82256f164cc9e0b59669efc19d57f8092706841d" + integrity sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.44.0.tgz#961a5903c74139390478bdc808bcde3fc45ab7af" + integrity sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw== + "@humanwhocodes/config-array@^0.10.4": version "0.10.4" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.4.tgz#01e7366e57d2ad104feea63e72248f22015c520c" @@ -2959,6 +2996,15 @@ debug "^4.1.1" minimatch "^3.0.4" +"@humanwhocodes/config-array@^0.11.10": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + "@humanwhocodes/config-array@^0.11.6": version "0.11.7" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.7.tgz#38aec044c6c828f6ed51d5d7ae3d9b9faf6dbb0f" @@ -3122,6 +3168,18 @@ jest-util "^29.4.1" slash "^3.0.0" +"@jest/console@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.6.1.tgz#b48ba7b9c34b51483e6d590f46e5837f1ab5f639" + integrity sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q== + dependencies: + "@jest/types" "^29.6.1" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.6.1" + jest-util "^29.6.1" + slash "^3.0.0" + "@jest/core@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" @@ -3327,6 +3385,40 @@ slash "^3.0.0" strip-ansi "^6.0.0" +"@jest/core@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.6.1.tgz#fac0d9ddf320490c93356ba201451825231e95f6" + integrity sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ== + dependencies: + "@jest/console" "^29.6.1" + "@jest/reporters" "^29.6.1" + "@jest/test-result" "^29.6.1" + "@jest/transform" "^29.6.1" + "@jest/types" "^29.6.1" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.5.0" + jest-config "^29.6.1" + jest-haste-map "^29.6.1" + jest-message-util "^29.6.1" + jest-regex-util "^29.4.3" + jest-resolve "^29.6.1" + jest-resolve-dependencies "^29.6.1" + jest-runner "^29.6.1" + jest-runtime "^29.6.1" + jest-snapshot "^29.6.1" + jest-util "^29.6.1" + jest-validate "^29.6.1" + jest-watcher "^29.6.1" + micromatch "^4.0.4" + pretty-format "^29.6.1" + slash "^3.0.0" + strip-ansi "^6.0.0" + "@jest/environment@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" @@ -3397,6 +3489,16 @@ "@types/node" "*" jest-mock "^29.4.1" +"@jest/environment@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.6.1.tgz#ee358fff2f68168394b4a50f18c68278a21fe82f" + integrity sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A== + dependencies: + "@jest/fake-timers" "^29.6.1" + "@jest/types" "^29.6.1" + "@types/node" "*" + jest-mock "^29.6.1" + "@jest/expect-utils@^28.1.3": version "28.1.3" resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.3.tgz#58561ce5db7cd253a7edddbc051fb39dda50f525" @@ -3432,6 +3534,13 @@ dependencies: jest-get-type "^29.2.0" +"@jest/expect-utils@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.6.1.tgz#ab83b27a15cdd203fe5f68230ea22767d5c3acc5" + integrity sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw== + dependencies: + jest-get-type "^29.4.3" + "@jest/expect@^28.1.3": version "28.1.3" resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-28.1.3.tgz#9ac57e1d4491baca550f6bdbd232487177ad6a72" @@ -3472,6 +3581,14 @@ expect "^29.4.1" jest-snapshot "^29.4.1" +"@jest/expect@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.6.1.tgz#fef18265188f6a97601f1ea0a2912d81a85b4657" + integrity sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg== + dependencies: + expect "^29.6.1" + jest-snapshot "^29.6.1" + "@jest/fake-timers@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" @@ -3556,6 +3673,18 @@ jest-mock "^29.4.1" jest-util "^29.4.1" +"@jest/fake-timers@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.6.1.tgz#c773efddbc61e1d2efcccac008139f621de57c69" + integrity sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg== + dependencies: + "@jest/types" "^29.6.1" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.6.1" + jest-mock "^29.6.1" + jest-util "^29.6.1" + "@jest/globals@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" @@ -3614,6 +3743,16 @@ "@jest/types" "^29.4.1" jest-mock "^29.4.1" +"@jest/globals@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.6.1.tgz#c8a8923e05efd757308082cc22893d82b8aa138f" + integrity sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A== + dependencies: + "@jest/environment" "^29.6.1" + "@jest/expect" "^29.6.1" + "@jest/types" "^29.6.1" + jest-mock "^29.6.1" + "@jest/reporters@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" @@ -3799,6 +3938,36 @@ strip-ansi "^6.0.0" v8-to-istanbul "^9.0.1" +"@jest/reporters@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.6.1.tgz#3325a89c9ead3cf97ad93df3a427549d16179863" + integrity sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.6.1" + "@jest/test-result" "^29.6.1" + "@jest/transform" "^29.6.1" + "@jest/types" "^29.6.1" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^5.1.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.6.1" + jest-util "^29.6.1" + jest-worker "^29.6.1" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + "@jest/schemas@^28.1.3": version "28.1.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-28.1.3.tgz#ad8b86a66f11f33619e3d7e1dcddd7f2d40ff905" @@ -3820,6 +3989,13 @@ dependencies: "@sinclair/typebox" "^0.25.16" +"@jest/schemas@^29.6.0": + version "29.6.0" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.0.tgz#0f4cb2c8e3dca80c135507ba5635a4fd755b0040" + integrity sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ== + dependencies: + "@sinclair/typebox" "^0.27.8" + "@jest/source-map@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" @@ -3856,6 +4032,15 @@ callsites "^3.0.0" graceful-fs "^4.2.9" +"@jest/source-map@^29.6.0": + version "29.6.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.0.tgz#bd34a05b5737cb1a99d43e1957020ac8e5b9ddb1" + integrity sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + "@jest/test-result@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" @@ -3916,6 +4101,16 @@ "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" +"@jest/test-result@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.6.1.tgz#850e565a3f58ee8ca6ec424db00cb0f2d83c36ba" + integrity sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw== + dependencies: + "@jest/console" "^29.6.1" + "@jest/types" "^29.6.1" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + "@jest/test-sequencer@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" @@ -3976,6 +4171,16 @@ jest-haste-map "^29.4.1" slash "^3.0.0" +"@jest/test-sequencer@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz#e3e582ee074dd24ea9687d7d1aaf05ee3a9b068e" + integrity sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg== + dependencies: + "@jest/test-result" "^29.6.1" + graceful-fs "^4.2.9" + jest-haste-map "^29.6.1" + slash "^3.0.0" + "@jest/transform@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409" @@ -4102,6 +4307,27 @@ slash "^3.0.0" write-file-atomic "^5.0.0" +"@jest/transform@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.6.1.tgz#acb5606019a197cb99beda3c05404b851f441c92" + integrity sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.1" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.6.1" + jest-regex-util "^29.4.3" + jest-util "^29.6.1" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + "@jest/types@^24.9.0": version "24.9.0" resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" @@ -4194,6 +4420,18 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" +"@jest/types@^29.6.1": + version "29.6.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.1.tgz#ae79080278acff0a6af5eb49d063385aaa897bf2" + integrity sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw== + dependencies: + "@jest/schemas" "^29.6.0" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" @@ -4203,6 +4441,11 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + "@jridgewell/resolve-uri@^3.0.3": version "3.0.5" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" @@ -4213,6 +4456,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.11" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" @@ -4242,6 +4490,14 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/trace-mapping@^0.3.18": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + "@keplr-wallet/types@^0.10.19": version "0.10.19" resolved "https://registry.yarnpkg.com/@keplr-wallet/types/-/types-0.10.19.tgz#cba3b7eb0012bfde87d5873ded39c3be95719dfc" @@ -4416,6 +4672,11 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== +"@noble/hashes@^1.2.0": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -4594,6 +4855,11 @@ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.1.tgz#782fa5da44c4f38ae9fd38e9184b54e451936118" integrity sha512-BUyKJGdDWqvWC5GEhyOiUrGNi9iJUr4CU0O2WxJL6QJhHeeA/NVBalH+FeK0r/x/W0rPymXt5s78TDS7d6lCwg== +"@scure/base@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" + integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + "@sinclair/typebox@^0.24.1": version "0.24.28" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.28.tgz#15aa0b416f82c268b1573ab653e4413c965fe794" @@ -4604,6 +4870,11 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.21.tgz#763b05a4b472c93a8db29b2c3e359d55b29ce272" integrity sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g== +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + "@sinonjs/commons@^1.7.0": version "1.8.3" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" @@ -5345,6 +5616,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= +"@types/ledgerhq__hw-transport@^4.21.4": + version "4.21.4" + resolved "https://registry.yarnpkg.com/@types/ledgerhq__hw-transport/-/ledgerhq__hw-transport-4.21.4.tgz#3a78a02d2b51d2b0dd8099412d5567d21118225c" + integrity sha512-vep+6yZnGv6owAthIY0w3f72w4dJIb4+yE5PCHveInTlZE9wukvU6Wc5Eig0OUUxcdhTazzeZx1xUaNVLqyQSg== + dependencies: + "@types/node" "*" + "@types/long@^4.0.1": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" @@ -5501,6 +5779,11 @@ dependencies: "@types/node" "*" +"@types/semver@^7.3.12": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + "@types/serve-index@^1.9.1": version "1.9.1" resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" @@ -5700,6 +5983,22 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/eslint-plugin@^5.59.2": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" + tsutils "^3.21.0" + "@typescript-eslint/experimental-utils@^5.0.0": version "5.15.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.15.0.tgz#407bbbdf1d11d24de81cfdf556b3a9f4252ba4ae" @@ -5717,6 +6016,16 @@ "@typescript-eslint/typescript-estree" "5.15.0" debug "^4.3.2" +"@typescript-eslint/parser@^5.59.2": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== + dependencies: + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + debug "^4.3.4" + "@typescript-eslint/scope-manager@5.15.0": version "5.15.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz#d97afab5e0abf4018d1289bd711be21676cdd0ee" @@ -5725,6 +6034,14 @@ "@typescript-eslint/types" "5.15.0" "@typescript-eslint/visitor-keys" "5.15.0" +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + "@typescript-eslint/type-utils@5.15.0": version "5.15.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz#d2c02eb2bdf54d0a645ba3a173ceda78346cf248" @@ -5734,11 +6051,26 @@ debug "^4.3.2" tsutils "^3.21.0" +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== + dependencies: + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" + debug "^4.3.4" + tsutils "^3.21.0" + "@typescript-eslint/types@5.15.0": version "5.15.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.15.0.tgz#c7bdd103843b1abae97b5518219d3e2a0d79a501" integrity sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA== +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== + "@typescript-eslint/typescript-estree@5.15.0": version "5.15.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz#81513a742a9c657587ad1ddbca88e76c6efb0aac" @@ -5752,6 +6084,19 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + "@typescript-eslint/utils@5.15.0", "@typescript-eslint/utils@^5.13.0": version "5.15.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.15.0.tgz#468510a0974d3ced8342f37e6c662778c277f136" @@ -5764,6 +6109,20 @@ eslint-scope "^5.1.1" eslint-utils "^3.0.0" +"@typescript-eslint/utils@5.62.0", "@typescript-eslint/utils@^5.10.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + eslint-scope "^5.1.1" + semver "^7.3.7" + "@typescript-eslint/visitor-keys@5.15.0": version "5.15.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz#5669739fbf516df060f978be6a6dce75855a8027" @@ -5772,6 +6131,14 @@ "@typescript-eslint/types" "5.15.0" eslint-visitor-keys "^3.0.0" +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== + dependencies: + "@typescript-eslint/types" "5.62.0" + eslint-visitor-keys "^3.3.0" + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -5935,13 +6302,6 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -"@zondax/ledger-namada@^0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@zondax/ledger-namada/-/ledger-namada-0.0.2.tgz#17d9fc66c8eb5d1436a8fa6b030732219af3d4c0" - integrity sha512-F/rsDAsOclrIPFbGMDFIxD+1gDbGyIKZXtZ9yJD9DMYA8d7rkWzmGdHo/uxXCnzJDHzsM04BI1tvH0qDhmKuaw== - dependencies: - "@ledgerhq/hw-transport" "^6.28.2" - abab@^2.0.3, abab@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" @@ -6025,6 +6385,11 @@ acorn@^8.8.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== +acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + address@^1.0.1, address@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" @@ -6181,6 +6546,14 @@ aria-query@^5.0.0: resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c" integrity sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg== +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -6202,6 +6575,17 @@ array-includes@^3.1.3, array-includes@^3.1.4: get-intrinsic "^1.1.1" is-string "^1.0.7" +array-includes@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" + is-string "^1.0.7" + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" @@ -6216,6 +6600,16 @@ array.prototype.flat@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" +array.prototype.flat@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" + integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + array.prototype.flatmap@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446" @@ -6225,6 +6619,16 @@ array.prototype.flatmap@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" +array.prototype.flatmap@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -6392,6 +6796,19 @@ babel-jest@^29.4.1: graceful-fs "^4.2.9" slash "^3.0.0" +babel-jest@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.6.1.tgz#a7141ad1ed5ec50238f3cd36127636823111233a" + integrity sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A== + dependencies: + "@jest/transform" "^29.6.1" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.5.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + babel-loader@^8.2.3: version "8.2.3" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" @@ -6486,6 +6903,16 @@ babel-plugin-jest-hoist@^29.4.0: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" +babel-plugin-jest-hoist@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz#a97db437936f441ec196990c9738d4b88538618a" + integrity sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + babel-plugin-macros@^2.0.0: version "2.8.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" @@ -6636,6 +7063,14 @@ babel-preset-jest@^29.4.0: babel-plugin-jest-hoist "^29.4.0" babel-preset-current-node-syntax "^1.0.0" +babel-preset-jest@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz#57bc8cc88097af7ff6a5ab59d1cd29d52a5916e2" + integrity sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg== + dependencies: + babel-plugin-jest-hoist "^29.5.0" + babel-preset-current-node-syntax "^1.0.0" + babel-preset-react-app@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz#ed6005a20a24f2c88521809fa9aea99903751584" @@ -6663,7 +7098,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base-x@^3.0.6: +base-x@^3.0.2, base-x@^3.0.6: version "3.0.9" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== @@ -6720,6 +7155,16 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +bip32@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/bip32/-/bip32-4.0.0.tgz#7fac3c05072188d2d355a4d6596b37188f06aa2f" + integrity sha512-aOGy88DDlVUhspIXJN+dVEtclhIsfAUppD43V0j40cPTld3pv/0X/MlrZSZ6jowIaQQzFwP8M6rFU2z2mVYjDQ== + dependencies: + "@noble/hashes" "^1.2.0" + "@scure/base" "^1.1.1" + typeforce "^1.11.5" + wif "^2.0.6" + bip39@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.4.tgz#5b11fed966840b5e1b8539f0f54ab6392969b2a0" @@ -6730,6 +7175,13 @@ bip39@^3.0.2: pbkdf2 "^3.0.9" randombytes "^2.0.1" +bip39@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.1.0.tgz#c55a418deaf48826a6ceb34ac55b3ee1577e18a3" + integrity sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A== + dependencies: + "@noble/hashes" "^1.2.0" + bluebird@^3.5.1, bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -6923,6 +7375,13 @@ bs-logger@0.x: dependencies: fast-json-stable-stringify "2.x" +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + bs58@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" @@ -6930,6 +7389,15 @@ bs58@^5.0.0: dependencies: base-x "^4.0.0" +bs58check@<3.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -7418,6 +7886,11 @@ core-js@^3.19.2: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== +core-js@^3.30.1: + version "3.31.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.31.1.tgz#f2b0eea9be9da0def2c5fece71064a7e5d687653" + integrity sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ== + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -7551,7 +8024,7 @@ crypto-js@3.1.9-1: resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.9-1.tgz#fda19e761fc077e01ffbfdc6e9fdfc59e8806cd8" integrity sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg= -crypto-js@^4.1.1: +crypto-js@4.1.1, crypto-js@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== @@ -7927,6 +8400,14 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + defined@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" @@ -8036,6 +8517,11 @@ diff-sequences@^29.3.1: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e" integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ== +diff-sequences@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" + integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -8413,11 +8899,67 @@ es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.19.1: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" +es-abstract@^1.20.4: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== + dependencies: + array-buffer-byte-length "^1.0.0" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.0" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + es-module-lexer@^0.9.0: version "0.9.3" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -8488,6 +9030,11 @@ eslint-config-prettier@^8.4.0, eslint-config-prettier@^8.5.0: resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== +eslint-config-prettier@^8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" + integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== + eslint-config-react-app@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-7.0.0.tgz#0fa96d5ec1dfb99c029b1554362ab3fa1c3757df" @@ -8516,6 +9063,15 @@ eslint-import-resolver-node@^0.3.6: debug "^3.2.7" resolve "^1.20.0" +eslint-import-resolver-node@^0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" + integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== + dependencies: + debug "^3.2.7" + is-core-module "^2.11.0" + resolve "^1.22.1" + eslint-import-resolver-typescript@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz#07661966b272d14ba97f597b51e1a588f9722f0a" @@ -8581,6 +9137,13 @@ eslint-module-utils@^2.7.3: dependencies: debug "^3.2.7" +eslint-module-utils@^2.7.4: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" + integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== + dependencies: + debug "^3.2.7" + eslint-plugin-flowtype@^8.0.3: version "8.0.3" resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz#e1557e37118f24734aa3122e7536a038d34a4912" @@ -8627,6 +9190,27 @@ eslint-plugin-import@^2.26.0: resolve "^1.22.0" tsconfig-paths "^3.14.1" +eslint-plugin-import@^2.27.5: + version "2.27.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" + integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + array.prototype.flatmap "^1.3.1" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.7" + eslint-module-utils "^2.7.4" + has "^1.0.3" + is-core-module "^2.11.0" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.values "^1.1.6" + resolve "^1.22.1" + semver "^6.3.0" + tsconfig-paths "^3.14.1" + eslint-plugin-jest@^25.3.0: version "25.7.0" resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz#ff4ac97520b53a96187bad9c9814e7d00de09a6a" @@ -8634,6 +9218,13 @@ eslint-plugin-jest@^25.3.0: dependencies: "@typescript-eslint/experimental-utils" "^5.0.0" +eslint-plugin-jest@^27.2.1: + version "27.2.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz#be4ded5f91905d9ec89aa8968d39c71f3b072c0c" + integrity sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw== + dependencies: + "@typescript-eslint/utils" "^5.10.0" + eslint-plugin-jsx-a11y@^6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8" @@ -8652,6 +9243,13 @@ eslint-plugin-jsx-a11y@^6.5.1: language-tags "^1.0.5" minimatch "^3.0.4" +eslint-plugin-prettier@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== + dependencies: + prettier-linter-helpers "^1.0.0" + eslint-plugin-react-hooks@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172" @@ -8700,6 +9298,14 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-scope@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + eslint-utils@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" @@ -8717,6 +9323,11 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== +eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + eslint-webpack-plugin@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz#83dad2395e5f572d6f4d919eedaa9cf902890fcb" @@ -8993,6 +9604,51 @@ eslint@^8.3.0, eslint@^8.9.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" +eslint@^8.40.0: + version "8.44.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.44.0.tgz#51246e3889b259bbcd1d7d736a0c10add4f0e500" + integrity sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.1.0" + "@eslint/js" "8.44.0" + "@humanwhocodes/config-array" "^0.11.10" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.0" + eslint-visitor-keys "^3.4.1" + espree "^9.6.0" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + espree@^9.3.1: version "9.3.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" @@ -9020,6 +9676,15 @@ espree@^9.4.0: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.3.0" +espree@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f" + integrity sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -9032,6 +9697,13 @@ esquery@^1.4.0: dependencies: estraverse "^5.1.0" +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" @@ -9197,6 +9869,18 @@ expect@^29.4.1: jest-message-util "^29.4.1" jest-util "^29.4.1" +expect@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.6.1.tgz#64dd1c8f75e2c0b209418f2b8d36a07921adfdf1" + integrity sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g== + dependencies: + "@jest/expect-utils" "^29.6.1" + "@types/node" "*" + jest-get-type "^29.4.3" + jest-matcher-utils "^29.6.1" + jest-message-util "^29.6.1" + jest-util "^29.6.1" + express@^4.17.1: version "4.17.3" resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" @@ -9299,6 +9983,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + fast-glob@^3.2.11, fast-glob@^3.2.9: version "3.2.11" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" @@ -9609,11 +10298,26 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +functions-have-names@^1.2.2, functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + futoin-hkdf@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/futoin-hkdf/-/futoin-hkdf-1.5.1.tgz#141f00427bc9950b38a42aa786b99c318b9b688d" @@ -9647,6 +10351,16 @@ get-intrinsic@^1.1.3: has "^1.0.3" has-symbols "^1.0.3" +get-intrinsic@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -9753,6 +10467,13 @@ globals@^13.15.0: dependencies: type-fest "^0.20.2" +globals@^13.19.0: + version "13.20.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + dependencies: + type-fest "^0.20.2" + globals@^13.6.0, globals@^13.9.0: version "13.13.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.13.0.tgz#ac32261060d8070e2719dd6998406e27d2b5727b" @@ -9767,6 +10488,13 @@ globalthis@^1.0.1: dependencies: define-properties "^1.1.3" +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globalyzer@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465" @@ -9817,6 +10545,11 @@ grapheme-splitter@^1.0.4: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + gzip-size@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" @@ -9839,6 +10572,11 @@ has-bigints@^1.0.1: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -9849,6 +10587,18 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" @@ -10207,6 +10957,15 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + interpret@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" @@ -10240,6 +10999,15 @@ is-arguments@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -10272,7 +11040,7 @@ is-buffer@~1.1.1: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.3: +is-callable@^1.1.3, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== @@ -10289,6 +11057,13 @@ is-core-module@^2.10.0, is-core-module@^2.9.0: dependencies: has "^1.0.3" +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + is-core-module@^2.2.0, is-core-module@^2.8.0, is-core-module@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" @@ -10347,7 +11122,7 @@ is-module@^1.0.0: resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= -is-negative-zero@^2.0.1: +is-negative-zero@^2.0.1, is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== @@ -10419,6 +11194,13 @@ is-shared-array-buffer@^1.0.1: resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -10443,7 +11225,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10, is-typed-array@^1.1.3: +is-typed-array@^1.1.10, is-typed-array@^1.1.3, is-typed-array@^1.1.9: version "1.1.10" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== @@ -10459,7 +11241,7 @@ is-typedarray@^1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-weakref@^1.0.1: +is-weakref@^1.0.1, is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== @@ -10587,6 +11369,14 @@ jest-changed-files@^29.4.0: execa "^5.0.0" p-limit "^3.1.0" +jest-changed-files@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.5.0.tgz#e88786dca8bf2aa899ec4af7644e16d9dcf9b23e" + integrity sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag== + dependencies: + execa "^5.0.0" + p-limit "^3.1.0" + jest-circus@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" @@ -10737,6 +11527,32 @@ jest-circus@^29.4.1: slash "^3.0.0" stack-utils "^2.0.3" +jest-circus@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.6.1.tgz#861dab37e71a89907d1c0fabc54a0019738ed824" + integrity sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ== + dependencies: + "@jest/environment" "^29.6.1" + "@jest/expect" "^29.6.1" + "@jest/test-result" "^29.6.1" + "@jest/types" "^29.6.1" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + is-generator-fn "^2.0.0" + jest-each "^29.6.1" + jest-matcher-utils "^29.6.1" + jest-message-util "^29.6.1" + jest-runtime "^29.6.1" + jest-snapshot "^29.6.1" + jest-util "^29.6.1" + p-limit "^3.1.0" + pretty-format "^29.6.1" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + jest-cli@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" @@ -10845,6 +11661,24 @@ jest-cli@^29.4.1: prompts "^2.0.1" yargs "^17.3.1" +jest-cli@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.6.1.tgz#99d9afa7449538221c71f358f0fdd3e9c6e89f72" + integrity sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing== + dependencies: + "@jest/core" "^29.6.1" + "@jest/test-result" "^29.6.1" + "@jest/types" "^29.6.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + import-local "^3.0.2" + jest-config "^29.6.1" + jest-util "^29.6.1" + jest-validate "^29.6.1" + prompts "^2.0.1" + yargs "^17.3.1" + jest-config@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" @@ -11015,6 +11849,34 @@ jest-config@^29.4.1: slash "^3.0.0" strip-json-comments "^3.1.1" +jest-config@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.6.1.tgz#d785344509065d53a238224c6cdc0ed8e2f2f0dd" + integrity sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.6.1" + "@jest/types" "^29.6.1" + babel-jest "^29.6.1" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.6.1" + jest-environment-node "^29.6.1" + jest-get-type "^29.4.3" + jest-regex-util "^29.4.3" + jest-resolve "^29.6.1" + jest-runner "^29.6.1" + jest-util "^29.6.1" + jest-validate "^29.6.1" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.6.1" + slash "^3.0.0" + strip-json-comments "^3.1.1" + jest-diff@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" @@ -11075,6 +11937,16 @@ jest-diff@^29.4.1: jest-get-type "^29.2.0" pretty-format "^29.4.1" +jest-diff@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.6.1.tgz#13df6db0a89ee6ad93c747c75c85c70ba941e545" + integrity sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.4.3" + jest-get-type "^29.4.3" + pretty-format "^29.6.1" + jest-docblock@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" @@ -11103,6 +11975,13 @@ jest-docblock@^29.2.0: dependencies: detect-newline "^3.0.0" +jest-docblock@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.4.3.tgz#90505aa89514a1c7dceeac1123df79e414636ea8" + integrity sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg== + dependencies: + detect-newline "^3.0.0" + jest-each@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" @@ -11169,6 +12048,17 @@ jest-each@^29.4.1: jest-util "^29.4.1" pretty-format "^29.4.1" +jest-each@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.6.1.tgz#975058e5b8f55c6780beab8b6ab214921815c89c" + integrity sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ== + dependencies: + "@jest/types" "^29.6.1" + chalk "^4.0.0" + jest-get-type "^29.4.3" + jest-util "^29.6.1" + pretty-format "^29.6.1" + jest-environment-jsdom@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" @@ -11268,6 +12158,18 @@ jest-environment-node@^29.4.1: jest-mock "^29.4.1" jest-util "^29.4.1" +jest-environment-node@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.6.1.tgz#08a122dece39e58bc388da815a2166c58b4abec6" + integrity sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ== + dependencies: + "@jest/environment" "^29.6.1" + "@jest/fake-timers" "^29.6.1" + "@jest/types" "^29.6.1" + "@types/node" "*" + jest-mock "^29.6.1" + jest-util "^29.6.1" + jest-fetch-mock@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz#31749c456ae27b8919d69824f1c2bd85fe0a1f3b" @@ -11296,6 +12198,11 @@ jest-get-type@^29.2.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408" integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA== +jest-get-type@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5" + integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg== + jest-haste-map@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" @@ -11411,6 +12318,25 @@ jest-haste-map@^29.4.1: optionalDependencies: fsevents "^2.3.2" +jest-haste-map@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.6.1.tgz#62655c7a1c1b349a3206441330fb2dbdb4b63803" + integrity sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig== + dependencies: + "@jest/types" "^29.6.1" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.4.3" + jest-util "^29.6.1" + jest-worker "^29.6.1" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + jest-jasmine2@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" @@ -11482,6 +12408,14 @@ jest-leak-detector@^29.4.1: jest-get-type "^29.2.0" pretty-format "^29.4.1" +jest-leak-detector@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz#66a902c81318e66e694df7d096a95466cb962f8e" + integrity sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ== + dependencies: + jest-get-type "^29.4.3" + pretty-format "^29.6.1" + jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" @@ -11542,6 +12476,16 @@ jest-matcher-utils@^29.4.1: jest-get-type "^29.2.0" pretty-format "^29.4.1" +jest-matcher-utils@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz#6c60075d84655d6300c5d5128f46531848160b53" + integrity sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA== + dependencies: + chalk "^4.0.0" + jest-diff "^29.6.1" + jest-get-type "^29.4.3" + pretty-format "^29.6.1" + jest-message-util@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" @@ -11647,6 +12591,21 @@ jest-message-util@^29.4.1: slash "^3.0.0" stack-utils "^2.0.3" +jest-message-util@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.6.1.tgz#d0b21d87f117e1b9e165e24f245befd2ff34ff8d" + integrity sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.1" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.6.1" + slash "^3.0.0" + stack-utils "^2.0.3" + jest-mock-extended@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/jest-mock-extended/-/jest-mock-extended-3.0.3.tgz#570e33b099f8da87487acb4cd7d820712dcc3b52" @@ -11712,6 +12671,15 @@ jest-mock@^29.4.1: "@types/node" "*" jest-util "^29.4.1" +jest-mock@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.6.1.tgz#049ee26aea8cbf54c764af649070910607316517" + integrity sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw== + dependencies: + "@jest/types" "^29.6.1" + "@types/node" "*" + jest-util "^29.6.1" + jest-pnp-resolver@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" @@ -11737,6 +12705,11 @@ jest-regex-util@^29.2.0: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.2.0.tgz#82ef3b587e8c303357728d0322d48bbfd2971f7b" integrity sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA== +jest-regex-util@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.4.3.tgz#a42616141e0cae052cfa32c169945d00c0aa0bb8" + integrity sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg== + jest-resolve-dependencies@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" @@ -11786,6 +12759,14 @@ jest-resolve-dependencies@^29.4.1: jest-regex-util "^29.2.0" jest-snapshot "^29.4.1" +jest-resolve-dependencies@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz#b85b06670f987a62515bbf625d54a499e3d708f5" + integrity sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw== + dependencies: + jest-regex-util "^29.4.3" + jest-snapshot "^29.6.1" + jest-resolve@^27.4.2, jest-resolve@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" @@ -11877,6 +12858,21 @@ jest-resolve@^29.4.1: resolve.exports "^2.0.0" slash "^3.0.0" +jest-resolve@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.6.1.tgz#4c3324b993a85e300add2f8609f51b80ddea39ee" + integrity sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.6.1" + jest-pnp-resolver "^1.2.2" + jest-util "^29.6.1" + jest-validate "^29.6.1" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + jest-runner@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" @@ -12039,6 +13035,33 @@ jest-runner@^29.4.1: p-limit "^3.1.0" source-map-support "0.5.13" +jest-runner@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.6.1.tgz#54557087e7972d345540d622ab5bfc3d8f34688c" + integrity sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ== + dependencies: + "@jest/console" "^29.6.1" + "@jest/environment" "^29.6.1" + "@jest/test-result" "^29.6.1" + "@jest/transform" "^29.6.1" + "@jest/types" "^29.6.1" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.4.3" + jest-environment-node "^29.6.1" + jest-haste-map "^29.6.1" + jest-leak-detector "^29.6.1" + jest-message-util "^29.6.1" + jest-resolve "^29.6.1" + jest-runtime "^29.6.1" + jest-util "^29.6.1" + jest-watcher "^29.6.1" + jest-worker "^29.6.1" + p-limit "^3.1.0" + source-map-support "0.5.13" + jest-runtime@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" @@ -12208,6 +13231,34 @@ jest-runtime@^29.4.1: slash "^3.0.0" strip-bom "^4.0.0" +jest-runtime@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.6.1.tgz#8a0fc9274ef277f3d70ba19d238e64334958a0dc" + integrity sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ== + dependencies: + "@jest/environment" "^29.6.1" + "@jest/fake-timers" "^29.6.1" + "@jest/globals" "^29.6.1" + "@jest/source-map" "^29.6.0" + "@jest/test-result" "^29.6.1" + "@jest/transform" "^29.6.1" + "@jest/types" "^29.6.1" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.6.1" + jest-message-util "^29.6.1" + jest-mock "^29.6.1" + jest-regex-util "^29.4.3" + jest-resolve "^29.6.1" + jest-snapshot "^29.6.1" + jest-util "^29.6.1" + slash "^3.0.0" + strip-bom "^4.0.0" + jest-serializer@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" @@ -12393,6 +13444,33 @@ jest-snapshot@^29.4.1: pretty-format "^29.4.1" semver "^7.3.5" +jest-snapshot@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.6.1.tgz#0d083cb7de716d5d5cdbe80d598ed2fbafac0239" + integrity sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.6.1" + "@jest/transform" "^29.6.1" + "@jest/types" "^29.6.1" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.6.1" + graceful-fs "^4.2.9" + jest-diff "^29.6.1" + jest-get-type "^29.4.3" + jest-matcher-utils "^29.6.1" + jest-message-util "^29.6.1" + jest-util "^29.6.1" + natural-compare "^1.4.0" + pretty-format "^29.6.1" + semver "^7.5.3" + jest-util@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" @@ -12477,6 +13555,18 @@ jest-util@^29.4.1: graceful-fs "^4.2.9" picomatch "^2.2.3" +jest-util@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.1.tgz#c9e29a87a6edbf1e39e6dee2b4689b8a146679cb" + integrity sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg== + dependencies: + "@jest/types" "^29.6.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + jest-validate@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" @@ -12549,6 +13639,18 @@ jest-validate@^29.4.1: leven "^3.1.0" pretty-format "^29.4.1" +jest-validate@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.6.1.tgz#765e684af6e2c86dce950aebefbbcd4546d69f7b" + integrity sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA== + dependencies: + "@jest/types" "^29.6.1" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.4.3" + leven "^3.1.0" + pretty-format "^29.6.1" + jest-watch-typeahead@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/jest-watch-typeahead/-/jest-watch-typeahead-1.0.0.tgz#4de2ca1eb596acb1889752afbab84b74fcd99173" @@ -12645,6 +13747,20 @@ jest-watcher@^29.4.1: jest-util "^29.4.1" string-length "^4.0.1" +jest-watcher@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.6.1.tgz#7c0c43ddd52418af134c551c92c9ea31e5ec942e" + integrity sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA== + dependencies: + "@jest/test-result" "^29.6.1" + "@jest/types" "^29.6.1" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.6.1" + string-length "^4.0.1" + jest-worker@^26.2.1: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" @@ -12709,6 +13825,16 @@ jest-worker@^29.4.1: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.1.tgz#64b015f0e985ef3a8ad049b61fe92b3db74a5319" + integrity sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA== + dependencies: + "@types/node" "*" + jest-util "^29.6.1" + merge-stream "^2.0.0" + supports-color "^8.0.0" + jest@^27.4.3: version "27.5.1" resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" @@ -12768,6 +13894,16 @@ jest@^29.4.1: import-local "^3.0.2" jest-cli "^29.4.1" +jest@^29.5.0: + version "29.6.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.6.1.tgz#74be1cb719c3abe439f2d94aeb18e6540a5b02ad" + integrity sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw== + dependencies: + "@jest/core" "^29.6.1" + "@jest/types" "^29.6.1" + import-local "^3.0.2" + jest-cli "^29.6.1" + js-crypto-env@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/js-crypto-env/-/js-crypto-env-0.3.2.tgz#02195723469da14449338ca2789fd7ff6784c533" @@ -13491,6 +14627,11 @@ nanoid@^3.3.4: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -13531,6 +14672,11 @@ node-addon-api@^2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== +node-addon-api@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -13645,6 +14791,11 @@ object-inspect@^1.11.0, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== +object-inspect@^1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + object-is@^1.0.1: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -13668,6 +14819,16 @@ object.assign@^4.1.0, object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + object.entries@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" @@ -13712,6 +14873,15 @@ object.values@^1.1.0, object.values@^1.1.5: define-properties "^1.1.3" es-abstract "^1.19.1" +object.values@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -13783,6 +14953,18 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -14602,11 +15784,23 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + prettier@^2.5.1: version "2.6.0" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.0.tgz#12f8f504c4d8ddb76475f441337542fa799207d4" integrity sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A== +prettier@^2.8.8: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + pretty-bytes@^5.3.0, pretty-bytes@^5.4.1: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" @@ -14684,6 +15878,15 @@ pretty-format@^29.4.1: ansi-styles "^5.0.0" react-is "^18.0.0" +pretty-format@^29.6.1: + version "29.6.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.6.1.tgz#ec838c288850b7c4f9090b867c2d4f4edbfb0f3e" + integrity sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog== + dependencies: + "@jest/schemas" "^29.6.0" + ansi-styles "^5.0.0" + react-is "^18.0.0" + process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" @@ -14809,6 +16012,11 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +pure-rand@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.2.tgz#a9c2ddcae9b68d736a8163036f088a2781c8b306" + integrity sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ== + q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -15285,6 +16493,15 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: call-bind "^1.0.2" define-properties "^1.1.3" +regexp.prototype.flags@^1.4.3: + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + functions-have-names "^1.2.3" + regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" @@ -15435,6 +16652,15 @@ resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.22.1: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^2.0.0-next.3: version "2.0.0-next.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" @@ -15516,6 +16742,15 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -15612,6 +16847,15 @@ secp256k1@^4.0.3: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" +secp256k1@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-5.0.0.tgz#be6f0c8c7722e2481e9773336d351de8cddd12f7" + integrity sha512-TKWX8xvoGHrxVdqbYeZM9w+izTF4b9z3NhSaDkdn81btvuh+ivbIMGT/zQvDtTFWhRlThpoz6LEYTr7n8A5GcA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^5.0.0" + node-gyp-build "^4.2.0" + secretjs@^0.17.0: version "0.17.5" resolved "https://registry.yarnpkg.com/secretjs/-/secretjs-0.17.5.tgz#5b55e46cfa2719714831fc2019e21c21959fe587" @@ -15675,6 +16919,13 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.7, semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + semver@^7.3.8: version "7.3.8" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" @@ -16099,6 +17350,15 @@ string.prototype.matchall@^4.0.6: regexp.prototype.flags "^1.3.1" side-channel "^1.0.4" +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimend@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" @@ -16107,6 +17367,15 @@ string.prototype.trimend@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimstart@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" @@ -16115,6 +17384,15 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -16749,6 +18027,15 @@ type-tagger@^1.0.0: resolved "https://registry.yarnpkg.com/type-tagger/-/type-tagger-1.0.0.tgz#dc6297e52e17097c1b92b42c16816a18f631e7f4" integrity sha512-FIPqqpmDgdaulCnRoKv1/d3U4xVBUrYn42QXWNP3XYmgfPUDuBUsgFOb9ntT0aIe0UsUP+lknpQ5d9Kn36RssA== +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -16756,11 +18043,21 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typeforce@^1.11.5: + version "1.18.0" + resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" + integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== + typescript-plugin-styled-components@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/typescript-plugin-styled-components/-/typescript-plugin-styled-components-2.0.0.tgz#97e94187cca0f3058c6ad8fefffbca6766c56123" integrity sha512-Wu7F96dwuphgiACHfu63vTbRRg6tkPwLnpFJwdxM70Y0PLfeKLRnvs2Yo5MAySMwE120ODMKk9W4TtJgY1ZumA== +typescript@^5.0.4: + version "5.1.6" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" + integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA== + typescript@^5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.3.tgz#8d84219244a6b40b6fb2b33cc1c062f715b9e826" @@ -16790,6 +18087,16 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" @@ -17395,6 +18702,18 @@ which-typed-array@^1.1.2: has-tostringtag "^1.0.0" is-typed-array "^1.1.10" +which-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.10.tgz#74baa2789991905c2076abb317103b866c64e69e" + integrity sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -17409,6 +18728,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wif@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/wif/-/wif-2.0.6.tgz#08d3f52056c66679299726fade0d432ae74b4704" + integrity sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ== + dependencies: + bs58check "<3.0.0" + wildcard@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" @@ -17630,7 +18956,7 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write-file-atomic@^4.0.1: +write-file-atomic@^4.0.1, write-file-atomic@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==