mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-12-24 13:24:05 -06:00
67 lines
2.5 KiB
JavaScript
67 lines
2.5 KiB
JavaScript
const Account = require("./account");
|
|
const Nat = require("./nat");
|
|
const Bytes = require("./bytes");
|
|
const RLP = require("./rlp");
|
|
const keccak256 = require("./hash").keccak256;
|
|
|
|
// EthereumRPC, IncompleteTransaction -> Promise Transaction
|
|
const addDefaults = (rpc, tx) => {
|
|
var baseDefaults = [tx.chainId || rpc("net_version", []), tx.gasPrice || rpc("eth_gasPrice", []), tx.nonce || rpc("eth_getTransactionCount", [tx.from, "latest"]), tx.value || "0x0", tx.data || "0x"];
|
|
const noAddress = address => !address || address === "" || address === "0x";
|
|
return Promise.all(baseDefaults).then(([chainIdNum, gasPrice, nonce, value, data]) => {
|
|
var chainId = Nat.fromNumber(chainIdNum);
|
|
var gasEstimator = tx.gas ? Promise.resolve(null) : rpc("eth_estimateGas", [{
|
|
from: noAddress(tx.from) ? null : tx.from,
|
|
to: noAddress(tx.to) ? null : tx.to,
|
|
value: tx.value,
|
|
nonce: tx.nonce,
|
|
data: tx.data
|
|
}]);
|
|
return gasEstimator.then(gasEstimate => {
|
|
if (gasEstimate.error) {
|
|
throw gasEstimate.error;
|
|
}
|
|
return {
|
|
chainId: chainId,
|
|
from: noAddress(tx.from) ? "0x" : tx.from.toLowerCase(),
|
|
to: noAddress(tx.to) ? "0x" : tx.to.toLowerCase(),
|
|
gasPrice: gasPrice,
|
|
gas: tx.gas ? tx.gas : Nat.div(Nat.mul(gasEstimate, "0x6"), "0x5"),
|
|
nonce: nonce,
|
|
value: value,
|
|
data: data ? data.toLowerCase() : null
|
|
};
|
|
});
|
|
});
|
|
};
|
|
|
|
// Transaction -> Bytes
|
|
const signingData = tx => {
|
|
return RLP.encode([Bytes.fromNat(tx.nonce), Bytes.fromNat(tx.gasPrice), Bytes.fromNat(tx.gas), tx.to ? tx.to.toLowerCase() : "0x", Bytes.fromNat(tx.value), tx.data, Bytes.fromNat(tx.chainId || "0x1"), "0x", "0x"]);
|
|
};
|
|
|
|
// Transaction, Account -> Bytes
|
|
const sign = (tx, account) => {
|
|
const data = signingData(tx);
|
|
const signature = Account.makeSigner(Nat.toNumber(tx.chainId || "0x1") * 2 + 35)(keccak256(data), account.privateKey);
|
|
const rawTransaction = RLP.decode(data).slice(0, 6).concat(Account.decodeSignature(signature));
|
|
return RLP.encode(rawTransaction);
|
|
};
|
|
|
|
// Bytes -> Address
|
|
const recover = rawTransaction => {
|
|
const values = RLP.decode(rawTransaction);
|
|
const signature = Account.encodeSignature(values.slice(6, 9));
|
|
const recovery = Bytes.toNumber(values[6]);
|
|
const extraData = recovery < 35 ? [] : [Bytes.fromNumber(recovery - 35 >> 1), "0x", "0x"];
|
|
const data = values.slice(0, 6).concat(extraData);
|
|
const dataHex = RLP.encode(data);
|
|
return Account.recover(keccak256(dataHex), signature);
|
|
};
|
|
|
|
module.exports = {
|
|
addDefaults,
|
|
signingData,
|
|
sign,
|
|
recover
|
|
}; |