import type { ApprovalQuorumRequestContext } from '@dynamic-labs-wallet/core'; import { Logger } from '@dynamic-labs/logger'; import { JwtVerifiedCredential, MFAAction, SignMessageContext, TokenScope } from '@dynamic-labs/sdk-api-core'; import { GenericNetwork, IUITransaction, WalletUiUtils } from '@dynamic-labs/types'; import { BitcoinSignPsbtResponse, Chain, CreateWalletAccountParams, IDynamicWaasConnector, ISendBalanceWalletConnector, ImportPrivateKeyParams, InternalWalletConnector } from '@dynamic-labs/wallet-connector-core'; import type { DynamicWaasBitcoinConnectorProps, ParsedTransaction } from '../../types'; import { BitcoinTransaction, EmbeddedWalletSignPsbtRequest } from '../../types'; import { BitcoinWalletConnector } from '../BitcoinWalletConnector'; declare const DynamicWaasBitcoinConnector_base: (abstract new (...args: any[]) => { [x: string]: any; name: string; overrideKey: string; isEmbeddedWallet: boolean; getSignedSessionId?: (() => Promise) | undefined; getSessionPublicKey?: (() => Promise) | undefined; getMfaToken?: ((props?: { mfaAction?: MFAAction | undefined; } | undefined) => Promise) | undefined; getWalletPassword?: import("@dynamic-labs/wallet-connector-core").GetWalletPasswordFn | undefined; getAuthToken?: (() => string) | undefined; getElevatedAccessToken?: ((props: { scope: TokenScope; }) => Promise) | undefined; onUnauthorized?: (() => void | Promise) | undefined; environmentId?: string | undefined; baseApiUrl?: string | undefined; relayUrl?: string | undefined; baseClientKeysharesRelayApiUrl?: string | undefined; dynamicWaasClient: import("@dynamic-labs-wallet/browser-wallet-client").DynamicWalletClient | undefined; revokeSignedSession: ((reason?: string | undefined) => void) | undefined; chainName: string; authMode: "cookie" | "header"; logger: Logger; __exportHandler: import("@dynamic-labs/waas").WaasExportHandler; validateActiveWallet(expectedAddress: string): Promise; setGetAuthTokenFunction(getAuthToken: () => string): void; setOnUnauthorizedFunction(onUnauthorized: () => void | Promise): void; setWaasAuthMode(authMode: "cookie" | "header"): void; setGetMfaTokenFunction(getMfaToken: (props?: { mfaAction?: MFAAction | undefined; } | undefined) => Promise): void; setGetElevatedAccessTokenFunction(getElevatedAccessToken: (params: { scope: TokenScope; }) => Promise): void; setGetWalletPasswordFunction(getWalletPassword: import("@dynamic-labs/wallet-connector-core").GetWalletPasswordFn): void; getPasswordIfNeeded({ accountAddress, }: { accountAddress: string; }): Promise; getPassword({ accountAddress, }: { accountAddress: string; }): Promise; setEnvironmentId(environmentId: string): void; setBaseApiUrl(baseApiUrl: string): void; setBaseClientKeysharesRelayApiUrl(baseClientKeysharesRelayApiUrl?: string | undefined): void; setRelayUrl(relayUrl: string): void; setGetSignedSessionIdFunction(getSignedSessionId: () => Promise): void; setGetSessionPublicKeyFunction(getSessionPublicKey: () => Promise): void; delegateKeyShares({ accountAddress, password, initialSignerRules, }: { accountAddress: string; password?: string | undefined; initialSignerRules?: import("@dynamic-labs-wallet/browser-wallet-client").WaasPolicyRule[] | undefined; }): Promise; createRevocableSignedSessionCallback(): { getSignedSessionId: () => Promise; }; createDynamicWaasClient(traceContext?: import("dist/packages/waas/utils/instrumentation").TraceContext | undefined): Promise; detachWaasClient(client: import("@dynamic-labs-wallet/browser-wallet-client").DynamicWalletClient | undefined, reason: string): boolean; getWaasWalletClient(traceContext?: import("dist/packages/waas/utils/instrumentation").TraceContext | undefined, { forceRebuild }?: { forceRebuild?: boolean | undefined; } | undefined): Promise; createWalletAccount({ thresholdSignatureScheme, password, bitcoinConfig, businessAccountId, }?: CreateWalletAccountParams | undefined): Promise<{ chainName: string; accountAddress: string; publicKeyHex: string; rawPublicKey: string | Uint8Array | undefined; }>; addSignerViaReshare({ accountAddress, walletId, businessAccountId, targetSignerIdentity, signerType, password, targetSignerPassword, intent, intentSignature, }: { accountAddress: string; walletId?: string | undefined; businessAccountId: string; targetSignerIdentity: { userId?: string | undefined; identifier?: string | undefined; identifierType?: string | undefined; }; signerType?: "endUser" | "server" | undefined; password?: string | undefined; targetSignerPassword?: string | undefined; /** * Maps the selected networkId to the BitcoinNetwork enum for internal WaaS * API calls (signing) — balance/UTXO/broadcast are address-driven and follow * the active address automatically. */ intent?: import("@dynamic-labs-wallet/core").BusinessAccountIntent | undefined; intentSignature?: string | undefined; }): Promise; importPrivateKey({ privateKey, thresholdSignatureScheme, publicAddressCheck, addressType, legacyWalletId, password, isRawScalarImport, }: ImportPrivateKeyParams): Promise; migrateFromFireblocks({ deviceId, jwt, walletPassword, ncwStorage, expectedAddresses, coinTypes, password, }: { deviceId: string; jwt: string; walletPassword: string; ncwStorage: Record; expectedAddresses: Record; coinTypes?: Record | undefined; password?: string | undefined; }): Promise>; exportPrivateKey({ accountAddress, displayContainer, password, }?: { accountAddress?: string | undefined; displayContainer?: HTMLIFrameElement | undefined; password?: string | undefined; } | undefined): Promise; getExportHandler(): { clear: () => void; }; exportClientKeyshares({ accountAddress, password, }: import("@dynamic-labs/wallet-connector-core").ExportClientKeysharesParams): Promise; runBackupLifecycle({ provider, accountAddress, password, performBackup, }: { provider: string; accountAddress: string; password?: string | undefined; performBackup: (prerequisites: { walletClient: import("@dynamic-labs-wallet/browser-wallet-client").DynamicWalletClient; resolvedPassword: string | undefined; signedSessionId: string; sessionPublicKey: string | undefined; traceContext: { traceId: string; startTime: number; }; }) => Promise; }): Promise; backupKeySharesToGoogleDrive({ accountAddress, password, googleDriveAccessToken, }: import("@dynamic-labs/wallet-connector-core").BackupKeySharesToGoogleDriveParams): Promise; exportClientKeysharesFromGoogleDrive({ accountAddress, password, }: { accountAddress: string; password?: string | undefined; }): Promise; backupKeySharesToICloud({ accountAddress, password, }: { accountAddress: string; password?: string | undefined; }): Promise; displayICloudSignIn({ displayContainer, }: { displayContainer: HTMLElement; }): Promise; hideICloudSignIn(): Promise; isICloudAuthenticated(): Promise; refreshWalletAccountShares({ accountAddress, password, }: import("@dynamic-labs/wallet-connector-core").RefreshWalletAccountSharesParams): Promise; reshareWalletAccountShares({ accountAddress, thresholdSignatureScheme, password, }: import("@dynamic-labs/wallet-connector-core").ReshareWalletAccountSharesParams): Promise; revokeDelegation({ accountAddress, password, }: { accountAddress: string; password?: string | undefined; }): Promise; updatePassword({ accountAddress, existingPassword, newPassword, passwordOverrides, }: import("@dynamic-labs/wallet-connector-core").UpdatePasswordParams): Promise; setPassword({ accountAddress, newPassword, }: { accountAddress: string; newPassword: string; }): Promise; signRawMessage({ accountAddress, approvalQuorum, context, message, password, }: { accountAddress: string; approvalQuorum?: ApprovalQuorumRequestContext | undefined; context?: SignMessageContext | undefined; message: string; password?: string | undefined; }): Promise; unlockWallet({ accountAddress, password, }: { accountAddress: string; password?: string | undefined; }): Promise; lockWallets(): Promise; lockWallet({ accountAddress }: { accountAddress: string; }): Promise; getWalletRecoveryState({ accountAddress, }: { accountAddress: string; }): Promise; createOfflineRecoveryShares({ accountAddress, password, cloudProviderAccessToken, mfaToken, recoveryEncryptionPublicKey, }: { accountAddress: string; password?: string | undefined; cloudProviderAccessToken?: string | undefined; mfaToken?: string | undefined; recoveryEncryptionPublicKey?: string | undefined; }): Promise; endSession(reason?: import("@dynamic-labs-sdk/client").LogoutReason | undefined): Promise; getActiveAccountAddress(): Promise; getConnectedAccounts(): Promise; generateTraceId(): string; buildErrorInstrumentContext(error: unknown): { errorCode: string | import("@dynamic-labs/utils").ErrorCode; errorMessage: string; errorType: string | undefined; } | { errorCode: string; errorMessage?: undefined; errorType?: undefined; }; instrument(message: string, context: import("@dynamic-labs/logger").InstrumentOptions & import("dist/packages/waas/utils/instrumentation").InstrumentContext & Record): void; instrumentAsync({ operation, resource, fn, context, }: { operation: string; resource: string; fn: (timing: import("dist/packages/waas/utils/instrumentation").InstrumentationTimer) => Promise; context?: Record | undefined; }): Promise; getPrivateBalance(): Promise<{ unshielded: Record; shielded: Record; dust: { balance: string; cap: string; }; address: string; dustSynced: boolean; }>; }) & typeof BitcoinWalletConnector; /** * Bitcoin connector for Dynamic WaaS (Wallet as a Service) * Extends BitcoinWalletConnector with WaaS functionality for Bitcoin transactions */ export declare class DynamicWaasBitcoinConnector extends DynamicWaasBitcoinConnector_base implements IDynamicWaasConnector, ISendBalanceWalletConnector { name: string; logger: Logger; overrideKey: string; isEmbeddedWallet: boolean; connectedChain: Chain; get key(): string; activeAccountAddress: string | undefined; protected walletUiUtils: WalletUiUtils; /** * The primary/active verified credential (first from the filtered array) * This is used for the active account address */ private _verifiedCredential; private mempoolApiService; private psbtBuilderService; private bitcoinNetworks; /** * @param props - Constructor properties including walletUiUtils */ constructor(props: DynamicWaasBitcoinConnectorProps); set verifiedCredential(verifiedCredential: JwtVerifiedCredential | undefined); get verifiedCredential(): JwtVerifiedCredential | undefined; /** * Override setVerifiedCredentials to filter and set Bitcoin WaaS credentials * Filters for credentials with walletName === 'dynamicwaas' and chain === 'bip122' * The base class already has verifiedCredentials property, so we just filter and set it */ setVerifiedCredentials(verifiedCredentials: JwtVerifiedCredential[]): void; /** * Gets the active wallet address * Falls back to verified credential address if no active account is set * @returns The wallet address or undefined * @throws {DynamicError} If no active wallet address is found */ getAddress(): Promise; /** * Gets all connected account addresses * @returns Array of connected account addresses (currently returns single active address) */ getConnectedAccounts(): Promise; /** * The currently selected Bitcoin network id (1 = mainnet, 2 = testnet). * One wallet (one key) exposes an address per network via network-tagged * additional addresses; switching networks swaps the active address. */ private activeNetworkId; /** * Gets the current Bitcoin network id (1 mainnet, 2 testnet) */ getNetwork(): Promise; /** * Maps the selected networkId to the BitcoinNetwork enum for internal WaaS * API calls (signing) — balance/UTXO/broadcast are address-driven and follow * the active address automatically. */ private getBitcoinNetworkEnum; /** * The address type the wallet's key was derived under, read back from the * address itself. * * `bitcoinConfig.addressType` is the only thing that selects a BTC * derivation path downstream (`getMPCChainConfig` throws without it), and a * wallet created by an import carries no server-side derivation metadata to * fall back on — so signing an imported wallet failed while a * Dynamic-created one signed fine. The address already encodes the answer: * witness v0 is P2WPKH (native segwit), v1 is P2TR (taproot), which are * exactly the two types `importPrivateKey` accepts. * * Falls back to native segwit for an address that is not bech32 (a legacy * P2PKH/P2SH encoding cannot come from this connector's own import or * create paths) so a decode failure can never make signing impossible. */ private getAddressTypeForSigning; supportsNetworkSwitching(): boolean; /** * Testnet when the testnet network (id 2) is selected — drives the widget's * native-denominated balance display (testnet coins have no fiat price). */ isTestnet(): Promise; /** * Balance follows the active (per-network) address: callers pass the * wallet's static primary address, which is the mainnet encoding — on * testnet the switched address must be queried instead (the mempool API * routing is address-driven). */ getBalance(address: string): Promise; /** * Finds the credential that owns `address`, either as its primary (mainnet) * address or as one of its network-tagged additional addresses. * * This connector is shared across every Bitcoin wallet of the user — * `verifiedCredentials` holds them all — so the owning credential must be * looked up by address. Reading `verifiedCredential` instead would always * answer with the user's *first* wallet. */ private findCredentialForAddress; /** @see findCredentialForAddress */ private findCredentialForActiveAddress; /** * True when `accountAddress` belongs to the same wallet as the currently * active address — including when the active address is a *different* * network-tagged encoding of that same wallet (e.g. the testnet address * set by switchNetwork, compared against the wallet's primary mainnet * address). * * Used by getWalletClientByAddress to avoid clobbering an explicit * switchNetwork: callers like ensureActiveAccount re-assert the wallet's * primary address before every send/sign, and setting activeAccountAddress * back to that primary address would silently undo the network switch — * UTXO/PSBT/broadcast calls would then run against the wrong (likely * unfunded) encoding while getNetwork still reports the switched network. * * Compares the two resolved credential *objects* by reference rather than * by id: both lookups run against the same verifiedCredentials array in * the same synchronous call, so `.find()` returns the identical element * for both addresses whenever they belong to the same wallet. Comparing * `.id` instead would be wrong whenever accountAddress doesn't resolve to * any known credential yet (e.g. a brand-new wallet not yet synced) — * `undefined === undefined` would falsely read as "same wallet". */ private isSameWalletAddress; /** * Wallet identity: keyshares/wallet records are keyed by the wallet's * primary (mainnet) address. On testnet the active address is the same * wallet's per-network encoding — WaaS lookups (password, signing) must use * the primary address (the same key signs both encodings). * * Resolved from the credential that owns the active address, so a user with * several Bitcoin wallets gets the identity of the wallet being spent from. * Never falls back to another wallet's address: a substituted key produces a * signature that looks valid locally and is rejected by the network, so the * failure has to surface here instead. */ private getWalletIdentityAddress; /** * Resolves the wallet's payment address for a network from the credential's * network-tagged additional addresses. Mainnet falls back to the primary * address (wallets created before per-network registration). */ private getPaymentAddressForNetwork; /** * Switches between Bitcoin mainnet (1) and testnet (2). Same key — the * active address swaps to the network's encoding; mempool/PSBT/broadcast * follow the address, signing follows getBitcoinNetworkEnum(). */ switchNetwork({ networkChainId, networkName, }: { networkChainId?: number | string; networkName?: string; }): Promise; /** * Get the enabled networks for Bitcoin * Returns configured networks from props * @returns Array containing Bitcoin network configurations */ getEnabledNetworks(): GenericNetwork[]; /** * Gets block explorer URLs for the current network * Returns mempool.space for Bitcoin transactions * @returns Array containing mempool.space URL */ getBlockExplorerUrlsForCurrentNetwork(): Promise; /** * Signs a message using the wallet UI utils for user interaction * @param message - The message to sign * @returns The signed message as a string */ signMessage(message: string, options?: { approvalQuorum?: ApprovalQuorumRequestContext; }): Promise; /** * Signs a Partially Signed Bitcoin Transaction (PSBT) for embedded wallets * * Embedded wallets only support PSBT format and automatically sign all inputs * that belong to the wallet address, unless `signingIndexes` narrows that set. * * The sighash type is read from the PSBT itself, falling back to * SIGHASH_DEFAULT (0x00) for Taproot and SIGHASH_ALL (0x01) otherwise. * `allowedSighash` restricts which declared types are accepted. * * @param request - The PSBT signing request. Only unsignedPsbtBase64 is required. * @returns The signed (but not finalized) PSBT response * @throws {DynamicError} If active account address is not set * @throws {DynamicError} If signed session ID is not available */ signPsbt(request: EmbeddedWalletSignPsbtRequest, options?: { approvalQuorum?: ApprovalQuorumRequestContext; }): Promise; /** * Sends a raw Bitcoin transaction to the mempool * @param rawTransaction - The raw transaction in hex format * @returns The transaction ID * @throws {DynamicError} If no transaction is specified or sending fails */ sendRawTransaction(rawTransaction: string): Promise; /** * Sends Bitcoin to a recipient address * This method combines buildPsbt, signPsbt, finalize, and sendRawTransaction into a single flow * @param transaction - The Bitcoin transaction containing recipient address and amount * @returns The transaction ID * @throws {DynamicError} If any step in the process fails */ sendBitcoin(transaction: BitcoinTransaction): Promise; sendBitcoinWithConfirmation(transaction: BitcoinTransaction): Promise; /** * Creates a new Bitcoin wallet account with Bitcoin-specific defaults. * If `bitcoinConfig.addressType` is not provided, the underlying BTC client * defaults to `native_segwit`. * @param thresholdSignatureScheme - The threshold signature scheme (default: 'TWO_OF_TWO') * @param password - Optional password for the wallet * @param bitcoinConfig - Bitcoin configuration (addressType, network) * @returns The created wallet account information */ createWalletAccount(params?: CreateWalletAccountParams): Promise<{ chainName: string; accountAddress: string; publicKeyHex: string; rawPublicKey: string | Uint8Array | undefined; }>; /** * Requires and validates `addressType` for Bitcoin, then delegates. * @param params - See ImportPrivateKeyParams. `addressType` is mandatory * here ('native_segwit' or 'taproot') and `privateKey` is WIF. * @throws {DynamicError} If addressType is missing or invalid for BTC */ importPrivateKey(params: ImportPrivateKeyParams): Promise; /** * Gets the wallet client for a specific account address and sets it as * active — unless `accountAddress` is just a different network-tagged * encoding of the wallet that's already active (see isSameWalletAddress), * in which case the current (possibly switchNetwork'd) active address is * left untouched. * @param accountAddress - The Bitcoin account address * @returns The WaaS wallet client instance */ getWalletClientByAddress({ accountAddress }: { accountAddress: string; }): Promise; /** * Rebinds the connector when the user switches primary wallet. One connector * instance is shared by every BTC wallet, so without this the connector stays * on whichever address it was first seeded with and every address-derived * read — displayed address, deposit address, balance — reports that wallet. * * Guarded by isSameWalletAddress so switching to a wallet that is already * active on a non-mainnet encoding does not reset it to the primary address. */ afterWalletSelectHook(walletAddress: string): void; /** * Selecting a wallet hands us its primary (mainnet) address, so binding it * verbatim would silently drop a switchNetwork the user already made. Map it * onto the network that is currently active instead. Falls back to the given * address when the wallet has no row for that network. */ private resolveAddressForActiveNetwork; /** * Gets the currently active account address * @returns The active account address or undefined if not set */ getActiveAccountAddress(): Promise; /** * Validates that the expected wallet address matches the active wallet * Updates the active account address if it doesn't match * @param expectedAddress - The expected wallet address to validate * @throws {DynamicError} If signed session ID is not available or account is not found */ validateActiveWallet(expectedAddress: string): Promise; /** * Signs a message with additional context information * @param message - The message to sign (string or object with raw property) * @param context - Additional context for the message signing * @returns The signed message as a string * @throws {DynamicError} If active account address is not set * @throws {DynamicError} If signed session ID is not available */ signMessageWithContext({ message, context, }: { message: string | { raw: string; }; context: SignMessageContext; }): Promise; /** * Builds a PSBT for a Bitcoin transaction with real UTXOs * @param transaction - Bitcoin transaction with recipient address, amount in satoshis, and optional fee priority * @returns A PSBT in Base64 format * @throws {DynamicError} If no active account address, insufficient funds, or other errors */ buildPsbt(transaction: BitcoinTransaction): Promise; /** * Creates a UI transaction for the send balance flow * @param from - The address sending the transaction * @returns A BitcoinUiTransaction instance * @throws {DynamicError} If active account address is not set */ createUiTransaction(from: string): Promise; /** * Parse a PSBT or finalized transaction and extract transaction information * Auto-detects format (hex/base64) and type (PSBT/finalized transaction) * @param psbtInput - The PSBT or finalized transaction in Base64 or hex format * @returns Parsed transaction data with inputs and outputs, or null if parsing fails */ parsePsbt(psbtInput: string): ParsedTransaction | null; /** * Parse a PSBT or finalized transaction from hex format * @param psbtHex - The PSBT or finalized transaction in hex format * @returns Parsed transaction data with inputs and outputs, or null if parsing fails */ parseHexPsbt(psbtHex: string): ParsedTransaction | null; /** * Parse a PSBT or finalized transaction from base64 format * @param psbtBase64 - The PSBT or finalized transaction in base64 format * @returns Parsed transaction data with inputs and outputs, or null if parsing fails */ parseBase64Psbt(psbtBase64: string): ParsedTransaction | null; /** * bitcoinjs network for the address encoding the parsers should emit. * Derived from the active address rather than activeNetworkId, which is * in-memory only and can report mainnet while a testnet address is active. */ private getPsbtNetwork; /** * Gets the public key for the active account * Falls back to the account address if public key retrieval fails * @returns The public key or account address as fallback * @throws {DynamicError} If no active account address is set * @throws {DynamicError} If signed session ID is not available */ getPublicKey(): Promise; /** * Helper function to convert BTC amount to satoshis * @param btcAmount - The Bitcoin amount to convert (number) * @returns The amount in satoshis as a BigInt * @throws {DynamicError} If the amount is negative */ btcToSatoshis(btcAmount: number): bigint; /** * Sets the active account address for this connector * @param accountAddress - The Bitcoin account address to set as active */ private setActiveAccountAddress; /** * Internal method to sign a message with MFA token * @param message - The message to sign * @returns The signed message as a string * @throws {DynamicError} If active account address is not set * @throws {DynamicError} If signed session ID is not available */ private internalSignMessage; } export {};