From bc2577232a2cc3e10f3048fcaa2d666584f42c4e Mon Sep 17 00:00:00 2001 From: Ulisses Ferreira Date: Thu, 27 Aug 2026 10:13:32 +0100 Subject: [PATCH] refactor(bitcoin-wallet-snap): convert enums to `as const` objects Convert locally-declared TypeScript enums to `as const` objects with derived union types. BREAKING: Type signatures change - Enum is now a union of string/number literals instead of a nominal enum type. Runtime member access is unchanged. --- .../bitcoin-wallet-snap/snap.manifest.json | 2 +- .../src/entities/account.ts | 51 +++++++++++-------- .../src/entities/confirmation.ts | 11 ++-- .../src/entities/currency.ts | 16 +++--- .../src/entities/send-flow.ts | 37 ++++++++------ .../bitcoin-wallet-snap/src/entities/snap.ts | 15 +++--- .../src/handlers/CronHandler.ts | 14 ++--- .../bitcoin-wallet-snap/src/handlers/caip.ts | 16 +++--- .../src/handlers/validation.ts | 42 ++++++++------- 9 files changed, 116 insertions(+), 88 deletions(-) diff --git a/packages/bitcoin-wallet-snap/snap.manifest.json b/packages/bitcoin-wallet-snap/snap.manifest.json index d59b88aac..afc82bd59 100644 --- a/packages/bitcoin-wallet-snap/snap.manifest.json +++ b/packages/bitcoin-wallet-snap/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/internal-snaps.git" }, "source": { - "shasum": "sYefpN30aR0fb7v2DtdJ+jNFSnJJX5jtqvdsDof4RHQ=", + "shasum": "DAuPn0nXZ23flLpbBbGrnOrZW6wYqw0MofHBQ9vjD5U=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/bitcoin-wallet-snap/src/entities/account.ts b/packages/bitcoin-wallet-snap/src/entities/account.ts index f8d27eee2..0bb396f5f 100644 --- a/packages/bitcoin-wallet-snap/src/entities/account.ts +++ b/packages/bitcoin-wallet-snap/src/entities/account.ts @@ -222,17 +222,20 @@ export type BitcoinAccount = { applyUnconfirmedTx(tx: Transaction, lastSeen: number): void; }; -export enum AccountCapability { - SignPsbt = 'signPsbt', - ComputeFee = 'computeFee', - FillPsbt = 'fillPsbt', - BroadcastPsbt = 'broadcastPsbt', - SendTransfer = 'sendTransfer', - GetUtxo = 'getUtxo', - ListUtxos = 'listUtxos', - PublicDescriptor = 'publicDescriptor', - SignMessage = 'signMessage', -} +export const AccountCapability = { + SignPsbt: 'signPsbt', + ComputeFee: 'computeFee', + FillPsbt: 'fillPsbt', + BroadcastPsbt: 'broadcastPsbt', + SendTransfer: 'sendTransfer', + GetUtxo: 'getUtxo', + ListUtxos: 'listUtxos', + PublicDescriptor: 'publicDescriptor', + SignMessage: 'signMessage', +} as const; + +export type AccountCapability = + (typeof AccountCapability)[keyof typeof AccountCapability]; /** * BitcoinAccountRepository is a repository that manages Bitcoin accounts. @@ -332,18 +335,22 @@ export type BitcoinAccountRepository = { getFrozenUTXOs(id: string): Promise; }; -export enum Purpose { - Legacy = 44, - Segwit = 49, - NativeSegwit = 84, - Taproot = 86, - Multisig = 45, -} +export const Purpose = { + Legacy: 44, + Segwit: 49, + NativeSegwit: 84, + Taproot: 86, + Multisig: 45, +} as const; -export enum Slip44 { - Bitcoin = 0, - Testnet = 1, -} +export type Purpose = (typeof Purpose)[keyof typeof Purpose]; + +export const Slip44 = { + Bitcoin: 0, + Testnet: 1, +} as const; + +export type Slip44 = (typeof Slip44)[keyof typeof Slip44]; export const addressTypeToPurpose: Record = { p2pkh: Purpose.Legacy, diff --git a/packages/bitcoin-wallet-snap/src/entities/confirmation.ts b/packages/bitcoin-wallet-snap/src/entities/confirmation.ts index 3a079b567..c05619a1b 100644 --- a/packages/bitcoin-wallet-snap/src/entities/confirmation.ts +++ b/packages/bitcoin-wallet-snap/src/entities/confirmation.ts @@ -39,10 +39,13 @@ export type SignPsbtConfirmationContext = { inputCount: number; }; -export enum ConfirmationEvent { - Confirm = 'confirmation-confirm', - Cancel = 'confirmation-cancel', -} +export const ConfirmationEvent = { + Confirm: 'confirmation-confirm', + Cancel: 'confirmation-cancel', +} as const; + +export type ConfirmationEvent = + (typeof ConfirmationEvent)[keyof typeof ConfirmationEvent]; /** * ConfirmationRepository is a repository that manages request confirmations for dApps. diff --git a/packages/bitcoin-wallet-snap/src/entities/currency.ts b/packages/bitcoin-wallet-snap/src/entities/currency.ts index 1b71c644c..8599f4b18 100644 --- a/packages/bitcoin-wallet-snap/src/entities/currency.ts +++ b/packages/bitcoin-wallet-snap/src/entities/currency.ts @@ -1,12 +1,14 @@ import type { Network } from '@metamask/bitcoindevkit'; -export enum CurrencyUnit { - Bitcoin = 'BTC', - Testnet = 'tBTC', - Signet = 'sBTC', - Regtest = 'rBTC', - Fiat = 'fiat', // Can also be cryptos like ETH, but will be fiat for 99% of users -} +export const CurrencyUnit = { + Bitcoin: 'BTC', + Testnet: 'tBTC', + Signet: 'sBTC', + Regtest: 'rBTC', + Fiat: 'fiat', // Can also be cryptos like ETH, but will be fiat for 99% of users +} as const; + +export type CurrencyUnit = (typeof CurrencyUnit)[keyof typeof CurrencyUnit]; export type CurrencyRate = { conversionRate: number; diff --git a/packages/bitcoin-wallet-snap/src/entities/send-flow.ts b/packages/bitcoin-wallet-snap/src/entities/send-flow.ts index bee8546b3..dc5651647 100644 --- a/packages/bitcoin-wallet-snap/src/entities/send-flow.ts +++ b/packages/bitcoin-wallet-snap/src/entities/send-flow.ts @@ -43,18 +43,20 @@ export type SendFormContext = { locale: string; }; -export enum SendFormEvent { - Amount = 'amount', - Recipient = 'recipient', - ClearRecipient = 'clearRecipient', - ClearAmount = 'clearAmount', - Confirm = 'confirm', - Cancel = 'cancel', - Max = 'max', - Account = 'account', - Asset = 'asset', - SwitchCurrency = 'switchCurrency', -} +export const SendFormEvent = { + Amount: 'amount', + Recipient: 'recipient', + ClearRecipient: 'clearRecipient', + ClearAmount: 'clearAmount', + Confirm: 'confirm', + Cancel: 'cancel', + Max: 'max', + Account: 'account', + Asset: 'asset', + SwitchCurrency: 'switchCurrency', +} as const; + +export type SendFormEvent = (typeof SendFormEvent)[keyof typeof SendFormEvent]; export type ReviewTransactionContext = { from: string; @@ -75,10 +77,13 @@ export type ReviewTransactionContext = { sendForm?: SendFormContext; }; -export enum ReviewTransactionEvent { - Send = 'send', - HeaderBack = 'headerBack', -} +export const ReviewTransactionEvent = { + Send: 'send', + HeaderBack: 'headerBack', +} as const; + +export type ReviewTransactionEvent = + (typeof ReviewTransactionEvent)[keyof typeof ReviewTransactionEvent]; /** * SendFlowRepository is a repository that manages Bitcoin Send flow interfaces. diff --git a/packages/bitcoin-wallet-snap/src/entities/snap.ts b/packages/bitcoin-wallet-snap/src/entities/snap.ts index e3a545ad2..386167a5f 100644 --- a/packages/bitcoin-wallet-snap/src/entities/snap.ts +++ b/packages/bitcoin-wallet-snap/src/entities/snap.ts @@ -46,12 +46,15 @@ export type SyncResult = { transactionsToNotify: WalletTx[]; }; -export enum TrackingSnapEvent { - TransactionFinalized = 'Transaction Finalized', - TransactionReceived = 'Transaction Received', - TransactionReorged = 'Transaction Reorged', - TransactionSubmitted = 'Transaction Submitted', -} +export const TrackingSnapEvent = { + TransactionFinalized: 'Transaction Finalized', + TransactionReceived: 'Transaction Received', + TransactionReorged: 'Transaction Reorged', + TransactionSubmitted: 'Transaction Submitted', +} as const; + +export type TrackingSnapEvent = + (typeof TrackingSnapEvent)[keyof typeof TrackingSnapEvent]; /** * The SnapClient represents the MetaMask Snap state and manages the BIP-32 entropy from the Wallet SRP. diff --git a/packages/bitcoin-wallet-snap/src/handlers/CronHandler.ts b/packages/bitcoin-wallet-snap/src/handlers/CronHandler.ts index f034158ff..bf772ec76 100644 --- a/packages/bitcoin-wallet-snap/src/handlers/CronHandler.ts +++ b/packages/bitcoin-wallet-snap/src/handlers/CronHandler.ts @@ -6,12 +6,14 @@ import { InexistentMethodError, SynchronizationError } from '../entities'; import type { SnapClient, SyncResult } from '../entities'; import type { SendFlowUseCases, AccountUseCases } from '../use-cases'; -export enum CronMethod { - SynchronizeAccounts = 'synchronizeAccounts', - RefreshRates = 'refreshRates', - SyncSelectedAccounts = 'syncSelectedAccounts', - FullScanAccount = 'fullScanAccount', -} +export const CronMethod = { + SynchronizeAccounts: 'synchronizeAccounts', + RefreshRates: 'refreshRates', + SyncSelectedAccounts: 'syncSelectedAccounts', + FullScanAccount: 'fullScanAccount', +} as const; + +export type CronMethod = (typeof CronMethod)[keyof typeof CronMethod]; export const SendFormRefreshRatesRequest = object({ interfaceId: string(), diff --git a/packages/bitcoin-wallet-snap/src/handlers/caip.ts b/packages/bitcoin-wallet-snap/src/handlers/caip.ts index fc8ea6207..f93465b3b 100644 --- a/packages/bitcoin-wallet-snap/src/handlers/caip.ts +++ b/packages/bitcoin-wallet-snap/src/handlers/caip.ts @@ -30,13 +30,15 @@ export const networkToScope = reverseMapping(scopeToNetwork); export const addressTypeToCaip = reverseMapping(caipToAddressType); -export enum Caip19Asset { - Bitcoin = 'bip122:000000000019d6689c085ae165831e93/slip44:0', - Testnet = 'bip122:000000000933ea01ad0ee984209779ba/slip44:0', - Testnet4 = 'bip122:00000000da84f2bafbbc53dee25a72ae/slip44:0', - Signet = 'bip122:00000008819873e925422c1ff0f99f7c/slip44:0', - Regtest = 'bip122:regtest/slip44:0', -} +export const Caip19Asset = { + Bitcoin: 'bip122:000000000019d6689c085ae165831e93/slip44:0', + Testnet: 'bip122:000000000933ea01ad0ee984209779ba/slip44:0', + Testnet4: 'bip122:00000000da84f2bafbbc53dee25a72ae/slip44:0', + Signet: 'bip122:00000008819873e925422c1ff0f99f7c/slip44:0', + Regtest: 'bip122:regtest/slip44:0', +} as const; + +export type Caip19Asset = (typeof Caip19Asset)[keyof typeof Caip19Asset]; export const NetworkStruct = enums(Object.values(BtcScope)); diff --git a/packages/bitcoin-wallet-snap/src/handlers/validation.ts b/packages/bitcoin-wallet-snap/src/handlers/validation.ts index 8dbfda3b1..edf13cdbe 100644 --- a/packages/bitcoin-wallet-snap/src/handlers/validation.ts +++ b/packages/bitcoin-wallet-snap/src/handlers/validation.ts @@ -22,25 +22,29 @@ import { import type { BitcoinAccount, CodifiedError, Logger } from '../entities'; import { ValidationError } from '../entities'; -export enum RpcMethod { - StartSendTransactionFlow = 'startSendTransactionFlow', - SignAndSendTransaction = 'signAndSendTransaction', - ComputeFee = 'computeFee', - VerifyMessage = 'verifyMessage', - OnAddressInput = 'onAddressInput', - OnAmountInput = 'onAmountInput', - ConfirmSend = 'confirmSend', - SignRewardsMessage = 'signRewardsMessage', - SignProofOfOwnership = 'signProofOfOwnership', -} - -export enum SendErrorCodes { - // eslint-disable-next-line @typescript-eslint/no-shadow - Required = 'Required', - Invalid = 'Invalid', - InsufficientBalance = 'InsufficientBalance', - InsufficientBalanceToCoverFee = 'InsufficientBalanceToCoverFee', -} +export const RpcMethod = { + StartSendTransactionFlow: 'startSendTransactionFlow', + SignAndSendTransaction: 'signAndSendTransaction', + ComputeFee: 'computeFee', + VerifyMessage: 'verifyMessage', + OnAddressInput: 'onAddressInput', + OnAmountInput: 'onAmountInput', + ConfirmSend: 'confirmSend', + SignRewardsMessage: 'signRewardsMessage', + SignProofOfOwnership: 'signProofOfOwnership', +} as const; + +export type RpcMethod = (typeof RpcMethod)[keyof typeof RpcMethod]; + +export const SendErrorCodes = { + Required: 'Required', + Invalid: 'Invalid', + InsufficientBalance: 'InsufficientBalance', + InsufficientBalanceToCoverFee: 'InsufficientBalanceToCoverFee', +} as const; + +export type SendErrorCodes = + (typeof SendErrorCodes)[keyof typeof SendErrorCodes]; export const NonEmptyStringStruct = refine( nonempty(string()),