UNPKG

@mayaprotocol/zcash-js

Version:

Zcash JavaScript library for Maya Protocol - Build and sign Zcash transparent transactions with memo support

106 lines (105 loc) 5.79 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const blake2b_wasm_1 = __importDefault(require("blake2b-wasm")); const _1 = require("."); const rpc_1 = require("./rpc"); // For ex, http://172.0.0.1:8232 for mainnet, port 18232 for regnet const host = process.env.ZCASHD_URL; const config = { server: { host: host, user: 'mayachain', password: 'password' }, mainnet: false }; const address = 'tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW'; // Helper to wait for next block async function waitForNextBlock(ms = 3000) { await new Promise(resolve => setTimeout(resolve, ms)); } test('get address of pubkey', () => { const addr = (0, _1.pkToAddr)(Buffer.from('02aa7ef4b1958837763303a675dea8f63eaf264494072f086acdbc78d0decb0d0f', 'hex'), Buffer.from(_1.testnetPrefix)); expect(addr).toBe('tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW'); }); test('tx fee', async () => { const utxos = await (0, rpc_1.getUTXOS)('tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', config); const utx = await (0, _1.buildTx)(0, 'tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', 'tmGys6dBuEGjch5LFnhdo5gpSa7jiNRWse6', 1000000, utxos, false); expect(utx.fee).toBe(15000); }); test('not enough funds', async () => { const utxos = await (0, rpc_1.getUTXOS)('tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', config); await expect((0, _1.buildTx)(0, 'tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', 'tmGys6dBuEGjch5LFnhdo5gpSa7jiNRWse6', 1000000000000, utxos, false, 'MEMO')).rejects.toThrow('Not enough funds'); }); test('invalid address', () => { expect((0, _1.isValidAddr)('tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', Buffer.from(_1.testnetPrefix))).toBeTruthy(); expect((0, _1.isValidAddr)('t1R97mnhVqcE7Yq8p7yL4E29gy8etq9V9pG', Buffer.from(_1.testnetPrefix))).toBeFalsy(); expect((0, _1.isValidAddr)('t1R97mnhVqcE7Yq8p7yL4E29gy8etq9V9pG', Buffer.from(_1.mainnetPrefix))).toBeTruthy(); expect((0, _1.isValidAddr)('tminvalidaddress', Buffer.from(_1.testnetPrefix))).toBeFalsy(); }); test('invalid t2t tx', async () => { // "from" address is from the wrong network (mainnet) await expect((0, rpc_1.getUTXOS)('t1R97mnhVqcE7Yq8p7yL4E29gy8etq9V9pG', config)).rejects.toThrow(); }); test('create/send t2t tx', async () => { try { await blake2b_wasm_1.default.ready(); const utxos = await (0, rpc_1.getUTXOS)('tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', config); const utx = await (0, _1.buildTx)(0, 'tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', 'tmGys6dBuEGjch5LFnhdo5gpSa7jiNRWse6', 1000000, utxos, false); const txb = await (0, _1.signAndFinalize)(utx.height, '458e7fb32f0f0f4b7df08b6eb1e269d59366920f5f800f907e7746b600cf516c', utx.inputs, utx.outputs); const txid = await (0, _1.sendRawTransaction)(txb, config); expect(typeof txid).toBe('string'); console.log(txid); // Wait for transaction to be mined await (0, rpc_1.waitForTransaction)(txid, config); // Wait for next block to avoid UTXO conflicts await waitForNextBlock(); } catch (error) { throw error; } }); test('create/send t2t tx with memo', async () => { await blake2b_wasm_1.default.ready(); const utxos = await (0, rpc_1.getUTXOS)('tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', config); const utx = await (0, _1.buildTx)(0, 'tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', 'tmGys6dBuEGjch5LFnhdo5gpSa7jiNRWse6', 1000000, utxos, false, 'swap:cacao:maya1a7gg93dgwlulsrqf6qtage985ujhpu068zllw7'); const txb = await (0, _1.signAndFinalize)(utx.height, '458e7fb32f0f0f4b7df08b6eb1e269d59366920f5f800f907e7746b600cf516c', utx.inputs, utx.outputs); const txid = await (0, _1.sendRawTransaction)(txb, config); expect(typeof txid).toBe('string'); console.log('TX with memo:', txid); // Wait for transaction to be mined await (0, rpc_1.waitForTransaction)(txid, config); // Wait for next block to avoid UTXO conflicts await waitForNextBlock(); }); test('send tx with memo and insufficient fee', async () => { await blake2b_wasm_1.default.ready(); const utxos = await (0, rpc_1.getUTXOS)('tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', config); // Build transaction with memo const utx = await (0, _1.buildTx)(0, 'tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW', 'tmGys6dBuEGjch5LFnhdo5gpSa7jiNRWse6', 1000000, utxos, false, 'swap:cacao:maya1a7gg93dgwlulsrqf6qtage985ujhpu068zllw7'); // Verify the correct fee is 25000 (max(2, 1+3+2) * 5000 = max(2,6) * 5000 = 30000) expect(utx.fee).toBe(30000); // Manually reduce the change output to simulate insufficient fee const modifiedOutputs = [...utx.outputs]; // Find the change output (first output to our own address) const changeIndex = modifiedOutputs.findIndex(o => o.type === 'pkh' && o.address === 'tmUzzEDRjvE3QC8RBUFD7DTi5LLL4zAEvKW'); if (changeIndex >= 0) { const changeOutput = modifiedOutputs[changeIndex]; if (changeOutput.type === 'pkh') { // Increase change by 25000 sats (reducing fee from 30000 to 5000) // This should be below the minimum relay fee modifiedOutputs[changeIndex] = { type: 'pkh', address: changeOutput.address, amount: changeOutput.amount + 25000 }; } } // Try to sign and send with insufficient fee const txb = await (0, _1.signAndFinalize)(utx.height, '458e7fb32f0f0f4b7df08b6eb1e269d59366920f5f800f907e7746b600cf516c', utx.inputs, modifiedOutputs); // This should fail due to insufficient fee await expect((0, _1.sendRawTransaction)(txb, config)).rejects.toThrow('66: tx unpaid action limit exceeded'); });