UNPKG

3.91 kBJavaScriptView Raw
1const { sha3, ecdsaSign, ecdsaRecover, privateKeyToAddress, rlpEncode } = require('./util/sign');
2const format = require('./util/format');
3
4class Transaction {
5 /**
6 * Create a transaction.
7 *
8 * @param options {object}
9 * @param options.from {string} - The sender address.
10 * @param options.nonce {string|number} - This allows to overwrite your own pending transactions that use the same nonce.
11 * @param options.gasPrice {string|number} - The price of gas for this transaction in drip.
12 * @param options.gas {string|number} - The amount of gas to use for the transaction (unused gas is refunded).
13 * @param [options.to=null] {string} - The destination address of the message, left undefined for a contract-creation transaction.
14 * @param [options.value=0] {string|number} - The value transferred for the transaction in drip, also the endowment if it’s a contract-creation transaction.
15 * @param options.storageLimit {string|number} - TODO
16 * @param options.epochHeight {string|number} - TODO
17 * @param [options.chainId=0] {string|number} - TODO
18 * @param [options.data='0x'] {string|Buffer} - Either a ABI byte string containing the data of the function call on a contract, or in the case of a contract-creation transaction the initialisation code.
19 * @param [options.r] {string|Buffer} - ECDSA signature r
20 * @param [options.s] {string|Buffer} - ECDSA signature s
21 * @param [options.v] {number} - ECDSA recovery id
22 * @return {Transaction}
23 */
24 constructor({ from, nonce, gasPrice, gas, to, value, storageLimit, epochHeight, chainId, data, v, r, s }) {
25 this.from = from;
26 this.nonce = nonce;
27 this.gasPrice = gasPrice;
28 this.gas = gas;
29 this.to = to;
30 this.value = value;
31 this.storageLimit = storageLimit;
32 this.epochHeight = epochHeight;
33 this.chainId = chainId;
34 this.data = data;
35 this.v = v;
36 this.r = r;
37 this.s = s;
38 }
39
40 /**
41 * Getter of transaction hash include signature.
42 *
43 * > Note: calculate every time.
44 *
45 * @return {string|undefined} If transaction has r,s,v return hex string, else return undefined.
46 */
47 get hash() {
48 try {
49 return format.hex(sha3(this.encode(true)));
50 } catch (e) {
51 return undefined;
52 }
53 }
54
55 /**
56 * Sign transaction and set 'r','s','v'.
57 *
58 * @param privateKey {string} - Private key hex string.
59 * @return {Transaction}
60 */
61 sign(privateKey) {
62 const privateKeyBuffer = format.buffer(privateKey);
63 const addressBuffer = privateKeyToAddress(privateKeyBuffer);
64 const { r, s, v } = ecdsaSign(sha3(this.encode(false)), privateKeyBuffer);
65
66 this.from = format.address(addressBuffer);
67 this.r = format.hex(r);
68 this.s = format.hex(s);
69 this.v = v;
70
71 return this;
72 }
73
74 /**
75 * Recover public key from signed Transaction.
76 *
77 * @return {string}
78 */
79 recover() {
80 const publicKey = ecdsaRecover(sha3(this.encode(false)), {
81 r: format.buffer(this.r),
82 s: format.buffer(this.s),
83 v: format.uInt(this.v),
84 });
85 return format.publicKey(publicKey);
86 }
87
88 /**
89 * Encode rlp.
90 *
91 * @param [includeSignature=false] {boolean} - Whether or not to include the signature.
92 * @return {Buffer}
93 */
94 encode(includeSignature) {
95 const { nonce, gasPrice, gas, to, value, storageLimit, epochHeight, chainId, data, v, r, s } = format.signTx(this);
96
97 const raw = includeSignature
98 ? [[nonce, gasPrice, gas, to, value, storageLimit, epochHeight, chainId, data], v, r, s]
99 : [nonce, gasPrice, gas, to, value, storageLimit, epochHeight, chainId, data];
100
101 return rlpEncode(raw);
102 }
103
104 /**
105 * Get the raw transaction hex string.
106 *
107 * @return {string} Hex string
108 */
109 serialize() {
110 return format.hex(this.encode(true));
111 }
112}
113
114module.exports = Transaction;