From ee94bc4f7df7d7cd5c7cf9896ada4ebf74033644 Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Thu, 30 Jan 2025 14:25:13 +1100 Subject: [PATCH] feat: Initial non working code --- .gitignore | 1 + atomic-swap.js | 209 +++++++++++++++ domain.json | 35 +++ hsd-ledger | 654 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 521 ++++++++++++++++++++++++++++++++++++ package.json | 20 ++ 6 files changed, 1440 insertions(+) create mode 100644 .gitignore create mode 100644 atomic-swap.js create mode 100644 domain.json create mode 100755 hsd-ledger create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/atomic-swap.js b/atomic-swap.js new file mode 100644 index 0000000..b03fcdd --- /dev/null +++ b/atomic-swap.js @@ -0,0 +1,209 @@ +'use strict'; + +const assert = require('bsert'); +const Network = require('hsd/lib/protocol/network'); +const FullNode = require('hsd/lib/node/fullnode'); +const MTX = require('hsd/lib/primitives/mtx'); +const Address = require('hsd/lib/primitives/address'); +const Output = require('hsd/lib/primitives/output'); +const Script = require('hsd/lib/script/script'); +const rules = require('hsd/lib/covenants/rules'); +const {types} = rules; +const {Resource} = require('hsd/lib/dns/resource'); +// const WalletClient = require('hsd/lib/client/wallet'); +const { NodeClient, WalletClient } = require('hs-client'); + +const network = Network.get('main'); +const minimist = require('minimist'); +const args = minimist(process.argv.slice(2)); + + +//! TODO this needs to hook into existing node +// const node = new FullNode({ +// memory: true, +// network: 'main' +// }); + +const nclient = new NodeClient({ + url: args.hsdIP || 'localhost', + apiKey: args.apiKey || '', + ssl: false, + host: args.hsdIP || 'localhost', + port: 12037 + }); + + const wclient = new WalletClient({ + url: args.hsdIP || 'localhost', + apiKey: args.apiKey || '', + ssl: false, + host: args.hsdIP || 'localhost', + port: 12039, + }); + +nclient.open(); +wclient.open(); + + +// const {wdb} = wclient.require('walletdb'); + +const price = args.price/1000000 || 1.234567; // 1.234567 HNS +const domainAddress = args.domainAddress || 'hs1qsyy6eujpt2wv0caa0d26tvwejx77zdks2pj8nz'; +const buyerAddress = args.buyer || 'hs1qcq8nzmlus8z5qqn6wvls9r0vg98tr6d6ga3fau'; +const sellerAddress = args.seller || 'hs1q962sf24659wm6ev26gshrfwg8ruhve4c34f0ur'; +const ns = args.nameInfo || {"name": "woodburn1","nameHash": "c93640a7772f786391c1c3ff2e99e4aaa442b6f2cf1fc6ec1790f2ea818dec08","state": "CLOSED","height": 175454,"renewal": 252162,"owner": {"hash": "337edb6e00aaf602a218d35d499b088872d2e74b9463066da845edccbe797c27","index": 4},"value": 1000000,"highest": 1000000,"data": "0001036e733108776f6f646275726e0001036e7332c006060204546573740548656c6c6f","transfer": 0,"revoked": 0,"claimed": 0,"renewals": 4,"registered": true,"expired": false,"weak": false,"stats": {"renewalPeriodStart": 252162,"renewalPeriodEnd": 357282,"blocksUntilExpire": 95192,"daysUntilExpire": 661.06}}; +const walletId = args.walletId || 'hot'; + +const name = ns.name; +const nameHash = ns.nameHash; + + + +// Alice constructs an incomplete transaction. +// input 0 and output 1 are committed by Alice's SINGLEREVERSE signature. +// output 0 can be added by either party since it's construction is +// dictated completely by consensus rules (it isn't signed yet). +// +// input 0: TRANSFER UTXO --> output 0: FINALIZE covenant +// (null) --- output 1: payment to Alice + +const owner = ns.owner; +wclient.execute('selectwallet', [walletId]); +const coin = wclient.getCoin(owner.hash, owner.index); + +const output0 = new Output(); +output0.value = coin.value; +output0.address = buyerAddress; +output0.covenant.setFinalize( + nameHash, + ns.height, + Buffer.from(name, 'ascii'), + 0, // flags, may be required if name was CLAIMed + ns.claimed, + ns.renewals, + wdb.getRenewalBlock() +); + +const output1 = new Output(); +output1.address = sellerAddress; +output1.value = price; + +const mtx = new MTX(); +mtx.addCoin(coin); +mtx.outputs.push(output0); +mtx.outputs.push(output1); + +// Sign +const rings = wclient.deriveInputs(mtx); +assert(rings.length === 1); +const signed = mtx.sign( + rings, + Script.hashType.SINGLEREVERSE | Script.hashType.ANYONECANPAY +); +assert(signed === 1); + +assert(mtx.verify()); +blob = mtx.encode().toString('hex'); +console.log(blob); + + +// COMPLETE TX + + // it('should complete transaction', async () => { + // // Bob receives the hex string as a blob and decodes. + // const mtx = MTX.decode(Buffer.from(blob, 'hex')); + + // // Bob should verify all the data in the MTX to ensure everything is valid, + // // but this is the minimum. + // const input0 = mtx.input(0).clone(); // copy input with Alice's signature + // const coinEntry = await nclient.chain.db.readCoin(input0.prevout); + // assert(coinEntry); // ensures that coin exists and is still unspent + + // const coin = coinEntry.toCoin(input0.prevout); + // assert(coin.covenant.type === types.TRANSFER); + // const addr = new Address({ + // version: coin.covenant.items[2].readInt8(), + // hash: coin.covenant.items[3] + // }); + // assert.deepStrictEqual(addr, bobReceive); // transfer is to Bob's address + + // // Fund the TX. + // // The hsd wallet is not designed to handle partially-signed TXs + // // or coins from outside the wallet, so a little hacking is needed. + // const changeAddress = await bob.changeAddress(); + // const rate = await wdb.estimateFee(); + // const coins = await bob.getSmartCoins(); + // // Add the external coin to the coin selector so we don't fail assertions + // coins.push(coin); + // await mtx.fund(coins, {changeAddress, rate}); + // // The funding mechanism starts by wiping out existing inputs + // // which for us includes Alice's signature. Replace it from our backup. + // mtx.inputs[0].inject(input0); + + // // Rearrange outputs. + // // Since we added a change output, the SINGELREVERSE is now broken: + // // + // // input 0: TRANSFER UTXO --> output 0: FINALIZE covenant + // // input 1: Bob's funds --- output 1: payment to Alice + // // (null) --- output 2: change to Bob + // const outputs = mtx.outputs.slice(); + // mtx.outputs = [outputs[0], outputs[2], outputs[1]]; + + // // Prepare to wait for mempool acceptance (race condition) + // const waiter = new Promise((resolve, reject) => { + // node.mempool.once('tx', resolve); + // }); + + // // Sign & Broadcast + // // Bob uses SIGHASHALL. The final TX looks like this: + // // + // // input 0: TRANSFER UTXO --> output 0: FINALIZE covenant + // // input 1: Bob's funds --- output 1: change to Bob + // // (null) --- output 2: payment to Alice + // const tx = await bob.sendMTX(mtx); + // bobFee = tx.getFee(mtx.view); + // assert(tx.verify(mtx.view)); + + // // Wait for mempool and check + // await waiter; + // assert(node.mempool.hasEntry(tx.hash())); + + // // Confirm + // await mineBlocks(1); + // }); + + // it('should verify that name has been swapped', async () => { + // const aliceNewBalance = await alice.getBalance(); + // const bobNewBalance = await bob.getBalance(); + + // // Alice got the monies + // // Note: This test works right now because the value of the name + // // Alice won in the auction is ZERO (she had the only bid) + // // See https://github.com/handshake-org/hsd/pull/464 for explanation + // // Currently hsd wallet does not account for FINALIZE correctly + // assert.strictEqual( + // aliceNewBalance.confirmed, + // aliceOriginalBalance.confirmed + price + // ); + // assert.strictEqual( + // bobNewBalance.confirmed, + // bobOriginalBalance.confirmed - price - bobFee + // ); + + // // Bob got the name + // const ns = await node.getNameStatus(nameHash); + // const owner = ns.owner; + // let coin = await alice.getCoin(owner.hash, owner.index); + // assert(!coin); + // coin = await bob.getCoin(owner.hash, owner.index); + // assert(coin); + + // const resource = Resource.fromJSON({ + // records: [{type: 'TXT', txt: ['Thanks Alice! --Bob']}] + // }); + // await bob.sendUpdate(name, resource); + // await mineBlocks(network.names.treeInterval); + // const actual = await node.chain.db.getNameState(nameHash); + // assert.bufferEqual(resource.encode(), actual.data); + + // // The End + // }); \ No newline at end of file diff --git a/domain.json b/domain.json new file mode 100644 index 0000000..912db69 --- /dev/null +++ b/domain.json @@ -0,0 +1,35 @@ +{ + "start": { + "reserved": false, + "week": 12, + "start": 14112, + "locked": false + }, + "info": { + "name": "woodburn1", + "nameHash": "c93640a7772f786391c1c3ff2e99e4aaa442b6f2cf1fc6ec1790f2ea818dec08", + "state": "CLOSED", + "height": 175454, + "renewal": 252162, + "owner": { + "hash": "337edb6e00aaf602a218d35d499b088872d2e74b9463066da845edccbe797c27", + "index": 4 + }, + "value": 1000000, + "highest": 1000000, + "data": "0001036e733108776f6f646275726e0001036e7332c006060204546573740548656c6c6f", + "transfer": 0, + "revoked": 0, + "claimed": 0, + "renewals": 4, + "registered": true, + "expired": false, + "weak": false, + "stats": { + "renewalPeriodStart": 252162, + "renewalPeriodEnd": 357282, + "blocksUntilExpire": 95192, + "daysUntilExpire": 661.06 + } + } +} \ No newline at end of file diff --git a/hsd-ledger b/hsd-ledger new file mode 100755 index 0000000..643bff0 --- /dev/null +++ b/hsd-ledger @@ -0,0 +1,654 @@ +#!/usr/bin/env node + +'use strict'; + +/** + * Module imports + */ + + + +const Config = require('bcfg'); +const { NodeClient, WalletClient } = require('hs-client'); +const { hd, MTX, Network } = require('hsd'); +const { Rules } = require('hsd/lib/covenants'); +const { hashName, types } = Rules; +const { util, HID, LedgerHSD, LedgerChange, LedgerCovenant } = require('..'); +const { Device } = HID; +// Import from renewal.js the functions to fetch domains and create a batch +const { fetchDomains, createBatch } = require('./renewal.js'); + + +/** + * Global constants + */ + +const VALID_CMDS = [ + 'createwallet', + 'createaccount', + 'createaddress', + 'sendtoaddress', + 'getwallets', + 'getaccounts', + 'getaccount', + 'getbalance', + 'sendraw', + 'signraw', + 'renew' +]; + +const VERSION = require('../package').version; + +async function createWallet(client, config, ledger, args) { + if (args.length !== 1) + throw new Error('Invalid arguments'); + + const id = args[0]; + const index = config.uint('account-index'); + const xpub = await ledger.getAccountXPUB(index); + const wallet = await client.createWallet(id, { + watchOnly: true, + accountKey: xpub.xpubkey(config.str('network')) + }); + + console.log(`Created wallet (id=hsd-ledger, wid=${wallet.wid}).`); + console.log(`Created account (name=default, account-index=${index}').`); +} + +async function createAccount(client, config, ledger, args) { + if (args.length !== 2) + throw new Error('Invalid arguments'); + + const id = config.str('wallet-id'); + const name = args[0]; + const index = parseInt(args[1], 10); + const xpub = await ledger.getAccountXPUB(index); + await client.createAccount(id, name, { + watchOnly: true, + accountKey: xpub.xpubkey(config.str('network')) + }); + + console.log(`Created account (name=${name}, account-index=${index}').`); +} + +async function createAddress(client, config, ledger, args) { + if (args.length !== 0) + throw new Error('Invalid arguments'); + + const id = config.str('wallet-id'); + const name = config.str('account-name'); + const addr = await client.createAddress(id, name); + const acct = await client.getAccount(id, name); + const xpub = hd.PublicKey.fromBase58(acct.accountKey, config.str('network')); + const account = (xpub.childIndex ^ hd.common.HARDENED) >>> 0; + + console.log(`Verify address on Ledger device: ${addr.address}`); + + await ledger.getAddress(account, addr.branch, addr.index, { confirm: true }); +} + +async function sendToAddress(wclient, nclient, config, ledger, args) { + if (args.length !== 2) + throw new Error('Invalid arguments'); + + const network = Network.get(config.str('network')); + const id = config.str('wallet-id'); + const acct = config.str('account-name'); + const address = args[0]; + const amount = parseFloat(args[1]); + + await wclient.execute('selectwallet', [id]); + + const params = [address, amount, '', '', false, acct]; + const json = await wclient.execute('createsendtoaddress', params); + const mtx = MTX.fromJSON(json); + let i, key; + + for (i = mtx.outputs.length - 1; i >= 0; i--) { + const output = mtx.outputs[i]; + const addr = output.address.toString(network.type); + key = await wclient.getKey(id, addr); + + if (key && key.branch) + break; + } + + if (!key || !key.branch) + throw new Error('Expected change address.'); + + const { account, branch, index } = key; + const coinType = network.keyPrefix.coinType; + const options = { + change: new LedgerChange({ + path: `m/44'/${coinType}'/${account}'/${branch}/${index}`, + index: i, + version: 0 + }) + }; + + util.displayDetails(console, network, mtx, options); + + const signed = await ledger.signTransaction(mtx, options); + const rawtx = signed.encode().toString('hex'); + const txid = await nclient.execute('sendrawtransaction', [rawtx]); + + console.log(`Submitted TXID: ${txid}`); +} +async function sendRaw(wclient, nclient, config, ledger, args) { // Create a function to sign raw transactions + if (args.length !== 2) // Make sure there are two arguments (batch, names) + throw new Error('Invalid arguments'); // Throw an error if there are not two arguments + + const network = Network.get(config.str('network')); // Get the network + const id = config.str('wallet-id'); // Get the wallet id + const acct = config.str('account-name'); // Get the account name + // Log the arguments to the console (for debugging) + + const batch = JSON.parse(args[0]); // Get the batch + const names = JSON.parse(args[1]); // Get the names + await wclient.execute('selectwallet', [id]); // Select the wallet + + try { + const mtx = MTX.fromJSON(batch.result); // Create a new MTX from the JSON + const hashes = {}; // Create an empty object to store the hashes + for (const name of names) { // Loop through the names + const hash = hashName(name); // Hash the name + hashes[hash] = name; // Add the hash to the hashes object to use later + } + + + let i, key; // Create variables to use later + const options = []; // Create an empty array to store the options + for (i = mtx.outputs.length - 1; i >= 0; i--) { // Loop through the outputs + const output = mtx.outputs[i]; // Get the output + const addr = output.address.toString(network.type); // Get the address + key = await wclient.getKey(id, addr); // Get the key + if (!key) // If there is no key + continue; // Continue to the next output + if (key.branch === 1) { // If the key is a change address + if (options.change) // If there is already a change address + throw new Error('Transaction should only have one change output.'); // Throw an error + const path = `m/44'/${network.keyPrefix.coinType}'/${key.account}'/${key.branch}/${key.index}`; // Create the derivation path + options.change = new LedgerChange({ path: `m/44'/${network.keyPrefix.coinType}'/${key.account}'/${key.branch}/${key.index}`, index: i, version: 0 }); // Add the change address to the options + } + const { account, branch, index } = key; // Get the account, branch, and index from the key + const coinType = network.keyPrefix.coinType; // Get the coin type from the network + switch (output.covenant.type) { + case types.NONE: + case types.BID: + case types.FINALIZE: + break; + case types.OPEN: + case types.REVEAL: + case types.REDEEM: + case types.REGISTER: + case types.UPDATE: + case types.RENEW: + case types.TRANSFER: + case types.REVOKE: { // If the covenant type is any of REVEAL, REDEEM, REGISTER, UPDATE, RENEW, TRANSFER, or REVOKE + if (options.covenants == null) // If there are no covenants + options.covenants = []; // Create an empty array for the covenants + const hash = output.covenant.items[0]; // Get the hash from the covenant + const name = hashes[hash]; // Get the name from the hashes object (is needed for SPV nodes) + if (name == undefined) { // If the name is not found + console.log("Name not found in file"); // Log that the name was not found + console.log(hash); // Log the hash (for debugging) + } + options.covenants.push(new LedgerCovenant({ index: i, name })); // Add the covenant to the options + + break; + } + default: + throw new Error('Unrecognized covenant type.'); + + } + + } // end for loop + util.displayDetails(console, network, mtx, options); // Display the details to the log for user verification + const signed = await ledger.signTransaction(mtx, options); // Sign the transaction with the ledger + const rawtx = signed.encode().toString('hex'); // Encode the transaction as hex + const txid = await nclient.execute('sendrawtransaction', [rawtx]); // Send the transaction to the network + console.log(`Submitted TXID: ${txid}`); // Log the TXID to the console to view the transaction on a block explorer + + } catch (err) { // Catch any errors + console.error(err); // Log the error to the console + } +} + +async function renew(wclient, nclient, config, ledger, args) { // Create a function to sign raw transactions + if (args.length !== 1) // Make sure there are two arguments (batch, names) + throw new Error('Invalid arguments'); // Throw an error if there are not two arguments + + const network = Network.get(config.str('network')); // Get the network + const id = config.str('wallet-id'); // Get the wallet id + const acct = config.str('account-name'); // Get the account name + // Log the arguments to the console (for debugging) + + const type = args[0]; // Get the batch type + var batch; // Create a variable to store the batch + var names + if (type === 'all') { + names = await fetchDomains(id,0); // Fetch the domains + console.log(names.length); + if (names.length === 0) { + console.log("No domains to renew"); + return; + } + } + else { + const days = parseInt(type, 10); // Get the number of days + names = await fetchDomains(id,days); // Fetch the domains + } + + console.log("Renewing domains: ", names.length); + if (names.length === 0) { + console.log("No domains to renew"); + return; + } + batch = await createBatch(names); // Create the batch + + await wclient.execute('selectwallet', [id]); // Select the wallet + + try { + const mtx = MTX.fromJSON(batch.result); // Create a new MTX from the JSON + const hashes = {}; // Create an empty object to store the hashes + for (const name of names) { // Loop through the names + const hash = hashName(name); // Hash the name + hashes[hash] = name; // Add the hash to the hashes object to use later + } + + + let i, key; // Create variables to use later + const options = []; // Create an empty array to store the options + for (i = mtx.outputs.length - 1; i >= 0; i--) { // Loop through the outputs + const output = mtx.outputs[i]; // Get the output + const addr = output.address.toString(network.type); // Get the address + key = await wclient.getKey(id, addr); // Get the key + if (!key) // If there is no key + continue; // Continue to the next output + if (key.branch === 1) { // If the key is a change address + if (options.change) // If there is already a change address + throw new Error('Transaction should only have one change output.'); // Throw an error + const path = `m/44'/${network.keyPrefix.coinType}'/${key.account}'/${key.branch}/${key.index}`; // Create the derivation path + options.change = new LedgerChange({ path: `m/44'/${network.keyPrefix.coinType}'/${key.account}'/${key.branch}/${key.index}`, index: i, version: 0 }); // Add the change address to the options + } + const { account, branch, index } = key; // Get the account, branch, and index from the key + const coinType = network.keyPrefix.coinType; // Get the coin type from the network + switch (output.covenant.type) { + case types.NONE: + case types.BID: + case types.FINALIZE: + break; + case types.OPEN: + case types.REVEAL: + case types.REDEEM: + case types.REGISTER: + case types.UPDATE: + case types.RENEW: + case types.TRANSFER: + case types.REVOKE: { // If the covenant type is any of REVEAL, REDEEM, REGISTER, UPDATE, RENEW, TRANSFER, or REVOKE + if (options.covenants == null) // If there are no covenants + options.covenants = []; // Create an empty array for the covenants + const hash = output.covenant.items[0]; // Get the hash from the covenant + const name = hashes[hash]; // Get the name from the hashes object (is needed for SPV nodes) + if (name == undefined) { // If the name is not found + console.log("Name not found in file"); // Log that the name was not found + console.log(hash); // Log the hash (for debugging) + } + options.covenants.push(new LedgerCovenant({ index: i, name })); // Add the covenant to the options + + break; + } + default: + throw new Error('Unrecognized covenant type.'); + + } + + } // end for loop + util.displayDetails(console, network, mtx, options); // Display the details to the log for user verification + const signed = await ledger.signTransaction(mtx, options); // Sign the transaction with the ledger + const rawtx = signed.encode().toString('hex'); // Encode the transaction as hex + const txid = await nclient.execute('sendrawtransaction', [rawtx]); // Send the transaction to the network + console.log(`Submitted TXID: ${txid}`); // Log the TXID to the console to view the transaction on a block explorer + + } catch (err) { // Catch any errors + console.error(err); // Log the error to the console + } +} + +async function signRaw(wclient, nclient, config, ledger, args) { // Create a function to sign raw transactions + if (args.length !== 2) // Make sure there are two arguments (batch, names) + throw new Error('Invalid arguments'); // Throw an error if there are not two arguments + + const network = Network.get(config.str('network')); // Get the network + const id = config.str('wallet-id'); // Get the wallet id + const acct = config.str('account-name'); // Get the account name + // Log the arguments to the console (for debugging) + + const batch = JSON.parse(args[0]); // Get the batch + const names = JSON.parse(args[1]); // Get the names + await wclient.execute('selectwallet', [id]); // Select the wallet + + try { + const mtx = MTX.fromJSON(batch.result); // Create a new MTX from the JSON + const hashes = {}; // Create an empty object to store the hashes + for (const name of names) { // Loop through the names + const hash = hashName(name); // Hash the name + hashes[hash] = name; // Add the hash to the hashes object to use later + } + + + let i, key; // Create variables to use later + const options = []; // Create an empty array to store the options + for (i = mtx.outputs.length - 1; i >= 0; i--) { // Loop through the outputs + const output = mtx.outputs[i]; // Get the output + const addr = output.address.toString(network.type); // Get the address + key = await wclient.getKey(id, addr); // Get the key + if (!key) // If there is no key + continue; // Continue to the next output + if (key.branch === 1) { // If the key is a change address + if (options.change) // If there is already a change address + throw new Error('Transaction should only have one change output.'); // Throw an error + const path = `m/44'/${network.keyPrefix.coinType}'/${key.account}'/${key.branch}/${key.index}`; // Create the derivation path + options.change = new LedgerChange({ path: `m/44'/${network.keyPrefix.coinType}'/${key.account}'/${key.branch}/${key.index}`, index: i, version: 0 }); // Add the change address to the options + } + const { account, branch, index } = key; // Get the account, branch, and index from the key + const coinType = network.keyPrefix.coinType; // Get the coin type from the network + switch (output.covenant.type) { + case types.NONE: + case types.BID: + case types.FINALIZE: + break; + case types.OPEN: + case types.REVEAL: + case types.REDEEM: + case types.REGISTER: + case types.UPDATE: + case types.RENEW: + case types.TRANSFER: + case types.REVOKE: { // If the covenant type is any of REVEAL, REDEEM, REGISTER, UPDATE, RENEW, TRANSFER, or REVOKE + if (options.covenants == null) // If there are no covenants + options.covenants = []; // Create an empty array for the covenants + const hash = output.covenant.items[0]; // Get the hash from the covenant + const name = hashes[hash]; // Get the name from the hashes object (is needed for SPV nodes) + if (name == undefined) { // If the name is not found + console.log("Name not found in file"); // Log that the name was not found + console.log(hash); // Log the hash (for debugging) + } + options.covenants.push(new LedgerCovenant({ index: i, name })); // Add the covenant to the options + + break; + } + default: + throw new Error('Unrecognized covenant type.'); + + } + + } // end for loop + util.displayDetails(console, network, mtx, options); // Display the details to the log for user verification + const signed = await ledger.signTransaction(mtx, options); // Sign the transaction with the ledger + console.log(signed); // Log the TX to the console + + } catch (err) { // Catch any errors + console.error(err); // Log the error to the console + } +} + +async function getWallets(client, args) { + if (args.length) + throw new Error('Too many arguments'); + + const wallets = await client.getWallets(); + + console.log(wallets); +} + +async function getAccounts(client, config, args) { + if (args.length) + throw new Error('Too many arguments'); + + const id = config.str('wallet-id'); + const accounts = await client.getAccounts(id); + + console.log(accounts); +} + +async function getAccount(client, config, args) { + if (args.length !== 1) + throw new Error('Invalid arguments'); + + const id = config.str('wallet-id'); + const name = args[0]; + const account = await client.getAccount(id, name); + + console.log(account); +} + +async function getBalance(client, config, args) { + if (args.length !== 0) + throw new Error('Invalid arguments'); + + const id = config.str('wallet-id'); + const name = config.str('account-name'); + const balance = await client.getBalance(id, name); + + console.log(balance); +} + +async function main() { + const device = await Device.requestDevice(); + device.set({ + timeout: 300000 // 5 minutes. + }); + + await device.open(); + + const config = new Config('hsd', { + suffix: 'network', + fallback: 'main', + alias: { + 'h': 'help', + 'i': 'accountindex', + 'a': 'accountname', + 'n': 'network', + 'p': 'projectsponsor', + 'q': 'qrcode', + 'k': 'showkey', + 'w': 'walletid' + } + }); + + config.load({ + argv: true, + env: true + }); + + config.inject({ + accountIndex: 0, + accountName: 'default', + network: 'main', + walletId: 'hsd-ledger', + token: '' + }); + + const argv = config.argv; + const cmd = argv.shift(); + const args = argv; + const type = config.str('network'); + const network = Network.get(type); + const id = config.str('wallet-id'); + const token = config.str('token'); + + if (config.str('help') && argv.length === 0) { + usage(); + process.exit(0); + } + + if (config.str('version') && argv.length === 0) { + version(); + process.exit(0); + } + + const ledger = new LedgerHSD({ + device: device, + network: type + }); + + const nclient = new NodeClient({ + url: config.str('url') || config.str('node-url'), + apiKey: config.str('api-key') || config.str('node-api-key'), + ssl: config.bool('ssl') || config.str('node-ssl'), + host: config.str('http-host') || config.str('node-http-host'), + port: config.uint('node-http-port') || network.rpcPort + }); + + const wclient = new WalletClient({ + url: config.str('url') || config.str('wallet-url'), + apiKey: config.str('api-key') || config.str('wallet-api-key'), + ssl: config.bool('ssl') || config.bool('wallet-ssl'), + host: config.str('http-host') || config.str('wallet-http-host'), + port: config.uint('wallet-http-port') || network.walletPort, + token + }); + + await nclient.open(); + await wclient.open(); + + try { + const wallets = await wclient.getWallets(); + + if (!wallets.includes(id)) { + if (id !== 'hsd-ledger') + throw new Error(`Wallet "${id}" does not exist.`); + + console.log('Default hsd-ledger wallet not detected.'); + + await createWallet(wclient, config, ledger, [id]); + } + + switch (cmd) { + case VALID_CMDS[0]: + await createWallet(wclient, config, ledger, args); + break; + + case VALID_CMDS[1]: + await createAccount(wclient, config, ledger, args); + break; + + case VALID_CMDS[2]: + await createAddress(wclient, config, ledger, args); + break; + + case VALID_CMDS[3]: + await sendToAddress(wclient, nclient, config, ledger, args); + break; + + case VALID_CMDS[4]: + await getWallets(wclient, args); + break; + + case VALID_CMDS[5]: + await getAccounts(wclient, config, args); + break; + + case VALID_CMDS[6]: + await getAccount(wclient, config, args); + break; + + case VALID_CMDS[7]: + await getBalance(wclient, config, args); + break; + + case VALID_CMDS[8]: + await sendRaw(wclient, nclient, config, ledger, args); + break; + case VALID_CMDS[9]: + await signRaw(wclient, nclient, config, ledger, args); + break; + case VALID_CMDS[10]: + await renew(wclient, nclient, config, ledger, args); + break; + default: + usage(new Error('Must provide valid command.')); + process.exit(1); + break; + } + } catch (e) { + throw (e); + } finally { + await wclient.close(); + await nclient.close(); + await device.close(); + } + + process.exit(0); +} + +/** + * Displays application version. + */ + +function version() { + console.log(`hsd-ledger v${VERSION}`); + console.log(''); +} + +/** + * Displays usage or error message. + * @param {String|Error} err - the error message or object + */ + +function usage(err) { + if (err) { + console.error(`${err.stack}`); + console.error(''); + return; + } + + console.log('usage:'); + console.log(' $ hsd-ledger createwallet '); + console.log(' $ hsd-ledger createaccount '); + console.log(' $ hsd-ledger createaddress'); + console.log(' $ hsd-ledger sendtoaddress
'); + console.log(' $ hsd-ledger getwallets'); + console.log(' $ hsd-ledger getaccounts'); + console.log(' $ hsd-ledger getaccount '); + console.log(' $ hsd-ledger getbalance'); + console.log(''); + console.log('options:'); + console.log(' --help'); + console.log(' --version'); + console.log(' -n, --network (default "main")'); + console.log(' -w, --wallet-id (default "hsd-ledger")'); + console.log(' -a, --account-name (default "default")'); + console.log(' -i, --account-index (default 0)'); + console.log(''); + console.log('The following options configure the node and wallet clients:'); + console.log(' --ssl'); + console.log(' --url '); + console.log(' --api-key '); + console.log(' --host (default "localhost")'); + console.log(''); + console.log('The following options configure the node client only:'); + console.log(' --node-ssl'); + console.log(' --node-url '); + console.log(' --node-api-key '); + console.log(' --node-host (default "localhost")'); + console.log(' --node-port (default 14037)'); + console.log(''); + console.log('The following options configure the wallet client only:'); + console.log(' --wallet-ssl'); + console.log(' --wallet-url '); + console.log(' --wallet-api-key '); + console.log(' --wallet-host (default "localhost")'); + console.log(' --wallet-port (default 14039)'); + console.log(''); +} + +/* + * Execute + */ + +main().catch((err) => { + usage(err); + process.exit(1); +}); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..213d938 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,521 @@ +{ + "name": "atomic-swap", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "atomic-swap", + "version": "1.0.0", + "license": "AGPL-3.0-only", + "dependencies": { + "hs-client": "^7.0.0", + "hsd": "^7.0.1", + "minimist": "^1.2.8" + } + }, + "node_modules/@handshake-org/bfilter": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@handshake-org/bfilter/-/bfilter-2.3.0.tgz", + "integrity": "sha512-vTKTVJvLHz2knpdnYMT0idb6R+HlOCbYKlw2L9Bk9oKOAXwjOIFUp6hnZKIVb87rYW8eEfUROrFG3+DcYwxm7w==", + "license": "MIT", + "dependencies": { + "bcrypto": "~5.4.0", + "bsert": "~0.0.12", + "bufio": "~1.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bcfg": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/bcfg/-/bcfg-0.2.2.tgz", + "integrity": "sha512-xa7hYK8ZgEV/Wjh+EJiKLLd+h8A0HGyhyntNMvKCeXIGepLqKUL3KYOE5zFz8EBv8sS3XruD5YPmYIjtwFOrZA==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.12" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/bcrypto": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/bcrypto/-/bcrypto-5.4.0.tgz", + "integrity": "sha512-KDX2CR29o6ZoqpQndcCxFZAtYA1jDMnXU3jmCfzP44g++Cu7AHHtZN/JbrN/MXAg9SLvtQ8XISG+eVD9zH1+Jg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bufio": "~1.0.7", + "loady": "~0.0.5" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bcrypto/node_modules/bufio": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/bufio/-/bufio-1.0.7.tgz", + "integrity": "sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bcurl": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/bcurl/-/bcurl-0.2.1.tgz", + "integrity": "sha512-7L00pT9SQEDzRIsRn53Il5pYHkeFlIoH0SdNIAbXdqsUMnq4IteTRuSZwC2f/uUKiRE5oW40MBhW72mquO9sQg==", + "license": "MIT", + "dependencies": { + "brq": "~0.1.10", + "bsert": "~0.0.12", + "bsock": "~0.1.10" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bdb": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/bdb/-/bdb-1.6.2.tgz", + "integrity": "sha512-3PxLeNKqwdqMjc/Ox5hontemGFt/AXGQsrEHFA0bynISfqhYI8r1qQNtJHEMonD6kcvkejfLA/5ad3n813kmdw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bsert": "~0.0.13", + "loady": "~0.0.5" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/bdns": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/bdns/-/bdns-0.1.5.tgz", + "integrity": "sha512-LNVkfM7ynlAD0CvPvO9cKxW8YXt1KOCRQZlRsGZWeMyymUWVdHQpZudAzH9chaFAz6HiwAnQxwDemCKDPy6Mag==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.10" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bevent": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/bevent/-/bevent-0.1.6.tgz", + "integrity": "sha512-vu1MYZIbZhz8s4/QDuqJ06L8BloELnMJxf/bGfp5ifqNpKpdCvgDw3ymsyzu27JJinDiGvx775V5NnTmWR7tFA==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.12" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bfile": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/bfile/-/bfile-0.2.3.tgz", + "integrity": "sha512-BhbmCLqDC+u8rPSeB/I8bRC8luQoUt+wD326CECXYXtE5GyTWL/q/OkNp58aH7XEREguEItvqM18s9vXLvg6fw==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bheep": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/bheep/-/bheep-0.1.6.tgz", + "integrity": "sha512-u44Xgb0Rr+Y/1chKqiUSY44mpBCglDxnapyfA6mssbJE+C7iyAPY4r8WMPqmdvZPYk7EU3ogbt4pKDItDMU87A==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.12" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/binet": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/binet/-/binet-0.3.9.tgz", + "integrity": "sha512-htptPuT5YTTRThIQAuWyCo+rIvXwAC+CrUq40ldhKHBPbZoMb76SBkI8NtvLkWussJr+lnR5Mc0rh1dpNBrBPg==", + "license": "MIT", + "dependencies": { + "bs32": "~0.1.7", + "bsert": "~0.0.12" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/blgr": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/blgr/-/blgr-0.2.1.tgz", + "integrity": "sha512-ShNWkj8qxjf0JEwDt1h675Lgx9EV8a2lRWVWtZrptqg/tIrISv0TM7s+NVNXEwyIlQYYIu4lQqjlGRYWUn4g5Q==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.12" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/blru": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/blru/-/blru-0.1.8.tgz", + "integrity": "sha512-9KsgRzBHx4GOJ48bRy0IZf42+f3nAhgAeeuWX5KBditHVqnCFL0ownd1QRr0aJVot7qlKEUYGPfM/tGHW6A3zw==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.12" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/blst": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/blst/-/blst-0.1.6.tgz", + "integrity": "sha512-P88SBVTdjKsvltTGXPayu9ACSZ36CNpECE8eZjPg+Mj++EB/VHOFUAnVIZ142NceSWYkVMBKiVENH49YHKHjFg==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.12" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bmutex": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/bmutex/-/bmutex-0.1.8.tgz", + "integrity": "sha512-NEI6oawCTA9hobAIubvpooRkq7hp+dBg0hf1KUJ3uV77PrXlUgLXr6D/mr6+sfJ0hx523lDaz/vEcJIbK9S1uw==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.13" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bns": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/bns/-/bns-0.15.0.tgz", + "integrity": "sha512-iJWQVE399vQzPfhalFMJGEQ7k5Ot2D6Mz8dkoPeLO8huWAMOiJNJ1tHzOu5j+ZyNNew6ITgG/LsSyaRPxvkXuw==", + "license": "MIT", + "dependencies": { + "bcrypto": "~5.4.0", + "bfile": "~0.2.2", + "bheep": "~0.1.5", + "binet": "~0.3.6", + "bs32": "~0.1.6", + "bsert": "~0.0.10", + "btcp": "~0.1.5", + "budp": "~0.1.6", + "bufio": "~1.0.7" + }, + "bin": { + "bns-keygen": "bin/bns-keygen", + "bns-prove": "bin/bns-prove", + "dig.js": "bin/dig.js", + "dig2json": "bin/dig2json", + "json2dig": "bin/json2dig", + "json2rr": "bin/json2rr", + "json2zone": "bin/json2zone", + "named.js": "bin/named.js", + "rr2json": "bin/rr2json", + "whois.js": "bin/whois.js", + "zone2json": "bin/zone2json" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "unbound": "~0.4.3" + } + }, + "node_modules/bns/node_modules/bufio": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/bufio/-/bufio-1.0.7.tgz", + "integrity": "sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/brq": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/brq/-/brq-0.1.10.tgz", + "integrity": "sha512-iil4TtQWw9Wb2G+mEP0iHqM8Q16mHINJzR5wHTsfKZTtcOVoEGj6yX3ed7yLQ92KR4QO9KjlrlO7/Y7766i7Tw==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.12" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bs32": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/bs32/-/bs32-0.1.7.tgz", + "integrity": "sha512-I0aKZCBneFTkcVNUIALzsOevqPIF93ynGPX6wj6pXmIBpXVGCqTgdvMx2QyR/NwgOIqMLH++Ovyum28abVG6QA==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.10" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bsert": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/bsert/-/bsert-0.0.13.tgz", + "integrity": "sha512-gYzSj8I2lDTKvl4aRSYs2CZIpeJugq7RjGhLRG+Jl//gEW5B2u1MKB6exVCL09FqYj6JRQAAgRwQHMOWvr7A8A==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bsock": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/bsock/-/bsock-0.1.11.tgz", + "integrity": "sha512-4COhlKKBfOQOomNvz1hjoPtN5ytpqbxkuCPvIPbYMvaZwNBKpo8dZa1LJjcN3wuAkjIIJLF/fc4o3e1DYiceQw==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.12" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bsocks": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bsocks/-/bsocks-0.2.6.tgz", + "integrity": "sha512-66UkjoB9f7lhT+WKgYq8MQa6nkr96mlX64JYMlIsXe/X4VeqNwvsx7UOE3ZqD6lkwg8GvBhapRTWj0qWO3Pw8w==", + "license": "MIT", + "dependencies": { + "binet": "~0.3.5", + "bsert": "~0.0.10" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/btcp": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/btcp/-/btcp-0.1.5.tgz", + "integrity": "sha512-tkrtMDxeJorn5p0KxaLXELneT8AbfZMpOFeoKYZ5qCCMMSluNuwut7pGccLC5YOJqmuk0DR774vNVQLC9sNq/A==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/budp": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/budp/-/budp-0.1.6.tgz", + "integrity": "sha512-o+a8NPq3DhV91j4nInjht2md6mbU1XL+7ciPltP66rw5uD3KP1m5r8lA94LZVaPKcFdJ0l2HVVzRNxnY26Pefg==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/buffer-map": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/buffer-map/-/buffer-map-0.0.8.tgz", + "integrity": "sha512-RlxrBAk98CqJdwSPgXOWYbC85xuq4H4vyGmW68BJ9IAGkCHQKC+flavb+d3LGxiDluczbTG8NhgKBRllpFGurA==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bufio": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bufio/-/bufio-1.2.3.tgz", + "integrity": "sha512-5Tt66bRzYUSlVZatc0E92uDenreJ+DpTBmSAUwL4VSxJn3e6cUyYwx+PoqML0GRZatgA/VX8ybhxItF8InZgqA==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bupnp": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bupnp/-/bupnp-0.2.6.tgz", + "integrity": "sha512-J6ykzJhZMxXKN78K+1NzFi3v/51X2Mvzp2hW42BWwmxIVfau6PaN99gyABZ8x05e8MObWbsAis23gShhj9qpbw==", + "license": "MIT", + "dependencies": { + "binet": "~0.3.5", + "brq": "~0.1.7", + "bsert": "~0.0.10" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/bval/-/bval-0.1.8.tgz", + "integrity": "sha512-38WQyq94sgKaJbHSmkOwZqba6Ac0KIKPO0SMDNg/mCcwUos2NIrMg5Bb2LkzIer+RzS186IYusNeSrJrKdaqhA==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.10" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bweb": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bweb/-/bweb-0.2.0.tgz", + "integrity": "sha512-JfpXemYqylNySwrhR7b4HZTrxnDhbOzNiIXCPBVQU6O8rTZ1wFDLFDr/7uQqkwzjyNZ4ZWTp5wP/pJY2IizfDA==", + "license": "MIT", + "dependencies": { + "bsert": "~0.0.10", + "bsock": "~0.1.9" + }, + "bin": { + "bweb": "bin/bweb" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/goosig": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/goosig/-/goosig-0.10.0.tgz", + "integrity": "sha512-+BVVLfxmawAmGVjjJpXzu5LNcFIOfgXgP7kWEyc3qu/xn9RMqbPbNfYDdHBZKfZkDMIO7Q4vD790iNYQAXhoFA==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bcrypto": "~5.4.0", + "bsert": "~0.0.10", + "loady": "~0.0.5" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/hs-client": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/hs-client/-/hs-client-7.0.0.tgz", + "integrity": "sha512-vynmtC9pfMC6zTqg5mcnTlM6BTvjtID0P3Y9wQZUPoiE4zAfAyucfBlc6QJ5pK3o+fKmDQnrIZ/g2GoySGR3dQ==", + "license": "MIT", + "dependencies": { + "bcfg": "~0.2.2", + "bcurl": "~0.2.1", + "bsert": "~0.0.13" + }, + "bin": { + "hsd-cli": "bin/hsd-cli", + "hsd-rpc": "bin/hsd-rpc", + "hsw-cli": "bin/hsw-cli", + "hsw-rpc": "bin/hsw-rpc" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/hsd": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/hsd/-/hsd-7.0.1.tgz", + "integrity": "sha512-5zju8h08RYENrmFZ5jBsclGt3VC5mH3s/TmNHNtc/EwuOaYnydyY+BfSiNPIaEsBsKVWgcXkb+8btigoB7CGbQ==", + "license": "MIT", + "dependencies": { + "@handshake-org/bfilter": "~2.3.0", + "bcfg": "~0.2.2", + "bcrypto": "~5.4.0", + "bcurl": "~0.2.1", + "bdb": "~1.6.1", + "bdns": "~0.1.5", + "bevent": "~0.1.6", + "bfile": "~0.2.3", + "bheep": "~0.1.6", + "binet": "~0.3.9", + "blgr": "~0.2.1", + "blru": "~0.1.8", + "blst": "~0.1.6", + "bmutex": "~0.1.7", + "bns": "~0.15.0", + "bsert": "~0.0.13", + "bsock": "~0.1.11", + "bsocks": "~0.2.6", + "btcp": "~0.1.5", + "buffer-map": "~0.0.8", + "bufio": "~1.2.2", + "bupnp": "~0.2.6", + "bval": "~0.1.8", + "bweb": "~0.2.0", + "goosig": "~0.10.0", + "n64": "~0.2.10", + "urkel": "~1.0.3" + }, + "bin": { + "hs-seeder": "bin/hs-seeder", + "hs-wallet": "bin/hsw", + "hsd": "bin/hsd", + "hsd-cli": "bin/hsd-cli", + "hsd-node": "bin/node", + "hsd-rpc": "bin/hsd-rpc", + "hsd-spvnode": "bin/spvnode", + "hsw-cli": "bin/hsw-cli", + "hsw-rpc": "bin/hsw-rpc" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/loady": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/loady/-/loady-0.0.5.tgz", + "integrity": "sha512-uxKD2HIj042/HBx77NBcmEPsD+hxCgAtjEWlYNScuUjIsh/62Uyu39GOR68TBR68v+jqDL9zfftCWoUo4y03sQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/n64": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/n64/-/n64-0.2.10.tgz", + "integrity": "sha512-uH9geV4+roR1tohsrrqSOLCJ9Mh1iFcDI+9vUuydDlDxUS1UCAWUfuGb06p3dj3flzywquJNrGsQ7lHP8+4RVQ==", + "license": "MIT", + "engines": { + "node": ">=2.0.0" + } + }, + "node_modules/unbound": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/unbound/-/unbound-0.4.3.tgz", + "integrity": "sha512-2ISqZLXtzp1l9f1V8Yr6S+zuhXxEwE1CjKHjXULFDHJcfhc9Gm3mn19hdPp4rlNGEdCivKYGKjYe3WRGnafYdA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "loady": "~0.0.5" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/urkel": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/urkel/-/urkel-1.0.3.tgz", + "integrity": "sha512-L2M46WWSaz1LpyUYFgnQg7WSOWtNcRx3uH+4GwHK1jbmYj6phLuIwirTVMlhfcZ0o/CWn5Y04UWLhmlvijZiDg==", + "license": "MIT", + "dependencies": { + "bfile": "~0.2.1", + "bmutex": "~0.1.6", + "bsert": "~0.0.10" + }, + "engines": { + "node": ">=8.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..877d023 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "atomic-swap", + "version": "1.0.0", + "description": "Atomic Swap tools", + "main": "atomic-swap.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://git.woodburn.au/nathanwoodburn/atomic-swap.git" + }, + "author": "Nathan.Woodburn/", + "license": "AGPL-3.0-only", + "dependencies": { + "hs-client": "^7.0.0", + "hsd": "^7.0.1", + "minimist": "^1.2.8" + } +}