├── .gitignore ├── package.json ├── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.tgz -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "truffle-hdwallet-provider-privkey", 3 | "version": "1.0.3", 4 | "description": "HD Wallet-enabled Web3 provider for use with raw private key", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/rhlsthrm/truffle-hdwallet-provider-privkey.git" 12 | }, 13 | "keywords": [ 14 | "ethereum" 15 | ], 16 | "author": "Rahul Sethuram ", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/rhlsthrm/truffle-hdwallet-provider-privkey/issues" 20 | }, 21 | "homepage": "https://github.com/rhlsthrm/truffle-hdwallet-provider-privkey#readme", 22 | "devDependencies": { 23 | "standard": "^10.0.3" 24 | }, 25 | "dependencies": { 26 | "ethereumjs-tx": "^1.3.4", 27 | "ethereumjs-wallet": "^0.6.0", 28 | "web3": "1.0.0-beta.33", 29 | "web3-provider-engine": "git+https://github.com/cgewecke/provider-engine.git#web3-one" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const FiltersSubprovider = require('web3-provider-engine/subproviders/filters.js') 2 | const HookedSubprovider = require('web3-provider-engine/subproviders/hooked-wallet.js') 3 | const NonceSubProvider = require('web3-provider-engine/subproviders/nonce-tracker.js'); 4 | const Web3 = require('web3') 5 | const Transaction = require('ethereumjs-tx') 6 | const ProviderEngine = require('web3-provider-engine') 7 | const ProviderSubprovider = require("web3-provider-engine/subproviders/provider.js"); 8 | const ethereumjsWallet = require('ethereumjs-wallet') 9 | 10 | function HDWalletProvider (privateKeys, providerUrl) { 11 | 12 | this.wallets = {}; 13 | this.addresses = []; 14 | 15 | // from https://github.com/trufflesuite/truffle-hdwallet-provider/pull/25/commits 16 | for (let key of privateKeys) { 17 | var wallet = ethereumjsWallet.fromPrivateKey(new Buffer(key, "hex")); 18 | var addr = '0x' + wallet.getAddress().toString('hex'); 19 | this.addresses.push(addr); 20 | this.wallets[addr] = wallet; 21 | } 22 | 23 | const tmpAccounts = this.addresses; 24 | const tmpWallets = this.wallets; 25 | 26 | this.engine = new ProviderEngine() 27 | 28 | // from https://github.com/trufflesuite/truffle-hdwallet-provider/pull/66 29 | this.engine.addProvider(new NonceSubProvider()) 30 | this.engine.addProvider( 31 | new HookedSubprovider({ 32 | getAccounts: function (cb) { 33 | cb(null, tmpAccounts) 34 | }, 35 | getPrivateKey: function (address, cb) { 36 | if (!tmpWallets[address]) { 37 | return cb('Account not found') 38 | } else { 39 | cb(null, tmpWallets[address].getPrivateKey().toString('hex')) 40 | } 41 | }, 42 | signTransaction: function (txParams, cb) { 43 | let pkey 44 | if (tmpWallets[txParams.from]) { 45 | pkey = tmpWallets[txParams.from].getPrivateKey() 46 | } else { 47 | cb('Account not found') 48 | } 49 | var tx = new Transaction(txParams) 50 | tx.sign(pkey) 51 | var rawTx = '0x' + tx.serialize().toString('hex') 52 | cb(null, rawTx) 53 | } 54 | }) 55 | ) 56 | this.engine.addProvider(new FiltersSubprovider()); 57 | this.engine.addProvider(new ProviderSubprovider(new Web3.providers.HttpProvider(providerUrl))); 58 | this.engine.start(); // Required by the provider engine. 59 | } 60 | 61 | HDWalletProvider.prototype.sendAsync = function () { 62 | this.engine.sendAsync.apply(this.engine, arguments) 63 | } 64 | 65 | HDWalletProvider.prototype.send = function () { 66 | return this.engine.send.apply(this.engine, arguments) 67 | } 68 | 69 | // returns the address of the given address_index, first checking the cache 70 | HDWalletProvider.prototype.getAddress = function (idx) { 71 | console.log('getting addresses', this.addresses[0], idx) 72 | if (!idx) { 73 | return this.addresses[0] 74 | } else { 75 | return this.addresses[idx] 76 | } 77 | } 78 | 79 | // returns the addresses cache 80 | HDWalletProvider.prototype.getAddresses = function () { 81 | return this.addresses 82 | } 83 | 84 | module.exports = HDWalletProvider 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # truffle-hdwallet-provider-privkey 2 | HD Wallet-enabled Web3 provider. Use it to sign transactions for addresses derived from a raw private key string. 3 | 4 | If you are using Web3 1.0, please use the `web3-one` branch. Install the package using `npm i truffle-hdwallet-provider-privkey@web3-one`. README is updated in that branch. 5 | 6 | ## Install 7 | 8 | ``` 9 | $ npm install truffle-hdwallet-provider-privkey@web3-one 10 | ``` 11 | 12 | ## General Usage 13 | 14 | You can use this provider wherever a Web3 provider is needed, not just in Truffle. For Truffle-specific usage, see next section. 15 | 16 | ```javascript 17 | const HDWalletProvider = require("truffle-hdwallet-provider-privkey"); 18 | const privKeys = ["ce2eab51c7c428...", "46c36f1970dcf37ec..."]; // private keys 19 | const provider = new HDWalletProvider(privKeys, "http://localhost:8545"); 20 | ``` 21 | 22 | By default, the `HDWalletProvider` will use the address of the first address that's generated from the private key. Currently, the `HDWalletProvider` manages only one address at a time, but it can be easily upgraded to manage (i.e., "unlock") multiple addresses. 23 | 24 | Parameters: 25 | 26 | - `privateKeys`: `string`. Array of private keys for multiple accounts (DO NOT SHARE THEM EVER). 27 | - `provider_uri`: `string`. URI of Ethereum client to send all other non-transaction-related Web3 requests. 28 | 29 | ## Truffle Usage 30 | 31 | ### Use Case 32 | 33 | I have a an account MetaMask and I want to use it to deploy my contracts to a testnet/mainnnet. 34 | 35 | ### Steps for MetaMask 36 | 37 | - Click 3 dots next to MetaMask 38 | - Click "Account Details" 39 | - Click "Export Private Key" and type password 40 | - Copy private key and use the below steps in your Truffle config. 41 | 42 | ### Usage 43 | 44 | You can easily use this within a Truffle configuration. For instance: 45 | 46 | truffle.js 47 | ```javascript 48 | const HDWalletProvider = require("truffle-hdwallet-provider-privkey"); 49 | 50 | const privateKeys = ["ce2eab51c7c428...", "46c36f1970dcf37ec..."]; // private keys 51 | 52 | module.exports = { 53 | networks: { 54 | development: { 55 | host: "localhost", 56 | port: 8545, 57 | network_id: "*" // Match any network id 58 | }, 59 | ropsten: { 60 | provider: () => { 61 | return new HDWalletProvider(privateKeys, "https://ropsten.infura.io/MY_INFURA_KEY") 62 | }, 63 | network_id: 3 64 | } 65 | } 66 | }; 67 | ``` 68 | 69 | ## Web3 Provider 70 | 71 | You can also use the Wallet provider as an easy way to get a Web3 object that has an unlocked account to sign transactions through an INFURA node. 72 | 73 | ```javascript 74 | const Web3 = require('web3') 75 | const WalletProvider = require('truffle-hdwallet-provider-privkey') 76 | 77 | const privKey = "2442e1526f1..."; // raw private key 78 | 79 | const w = new WalletProvider(privKey, "https://ropsten.infura.io/MY_INFURA_KEY") 80 | web3 = new Web3(w.engine) 81 | ``` 82 | 83 | ## Notes 84 | 85 | Make sure the `from` address you use when sending transactions is entirely lowercase or you will see an error like this: 86 | 87 | ``` 88 | TypeError: private key should be a Buffer 89 | ``` 90 | 91 | --------------------------------------------------------------------------------