UNPKG

nexa-wallet-sdk

Version:

Wallet SDK for the Nexa blockchain

500 lines (388 loc) 12.6 kB
# Nexa Wallet SDK Production-ready TypeScript SDK for building Nexa blockchain wallets and dApps. ## Features - **Wallet Management**: Create wallets from seed phrases or private keys - **Account Types**: Support for multiple account types (NEXA, Vault, DApp) - **Transaction Building**: Fluent API for building and signing transactions - **Token Operations**: Create, mint, melt, and transfer tokens and NFTs - **Watch-Only Wallets**: Monitor addresses without storing private keys - **Network Support**: Mainnet and testnet compatibility - **Multiple Formats**: CommonJS, ES modules, and browser bundles ## Installation ```bash npm install nexa-wallet-sdk ``` ## Quick Start ### Basic Wallet Setup ```typescript import { Wallet, rostrumProvider } from 'nexa-wallet-sdk' // Connect to the default mainnet node await rostrumProvider.connect() // Connect to a specific network (mainnet or testnet) await rostrumProvider.connect('testnet') // Uses predefined testnet node await rostrumProvider.connect('mainnet') // Uses predefined mainnet node // Connect to a custom node (ignores network parameter) await rostrumProvider.connect({ host: 'your-custom-node.example.com', port: 30004, scheme: 'wss' // or 'ws' for unencrypted connection }) // Create wallet from seed phrase const wallet = new Wallet( 'your twelve word seed phrase goes here for wallet creation', 'testnet' // or 'mainnet' ) // Initialize wallet to discover accounts await wallet.initialize() // Get the default account const account = wallet.accountStore.getAccount('1.0') ``` ### Simple Transaction ```typescript // Send 100 NEXA const tx = await wallet.newTransaction(account) .onNetwork('testnet') .sendTo('nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc', '10000') .populate() .sign() .build() console.log('Transaction:', tx) ``` ## Core Concepts ### Accounts The SDK supports different account types: - **NEXA Account**: Standard accounts for regular transactions - **Vault Account**: Secure storage accounts - **DApp Account**: Application-specific accounts ```typescript // Get a new receiving address (This only returns a different address for default accounts) const address = account.getNewAddress() // Check account balance const balance = account.balance console.log('Confirmed:', balance.confirmed) console.log('Unconfirmed:', balance.unconfirmed) // Get transaction history const transactions = await account.getTransactions() ``` ### Transaction Building All transactions follow the same pattern: **create → configure → populate → sign → build** ```typescript const tx = await wallet.newTransaction(account) .onNetwork('testnet') // 1. Set network .sendTo(address, amount) // 2. Configure outputs .addOpReturn(data) // 3. Add optional data .populate() // 4. Find inputs and calculate fees .sign() // 5. Sign the transaction .build() // 6. Get final transaction hex ``` ## Transaction Examples ### Basic Send Transaction ```typescript // Send 500 Nexa const tx = await wallet.newTransaction(account) .onNetwork('testnet') .sendTo('nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc', '50000') .populate() .sign() .build() ``` ### Multiple Outputs ```typescript const tx = await wallet.newTransaction(account) .onNetwork('testnet') .sendTo('nexatest:address1', '10000') .sendTo('nexatest:address2', '20000') .sendTo('nexatest:address3', '30000') .addOpReturn('Multi-output transaction') .populate() .sign() .build() ``` ### Fee From Amount ```typescript // Deduct transaction fee from the send amount const tx = await wallet.newTransaction(account) .sendTo(recipient, '50000') .feeFromAmount() // Fee will be subtracted from the 50000 .populate() .sign() .build() ``` ### Consolidate UTXOs ```typescript // Consolidate all UTXOs to a single address const tx = await wallet.newTransaction(account) .consolidate('nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc') .populate() .sign() .build() ``` ## Token Operations ### Create a Fungible Token ```typescript const tx = await wallet.newTransaction(account) .onNetwork('testnet') .token( 'MyToken', // Token name 'MTK', // Ticker symbol 8, // Decimal places 'https://mytoken.com/info', // Documentation URL 'sha256hash' // Documentation hash ) .populate() .sign() .build() ``` ### Create an NFT Collection ```typescript const tx = await wallet.newTransaction(account) .onNetwork('testnet') .collection( 'My NFT Collection', 'MNC', 'https://mycollection.com/metadata', 'collectionhash' ) .populate() .sign() .build() ``` ### Mint an NFT ```typescript const parentCollectionId = 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx' const tx = await wallet.newTransaction(account) .onNetwork('testnet') .nft( parentCollectionId, 'https://mynft.com/content.zip', 'contenthash123' ) .populate() .sign() .build() ``` ### Token Transfers ```typescript const tokenId = 'nexatest:tqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc' const tx = await wallet.newTransaction(account) .onNetwork('testnet') .sendTo('nexatest:recipient', '1000') // Send NEXA .sendToToken('nexatest:recipient', '500', tokenId) // Send tokens .populate() .sign() .build() ``` ### Mint Additional Tokens ```typescript const tx = await wallet.newTransaction(account) .onNetwork('testnet') .mint(tokenId, '1000000') // Mint 1,000,000 token units .populate() .sign() .build() ``` ### Burn (Melt) Tokens ```typescript const tx = await wallet.newTransaction(account) .onNetwork('testnet') .melt(tokenId, '500000') // Burn 500,000 token units .populate() .sign() .build() ``` ## Authority Management ### Renew Token Authorities ```typescript const tx = await wallet.newTransaction(account) .onNetwork('testnet') .renewAuthority( tokenId, ['mint', 'melt'], // Permissions to renew 'nexatest:nqtsq5g5...' // Optional: new authority address ) .populate() .sign() .build() ``` ### Delete Token Authority ```typescript const tx = await wallet.newTransaction(account) .onNetwork('testnet') .deleteAuthority(tokenId, 'abc123:0') // outpoint of authority to delete .populate() .sign() .build() ``` ## Watch-Only Wallets Watch-only wallets allow you to monitor addresses and create unsigned transactions without storing private keys. ### Create Watch-Only Wallet ```typescript import { WatchOnlyWallet } from 'nexa-wallet-sdk' const watchOnlyWallet = new WatchOnlyWallet([ { address: 'nexatest:nqtsq5g5dsgh6mwjchqypn8hvdrjue0xpmz293fl7rm926xv' } ], 'testnet') ``` ### Create Unsigned Transaction ```typescript const unsignedTx = await watchOnlyWallet.newTransaction() .sendTo('nexatest:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc', '100000') .addOpReturn("Watch-only transaction") .populate() .build() ``` ### Sign Watch-Only Transaction ```typescript // Pass the unsigned transaction to a wallet with private keys const signedTx = await wallet.newTransaction(account, unsignedTx) .sign() .build() ``` ### Subscribe to Address Updates ```typescript const myCallback = (notification) => { console.log('Address activity:', notification) } await watchOnlyWallet.subscribeToAddressNotifications(myCallback) // Later, to prevent memory leaks: await watchOnlyWallet.unsubscribeFromAddressNotifications(myCallback) ``` ## Advanced Features ### Address Notifications ```typescript // Define your callback function const myCallback = (notification) => { console.log('Address notification:', notification) } // Subscribe to a single address await wallet.subscribeToAddressNotifications( 'nexa:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc', myCallback ) // Subscribe to addresses as an array const addresses = [ 'nexa:nqtsq5g5jsdmqqywaqd82lhnnk3a8wqunjz6gtxdtavnnekc' ] await wallet.subscribeToAddressNotifications(addresses, myCallback) // Subscribe to all wallet addresses const accounts = wallet.accountStore.listAccounts() const allAddresses = accounts.flatMap(account => account.getAddresses().map(addr => addr.address) ) await wallet.subscribeToAddressNotifications(allAddresses, myCallback) // Always unsubscribe when done to prevent memory leaks await wallet.unsubscribeFromAddressNotifications(allAddresses, myCallback) ``` ### Parse Existing Transactions ```typescript // From hex string const tx = await wallet.newTransaction(account) .parseTxHex('0100000001...') .sign() .build() // From buffer const txBuffer = Buffer.from('0100000001...', 'hex') const tx = await wallet.newTransaction(account) .parseTxBuffer(txBuffer) .sign() .build() ``` ### Export Wallet Data ```typescript const walletData = wallet.export() // Contains encrypted seed and account information for backup ``` ### Broadcasting Transactions ```typescript // Broadcast a signed transaction const txId = await wallet.sendTransaction(signedTxHex) console.log('Transaction ID:', txId) // Or use watch-only wallet const txId = await watchOnlyWallet.sendTransaction(signedTxHex) ``` ## Available Exports The SDK exports the following components: ```typescript import { // Core classes Wallet, WatchOnlyWallet, // Account types BaseAccount, DefaultAccount, DappAccount, VaultAccount, AccountStore, // Transaction creators WalletTransactionCreator, WatchOnlyTransactionCreator, // Network provider rostrumProvider, // Utility functions ValidationUtils, isValidNexaAddress, // Utility classes AccountKeysUtils, // Enums AccountType, TxTokenType, // Types AccountKeys, AccountIndexes, AddressKey, Balance, WatchOnlyAddress, TransactionEntity, TokenAction } from 'nexa-wallet-sdk' ``` ## Error Handling ```typescript try { const tx = await wallet.newTransaction(account) .sendTo('invalid-address', '1000') .populate() .sign() .build() } catch (error) { if (error.message.includes('Invalid address')) { console.error('Invalid Nexa address provided') } else if (error.message.includes('Insufficient funds')) { console.error('Not enough balance for transaction') } else { console.error('Transaction failed:', error.message) } } ``` ## Network Configuration ```typescript // Testnet (for development) const testnetWallet = new Wallet(seedPhrase, 'testnet') // Mainnet (for production) const mainnetWallet = new Wallet(seedPhrase, 'mainnet') // Always specify network in transactions const tx = await wallet.newTransaction(account) .onNetwork('testnet') // Must match wallet network .sendTo(address, amount) .populate() .sign() .build() ``` ## Best Practices 1. **Always Connect First**: Call `await rostrumProvider.connect()` before wallet operations 2. **Network Consistency**: Ensure wallet and transaction networks match 3. **Amount Precision**: Use strings for amounts to avoid floating-point precision issues 4. **Error Handling**: Wrap wallet operations in try-catch blocks 5. **Private Key Security**: Never log or expose private keys or seed phrases 6. **Address Validation**: Validate addresses before sending transactions 7. **Fee Estimation**: Use `populate()` to estimate fees before signing 8. **Memory Management**: Always unsubscribe from address notifications when done to prevent memory leaks ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. ## License This project is licensed under the MIT License - see the LICENSE file for details. ## Support For issues and questions: - GitHub Issues: [wallet-sdk-ts issues](https://gitlab.com/nexa/wallet-sdk-ts/issues) - Documentation: [Nexa Documentation](https://docs.nexa.org) --- **⚠️ Security Notice**: Never share your seed phrases or private keys. Always verify addresses before sending transactions. This SDK is for development purposes - use appropriate security measures in production applications.