2

Is it possible to sign a user in web3 without MetaMask? I am trying to execute a smart contract I created and I'm using Infura to connect to the Kovan test network, but web3.eth.accounts[0] is undefined. How can I sign a user in without having to use MetaMask? Is this even possible? If not, how should I approach this problem? Please and thank you!

5

What you should do in this case is use the web3-provider-engine. An example code snippet functioning with a custom private key and Infura API URL (Or even TestRPC) would be the following:

//Provider Engine sub-modules

const ProviderEngine = require('web3-provider-engine')
const CacheSubprovider = require('web3-provider-engine/subproviders/cache.js')
const FixtureSubprovider = require('web3-provider-engine/subproviders/fixture.js')
const FilterSubprovider = require('web3-provider-engine/subproviders/filters.js')
const VmSubprovider = require('web3-provider-engine/subproviders/vm.js')
const NonceSubprovider = require('web3-provider-engine/subproviders/nonce-tracker.js')
const RpcSubprovider = require('web3-provider-engine/subproviders/rpc.js')

//EthereumJS Wallet Sub-Provider

const WalletSubprovider = require('ethereumjs-wallet/provider-engine')
const walletFactory = require('ethereumjs-wallet')

//Web3 Module

const Web3 = require('web3')

//Wallet Initialization

var privateKey = "3a1076bf45ab87712ad64ccb3b10217737f7faacbf2872e88fdd9a537d8fe266"
var privateKeyBuffer = new Buffer(privateKey, "hex")
var myWallet = walletFactory.fromPrivateKey(privateKeyBuffer)

//Engine initialization & sub-provider attachment

var engine = new ProviderEngine();

engine.addProvider(new FixtureSubprovider({
  web3_clientVersion: 'ProviderEngine/v0.0.0/javascript',
  net_listening: true,
  eth_hashrate: '0x00',
  eth_mining: false,
  eth_syncing: true,
}))

// cache layer
engine.addProvider(new CacheSubprovider())

// filters
engine.addProvider(new FilterSubprovider())

// pending nonce
engine.addProvider(new NonceSubprovider())

// vm
engine.addProvider(new VmSubprovider())

// Here the URL can be your localhost for TestRPC or the Infura URL
engine.addProvider(new RpcSubprovider({
  rpcUrl: 'https://mainnet.infura.io/YOUR_ACCESS_TOKEN',
}))

// Wallet Attachment
engine.addProvider(new WalletSubprovider(myWallet))

// network connectivity error
engine.on('error', function(err){
  // report connectivity errors
  console.error(err.stack)
})

// start polling for blocks
engine.start()

//Actual Initialization of the web3 module

var web3 = new Web3(engine)

You will be able to sign any transactions you want with your supplied private key by specifying your public key as the "from" value in the settings object of each perspective web3 function call.

EDIT: I personally despise the web3 library and as a result, I decided to revamp the snippet to use the ethers.js library which has a more human-readable API:

//Provider Engine sub-modules

const ethers = require('ethers');
const Wallet = ethers.Wallet;
const Contract = ethers.Contract;
const utils = ethers.utils;
const providers = ethers.providers; 

//Note the "0x" appended at the start
let privateKey = "0x3a1076bf45ab87712ad64ccb3b10217737f7faacbf2872e88fdd9a537d8fe266";

let network = "http://192.168.1.1:8545";

//let network = "kovan";
//let network = "ropsten";
//let network = "rinkeby";
//let network = "homestead";

//let infuraAPIKey = "9LPi9fDukz8phfLXdy5K";

let provider = new providersJsonRpcProvider(network, 'homestead');
//let provider = new providers.InfuraProvider(network, infuraAPIKey);

let serverWallet = new Wallet(privateKey, provider);

That's basically it. You can now send transactions with it or construct Contract objects to interact with contracts with it. Refer to the ethers.js documentation for more.

  • I think something has changed. First, I had to add myWallet this way: engine.addProvider(new WalletSubprovider(myWallet, {})), probably just an API change. I can call read-only contract methods with this engine, but sending transactions results in [Error: Method not found] message: 'Method not found', code: -32601 – sudo Apr 8 '18 at 22:44
  • 1
    @sudo I would suggest using an alternative library. I have added an alternative code snippet to the original topic using ethers.js which I find quite user intuitive. – Alex Papageorgiou Apr 11 '18 at 16:35
  • Thanks. A couple of days ago, I ended up figuring out how to manually sign my transactions with web3 instead of using MetaMask's library, and yes, it was horribly painful. I'll try your ether.js setup next time because it looks much nicer. Anyway, this is what I got working for web3: gist.github.com/AlecZadikian9001/… – sudo Apr 11 '18 at 17:41
1

maybe this helps https://github.com/MetaMask/provider-engine and some info here http://truffleframework.com/tutorials/using-infura-custom-provider

  • 1
    Whilst this may answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference. – user47887 Nov 9 '18 at 15:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.