@nomiclabs/buidler
Version:
Buidler is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.
168 lines • 7.51 kB
JavaScript
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const keys_derivation_1 = require("../../util/keys-derivation");
const errors_1 = require("../errors");
const errors_list_1 = require("../errors-list");
const provider_utils_1 = require("./provider-utils");
const wrapper_1 = require("./wrapper");
// This library's types are wrong, they don't type check
// tslint:disable-next-line no-var-requires
const ethSigUtil = require("eth-sig-util");
const HD_PATH_REGEX = /^m(:?\/\d+'?)+\/?$/;
function createLocalAccountsProvider(provider, hexPrivateKeys) {
const { bufferToHex, toBuffer, privateToAddress, } = require("ethereumjs-util");
const privateKeys = hexPrivateKeys.map((h) => toBuffer(h));
const addresses = privateKeys.map((pk) => bufferToHex(privateToAddress(pk)));
const getChainId = provider_utils_1.createChainIdGetter(provider);
function getPrivateKey(address) {
for (let i = 0; i < address.length; i++) {
if (addresses[i] === address.toLowerCase()) {
return privateKeys[i];
}
}
}
return wrapper_1.wrapSend(provider, async (method, params) => {
const { ecsign, hashPersonalMessage, toRpcSig } = await Promise.resolve().then(() => __importStar(require("ethereumjs-util")));
if (method === "eth_accounts" || method === "eth_requestAccounts") {
return [...addresses];
}
if (method === "eth_sign") {
const [address, data] = params;
if (address !== undefined) {
if (data === undefined) {
throw new errors_1.BuidlerError(errors_list_1.ERRORS.NETWORK.ETHSIGN_MISSING_DATA_PARAM);
}
const privateKey = getPrivateKey(address);
if (privateKey === undefined) {
throw new errors_1.BuidlerError(errors_list_1.ERRORS.NETWORK.NOT_LOCAL_ACCOUNT, {
account: address,
});
}
const messageHash = hashPersonalMessage(toBuffer(data));
const signature = ecsign(messageHash, privateKey);
return toRpcSig(signature.v, signature.r, signature.s);
}
}
if (method === "eth_signTypedData") {
const [address, data] = params;
if (address !== undefined) {
if (data === undefined) {
throw new errors_1.BuidlerError(errors_list_1.ERRORS.NETWORK.ETHSIGN_MISSING_DATA_PARAM);
}
const privateKey = getPrivateKey(address);
if (privateKey === undefined) {
throw new errors_1.BuidlerError(errors_list_1.ERRORS.NETWORK.NOT_LOCAL_ACCOUNT, {
account: address,
});
}
return ethSigUtil.signTypedData_v4(privateKey, {
data,
});
}
}
if (method === "eth_sendTransaction" && params.length > 0) {
const tx = params[0];
if (tx.gas === undefined) {
throw new errors_1.BuidlerError(errors_list_1.ERRORS.NETWORK.MISSING_TX_PARAM_TO_SIGN_LOCALLY, { param: "gas" });
}
if (tx.gasPrice === undefined) {
throw new errors_1.BuidlerError(errors_list_1.ERRORS.NETWORK.MISSING_TX_PARAM_TO_SIGN_LOCALLY, { param: "gasPrice" });
}
if (tx.nonce === undefined) {
tx.nonce = await provider.send("eth_getTransactionCount", [
tx.from,
"pending",
]);
}
const privateKey = getPrivateKey(tx.from);
if (privateKey === undefined) {
throw new errors_1.BuidlerError(errors_list_1.ERRORS.NETWORK.NOT_LOCAL_ACCOUNT, {
account: tx.from,
});
}
const chainId = await getChainId();
const rawTransaction = await getSignedTransaction(tx, chainId, privateKey);
return provider.send("eth_sendRawTransaction", [
bufferToHex(rawTransaction),
]);
}
return provider.send(method, params);
});
}
exports.createLocalAccountsProvider = createLocalAccountsProvider;
function createHDWalletProvider(provider, mnemonic, hdpath = "m/44'/60'/0'/0/", initialIndex = 0, count = 10) {
if (hdpath.match(HD_PATH_REGEX) === null) {
throw new errors_1.BuidlerError(errors_list_1.ERRORS.NETWORK.INVALID_HD_PATH, { path: hdpath });
}
if (!hdpath.endsWith("/")) {
hdpath += "/";
}
const privateKeys = [];
for (let i = initialIndex; i < initialIndex + count; i++) {
const privateKey = keys_derivation_1.deriveKeyFromMnemonicAndPath(mnemonic, hdpath + i.toString());
if (privateKey === undefined) {
throw new errors_1.BuidlerError(errors_list_1.ERRORS.NETWORK.CANT_DERIVE_KEY, {
mnemonic,
path: hdpath,
});
}
privateKeys.push(privateKey);
}
const { bufferToHex } = require("ethereumjs-util");
return createLocalAccountsProvider(provider, privateKeys.map((pk) => bufferToHex(pk)));
}
exports.createHDWalletProvider = createHDWalletProvider;
function createSenderProvider(provider, from) {
let addresses = from === undefined ? undefined : [from];
return wrapper_1.wrapSend(provider, async (method, params) => {
if (method === "eth_sendTransaction" ||
method === "eth_call" ||
method === "eth_estimateGas") {
const tx = params[0];
if (tx !== undefined && tx.from === undefined) {
const [senderAccount] = await getAccounts();
if (senderAccount !== undefined) {
tx.from = senderAccount;
}
else if (method === "eth_sendTransaction") {
throw new errors_1.BuidlerError(errors_list_1.ERRORS.NETWORK.NO_REMOTE_ACCOUNT_AVAILABLE);
}
}
}
return provider.send(method, params);
});
async function getAccounts() {
if (addresses !== undefined) {
return addresses;
}
addresses = (await provider.send("eth_accounts"));
return addresses;
}
}
exports.createSenderProvider = createSenderProvider;
async function getSignedTransaction(tx, chainId, privateKey) {
const chains = require("ethereumjs-common/dist/chains");
const { Transaction } = await Promise.resolve().then(() => __importStar(require("ethereumjs-tx")));
let transaction;
if (chains.chains.names[chainId] !== undefined) {
transaction = new Transaction(tx, { chain: chainId });
}
else {
const { default: Common } = await Promise.resolve().then(() => __importStar(require("ethereumjs-common")));
const common = Common.forCustomChain("mainnet", {
chainId,
networkId: chainId,
}, "istanbul");
transaction = new Transaction(tx, { common });
}
transaction.sign(privateKey);
return transaction.serialize();
}
//# sourceMappingURL=accounts.js.map
;