UNPKG

@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
"use strict"; 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