5 require("dotenv").config({ path: ".env" });
6 require("dotenv").config({ path: ".env.secret" });
8 let privKey = process.env.PRIVATE_KEY;
10 let Fs = require("fs").promises;
12 let Dashcore = require("@dashevo/dashcore-lib");
13 let request = require("./lib/request.js");
15 let baseUrl = `https://insight.dash.org/insight-api`;
19 console.info(`Usage:`);
20 console.info(` create-tx [key-file] <change> <address:amount,>`);
22 console.info(`Example:`);
23 console.info(` create-tx ./key.wif XkY...w6C Xkz...aDf:1000`);
27 async function main() {
28 if (["help", "--help", "-h"].includes(process.argv[2])) {
34 let args = process.argv.slice(2);
36 let keyFile = args.shift();
37 // TODO error handling
38 privKey = await Fs.readFile(keyFile, "ascii").trim();
41 let changeAddr = args.shift();
42 let payments = args.map(function (payment) {
43 let parts = payment.split(":");
44 if (2 !== parts.length) {
51 // TODO check for bad input (i.e. decimal)
52 satoshis: parseInt(parts[1], 10),
56 // TODO check validity
57 if (!payments.length) {
63 let pk = new Dashcore.PrivateKey(privKey);
64 let pub = pk.toPublicKey().toAddress().toString();
66 /** @type InsightUtxo */
67 let utxoUrl = `${baseUrl}/addr/${pub}/utxo`;
68 let utxoResp = await request({ url: utxoUrl, json: true });
70 /** @type Array<Utxo> */
73 await utxoResp.body.reduce(async function (promise, utxo) {
76 let txUrl = `${baseUrl}/tx/${utxo.txid}`;
77 let txResp = await request({ url: txUrl, json: true });
78 let data = txResp.body;
80 // TODO the ideal would be the smallest amount that is greater than the required amount
83 data.vout.some(function (vout, index) {
84 if (!vout.scriptPubKey?.addresses?.includes(utxo.address)) {
88 let satoshis = parseInt(vout.value[0] + vout.value.slice(2), 10);
89 if (utxo.satoshis !== satoshis) {
99 outputIndex: utxoIndex,
100 address: utxo.address,
101 script: utxo.scriptPubKey,
102 satoshis: utxo.satoshis,
104 }, Promise.resolve());
106 let tx = new Dashcore.Transaction().from(utxos);
107 tx.change(changeAddr);
108 payments.forEach(async function (payment) {
109 tx.to(payment.address, payment.satoshis);
113 // TODO get the *real* fee
114 console.warn('Fee:', tx.getFee());
115 console.info(tx.serialize());
118 main().catch(function (err) {
119 console.error("Fail:");
120 console.error(err.stack || err);