UNPKG

nexa-wallet-sdk

Version:

Wallet SDK for the Nexa blockchain

1,391 lines 63.7 kB
import { HDPrivateKey, PublicKey, Networkish, Script, AddressType, TransactionBuilder, ScriptElement } from "libnexa-ts"; import { ElectrumClient, SubscribeCallback } from "@vgrunner/electrum-cash"; import { DAppInfo } from "wallet-comms-sdk"; type RostrumTransportScheme = 'ws' | 'wss' | "tcp" | "tcp_tls"; interface RostrumParams { scheme: RostrumTransportScheme; host: string; port: number; } interface BlockTip { height: number; hex: string; } interface IFirstUse { block_hash: string; block_height: number; height: number; tx_hash: string; } interface ITokenGenesis { decimal_places?: number; document_hash?: string; document_url?: string; group: string; height: number; name?: string; op_return?: string; ticker?: string; token_id_hex: string; txid: string; txidem: string; op_return_id: number; } interface ITokensBalance { cursor?: any; confirmed: Record<string, bigint | number>; unconfirmed: Record<string, bigint | number>; } interface ITokenUtxo { group: string; height: number; outpoint_hash: string; token_amount: number | bigint; token_id_hex: string; tx_hash: string; tx_pos: number; value: number; permissions?: string[]; address?: string; } interface IListUnspentRecord { has_token: boolean; height: number; outpoint_hash: string; tx_hash: string; tx_pos: number; value: number; } interface IUtxo { addresses: string[]; amount: number; group: string; group_authority: bigint | number; group_quantity: bigint | number; height: number; scripthash: string; scriptpubkey: string; spent: ISpent; status: string; template_argumenthash: string; template_scripthash: string; token_id_hex: string; tx_hash: string; tx_idem: string; tx_pos: number; permissions?: string[]; } interface ISpent { height: number; tx_hash: string; tx_pos: number; } interface ITransaction { blockhash: string; blocktime: number; confirmations: number; fee: number; fee_satoshi: number; hash: string; height: number; hex: string; locktime: number; size: number; time: number; txid: string; txidem: string; version: number; vin: ITXInput[]; vout: ITXOutput[]; } interface ITXInput { outpoint: string; scriptSig: IScriptSig; sequence: number; value: number; value_satoshi: bigint | number; addresses: string[]; group: string; groupAuthority: bigint | number; groupQuantity: bigint | number; } interface ITXOutput { n: number; outpoint_hash: string; scriptPubKey: IScriptPubKey; type: number; value: number; value_satoshi: bigint | number; } interface IScriptSig { asm: string; hex: string; } interface IScriptPubKey { addresses: string[]; argHash: string; asm: string; group: string; groupAuthority: bigint | number; groupQuantity: bigint | number; hex: string; scriptHash: string; token_id_hex?: string; type: string; } interface ITXHistory { fee?: number; height: number; tx_hash: string; } export interface AccountKeys { receiveKeys: AddressKey[]; changeKeys: AddressKey[]; } export interface WatchOnlyAddress { address: string; xPub?: PublicKey; derivationPath?: string; } export interface AccountIndexes { rIndex: number; cIndex: number; } export interface TxStatus { height: number; } export interface HodlStatus { idx: number; } export interface AddressKey { key: HDPrivateKey; address: string; balance: string; tokensBalance: Record<string, Balance>; } export interface Balance { confirmed: string | number; unconfirmed: string | number; } export class AccountKeysUtils { static getAllKeys(keys: AccountKeys): AddressKey[]; static getAllAddresses(keys: AccountKeys): string[]; } declare class RostrumProvider { constructor(); /** * Get Rostum Server Version */ getVersion(): Promise<string[]>; /** * Get the block tip of the network / chain we are currently connected to */ getBlockTip(): Promise<BlockTip>; /** * Get the nexa balance of an address without the token balances * @param address */ getBalance(address: string): Promise<Balance>; /** * Get The transaction history for an address * @param address */ getTransactionHistory(address: string): Promise<ITXHistory[]>; /** * Get the block height or block has of when the address was first used * @param address */ getFirstUse(address: string): Promise<IFirstUse>; /** * Get a single transaction object * @param id * @param verbose */ getTransaction(id: string, verbose?: boolean): Promise<ITransaction>; /** * Get a single unspent output including group data * @param outpoint */ getUtxo(outpoint: string): Promise<IUtxo>; /** * Get Utxos only containing nexa information * @param address */ getNexaUtxos(address: string): Promise<IListUnspentRecord[]>; /** * Get all the utxo's for a token at an address * @param address * @param token */ getTokenUtxos(address: string, token: string): Promise<ITokenUtxo[]>; /** * Get the token balances for an address * @param address * @param token */ getTokensBalance(address: string, token?: string): Promise<ITokensBalance>; /** * Get the token genesis for a token * @param token */ getTokenGenesis(token: string): Promise<ITokenGenesis>; /** * Subscribe to address call back notifications, handy for updating the user when they receive nexa or tokens in * their wallet * @param addresses * @param callback */ subscribeToAddresses(addresses: string[], callback: SubscribeCallback): Promise<void>; /** * Unsubscribe from address notifications to prevent memory leaks * @param addresses * @param callback */ unsubscribeFromAddresses(addresses: string[], callback: SubscribeCallback): Promise<void>; /** * Broadcast a presigned transaction hash * @param txHex */ broadcast(txHex: string): Promise<string>; /** * Get the latency of the server connection */ getLatency(): Promise<number>; /** * Create initial connection with the rostrum server * @param netOrParams - Network identifier or RostrumParams object * @param params - RostrumParams object (for backward compatibility) * @param electrumClient - Optional pre-configured ElectrumClient instance */ connect(netOrParams?: Networkish | RostrumParams, params?: RostrumParams, electrumClient?: ElectrumClient): Promise<void>; /** * Disconnect from the rostrum server * @param force */ disconnect(force?: boolean): Promise<boolean>; } export const rostrumProvider: RostrumProvider; export type PermissionLabel = 'authorise' | 'mint' | 'melt' | 'rescript' | 'subgroup'; export type TxEntityState = 'incoming' | 'outgoing' | 'both'; export interface TxTemplateData { templateScript: Script; constraintScript: Script; visibleArgs: any[]; publicKey?: PublicKey; } export interface TxOptions { isConsolidate?: boolean; toChange?: string; templateData?: TxTemplateData; feeFromAmount?: boolean; } export interface TokenAction { token?: string; parentToken?: string; amount: bigint; action: string; extraData?: { perms?: PermissionLabel[]; outpoint?: string; opReturnData?: string; address?: string; quantity?: bigint; }; } export interface TransactionEntity { txIdem: string; txId: string; time: number; height: number; payTo: string; state: TxEntityState; value: string; fee: number; token: string; extraGroup: string; txGroupType: number; tokenAmount: string; } export abstract class BaseAccount { get transactions(): Map<string, TransactionEntity>; protected readonly _bip44Account: number; protected constructor(_bip44Account: number); abstract get accountIndexes(): AccountIndexes; abstract get accountKeys(): AccountKeys; abstract getNewChangeAddress(): string; abstract getNewAddress(): string; abstract getAccountStoreKey(): string; abstract getAccountType(): AccountType; abstract loadBalances(): Promise<void>; abstract getKeyFromAddress(address: string): AddressKey; abstract getTransactions(fromHeight?: number, address?: string): Promise<Map<string, TransactionEntity>>; abstract getAddresses(): AddressKey[]; abstract hasChangeAddresses(): boolean; abstract getPrimaryAddressKey(): AddressKey; get balance(): Balance; set balance(value: Balance); get tokenBalances(): Record<string, Balance>; set tokenBalances(value: Record<string, Balance>); get tokenAuthorities(): Record<string, ITokenUtxo[]>; set tokenAuthorities(value: Record<string, ITokenUtxo[]>); protected fetchAndClassifyTransactions(transactionAddress: string, fromHeight?: number): Promise<Map<string, TransactionEntity>>; } export class DappAccount extends BaseAccount { constructor(bip44Account: number, accountIndex: number, addressKey: AddressKey); getAccountStoreKey(): string; getAccountType(): AccountType; getNewAddress(): string; getNewChangeAddress(): string; get accountIndexes(): AccountIndexes; get accountKeys(): AccountKeys; loadBalances(): Promise<void>; getKeyFromAddress(address: string): AddressKey; getTransactions(fromHeight?: number, address?: string): Promise<Map<string, TransactionEntity>>; getAddresses(): AddressKey[]; hasChangeAddresses(): boolean; getPrimaryAddressKey(): AddressKey; } export class DefaultAccount extends BaseAccount { constructor(bip44Account: number, accountIndexes: AccountIndexes, accountKeys: AccountKeys); getAccountStoreKey(): string; getAccountType(): AccountType; getNewAddress(): string; getNewChangeAddress(): string; get accountIndexes(): AccountIndexes; get accountKeys(): AccountKeys; loadBalances(): Promise<void>; getKeyFromAddress(address: string): AddressKey; getTransactions(fromHeight?: number, address?: string): Promise<Map<string, TransactionEntity>>; getAddresses(): AddressKey[]; hasChangeAddresses(): boolean; getPrimaryAddressKey(): AddressKey; } export class VaultAccount extends BaseAccount { constructor(bip44Account: number, accountIndex: number, addressKey: AddressKey); getAccountStoreKey(): string; getAccountType(): AccountType; getNewAddress(): string; getNewChangeAddress(): string; get accountIndexes(): AccountIndexes; get accountKeys(): AccountKeys; loadBalances(): Promise<void>; getKeyFromAddress(address: string): AddressKey; getTransactions(fromHeight?: number, address?: string): Promise<Map<string, TransactionEntity>>; getAddresses(): AddressKey[]; hasChangeAddresses(): boolean; getPrimaryAddressKey(): AddressKey; } export enum TxTokenType { NO_GROUP = 0, CREATE = 1, MINT = 2, MELT = 3, RENEW = 4, TRANSFER = 5 } export enum AccountType { NEXA_ACCOUNT = 0, VAULT_ACCOUNT = 1, DAPP_ACCOUNT = 2 } export function isValidNexaAddress(address: string, network: Networkish, type?: AddressType): boolean; /** * Abstract base class for creating and managing transactions in the NEXA blockchain. * Provides common functionality for transaction building including token operations, * address validation, and output creation. */ declare abstract class TransactionCreator { /** * Creates a new TransactionCreator instance * @param tx Optional existing TransactionBuilder, hex string, or buffer */ protected constructor(tx?: TransactionBuilder | string | Buffer); /** * Parse transaction from hex string with common logic * @param tx Transaction hex string * @returns This instance for chaining */ parseTxHex(tx: string): this; /** * Hook for subclasses to handle individual parsed inputs * @param input The original input from the transaction * @param utxo UTXO data for this input * @param index Input index */ protected handleParsedInput(input: any, utxo: any, index: number): Promise<void>; /** * Hook for subclasses to perform post-processing after parsing is complete */ protected handleParsingComplete(): Promise<void>; /** Parse transaction from buffer - must be implemented by subclasses */ abstract parseTxBuffer(tx: Buffer): this; /** * Sets the network for this transaction * @param network Network name or Networkish object * @returns This instance for chaining */ onNetwork(network: string | Networkish): this; /** Gets transaction options */ get txOptions(): TxOptions; /** Sets transaction options */ set txOptions(value: TxOptions); /** Gets the network for this transaction */ get network(): Networkish; /** Sets the network for this transaction */ set network(value: Networkish); /** Gets the builder function array */ get builder(): (() => Promise<any>)[]; /** Sets the builder function array */ set builder(value: (() => Promise<any>)[]); /** Gets the underlying transaction builder */ get transactionBuilder(): TransactionBuilder; /** Sets the underlying transaction builder */ set transactionBuilder(value: TransactionBuilder); /** Gets the set of token actions */ get tokens(): Set<TokenAction>; /** Sets the set of token actions */ set tokens(value: Set<TokenAction>); /** Gets the total NEXA value being sent */ get totalValue(): bigint; /** Sets the total NEXA value being sent */ set totalValue(value: bigint); /** Gets the set of spent outpoints */ get spentOutpoints(): Set<string>; /** * Updates the spent outpoints set with current transaction inputs * @returns Set of outpoint hashes that are already spent */ protected updateSpentOutpoints(): Set<string>; /** * Validates and creates a token action * @param toAddr Destination address * @param amount Amount to send * @param token Token ID * @param action Action type (mint, melt, send, etc.) * @param parent Optional parent token ID (for NFT/SFT minting) * @throws Error if validation fails */ protected tokenAction(toAddr: string, amount: string, token: string, action: string, parent?: string): void; /** * Configures transaction to consolidate UTXOs to a single address * @param toAddr Address to consolidate funds to * @returns This instance for chaining */ consolidate(toAddr: string): this; /** * Configures transaction to deduct fee from the send amount * @returns This instance for chaining */ feeFromAmount(): this; /** * Adds a token send operation to the transaction * @param toAddr Destination address * @param amount Amount of tokens to send * @param token Token ID * @param dustAmount Optional dust amount for the output (defaults to Transaction.DUST_AMOUNT) * @returns This instance for chaining */ sendToToken(toAddr: string, amount: string, token: string, dustAmount?: number): this; /** * Adds a NEXA send operation to the transaction * @param toAddr Destination address * @param amount Amount of NEXA to send * @returns This instance for chaining */ sendTo(toAddr: string, amount: string): this; /** * Adds a token authority renewal operation * @param token Token ID to renew authority for * @param perms Permissions to renew * @param toAddr * @returns This instance for chaining */ renewAuthority(token: string, perms: PermissionLabel[], toAddr?: string): this; /** * Adds a token authority deletion operation * @param token Token ID to delete authority for * @param outpoint Outpoint of the authority to delete * @returns This instance for chaining */ deleteAuthority(token: string, outpoint: string): this; /** * Creates a legacy token (not implemented) * @returns This instance for chaining */ legacyToken(name: string, ticker: string, decimals: number, docUrl: string, docHash: string): this; /** * Creates a legacy group (not implemented) * @returns This instance for chaining */ legacyGroup(name: string, ticker: string, docUrl: string, docHash: string): this; /** * Creates a token with metadata * @param name Token name * @param ticker Token ticker symbol * @param decimals Number of decimal places * @param docUrl URL to token documentation * @param docHash Hash of token documentation * @returns This instance for chaining */ token(name: string, ticker: string, decimals: number, docUrl: string, docHash: string): this; /** * Creates an NFT collection with metadata * @param name Collection name * @param ticker Collection ticker symbol * @param docUrl URL to collection documentation * @param docHash Hash of collection documentation * @returns This instance for chaining */ collection(name: string, ticker: string, docUrl: string, docHash: string): this; /** * Creates an NFT within a collection * @param parent Parent collection token ID * @param zipUrl URL to NFT content ZIP file * @param zipHash Hash of NFT content ZIP file * @returns This instance for chaining */ nft(parent: string, zipUrl: string, zipHash: string): this; /** * Creates an SFT (Semi-Fungible Token) within a collection with specified quantity * @param parent Parent collection token ID * @param zipUrl URL to SFT content ZIP file * @param zipHash Hash of SFT content ZIP file * @param quantity Quantity of SFTs to create * @returns This instance for chaining */ sft(parent: string, zipUrl: string, zipHash: string, quantity: bigint): this; /** * Adds an OP_RETURN output to the transaction * @param data Data to include in the OP_RETURN * @param isFullScript Whether the data is already a complete script * @returns This instance for chaining */ addOpReturn(data: Buffer | string | Script, isFullScript?: boolean): this; /** * Adds nexa contract constraint to spending inputs * @param templateScript * @param constraintScript * @param visibleArgs * @param pubKey * @returns This instance for chaining */ addContract(templateScript: Script, constraintScript: Script, visibleArgs: any[], pubKey?: PublicKey): this; /** Populates the transaction with inputs and outputs - must be implemented by subclasses */ abstract populate(): this; /** * Builds the transaction by executing all queued operations * @returns Promise resolving to the serialized transaction hex */ build(): Promise<string>; } export class WalletTransactionCreator extends TransactionCreator { constructor(fromAccount: BaseAccount, tx?: TransactionBuilder | string | Buffer); fromAccount(fromAccount: BaseAccount): this; parseTxHex(tx: string): this; /** * Handle wallet-specific logic for each parsed input (find and store private keys) */ protected handleParsedInput(input: any, utxo: any, index: number): Promise<void>; /** * Handle wallet-specific post-processing after parsing is complete */ protected handleParsingComplete(): Promise<void>; parseTxBuffer(tx: Buffer): this; mint(token: string, amount: string, parent?: string): this; melt(token: string, amount: string, parent?: string): this; sendAuthority(token: string, perms: PermissionLabel[], toAddr: string): this; populate(): this; sign(): this; buildSatisfier(elements: ScriptElement[]): Script; buildScriptSig(template: Script, constraint: Script | undefined, satisfierElements: ScriptElement[]): Script; } /** * AccountStore manages a collection of wallet accounts of different types. * It provides functionality to create, import, export, and manage accounts * including DApp accounts, Vault accounts, and Default NEXA accounts. */ export class AccountStore { /** * Creates a new AccountStore instance * Initializes an empty map to store accounts */ constructor(); /** * Creates a new account of the specified type * @param accountType Type of account to create (DAPP, VAULT, or DEFAULT) * @param masterKey Master HD private key for deriving account keys * @param forceNextIndex If true, forces the next sequential index regardless of blockchain usage * @returns Promise resolving to the created account */ createAccount(accountType: AccountType, masterKey: HDPrivateKey, forceNextIndex?: boolean): Promise<BaseAccount>; /** * Finds the private key associated with a given address across all accounts * @param address The address to search for * @returns The AddressKey containing the private key, or null if not found */ findKeyForAddress(address: string): AddressKey | null; /** * Imports an existing account into the store * @param accountData The account data to import * @throws Error if an account with the same key already exists */ importAccount(accountData: BaseAccount): void; /** * Exports account data by index * @param accountIndex The account index to export * @returns The account data * @throws Error if the account doesn't exist */ exportAccount(accountIndex: string): BaseAccount; /** * Removes an account from the store * @param accountIndex The account index to remove * @throws Error if the account doesn't exist */ removeAccount(accountIndex: string): void; /** * Returns all accounts in the store * @returns Map of account store keys to BaseAccount objects */ listAccounts(): Map<string, BaseAccount>; /** * Retrieves a specific account by its index * @param index The account index to retrieve * @returns The account if found, undefined otherwise */ getAccount(index: string): BaseAccount | undefined; /** * Retrieves all accounts of a specific type * @param accountType The type of accounts to retrieve * @returns Array of accounts matching the specified type */ getAccountsByType(accountType: AccountType): BaseAccount[]; } /** Type definition for constructor functions */ type Class<T> = new (...args: any[]) => T; /** * Utility class for validating arguments and state conditions * * Provides methods to validate function arguments and application state * with consistent error handling and messaging. */ export class ValidationUtils { /** * Validate that a state condition is true * * @param condition - The condition to validate * @param message - Error message to throw if condition is false * @throws {Error} If condition is false * * @example * ```typescript * ValidationUtils.validateState(wallet.isInitialized, 'Wallet must be initialized'); * ``` */ static validateState(condition: boolean, message: string): void; /** * Validate that an argument condition is true * * @param condition - The condition to validate * @param argumentName - Name of the argument being validated * @param message - Optional additional error message * @throws {Error} If condition is false * * @example * ```typescript * ValidationUtils.validateArgument( * typeof amount === 'number', * 'amount', * 'must be a number' * ); * ``` */ static validateArgument(condition: boolean, argumentName: string, message?: string): void; /** * Validate that an argument is of the expected type * * @param argument - The argument to validate * @param type - Expected type (string name or constructor function) * @param argumentName - Name of the argument being validated * @throws {TypeError} If argument is not of expected type * * @example * ```typescript * ValidationUtils.validateArgumentType(buffer, 'Buffer', 'data'); * ValidationUtils.validateArgumentType(wallet, Wallet, 'wallet'); * ValidationUtils.validateArgumentType(amount, 'number', 'amount'); * ``` */ static validateArgumentType<T>(argument: unknown, type: string | Class<T>, argumentName?: string): void; } /** * Main Wallet class for managing Nexa blockchain wallet operations * * This class provides comprehensive wallet functionality including: * - Creating wallets from seed phrases or private keys * - Account discovery and management * - Transaction creation and signing * - Message signing and verification * - Multi-account support with different account types * * @example * ```typescript * // Create a new wallet with random seed phrase * const wallet = Wallet.create(); * * // Restore wallet from existing seed phrase * const wallet = Wallet.fromSeedPhrase('your twelve word seed phrase here'); * * // Initialize wallet (discovers accounts and balances) * await wallet.initialize(); * * // Create a new account * const account = await wallet.newAccount('DefaultAccount'); * * // Create and send a transaction * const tx = wallet.newTransaction(account) * .to('nexa:address', 1000000) // 1 NEXA in satoshis * .sign(); * * const txId = await wallet.sendTransaction(tx.toHex()); * ``` */ export class Wallet { /** * Creates a new Wallet instance * * @param data - Optional wallet data: * - undefined: Generate new random seed phrase * - string: Use as BIP39 seed phrase * - HDPrivateKey: Use as master key directly * @param network - Network name ('mainnet', 'testnet', 'regtest'). Defaults to 'mainnet' * * @example * ```typescript * // Create new wallet with random seed * const wallet = new Wallet(); * * // Create from seed phrase * const wallet = new Wallet('abandon abandon abandon...'); * * // Create from master key * const masterKey = HDPrivateKey.fromString('xprv...'); * const wallet = new Wallet(masterKey); * * // Create on testnet * const wallet = new Wallet(undefined, 'testnet'); * ``` */ constructor(data?: string | HDPrivateKey | undefined, network?: string); /** * Create a new wallet with a randomly generated seed phrase * * This is the recommended way to create a new wallet for first-time users. * The generated seed phrase should be securely stored by the user. * * @returns A new Wallet instance with a random 12-word seed phrase * * @example * ```typescript * const wallet = Wallet.create(); * console.log(wallet.export().phrase); // Store this securely! * ``` */ static create(): Wallet; /** * Create a wallet from an existing BIP39 seed phrase * * Use this method to restore a wallet from a previously generated seed phrase. * The seed phrase should be a valid BIP39 mnemonic. * * @param phrase - The BIP39 seed phrase (12 or 24 words) * @param network - Optional network name ('mainnet', 'testnet', 'regtest') * @returns A new Wallet instance restored from the seed phrase * @throws {Error} If the seed phrase is invalid or not provided * * @example * ```typescript * const wallet = Wallet.fromSeedPhrase( * 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about', * 'testnet' * ); * ``` */ static fromSeedPhrase(phrase: string, network?: string): Wallet; /** * Create a wallet from an extended private key (xpriv) * * Use this method to create a wallet from a master private key in extended format. * This is useful for advanced users who want to use a specific key derivation. * * @param xpriv - The extended private key string (starts with 'xprv') * @param network - Optional network name ('mainnet', 'testnet', 'regtest') * @returns A new Wallet instance using the provided master key * @throws {Error} If the private key is invalid or not provided * * @example * ```typescript * const wallet = Wallet.fromXpriv( * 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi' * ); * ``` */ static fromXpriv(xpriv: string, network?: string): Wallet; /** * Initialize the wallet by discovering accounts and loading balances * * This method performs account discovery using the BIP44 derivation path * and scans for existing accounts with transaction history or balances. * Must be called before using the wallet's accounts. * * @returns Promise that resolves when initialization is complete * * @example * ```typescript * const wallet = Wallet.fromSeedPhrase('your seed phrase'); * await wallet.initialize(); * * // Now you can access discovered accounts * const accounts = wallet.accountStore.listAccounts(); * ``` */ initialize(): Promise<void>; /** * Create a new transaction builder for this wallet * * @param fromAccount - The account to send the transaction from * @param x - Optional existing transaction data: * - TransactionBuilder: Use existing transaction builder * - string: Parse from hex string * - Buffer: Parse from binary buffer * - undefined: Create new empty transaction * @returns A new WalletTransactionCreator instance * * @example * ```typescript * const account = wallet.accountStore.getAccount(0); * const tx = wallet.newTransaction(account) * .to('nexa:address', 1000000) // 1 NEXA * .sign(); * * // Or from existing transaction hex * const tx = wallet.newTransaction(account, 'raw_tx_hex') * .sign(); * ``` */ newTransaction(fromAccount: BaseAccount, x?: TransactionBuilder | string | Buffer): WalletTransactionCreator; /** * Create a new account for this wallet * * @param accountType - The type of account to create: * - 'DefaultAccount': Standard account for general use * - 'VaultAccount': Secured account with additional protection * - 'DappAccount': Account optimized for dApp interactions * @returns Promise that resolves to the newly created account * * @example * ```typescript * const defaultAccount = await wallet.newAccount('DefaultAccount'); * const vaultAccount = await wallet.newAccount('VaultAccount'); * const dappAccount = await wallet.newAccount('DappAccount'); * ``` */ newAccount(accountType: AccountType): Promise<BaseAccount>; /** * Broadcast a signed transaction to the Nexa network * * @param transaction - The signed transaction in hex format * @returns Promise that resolves to the transaction ID (txid) * @throws {Error} If the transaction is invalid or broadcast fails * * @example * ```typescript * const tx = wallet.newTransaction(account) * .to('nexa:address', 1000000) * .sign(); * * const txId = await wallet.sendTransaction(tx.toHex()); * console.log('Transaction sent:', txId); * ``` */ sendTransaction(transaction: string): Promise<string>; /** * Subscribe to address notifications for transaction updates * * This method allows you to monitor one or more addresses for incoming and outgoing transactions. * You can provide either a single address string or an array of addresses. The callback will be * invoked whenever there are updates to any of the monitored addresses. * * @param addresses - A single address string or array of addresses to monitor * @param callback - Function to call when address notifications are received * @returns Promise that resolves when subscription is established * @throws {Error} If addresses parameter is invalid or empty * * @example * ```typescript * // Subscribe to a single address * await wallet.subscribeToAddressNotifications( * 'nexa:address123', * (notification) => { * console.log('Address notification:', notification); * } * ); * * // Subscribe to multiple addresses * await wallet.subscribeToAddressNotifications( * ['nexa:address1', 'nexa:address2', 'nexa:address3'], * (notification) => { * console.log('Address notification:', notification); * } * ); * * // Subscribe to all wallet addresses * const accounts = wallet.accountStore.listAccounts(); * const addresses = accounts.flatMap(account => * account.getAddresses().map(addr => addr.address) * ); * await wallet.subscribeToAddressNotifications(addresses, callback); * ``` */ subscribeToAddressNotifications(addresses: string | string[], callback: SubscribeCallback): Promise<void>; /** * Unsubscribe from address notifications to prevent memory leaks * * This method stops listening for notifications on the specified addresses. * It's important to call this method when you no longer need to monitor addresses * to prevent memory leaks from accumulating callback references. * * @param addresses - Single address string or array of address strings to unsubscribe from * @param callback - The exact same callback function used in subscribeToAddressNotifications * * @example * ```typescript * // Unsubscribe from a single address * await wallet.unsubscribeFromAddressNotifications( * 'nexa:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc', * myCallback * ); * * // Unsubscribe from multiple addresses * await wallet.unsubscribeFromAddressNotifications(addresses, myCallback); * ``` */ unsubscribeFromAddressNotifications(addresses: string | string[], callback: SubscribeCallback): Promise<void>; /** * Sign a message using a specific address from this wallet * * The message is signed using the private key associated with the given address. * This can be used for authentication or to prove ownership of an address. * * @param message - The message to sign * @param addressToUse - The address whose private key should sign the message * @returns The signature as a base64-encoded string * @throws {Error} If the address is not owned by this wallet * * @example * ```typescript * const account = wallet.accountStore.getAccount(0); * const address = account.getReceiveAddress(); * const signature = wallet.signMessage('Hello World', address); * ``` */ signMessage(message: string, addressToUse: string): string; /** * Verify a message signature against an address * * This method can verify signatures created by any address, not just addresses * owned by this wallet. It's useful for verifying messages from other parties. * * @param message - The original message that was signed * @param signature - The signature to verify (base64-encoded) * @param address - The address that supposedly signed the message * @returns true if the signature is valid, false otherwise * @throws {Error} If any parameters are missing or invalid * * @example * ```typescript * const isValid = wallet.verifyMessage( * 'Hello World', * 'signature_string', * 'nexa:address' * ); * console.log('Signature valid:', isValid); * ``` */ verifyMessage(message: string, signature: string, address: string): boolean; /** * Export the wallet data for backup or storage * * Returns an object containing the wallet's seed phrase, master key, and accounts. * This data can be used to restore the wallet later. The seed phrase should be * stored securely as it provides full access to the wallet. * * @returns Object containing wallet data * @property {string} phrase - The BIP39 seed phrase (if available) * @property {HDPrivateKey} masterKey - The master private key * @property {BaseAccount[]} accounts - Array of discovered accounts * * @example * ```typescript * const walletData = wallet.export(); * * // Store the seed phrase securely * const seedPhrase = walletData.phrase; * * // Later, restore the wallet * const restoredWallet = Wallet.fromSeedPhrase(seedPhrase); * ``` */ export(): any; /** * Get the account store for managing wallet accounts * * The account store provides methods to create, import, and manage accounts * within this wallet. Each account has its own set of addresses and keys. * * @returns The wallet's account store * * @example * ```typescript * const accountStore = wallet.accountStore; * const accounts = accountStore.listAccounts(); * const firstAccount = accountStore.getAccount(0); * ``` */ get accountStore(): AccountStore; /** * Get the network this wallet is operating on * * @returns The network object (mainnet, testnet, or regtest) * * @example * ```typescript * const network = wallet.network; * console.log('Network:', network.name); * ``` */ get network(): Networkish; /** * Get the current sequential indexing setting * * @returns true if forcing sequential indexing, false if using discovery-based indexing * * @example * ```typescript * const isSequential = wallet.forceSequentialIndexing; * console.log('Sequential indexing:', isSequential); * ``` */ get forceSequentialIndexing(): boolean; /** * Set whether to force sequential account indexing * * When enabled, new accounts will use sequential indexes (0, 1, 2, ...) regardless * of blockchain activity. This is useful for multi-user wallets where each user * needs a unique account even if they haven't used it yet. * * When disabled (default), account creation uses discovery-based indexing which * scans the blockchain for existing activity before assigning indexes. * * @param force - true to force sequential indexing, false for discovery-based * * @example * ```typescript * // Enable sequential indexing for multi-user scenarios * wallet.forceSequentialIndexing = true; * * // Create accounts - they'll be 2.0, 2.1, 2.2 regardless of usage * const alice = await wallet.newAccount(AccountType.DAPP_ACCOUNT); * const bob = await wallet.newAccount(AccountType.DAPP_ACCOUNT); * const charlie = await wallet.newAccount(AccountType.DAPP_ACCOUNT); * * // Disable for normal discovery-based indexing * wallet.forceSequentialIndexing = false; * ``` */ set forceSequentialIndexing(force: boolean); } /** * WatchOnlyTransactionCreator extends TransactionCreator to handle transaction creation * for watch-only wallets. It manages addresses without private keys and delegates * UTXO selection and input population to specialized utility functions. */ export class WatchOnlyTransactionCreator extends TransactionCreator { /** * Creates a new WatchOnlyTransactionCreator * @param tx Optional existing transaction builder or transaction data */ constructor(tx?: TransactionBuilder | string | Buffer); /** * Sets the source addresses for transaction inputs * @param address Single address string, array of addresses, or WatchOnlyAddress objects * @returns This instance for chaining */ from(address: string | string[] | WatchOnlyAddress[] | WatchOnlyAddress): this; /** * Adds a token minting operation to the transaction * @param token Token ID to mint * @param amount Amount to mint * @param toAddr Destination address for minted tokens * @param parent Optional parent token ID (for NFT/SFT minting) * @returns This instance for chaining */ mint(token: string, amount: string, toAddr: string, parent?: string): this; /** * Adds a token melting operation to the transaction * @param token Token ID to melt * @param amount Amount to melt * @param toAddr Destination address for change of melted tokens * @param parent Optional parent token ID (for NFT/SFT melting) * @returns This instance for chaining */ melt(token: string, amount: string, toAddr: string, parent?: string): this; sendAuthority(token: string, perms: PermissionLabel[], toAddr: string): this; /** * Populates the transaction with inputs and outputs based on the configured actions. * Handles different token operations (mint, melt, group creation, etc.) and * populates NEXA inputs for transaction fees. * @returns This instance for chaining */ populate(): this; /** * Parse transaction from buffer (not implemented for watch-only) * @param tx Transaction buffer * @returns This instance for chaining * @throws Error indicating method not implemented */ parseTxBuffer(tx: Buffer): this; /** * Parse transaction from hex string using enhanced base class implementation * @param tx Transaction hex string * @returns This instance for chaining */ parseTxHex(tx: string): this; /** * Handle watch-only specific logic for each parsed input (track addresses for signing) */ protected handleParsedInput(_input: any, utxo: any, _index: number): Promise<void>; } /** * WatchOnlyWallet provides functionality for monitoring and creating transactions * for addresses without storing private keys. This allows users to track balances * and create unsigned transactions that can be signed elsewhere. */ export class WatchOnlyWallet { /** * Creates a new WatchOnlyWallet instance * @param addressesToWatch Array of addresses to monitor * @param network Optional network name (defaults to mainnet) * @throws Error if validation fails */ constructor(addressesToWatch: WatchOnlyAddress[], network?: string); /** * Creates a new transaction creator for this watch-only wallet * @param x Optional transaction data - can be a TransactionBuilder, hex string, or Buffer * @returns WatchOnlyTransactionCreator configured with wallet's addresses and network */ newTransaction(x?: TransactionBuilder | string | Buffer): WatchOnlyTransactionCreator; /** * Broadcasts a signed transaction to the network * @param transaction Hex-encoded signed transaction * @returns Promise resolving to transaction ID * @throws Error if transaction is invalid or broadcast fails */ sendTransaction(transaction: string): Promise<string>; subscribeToAddressNotifications(callback: SubscribeCallback): Promise<void>; /** * Unsubscribe from address notifications to prevent memory leaks * * This method stops listening for notifications on all watched addresses. * The callback parameter must be the exact same function reference that was * used in the subscribeToAddressNotifications call. * * @param callback - The exact same callback function used in subscribeToAddressNotifications * * @example * ```typescript * const myCallback = (notification) => console.log(notification); * await watchOnlyWallet.subscribeToAddressNotifications(myCallback); * * // Later, to prevent memory leaks: * await watchOnlyWallet.unsubscribeFromAddressNotifications(myCallback); * ``` */ unsubscribeFromAddressNotifications(callback: SubscribeCallback): Promise<void>; /** * Gets the list of addresses being watched * @returns Array of watched addresses (copy to prevent mutation) */ getWatchedAddresses(): WatchOnlyAddress[]; } /** * Details for transaction signing approval request */ export interface TransactionApprovalDetails { dApp: DAppInfo; account: string; transactionHex: string; broadcast: boolean; sighashSpec?: any; recipients?: Array<{ address: string; amount: string; token?: string; }>; totalAmount?: string; fees?: string; opReturn?: string; tokenOutputs?: Array<{ tokenId: string; amount: string; }>; } /** * Details for message signing approval request */ export interface MessageApprovalDetails { dApp: DAppInfo; account: string; message: string; messagePreview: string; } /** * Details for send transaction approval request */ export interface SendTransactionApprovalDetails { dApp: DAppInfo; fromAccount: string; recipients: Array<{ address: string; amount: string; token?: string; }>; totalAmount: string; estimatedFees?: string; opReturn?: string; } /** * Details for network switching approval request */ export interface NetworkSwitchApprovalDetails { dApp: DAppInfo; currentNetwork: string; requestedNetwork: string; } /** * Details for add token approval request */ export interface AddTokenApprovalDetails { dApp: DAppInfo; account: string; tokenId: string; tokenInfo?: { name?: string; symbol?: string; decimals?: number; }; } /** * Approval callbacks interface for handling user approval requests */ export interface ApprovalCallbacks { /** * Request approval for transaction signing * @param details Transaction details for user review * @returns Promise<boolean> true if approved, false if rejected */ approveTransaction?: (details: TransactionApprovalDetails) => Promise<boolean>; /** * Request approval for message signing * @param details Message details for user review * @returns Promise<boolean> true if approved, false if rejected */ approveMessage?: (details: MessageApprovalDetails) => Promise<boolean>; /** * Request approval for sending a transaction * @param details Send transaction details for user review * @returns Promise<boolean> true if approved, false if rejected */ approveSendTransaction?: (details: SendTransactionApprovalDetails) => Promise<boolean>; /** * Request approval for network switching * @param details Network switch details for user review * @returns Promise<boolean> true if approved, false if rejected */ approveNetworkSwitch?: (details: NetworkSwitchApprovalDetails) => Promise<boolean>; /** * Request approval for adding a token * @param details Add token details for user review * @returns Promise<boolean> true if approved, false if rejected */ approveAddToken?: (details: AddTokenApprovalDetails) => Promise<boolean>; /** * Request approval for connecting to a dApp * @param dAppInfo DApp information for user review * @returns Promise<boolean> true if approved, false if rejected */ approveConnection?: (dAppInfo: DAppInfo) => Promise<boolean>; } /** * Default approval callbacks that auto-approve everything (for backwards compatibility) */ export const AUTO_APPROVE_CALLBACKS: ApprovalCallbacks; /** * Wallet-side WalletComms integration for receiving and handling dApp requests * * This class runs inside wallet applications and handles incoming requests from dApps. * It manages session connections, message signing, transaction signing, and network switching. * The wallet holds private keys and can actually sign transactions. * * @example * ```typescript * const wallet = Wallet.fromSeedPhrase('...'); * await wallet.initialize(); * * const walletComms = new WalletCommsIntegration(wallet); * * // Connect to a dApp using a pairing URI (usually from QR code) * const dAppInfo = await walletComms.connect('wl:1@relay.net/...'); * console.log('Connected to:', dAppInfo.name); * * // The integration automatically handles dApp requests * ``` */ export class WalletCommsIntegration { constructor(wallet: Wallet, approvalCallbacks?: ApprovalCallbacks); /** * Set approval callbacks for handling user consent */ setApprovalCallbacks(callbacks: ApprovalCallbacks): void; /** * Connect to a dApp using a pairing URI * * This method will only use DApp accounts for security isolation. * If no DApp account is provided, the first available one will be used or created. * * @param pairingURI - The pairing URI from the dApp (usually from QR code) * @param dappAccount - Optional specific DApp account to use (defaults to first available) * @returns Information about the connected dApp */ connect(pairingURI: string, dappAccount?: DAppAccount): Promise<DAppInfo>; /** * Disconnect from the current dApp session */ disconnect(): void; /** * Switch the active account */ setActiveAccount(account: BaseAccount): void; /** * Get the current active account */ getActiveAccount(): BaseAccount | null; /** * Check if connected to a dApp */ isConnectedToDApp(): boolean; /** * Get the current session details */ getSessionInfo(): any; /*