diff --git a/examples/transactions/qihdwallet-aggregate.js b/examples/transactions/qihdwallet-aggregate.js new file mode 100644 index 00000000..df4ef8ed --- /dev/null +++ b/examples/transactions/qihdwallet-aggregate.js @@ -0,0 +1,99 @@ +const { + JsonRpcProvider, + Mnemonic, + QiHDWallet, + Zone, +} = require('../../lib/commonjs/quais'); +require('dotenv').config(); + +/** + * Qi HD Wallet UTXO Aggregation Example + * + * This script demonstrates how to aggregate multiple UTXOs into larger denominations + * in a QiHDWallet. It implements QIP-7 specifications for UTXO management and + * optimization of wallet holdings. + * + * The script demonstrates: + * 1. Creating and connecting a QiHDWallet to a provider + * 2. Scanning the wallet for available UTXOs in a specific zone + * 3. Displaying wallet addresses and current UTXO distribution + * 4. Attempting to aggregate smaller denomination UTXOs into larger ones + * 5. Verifying the aggregation results + * + * Usage: + * First, set up your .env file with: + * MNEMONIC="your twelve word mnemonic phrase here" + * RPC_URL="your Quai node RPC endpoint" + * + * Then run: + * ``` + * node qihdwallet-aggregate.js + * ``` + * + * The script will output: + * - Wallet addresses (both external and change) + * - Initial balance and UTXO distribution + * - Aggregation transaction details + * - Final balance and updated UTXO distribution + * + * Note: This example uses the Cyprus1 zone for demonstration. The aggregation + * process follows QIP-7 specifications for UTXO management, attempting to combine + * smaller denominations into larger ones when possible. The transaction will fail + * if no beneficial aggregation is possible with the current UTXO set. + */ + +async function main() { + // Create provider + const options = {usePathing: false}; + const provider = new JsonRpcProvider(process.env.RPC_URL, undefined, options); + + // Create wallet and connect to provider + console.log(process.env.RPC_URL) + const aliceMnemonic = Mnemonic.fromPhrase(process.env.MNEMONIC); + const aliceWallet = QiHDWallet.fromMnemonic(aliceMnemonic); + aliceWallet.connect(provider); + + // Scan Alice wallet + console.log("...scanning alice wallet"); + await aliceWallet.scan(Zone.Cyprus1); + + // log alice change wallet addresses + console.log("Alice change wallet addresses: ", aliceWallet.getChangeAddressesForZone(Zone.Cyprus1).map(a => a.address)); + // log alice external wallet addresses + console.log("Alice external wallet addresses: ", aliceWallet.getAddressesForZone(Zone.Cyprus1).map(a => a.address)); + + // Get Alice initial balance + console.log("...getting alice initial balance"); + const aliceInitialBalance = await aliceWallet.getBalanceForZone(Zone.Cyprus1); + console.log("Alice initial balance: ", aliceInitialBalance); + + // log Alice outpoints + console.log("Alice outpoints: ", JSON.stringify(aliceWallet.getOutpoints(Zone.Cyprus1), null, 2)); + + // Send Qi + console.log("...aggregating alice balance"); + const tx = await aliceWallet.aggregate(Zone.Cyprus1); + console.log("... Alice transaction sent. Waiting for receipt..."); + + // Wait for tx to be mined + const txReceipt = await tx.wait(); + console.log("Alice's transaction receipt (block number): ", txReceipt.blockNumber); + + // Get Alice final balance + console.log("...getting alice final balance"); + const aliceFinalBalance = await aliceWallet.getBalanceForZone(Zone.Cyprus1); + console.log("Alice final balance: ", aliceFinalBalance); + + // sync Alice wallet and log outpoints + console.log("...syncing alice wallet and logging outpoints"); + await aliceWallet.scan(Zone.Cyprus1); + console.log("Alice outpoints: ", JSON.stringify(aliceWallet.getOutpoints(Zone.Cyprus1), null, 2)); + +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/examples/transactions/qihdwallet-convert-to-quai.js b/examples/transactions/qihdwallet-convert-to-quai.js new file mode 100644 index 00000000..b8362e5a --- /dev/null +++ b/examples/transactions/qihdwallet-convert-to-quai.js @@ -0,0 +1,102 @@ +const { + JsonRpcProvider, + Mnemonic, + QiHDWallet, + QuaiHDWallet, + Zone, +} = require('../../lib/commonjs/quais'); +require('dotenv').config(); + +/** + * Qi to Quai Conversion Example + * + * This script demonstrates how to convert Qi (UTXO-based) tokens to Quai (EVM-based) tokens + * using QiHDWallet. It implements QIP-7 specifications for UTXO management and cross-ledger + * conversion between Qi and Quai ledgers. + * + * The script demonstrates: + * 1. Creating both Qi and Quai HD wallets from the same mnemonic + * 2. Scanning the Qi wallet for available UTXOs in a specific zone + * 3. Displaying wallet addresses and current UTXO distribution + * 4. Converting a specified amount of Qi tokens to Quai tokens + * 5. Verifying the conversion results in both ledgers + * + * Usage: + * First, set up your .env file with: + * MNEMONIC="your twelve word mnemonic phrase here" + * RPC_URL="your Quai node RPC endpoint" + * + * Then run: + * ``` + * node qihdwallet-convert-to-quai.js + * ``` + * + * The script will output: + * - Qi and Quai wallet addresses + * - Initial Qi balance and UTXO distribution + * - Conversion transaction details + * - Final Quai balance after conversion + * + * Note: This example uses the Cyprus1 zone for demonstration. The conversion + * process follows QIP-7 specifications for cross-ledger operations, allowing + * users to move value between Qi (UTXO) and Quai (EVM) ledgers within the + * same zone. The transaction will fail if insufficient UTXOs are available + * for the requested conversion amount. + */ + +async function main() { + // Create provider + const options = {usePathing: false}; + const provider = new JsonRpcProvider(process.env.RPC_URL, undefined, options); + + // Create wallet and connect to provider + console.log(process.env.RPC_URL) + const aliceMnemonic =Mnemonic.fromPhrase(process.env.MNEMONIC); + const aliceQiWallet =QiHDWallet.fromMnemonic(aliceMnemonic); + aliceQiWallet.connect(provider); + + const aliceQuaiWallet =QuaiHDWallet.fromMnemonic(aliceMnemonic); + aliceQuaiWallet.connect(provider); + // get alice quai address + const aliceQuaiAddressInfo = aliceQuaiWallet.getNextAddressSync(0,Zone.Cyprus1); + console.log("Alice Quai address: ", aliceQuaiAddressInfo.address); + + // Scan Alice wallet + console.log("...scanning alice wallet"); + await aliceQiWallet.scan(Zone.Cyprus1); + + // log alice change wallet addresses + console.log("Alice change wallet addresses: ", aliceQiWallet.getChangeAddressesForZone(Zone.Cyprus1).map(a => a.address)); + // log alice external wallet addresses + console.log("Alice external wallet addresses: ", aliceQiWallet.getAddressesForZone(Zone.Cyprus1).map(a => a.address)); + + // Get Alice initial balance + console.log("...getting alice initial balance"); + const aliceInitialQiBalance = await aliceQiWallet.getBalanceForZone(Zone.Cyprus1); + console.log("Alice initial Qi balance: ", aliceInitialQiBalance); + + // log Alice outpoints + console.log("Alice outpoints: ", JSON.stringify(aliceQiWallet.getOutpoints(Zone.Cyprus1), null, 2)); + + const amountToConvert = 100000; + console.log(`...converting ${amountToConvert} Qi to Quai address ${aliceQuaiAddressInfo.address}`); + + const tx = await aliceQiWallet.convertToQuai(aliceQuaiAddressInfo.address, amountToConvert); + console.log("... Alice transaction sent. Waiting for receipt..."); + + // Wait for tx to be mined + const txReceipt = await tx.wait(); + console.log("Alice's transaction receipt (block number): ", txReceipt.blockNumber); + + // Get Alice updated Quai balance + const aliceUpdatedQuaiBalance = await provider.getBalance(aliceQuaiAddressInfo.address); + console.log("Alice updated Quai balance: ", aliceUpdatedQuaiBalance); + +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/examples/transactions/qihdwallet-sendTransaction.js b/examples/transactions/qihdwallet-sendTransaction.js new file mode 100644 index 00000000..d4964ab0 --- /dev/null +++ b/examples/transactions/qihdwallet-sendTransaction.js @@ -0,0 +1,124 @@ +const { + JsonRpcProvider, + Mnemonic, + QiHDWallet, + Zone, +} = require('../../lib/commonjs/quais'); +require('dotenv').config(); + +/** + * Qi HD Wallet Transaction Example + * + * This script demonstrates how to perform UTXO-based transactions using QiHDWallet + * between two parties (Alice and Bob) on the Quai network. It implements BIP-0047 + * payment codes for secure address generation and QIP-7 for UTXO transactions. + * + * The script demonstrates: + * 1. Creating QiHDWallets for both sender (Alice) and receiver (Bob) + * 2. Generating and exchanging payment codes between parties + * 3. Opening payment channels using BIP-0047 + * 4. Scanning wallets for available UTXOs + * 5. Sending Qi tokens from Alice to Bob using payment codes + * + * Usage: + * First, set up your .env file with: + * MNEMONIC="sender's twelve word mnemonic phrase here" + * RPC_URL="your Quai node RPC endpoint" + * + * Then run: + * ``` + * node qihdwallet-sendTransaction.js + * ``` + * + * The script will output: + * - Payment codes for both Alice and Bob + * - Wallet addresses for both parties + * - Initial balances + * - Transaction details and confirmation + * + * Note: This example uses the Cyprus1 zone for demonstration. The QiHDWallet + * implements UTXO-based transactions as specified in QIP-7, with privacy features + * from BIP-0047 payment codes. + */ + +async function main() { + // Create provider + const options = {usePathing: false}; + const provider = new JsonRpcProvider(process.env.RPC_URL, undefined, options); + + // Create wallet and connect to provider + console.log(process.env.RPC_URL) + const aliceMnemonic = Mnemonic.fromPhrase(process.env.MNEMONIC); + const aliceWallet = QiHDWallet.fromMnemonic(aliceMnemonic); + aliceWallet.connect(provider); + + // Get Alice payment code + const alicePaymentCode = aliceWallet.getPaymentCode(0); + console.log("Alice payment code: ", alicePaymentCode); + + // Create Bob wallet + const BOB_MNEMONIC = "innocent perfect bus miss prevent night oval position aspect nut angle usage expose grace juice"; + const bobMnemonic = Mnemonic.fromPhrase(BOB_MNEMONIC); + const bobWallet = QiHDWallet.fromMnemonic(bobMnemonic); + bobWallet.connect(provider); + + // Get Bob payment code + const bobPaymentCode = bobWallet.getPaymentCode(0); + console.log("Bob payment code: ", bobPaymentCode); + + // Open channel + aliceWallet.openChannel(bobPaymentCode); + bobWallet.openChannel(alicePaymentCode); + + // Scan Alice wallet + console.log("...scanning alice wallet"); + await aliceWallet.scan(Zone.Cyprus1); + + // log alice change wallet addresses + console.log("Alice change wallet addresses: ", aliceWallet.getChangeAddressesForZone(Zone.Cyprus1).map(a => a.address)); + // log alice external wallet addresses + console.log("Alice external wallet addresses: ", aliceWallet.getAddressesForZone(Zone.Cyprus1).map(a => a.address)); + + // // Scan Bob wallet + console.log("...scanning bob wallet"); + await bobWallet.scan(Zone.Cyprus1); + + // Get Alice initial balance + console.log("...getting alice initial balance"); + const aliceInitialBalance = await aliceWallet.getBalanceForZone(Zone.Cyprus1); + console.log("Alice initial balance: ", aliceInitialBalance); + + // Get Bob initial balance + console.log("...getting bob initial balance"); + const bobInitialBalance = await bobWallet.getBalanceForZone(Zone.Cyprus1); + console.log("Bob initial balance: ", bobInitialBalance); + + // log Alice outpoints + console.log("Alice outpoints: ", JSON.stringify(aliceWallet.getOutpoints(Zone.Cyprus1), null, 2)); + + // Send Qi + const amountToSendToBob = 15000000; + console.log(`...sending ${amountToSendToBob} qit to Bob`); + const tx = await aliceWallet.sendTransaction(bobPaymentCode, amountToSendToBob, Zone.Cyprus1, Zone.Cyprus1); + console.log("... Alice transaction sent. Waiting for receipt..."); + + // Wait for tx to be mined + const txReceipt = await tx.wait(); + console.log("Alice's transaction receipt received. Block number: ", txReceipt.blockNumber); + + // Scan Bob wallet + console.log("...scanning bob wallet"); + await bobWallet.scan(Zone.Cyprus1); + + // Get Bob final balance + console.log("...getting bob final balance"); + const bobFinalBalance = await bobWallet.getBalanceForZone(Zone.Cyprus1); + console.log("Bob final balance: ", bobFinalBalance); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/examples/transactions/quaihdwallet-send-quai-tx.js b/examples/transactions/quaihdwallet-send-quai-tx.js new file mode 100644 index 00000000..3c8f94dd --- /dev/null +++ b/examples/transactions/quaihdwallet-send-quai-tx.js @@ -0,0 +1,91 @@ +const { + JsonRpcProvider, + Mnemonic, + QuaiHDWallet, + QuaiTransaction, + Zone, +} = require('../../lib/commonjs/quais'); +require('dotenv').config(); + +/** + * Quai HD Wallet Transaction Example + * + * This script demonstrates how to perform EVM-based transactions using QuaiHDWallet + * on the Quai network. It shows the basic functionality of sending Quai tokens + * between addresses within the same wallet. + * + * The script demonstrates: + * 1. Creating and connecting a QuaiHDWallet to a provider + * 2. Generating new addresses within a specific zone + * 3. Checking initial balances + * 4. Sending Quai tokens between addresses + * 5. Verifying transaction completion and final balances + * + * Usage: + * First, set up your .env file with: + * MNEMONIC="your twelve word mnemonic phrase here" + * RPC_URL="your Quai node RPC endpoint" + * + * Then run: + * ``` + * node quaihdwallet-send-quai-tx.js + * ``` + * + * The script will output: + * - Generated sender and receiver addresses + * - Initial balance of the receiver + * - Transaction details and confirmation + * - Final balance after transfer + * + * Note: This example uses the Cyprus1 zone for demonstration. The transaction + * follows standard EVM-based operations, with optional parameters for chainId, + * nonce, gasLimit, and gasPrice that can be customized as needed. The transaction + * will fail if the sender has insufficient funds or if gas parameters are incorrectly + * specified. + */ + + +async function main() { + // Create provider + const options = {usePathing: false}; + const provider = new JsonRpcProvider(process.env.RPC_URL, undefined, options); + + // Create wallet and connect to provider + const mnemonic = Mnemonic.fromPhrase(process.env.MNEMONIC); + const quaiWallet = QuaiHDWallet.fromMnemonic(mnemonic); + quaiWallet.connect(provider); + + // Create tx + const addressInfo1 = await quaiWallet.getNextAddress(0, Zone.Cyprus1); + const from = addressInfo1.address; + const txObj = new QuaiTransaction(from); + const addressInfo2 = await quaiWallet.getNextAddress(0, Zone.Cyprus1); + const to = addressInfo2.address; + txObj.to = to; + const initialBalance = await provider.getBalance(to); + console.log('Initial balance:', initialBalance); + txObj.value = BigInt(420000); + /* + * The following fields are optional, but can be set as follows: + * txObj.chainId = BigInt(9000); + * txObj.nonce = await provider.getTransactionCount(from, 'latest'); + * txObj.gasLimit = BigInt(1000000); + * txObj.gasPrice = BigInt(30000000000000), + */ + + // Sign and send the transaction + const tx = await quaiWallet.sendTransaction(txObj); + + // Wait for tx to be mined + const txReceipt = await tx.wait(); + console.log('\nTx included in block:', txReceipt.blockNumber); + const finalBalance = await provider.getBalance(to); + console.log('Final balance:', finalBalance); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/examples/transactions/send-qi-tx.js b/examples/transactions/send-qi-tx.js deleted file mode 100644 index e6cc9b75..00000000 --- a/examples/transactions/send-qi-tx.js +++ /dev/null @@ -1,73 +0,0 @@ -const quais = require('../../lib/commonjs/quais'); -require('dotenv').config(); - -async function main() { - // Create provider - const provider = new quais.JsonRpcProvider(process.env.RPC_URL); - - // Create wallet and connect to provider - console.log(process.env.RPC_URL) - const mnemonic = quais.Mnemonic.fromPhrase(process.env.MNEMONIC); - console.log(mnemonic) - const qiWallet = quais.QiHDWallet.fromMnemonic(mnemonic); - qiWallet.connect(provider); - - // Get address info - const addressInfo1 = await qiWallet.getNextAddress(0, quais.Zone.Cyprus1); - const addr1 = addressInfo1.address; - const pubkey1 = addressInfo1.pubKey; - - // Define the outpoints for addr1 (this is just an example outpoint) - // Outpoints are typically obtained via the getOutpointsForAddress function - const outpointsInfo = [ - { - outpoint: { - txhash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', - index: 0, - denomination: 7, - }, - address: addr1, - zone: quais.Zone.Cyprus1, - }, - ]; - - // Polulate wallet with outpoints - qiWallet.importOutpoints(outpointsInfo); - - // Set tx inputs and outputs for the Qi Tx - let txInputs = [ - { - txhash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', - index: 0, - pubkey: pubkey1, - }, - ]; - - let txOutputs = [ - { - address: '0x002F4783248e2D6FF1aa6482A8C0D7a76de3C329', - denomination: 7, - }, - ]; - - // Create the Qi Tx to be signed - const txObj = new quais.QiTransaction(); - txObj.txInputs = txInputs; - txObj.txOutputs = txOutputs; - - // Sign and send the tx - console.log('\nSending Qi Tx...') - const tx = await qiWallet.sendTransaction(txObj); - console.log('\nTx:', tx) - - // Wait for tx to be mined - const txReceipt = await tx.wait(); - console.log('\nTx receipt:', txReceipt); -} - -main() - .then(() => process.exit(0)) - .catch((error) => { - console.error(error); - process.exit(1); - }); diff --git a/examples/transactions/send-quai-tx.js b/examples/transactions/send-quai-tx.js deleted file mode 100644 index c5d36b2f..00000000 --- a/examples/transactions/send-quai-tx.js +++ /dev/null @@ -1,40 +0,0 @@ -const quais = require('../../lib/commonjs/quais'); -require('dotenv').config(); - -async function main() { - // Create provider - const provider = new quais.JsonRpcProvider(process.env.RPC_URL); - - // Create wallet and connect to provider - const mnemonic = quais.Mnemonic.fromPhrase(process.env.MNEMONIC); - const quaiWallet = quais.QuaiHDWallet.fromMnemonic(mnemonic); - quaiWallet.connect(provider); - - // Create tx - const addressInfo1 = await quaiWallet.getNextAddress(0, quais.Zone.Cyprus1); - const from = addressInfo1.address; - const txObj = new quais.QuaiTransaction(from); - txObj.to = '0x002F4783248e2D6FF1aa6482A8C0D7a76de3C329'; - txObj.value = BigInt(4200000); - /* - * The following fields are optional, but can be set as follows: - * txObj.chainId = BigInt(9000); - * txObj.nonce = await provider.getTransactionCount(from, 'latest'); - * txObj.gasLimit = BigInt(1000000); - * txObj.gasPrice = BigInt(30000000000000), - */ - - // Sign and send the transaction - const tx = await quaiWallet.sendTransaction(txObj); - - // Wait for tx to be mined - const txReceipt = await tx.wait(); - console.log('\nTx receipt:', txReceipt); -} - -main() - .then(() => process.exit(0)) - .catch((error) => { - console.error(error); - process.exit(1); - });