@dashincubator/blocktx
Advanced tools
Comparing version 0.9.0-0 to 0.9.0-1
177
blocktx.js
@@ -66,3 +66,3 @@ (function (exports) { | ||
Tx.OUTPUT_SIZE = // 34 each | ||
8 + // base units value | ||
8 + // satoshis (base units) value | ||
1 + // lockscript size | ||
@@ -72,6 +72,7 @@ 25; // lockscript | ||
/** | ||
* Calculates the minimum fee (<= 25% likely to be correct) and maximum lowest possible fee. | ||
* @param {TxInfo} txInfo | ||
* @returns {[Number, Number]} | ||
* @returns {[Number, Number]} - min and max fees | ||
*/ | ||
Tx.estimate = function (txInfo) { | ||
Tx.estimates = function (txInfo) { | ||
let size = Tx._HEADER_ONLY_SIZE; | ||
@@ -88,2 +89,3 @@ | ||
// TODO return median | ||
return [size, maxSize]; | ||
@@ -93,5 +95,20 @@ }; | ||
/** | ||
* Calculates the median fee, which is 75% likely to be correct | ||
* @param {TxInfo} txInfo | ||
* @returns {Number} | ||
*/ | ||
Tx.estimate = function (txInfo) { | ||
let [minFee, maxFee] = Tx.estimates(txInfo); | ||
let feeSpread = maxFee - minFee; | ||
let halfFeeSpread = Math.ceil(feeSpread / 2); | ||
let medianFee = minFee + halfFeeSpread; | ||
return medianFee; | ||
}; | ||
/** | ||
* @param {TxDeps} myUtils | ||
*/ | ||
Tx.create = function (myUtils) { | ||
myUtils = Object.assign({}, Tx.utils, myUtils); | ||
/** | ||
@@ -115,5 +132,7 @@ * @param {TxInfo} txInfo | ||
return { | ||
let txInst = { | ||
_utils: myUtils, | ||
hashAndSignAll: hashAndSignAll, | ||
}; | ||
return txInst; | ||
}; | ||
@@ -126,3 +145,4 @@ | ||
Tx._createKeyUtils = function (myUtils, keys) { | ||
return { | ||
let _getPublicKey = myUtils.getPublicKey || getPublicKey; | ||
let _utils = { | ||
/** @type {TxGetPrivateKey} */ | ||
@@ -134,15 +154,23 @@ getPrivateKey: async function (_, i) { | ||
/** @type {TxGetPublicKey} */ | ||
getPublicKey: async function (txInput, i, txInputs) { | ||
if (myUtils.getPublicKey) { | ||
return await myUtils.getPublicKey(txInput, i, txInputs); | ||
} | ||
getPublicKey: _getPublicKey, | ||
sign: myUtils.sign, | ||
}; | ||
let privKey = keys[i]; | ||
/** @type {TxGetPublicKey} */ | ||
async function getPublicKey(txInput, i, txInputs) { | ||
let privKey = keys[i]; | ||
//@ts-ignore | ||
let pubKey = myUtils.toPublicKey(privKey); | ||
if ("string" === typeof pubKey) { | ||
console.warn( | ||
"oops, you gave a publicKey as hex (deprecated) rather than a buffer", | ||
); | ||
//@ts-ignore | ||
let pubKeyHex = myUtils.toPublicKey(privKey); | ||
let pubKey = Tx.utils.hexToU8(pubKeyHex); | ||
return pubKey; | ||
}, | ||
sign: myUtils.sign, | ||
}; | ||
pubKey = Tx.utils.hexToU8(pubKey); | ||
} | ||
//@ts-ignore | ||
return pubKey; | ||
} | ||
return Object.assign(_utils, myUtils); | ||
}; | ||
@@ -169,3 +197,10 @@ | ||
if (!myUtils.getPrivateKey) { | ||
console.warn(`you must provide 'keys' or 'getPrivateKey()'`); | ||
//@ts-ignore | ||
if (!txInfo?.inputs?.[0]?.getPrivateKey) { | ||
throw new Error(""); | ||
} | ||
//@ts-ignore | ||
myUtils.getPrivateKey = async function (txInput) { | ||
//@ts-ignore | ||
let privKey = await txInput.getPrivateKey(); | ||
@@ -175,9 +210,22 @@ return privKey; | ||
} | ||
//@ts-ignore | ||
if (txInfo?.inputs?.[0]?.getPrivateKey) { | ||
console.warn(`deprecated use of 'txInput.getPrivateKey()'`); | ||
} | ||
// temp shim | ||
if (!myUtils.getPublicKey) { | ||
//@ts-ignore | ||
myUtils.getPublicKey = async function (txInput, i, inputs) { | ||
//@ts-ignore | ||
let privKey = await myUtils.getPrivateKey(txInput, i, inputs); | ||
let pubKeyHex = await myUtils.toPublicKey(privKey); | ||
let pubKey = Tx.utils.hexToU8(pubKeyHex); | ||
//@ts-ignore | ||
let pubKey = await myUtils.toPublicKey(privKey); | ||
if ("string" === typeof pubKey) { | ||
console.warn( | ||
"oops, you gave a publicKey as hex (deprecated) rather than a buffer", | ||
); | ||
//@ts-ignore | ||
pubKey = Tx.utils.hexToU8(pubKey); | ||
} | ||
return pubKey; | ||
@@ -197,8 +245,18 @@ }; | ||
let sigHex = await myUtils.sign({ | ||
let sigBuf = await myUtils.sign({ | ||
privateKey: privKey, | ||
hash: txHashBuf, | ||
}); | ||
let sigHex = Tx.utils.u8ToHex(sigBuf); | ||
if ("string" === typeof sigBuf) { | ||
console.warn(`sign() should return a Uint8Array of an ASN.1 signature`); | ||
sigHex = sigBuf; | ||
} | ||
let pubKeyHex = txInput.publicKey; | ||
if ("string" !== typeof pubKeyHex) { | ||
console.warn( | ||
`utxo inputs should be plain JSON and use hex rather than buffers for 'publicKey'`, | ||
); | ||
} | ||
if (!pubKeyHex) { | ||
@@ -213,4 +271,4 @@ //@ts-ignore | ||
outputIndex: txInput.outputIndex, | ||
signature: sigHex.toString(), | ||
publicKey: pubKeyHex.toString(), | ||
signature: sigHex, | ||
publicKey: pubKeyHex, | ||
sigHashType: _sigHashType, | ||
@@ -224,3 +282,3 @@ }; | ||
txInput._lockScript = txInfo.inputs[i].script; | ||
txInput._publicKey = pubKeyHex.toString(); | ||
txInput._publicKey = pubKeyHex; | ||
txInput._sigHashType = _sigHashType; | ||
@@ -329,2 +387,3 @@ | ||
_debug = false, | ||
_DANGER_donate = false, | ||
}) { | ||
@@ -407,10 +466,23 @@ let sep = ""; | ||
if (!outputs.length) { | ||
throw new Error( | ||
`'outputs' list cannot empty (length 0) - TODO add a 'donate: true' option`, | ||
); | ||
if (!_DANGER_donate) { | ||
throw new Error( | ||
`'outputs' list must not be empty - use the developer debug option '_DANGER_donate: true' to bypass`, | ||
); | ||
} | ||
} | ||
outputs.forEach(function (output, i) { | ||
let units = toUint64LE(output.units); | ||
tx.push(units); | ||
if (!output.satoshis) { | ||
throw new Error(`every output must have 'satoshis'`); | ||
} | ||
let satoshis = toUint64LE(output.satoshis); | ||
tx.push(satoshis); | ||
if (!output.pubKeyHash) { | ||
if (!output.address) { | ||
throw new Error( | ||
`every output must have 'pubKeyHash' (or 'address' if base58check is loaded)`, | ||
); | ||
} | ||
output.pubKeyHash = Tx.utils.addrToPubKeyHash(output.address); | ||
} | ||
assertHex(output.pubKeyHash, `output[${i}].pubKeyHash`); | ||
@@ -518,2 +590,44 @@ let lockScript = `${PKH_SCRIPT_SIZE}${OP_DUP}${OP_HASH160}${PKH_SIZE}${output.pubKeyHash}${OP_EQUALVERIFY}${OP_CHECKSIG}`; | ||
/** | ||
* @param {String} addr | ||
* @returns {String} - pubKeyHash in the raw (hex) | ||
*/ | ||
Tx.utils.addrToPubKeyHash = function (addr) { | ||
let Base58Check = require("@dashincubator/base58check").Base58Check; | ||
let b58c = Base58Check.create({ | ||
pubKeyHashVersion: "4c", | ||
privateKeyVersion: "cc", | ||
}); | ||
// XXX bad idea? | ||
// using .decode to avoid the async of .verify | ||
let parts = b58c.decode(addr); | ||
return parts.pubKeyHash; | ||
}; | ||
/** @type TxSign */ | ||
Tx.utils.sign = async function signTx({ privateKey, hash }) { | ||
let Secp256k1 = | ||
//@ts-ignore | ||
exports.nobleSecp256k1 || require("@dashincubator/secp256k1"); | ||
let sigOpts = { canonical: true }; | ||
let sigBuf = await Secp256k1.sign(hash, privateKey, sigOpts); | ||
return sigBuf; | ||
}; | ||
/** | ||
* @param {Uint8Array} privateKey | ||
* @returns {String} - pubKeyHash in the raw (hex) | ||
*/ | ||
Tx.utils.toPublicKey = function (privateKey) { | ||
let Secp256k1 = | ||
//@ts-ignore | ||
exports.nobleSecp256k1 || require("@dashincubator/secp256k1"); | ||
let isCompressed = true; | ||
let pubKeyBuf = Secp256k1.getPublicKey(privateKey, isCompressed); | ||
return pubKeyBuf; | ||
}; | ||
/** | ||
* Caution: JS can't handle 64-bit ints | ||
@@ -788,4 +902,5 @@ * @param {BigInt|Number} n - 64-bit BigInt or < 52-bit Number | ||
* @typedef TxOutput | ||
* @prop {String} pubKeyHash - payaddr's raw hex value (decoded, not Base58Check) | ||
* @prop {Number} units - the number of smallest units of the currency (duffs / satoshis) | ||
* @prop {String} [address] - payAddr as Base58Check (human-friendly) | ||
* @prop {String} [pubKeyHash] - payAddr's raw hex value (decoded, not Base58Check) | ||
* @prop {Number} satoshis - the number of smallest units of the currency | ||
*/ | ||
@@ -814,3 +929,3 @@ | ||
* @param {TxSignOpts} opts | ||
* @returns {TxInfo} | ||
* @returns {Uint8Array} | ||
* | ||
@@ -825,3 +940,3 @@ * @typedef TxSignOpts | ||
* @param {Uint8Array} privateKey | ||
* @returns {String} - public key hex | ||
* @returns {Uint8Array} - public key hex | ||
*/ | ||
@@ -828,0 +943,0 @@ |
{ | ||
"name": "@dashincubator/blocktx", | ||
"version": "0.9.0-0", | ||
"version": "0.9.0-1", | ||
"description": "Create Blockchain transactions with Vanilla JS (0 deps, cross-platform)", | ||
@@ -22,3 +22,3 @@ "main": "index.js", | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"_version": "npm version -m \"chore(release): bump to v%s\"", | ||
"bump": "npm version -m \"chore(release): bump to v%s\"", | ||
"fmt": "npx -p prettier@2.x -- prettier -w '**/*.{js,md}'", | ||
@@ -39,6 +39,6 @@ "lint": "npx -p typescript@4.x -- tsc -p ./jsconfig.json", | ||
"homepage": "https://github.com/dashhive/blocktx.js#readme", | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@dashincubator/base58check": "^1.3.1", | ||
"@dashincubator/secp256k1": "^1.7.1-1" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
47144
1044
2