@opcat-labs/opcat 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mocharc.yaml +3 -0
- package/index.d.ts +1541 -0
- package/index.js +74 -0
- package/lib/address.js +478 -0
- package/lib/block/block.js +277 -0
- package/lib/block/blockheader.js +295 -0
- package/lib/block/index.js +4 -0
- package/lib/block/merkleblock.js +323 -0
- package/lib/bn.js +3423 -0
- package/lib/crypto/bn.js +278 -0
- package/lib/crypto/ecdsa.js +339 -0
- package/lib/crypto/hash.browser.js +171 -0
- package/lib/crypto/hash.js +2 -0
- package/lib/crypto/hash.node.js +171 -0
- package/lib/crypto/point.js +221 -0
- package/lib/crypto/random.browser.js +28 -0
- package/lib/crypto/random.js +2 -0
- package/lib/crypto/random.node.js +11 -0
- package/lib/crypto/signature.js +325 -0
- package/lib/encoding/base58.js +111 -0
- package/lib/encoding/base58check.js +121 -0
- package/lib/encoding/bufferreader.js +212 -0
- package/lib/encoding/bufferwriter.js +140 -0
- package/lib/encoding/decode-asm.js +24 -0
- package/lib/encoding/decode-hex.js +32 -0
- package/lib/encoding/decode-script-chunks.js +43 -0
- package/lib/encoding/encode-hex.js +284 -0
- package/lib/encoding/is-hex.js +7 -0
- package/lib/encoding/varint.js +75 -0
- package/lib/errors/index.js +54 -0
- package/lib/errors/spec.js +314 -0
- package/lib/hash-cache.js +50 -0
- package/lib/hdprivatekey.js +678 -0
- package/lib/hdpublickey.js +525 -0
- package/lib/message/message.js +191 -0
- package/lib/mnemonic/mnemonic.js +303 -0
- package/lib/mnemonic/pbkdf2.browser.js +68 -0
- package/lib/mnemonic/pbkdf2.js +2 -0
- package/lib/mnemonic/pbkdf2.node.js +68 -0
- package/lib/mnemonic/words/chinese.js +2054 -0
- package/lib/mnemonic/words/english.js +2054 -0
- package/lib/mnemonic/words/french.js +2054 -0
- package/lib/mnemonic/words/index.js +8 -0
- package/lib/mnemonic/words/italian.js +2054 -0
- package/lib/mnemonic/words/japanese.js +2054 -0
- package/lib/mnemonic/words/spanish.js +2054 -0
- package/lib/networks.js +379 -0
- package/lib/opcode.js +255 -0
- package/lib/privatekey.js +374 -0
- package/lib/publickey.js +386 -0
- package/lib/script/index.js +5 -0
- package/lib/script/interpreter.js +1834 -0
- package/lib/script/script.js +1074 -0
- package/lib/script/stack.js +109 -0
- package/lib/script/write-i32-le.js +17 -0
- package/lib/script/write-push-data.js +35 -0
- package/lib/script/write-u16-le.js +12 -0
- package/lib/script/write-u32-le.js +16 -0
- package/lib/script/write-u64-le.js +24 -0
- package/lib/script/write-u8-le.js +8 -0
- package/lib/script/write-varint.js +46 -0
- package/lib/transaction/index.js +7 -0
- package/lib/transaction/input/index.js +5 -0
- package/lib/transaction/input/input.js +354 -0
- package/lib/transaction/input/multisig.js +242 -0
- package/lib/transaction/input/publickey.js +100 -0
- package/lib/transaction/input/publickeyhash.js +118 -0
- package/lib/transaction/output.js +231 -0
- package/lib/transaction/sighash.js +167 -0
- package/lib/transaction/signature.js +97 -0
- package/lib/transaction/transaction.js +1639 -0
- package/lib/transaction/unspentoutput.js +113 -0
- package/lib/util/_.js +47 -0
- package/lib/util/js.js +90 -0
- package/lib/util/preconditions.js +33 -0
- package/package.json +26 -0
- package/test/address.js +509 -0
- package/test/block/block.js +251 -0
- package/test/block/blockheader.js +275 -0
- package/test/block/merklebloack.js +211 -0
- package/test/crypto/bn.js +177 -0
- package/test/crypto/ecdsa.js +391 -0
- package/test/crypto/hash.browser.js +135 -0
- package/test/crypto/hash.js +136 -0
- package/test/crypto/point.js +224 -0
- package/test/crypto/random.js +32 -0
- package/test/crypto/signature.js +409 -0
- package/test/data/bip69.json +215 -0
- package/test/data/bitcoind/base58_keys_invalid.json +52 -0
- package/test/data/bitcoind/base58_keys_valid.json +335 -0
- package/test/data/bitcoind/blocks.json +22 -0
- package/test/data/bitcoind/script_tests.json +3822 -0
- package/test/data/bitcoind/sig_canonical.json +7 -0
- package/test/data/bitcoind/sig_noncanonical.json +36 -0
- package/test/data/bitcoind/tx_invalid.json +445 -0
- package/test/data/bitcoind/tx_valid.json +44 -0
- package/test/data/blk86756-testnet.dat +0 -0
- package/test/data/blk86756-testnet.js +14 -0
- package/test/data/blk86756-testnet.json +684 -0
- package/test/data/block.hex +1 -0
- package/test/data/ecdsa.json +230 -0
- package/test/data/merkleblocks.js +488 -0
- package/test/data/messages.json +22 -0
- package/test/data/sighash.json +12 -0
- package/test/data/tx_creation.json +95 -0
- package/test/encoding/base58.js +131 -0
- package/test/encoding/base58check.js +136 -0
- package/test/encoding/bufferreader.js +337 -0
- package/test/encoding/bufferwriter.js +172 -0
- package/test/encoding/varint.js +104 -0
- package/test/hashCache.js +67 -0
- package/test/hdkeys.js +445 -0
- package/test/hdprivatekey.js +332 -0
- package/test/hdpublickey.js +304 -0
- package/test/index.js +16 -0
- package/test/message/message.js +204 -0
- package/test/mnemonic/data/fixtures.json +300 -0
- package/test/mnemonic/mnemonic.js +259 -0
- package/test/mnemonic/mocha.opts +1 -0
- package/test/mnemonic/pbkdf2.test.js +59 -0
- package/test/networks.js +159 -0
- package/test/opcode.js +161 -0
- package/test/privatekey.js +439 -0
- package/test/publickey.js +554 -0
- package/test/script/interpreter.js +734 -0
- package/test/script/script.js +1437 -0
- package/test/transaction/deserialize.js +34 -0
- package/test/transaction/input/input.js +90 -0
- package/test/transaction/input/multisig.js +90 -0
- package/test/transaction/input/publickey.js +68 -0
- package/test/transaction/input/publickeyhash.js +51 -0
- package/test/transaction/output.js +185 -0
- package/test/transaction/sighash.js +65 -0
- package/test/transaction/signature.js +114 -0
- package/test/transaction/transaction.js +1109 -0
- package/test/transaction/unspentoutput.js +110 -0
- package/test/util/js.js +76 -0
- package/test/util/preconditions.js +79 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _ = require('../util/_');
|
|
4
|
+
var $ = require('../util/preconditions');
|
|
5
|
+
var JSUtil = require('../util/js');
|
|
6
|
+
|
|
7
|
+
var Script = require('../script');
|
|
8
|
+
var Address = require('../address');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Represents an unspent output information: its script, associated amount and address,
|
|
12
|
+
* transaction id and output index.
|
|
13
|
+
*
|
|
14
|
+
* @constructor
|
|
15
|
+
* @param {object} data
|
|
16
|
+
* @param {string} data.txid the previous transaction id
|
|
17
|
+
* @param {string=} data.txId alias for `txid`
|
|
18
|
+
* @param {number} data.vout the index in the transaction
|
|
19
|
+
* @param {number=} data.outputIndex alias for `vout`
|
|
20
|
+
* @param {string|Script} data.scriptPubKey the script that must be resolved to release the funds
|
|
21
|
+
* @param {string|Script=} data.script alias for `scriptPubKey`
|
|
22
|
+
* @param {number} data.amount amount of bitcoins associated
|
|
23
|
+
* @param {number=} data.satoshis alias for `amount`, but expressed in satoshis (1 OPCAT = 1e8 satoshis)
|
|
24
|
+
* @param {string|Address=} data.address the associated address to the script, if provided
|
|
25
|
+
*/
|
|
26
|
+
function UnspentOutput(data) {
|
|
27
|
+
if (!(this instanceof UnspentOutput)) {
|
|
28
|
+
return new UnspentOutput(data);
|
|
29
|
+
}
|
|
30
|
+
$.checkArgument(_.isObject(data), 'Must provide an object from where to extract data');
|
|
31
|
+
var address = data.address ? new Address(data.address) : undefined;
|
|
32
|
+
var txId = data.txid ? data.txid : data.txId;
|
|
33
|
+
if (!txId || !JSUtil.isHexaString(txId) || txId.length > 64) {
|
|
34
|
+
// TODO: Use the errors library
|
|
35
|
+
throw new Error('Invalid TXID in object', data);
|
|
36
|
+
}
|
|
37
|
+
var outputIndex = _.isUndefined(data.vout) ? data.outputIndex : data.vout;
|
|
38
|
+
if (!_.isNumber(outputIndex)) {
|
|
39
|
+
throw new Error('Invalid outputIndex, received ' + outputIndex);
|
|
40
|
+
}
|
|
41
|
+
$.checkArgument(
|
|
42
|
+
!_.isUndefined(data.scriptPubKey) || !_.isUndefined(data.script),
|
|
43
|
+
'Must provide the scriptPubKey for that output!',
|
|
44
|
+
);
|
|
45
|
+
var script = new Script(data.scriptPubKey || data.script);
|
|
46
|
+
$.checkArgument(
|
|
47
|
+
!_.isUndefined(data.amount) || !_.isUndefined(data.satoshis),
|
|
48
|
+
'Must provide an amount for the output',
|
|
49
|
+
);
|
|
50
|
+
var amount = !_.isUndefined(data.amount) ? Math.round(data.amount * 1e8) : data.satoshis;
|
|
51
|
+
var outputData = !_.isUndefined(data.data) ? Buffer.from(data.data, 'hex') : Buffer.from([])
|
|
52
|
+
$.checkArgument(_.isNumber(amount), 'Amount must be a number');
|
|
53
|
+
JSUtil.defineImmutable(this, {
|
|
54
|
+
address: address,
|
|
55
|
+
txId: txId,
|
|
56
|
+
outputIndex: outputIndex,
|
|
57
|
+
script: script,
|
|
58
|
+
satoshis: amount,
|
|
59
|
+
data: outputData,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Provide an informative output when displaying this object in the console
|
|
65
|
+
* @returns string
|
|
66
|
+
*/
|
|
67
|
+
UnspentOutput.prototype.inspect = function () {
|
|
68
|
+
return (
|
|
69
|
+
'<UnspentOutput: ' +
|
|
70
|
+
this.txId +
|
|
71
|
+
':' +
|
|
72
|
+
this.outputIndex +
|
|
73
|
+
', satoshis: ' +
|
|
74
|
+
this.satoshis +
|
|
75
|
+
', address: ' +
|
|
76
|
+
this.address +
|
|
77
|
+
'>'
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* String representation: just "txid:index"
|
|
83
|
+
* @returns string
|
|
84
|
+
*/
|
|
85
|
+
UnspentOutput.prototype.toString = function () {
|
|
86
|
+
return this.txId + ':' + this.outputIndex;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Deserialize an UnspentOutput from an object
|
|
91
|
+
* @param {object|string} data
|
|
92
|
+
* @return UnspentOutput
|
|
93
|
+
*/
|
|
94
|
+
UnspentOutput.fromObject = function (data) {
|
|
95
|
+
return new UnspentOutput(data);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Returns a plain object (no prototype or methods) with the associated info for this output
|
|
100
|
+
* @return {object}
|
|
101
|
+
*/
|
|
102
|
+
UnspentOutput.prototype.toObject = UnspentOutput.prototype.toJSON = function toObject() {
|
|
103
|
+
return {
|
|
104
|
+
address: this.address ? this.address.toString() : undefined,
|
|
105
|
+
txid: this.txId,
|
|
106
|
+
vout: this.outputIndex,
|
|
107
|
+
scriptPubKey: this.script.toBuffer().toString('hex'),
|
|
108
|
+
amount: Number.parseFloat((this.satoshis / 1e8).toFixed(8)),
|
|
109
|
+
data: this.data.toString('hex')
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
module.exports = UnspentOutput;
|
package/lib/util/_.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _ = {};
|
|
4
|
+
|
|
5
|
+
_.isArray = (t) => Array.isArray(t);
|
|
6
|
+
_.isNumber = (t) => typeof t === 'number';
|
|
7
|
+
_.isObject = (t) => t && typeof t === 'object';
|
|
8
|
+
_.isString = (t) => typeof t === 'string';
|
|
9
|
+
_.isUndefined = (t) => typeof t === 'undefined';
|
|
10
|
+
_.isFunction = (t) => typeof t === 'function';
|
|
11
|
+
_.isNull = (t) => t === null;
|
|
12
|
+
_.isDate = (t) => t instanceof Date;
|
|
13
|
+
_.extend = (a, b) => Object.assign(a, b);
|
|
14
|
+
_.noop = () => {};
|
|
15
|
+
_.every = (a, f) => a.every(f || ((t) => t));
|
|
16
|
+
_.map = (a, f) => Array.from(a).map(f || ((t) => t));
|
|
17
|
+
_.includes = (a, e) => a.includes(e);
|
|
18
|
+
_.each = (a, f) => a.forEach(f);
|
|
19
|
+
_.clone = (o) => Object.assign({}, o);
|
|
20
|
+
_.pick = (object, keys) => {
|
|
21
|
+
const obj = {};
|
|
22
|
+
keys.forEach((key) => {
|
|
23
|
+
if (typeof object[key] !== 'undefined') {
|
|
24
|
+
obj[key] = object[key];
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return obj;
|
|
28
|
+
};
|
|
29
|
+
_.values = (o) => Object.values(o);
|
|
30
|
+
_.filter = (a, f) => a.filter(f);
|
|
31
|
+
_.reduce = (a, f, s) => a.reduce(f, s);
|
|
32
|
+
_.without = (a, n) => a.filter((t) => t !== n);
|
|
33
|
+
_.shuffle = (a) => {
|
|
34
|
+
const result = a.slice(0);
|
|
35
|
+
for (let i = result.length - 1; i > 0; i--) {
|
|
36
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
37
|
+
[result[i], result[j]] = [result[j], result[i]];
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
_.difference = (a, b) => a.filter((t) => !b.includes(t));
|
|
42
|
+
_.findIndex = (a, f) => a.findIndex(f);
|
|
43
|
+
_.some = (a, f) => a.some(f);
|
|
44
|
+
_.range = (n) => [...Array(n).keys()];
|
|
45
|
+
_.isPositiveNumber = (n) => n < 0x7e;
|
|
46
|
+
|
|
47
|
+
module.exports = _;
|
package/lib/util/js.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _ = require('./_');
|
|
4
|
+
var $ = require('./preconditions');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Determines whether a string contains only hexadecimal values
|
|
8
|
+
*
|
|
9
|
+
* @name JSUtil.isHexa
|
|
10
|
+
* @param {string} value
|
|
11
|
+
* @return {boolean} true if the string is the hexa representation of a number
|
|
12
|
+
*/
|
|
13
|
+
var isHexa = function isHexa(value) {
|
|
14
|
+
if (!_.isString(value)) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return /^[0-9a-fA-F]+$/.test(value);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @namespace JSUtil
|
|
22
|
+
*/
|
|
23
|
+
module.exports = {
|
|
24
|
+
/**
|
|
25
|
+
* Test if an argument is a valid JSON object. If it is, returns a truthy
|
|
26
|
+
* value (the json object decoded), so no double JSON.parse call is necessary
|
|
27
|
+
*
|
|
28
|
+
* @param {string} arg
|
|
29
|
+
* @return {Object|boolean} false if the argument is not a JSON string.
|
|
30
|
+
*/
|
|
31
|
+
isValidJSON: function isValidJSON(arg) {
|
|
32
|
+
var parsed;
|
|
33
|
+
if (!_.isString(arg)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
parsed = JSON.parse(arg);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (typeof parsed === 'object') {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
},
|
|
46
|
+
isHexa: isHexa,
|
|
47
|
+
isHexaString: isHexa,
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Define immutable properties on a target object
|
|
51
|
+
*
|
|
52
|
+
* @param {Object} target - An object to be extended
|
|
53
|
+
* @param {Object} values - An object of properties
|
|
54
|
+
* @return {Object} The target object
|
|
55
|
+
*/
|
|
56
|
+
defineImmutable: function defineImmutable(target, values) {
|
|
57
|
+
Object.keys(values).forEach(function (key) {
|
|
58
|
+
Object.defineProperty(target, key, {
|
|
59
|
+
configurable: false,
|
|
60
|
+
enumerable: true,
|
|
61
|
+
value: values[key],
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
return target;
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* Checks that a value is a natural number, a positive integer or zero.
|
|
68
|
+
*
|
|
69
|
+
* @param {*} value
|
|
70
|
+
* @return {Boolean}
|
|
71
|
+
*/
|
|
72
|
+
isNaturalNumber: function isNaturalNumber(value) {
|
|
73
|
+
return (
|
|
74
|
+
typeof value === 'number' && isFinite(value) && Math.floor(value) === value && value >= 0
|
|
75
|
+
);
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Transform a 4-byte integer (unsigned value) into a Buffer of length 4 (Big Endian Byte Order)
|
|
80
|
+
*
|
|
81
|
+
* @param {number} integer
|
|
82
|
+
* @return {Buffer}
|
|
83
|
+
*/
|
|
84
|
+
integerAsBuffer: function integerAsBuffer(integer) {
|
|
85
|
+
$.checkArgumentType(integer, 'number', 'integer');
|
|
86
|
+
const buf = Buffer.allocUnsafe(4);
|
|
87
|
+
buf.writeUInt32BE(integer, 0);
|
|
88
|
+
return buf;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('../errors');
|
|
4
|
+
var _ = require('./_');
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
checkState: function (condition, message) {
|
|
8
|
+
if (!condition) {
|
|
9
|
+
throw new errors.InvalidState(message);
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
checkArgument: function (condition, argumentName, message, docsPath) {
|
|
13
|
+
if (!condition) {
|
|
14
|
+
throw new errors.InvalidArgument(argumentName, message, docsPath);
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
checkArgumentType: function (argument, type, argumentName) {
|
|
18
|
+
argumentName = argumentName || '(unknown name)';
|
|
19
|
+
if (_.isString(type)) {
|
|
20
|
+
if (type === 'Buffer') {
|
|
21
|
+
if (!Buffer.isBuffer(argument)) {
|
|
22
|
+
throw new errors.InvalidArgumentType(argument, type, argumentName);
|
|
23
|
+
}
|
|
24
|
+
} else if (typeof argument !== type) {
|
|
25
|
+
throw new errors.InvalidArgumentType(argument, type, argumentName);
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
if (!(argument instanceof type)) {
|
|
29
|
+
throw new errors.InvalidArgumentType(argument, type.name, argumentName);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@opcat-labs/opcat",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "opcat base SDK",
|
|
5
|
+
"main": "./index.js",
|
|
6
|
+
"types": "./index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"lint": "standard --fix",
|
|
9
|
+
"test": "mocha"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"assert": "^2.1.0",
|
|
13
|
+
"bs58": "=4.0.1",
|
|
14
|
+
"buffer": "^6.0.3",
|
|
15
|
+
"elliptic": "^6.6.1",
|
|
16
|
+
"hash.js": "^1.1.7",
|
|
17
|
+
"inherits": "2.0.3",
|
|
18
|
+
"unorm": "1.4.1"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"parcel": "^2.15.2",
|
|
22
|
+
"sinon": "^20.0.0"
|
|
23
|
+
},
|
|
24
|
+
"author": "",
|
|
25
|
+
"license": "ISC"
|
|
26
|
+
}
|