diff --git a/bin/create-memo.js b/bin/create-memo.js index d75afda..64ef391 100755 --- a/bin/create-memo.js +++ b/bin/create-memo.js @@ -97,27 +97,32 @@ async function main() { console.info(`Fee: ${feeDash} (${feeDuffs})`); //change.satoshis = sats; - let dashTx = DashTx.create({ - /** @type {import('../dashtx.js').TxSign} */ + /** @type {import('../dashtx.js').TxKeyUtils} */ + let keyUtils = { sign: async function (privKeyBytes, hashBytes) { let sigOpts = { canonical: true }; let sigBuf = await Secp256k1.sign(hashBytes, privKeyBytes, sigOpts); return sigBuf; }, + getPublicKey: async function (txInput, i) { + let privKeyBytes = await keyUtils.getPrivateKey(txInput, i); + if (!privKeyBytes) { + return null; + } + let pubKeyBytes = await keyUtils.toPublicKey(privKeyBytes); + + return pubKeyBytes; + }, getPrivateKey: async function () { return privKeyBytes; }, - toPublicKey: - /** - * @param {Uint8Array} privBytes - * @returns {Promise} - */ - async function (privBytes) { - let isCompressed = true; - let pubBytes = Secp256k1.getPublicKey(privBytes, isCompressed); - return pubBytes; - }, - }); + toPublicKey: async function (privBytes) { + let isCompressed = true; + let pubBytes = Secp256k1.getPublicKey(privBytes, isCompressed); + return pubBytes; + }, + }; + let dashTx = DashTx.create(keyUtils); //@ts-ignore let txInfoSigned = await dashTx.hashAndSignAll(txInfo); diff --git a/dashtx.js b/dashtx.js index a53c080..ef4b5a7 100644 --- a/dashtx.js +++ b/dashtx.js @@ -56,6 +56,7 @@ /** * @typedef TxUtils + * @prop {TxRPC} rpc * @prop {TxToVarInt} toVarInt * @prop {TxToVarIntSize} toVarIntSize * @prop {TxReverseHex} reverseHex @@ -66,7 +67,7 @@ /** * @callback TxCreate - * @param {TxDeps} keyUtils + * @param {TxKeyUtils} keyUtils * @returns {tx} */ @@ -272,6 +273,9 @@ var DashTx = ("object" === typeof module && exports) || {}; return pubKeyBytes; }; } + /** @type {TxDeps} */ + //@ts-ignore + let keyDeps = keyUtils; let txInst = {}; @@ -313,7 +317,7 @@ var DashTx = ("object" === typeof module && exports) || {}; for (let i = 0; i < txInfo.inputs.length; i += 1) { let txInput = txInfo.inputs[i]; - let privBytes = await keyUtils.getPrivateKey(txInput, i, txInfo.inputs); + let privBytes = await keyDeps.getPrivateKey(txInput, i, txInfo.inputs); if (privBytes) { txInput = await txInst.hashAndSignInput( privBytes, @@ -358,7 +362,7 @@ var DashTx = ("object" === typeof module && exports) || {}; let txBytes = Tx.utils.hexToBytes(txHex); let txHashBuf = await Tx.doubleSha256(txBytes); - let sigBuf = await keyUtils.sign(privBytes, txHashBuf); + let sigBuf = await keyDeps.sign(privBytes, txHashBuf); let sigHex = ""; if ("string" === typeof sigBuf) { console.warn(`sign() should return a Uint8Array of an ASN.1 signature`); @@ -369,7 +373,10 @@ var DashTx = ("object" === typeof module && exports) || {}; let pubKeyHex = txInput.publicKey; if (!pubKeyHex) { - let pubKey = await keyUtils.getPublicKey(txInput, i, txInfo.inputs); + let pubKey = await keyDeps.getPublicKey(txInput, i, txInfo.inputs); + if (!pubKey) { + throw new Error(`no public key for input ${i}`); + } pubKeyHex = Tx.utils.bytesToHex(pubKey); } if ("string" !== typeof pubKeyHex) { @@ -1693,14 +1700,7 @@ var DashTx = ("object" === typeof module && exports) || {}; } } - /** - * @param {String} basicAuthUrl - ex: https://api:token@trpc.digitalcash.dev/ - * http://user:pass@localhost:19998/ - * @param {String} method - the rpc, such as 'getblockchaininfo', - * 'getaddressdeltas', or 'help' - * @param {...any} params - the arguments for the specific rpc - * ex: rpc(url, 'help', 'getaddressdeltas') - */ + /** @type {TxRPC} */ TxUtils.rpc = async function rpc(basicAuthUrl, method, ...params) { let url = new URL(basicAuthUrl); let baseUrl = `${url.protocol}//${url.host}${url.pathname}`; @@ -1936,12 +1936,13 @@ if ("object" === typeof module) { */ /** - * @typedef TxDeps + * @typedef TxKeyUtils * @prop {TxGetPrivateKey} getPrivateKey - * @prop {TxGetPublicKey} getPublicKey - efficiently get public key bytes - * @prop {TxToPublicKey} [toPublicKey] - convert private bytes to pub bytes + * @prop {TxGetPublicKey} [getPublicKey] - efficiently get public key bytes + * @prop {TxToPublicKey} toPublicKey - convert private bytes to pub bytes * @prop {TxSign} sign */ +/** @typedef {Required} TxDeps */ /** * @typedef TxFees @@ -2157,17 +2158,17 @@ if ("object" === typeof module) { /** * @callback TxGetPrivateKey * @param {TxInputForSig} txInput - * @param {Uint53} i - * @param {Array} txInputs - * @returns {Promise} - private key Uint8Array + * @param {Uint53} [i] + * @param {Array} [txInputs] + * @returns {Promise} - private key Uint8Array */ /** * @callback TxGetPublicKey * @param {TxInputForSig} txInput - * @param {Uint53} i - * @param {Array} txInputs - * @returns {Promise} - public key Uint8Array + * @param {Uint53} [i] + * @param {Array} [txInputs] + * @returns {Promise} - public key Uint8Array */ /** @@ -2356,6 +2357,16 @@ if ("object" === typeof module) { * @returns {Promise} - public key buf */ +/** + * @callback TxRPC + * @param {String} basicAuthUrl - ex: https://api:token@trpc.digitalcash.dev/ + * http://user:pass@localhost:19998/ + * @param {String} method - the rpc, such as 'getblockchaininfo', + * 'getaddressdeltas', or 'help' + * @param {...any} params - the arguments for the specific rpc + * ex: rpc(url, 'help', 'getaddressdeltas') + */ + /** * Caution: JS can't handle 64-bit ints * @callback TxToVarInt