10

I'm using web3, truffle and testrpc.

In my smart contract, some of the functions can only be called by the owner (or creator) of the contract (i.e. onlyOwner functions). So, I've defined some modifier for that. Also, in the smart contract, I have defined a variable called owner that can be called by anyone to see who the owner is.

I'm designing a UI. I'd like to alert the users, in UI, if they call the onlyOwner functions (e.g. you're not the owner). In my .js file I can call owner.call(); to get the owner address. But I don't know how to get the users address to compare it with the owner address.

Question: How can I get the user's address via web3?


Also, when we switch the default account (i.e. the first account) in MetaMask to 2nd, 3rd, .. account, how the .js file can recognize it and use that account as the default one?

Aydin
  • 2,117
  • 6
  • 25
  • 41

5 Answers5

8

If you are using web(version 0.19.0: latest stable), you can do

1. Download Web3

bower install web3@0.19.0

2. Algo to load Web3, check the connection and retrieve the accounts

<html>
<body>
    <div id="address"></div>

    <script src="bower_components/web3/dist/web3.min.js"></script>
    <script>

        window.addEventListener('load', function() {


            // Load WEB3
            // Check wether it's already injected by something else (like Metamask or Parity Chrome plugin)
            if(typeof web3 !== 'undefined') {
                web3 = new Web3(web3.currentProvider);  

            // Or connect to a node
            } else {
                web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
            }

            // Check the connection
            if(!web3.isConnected()) {
                console.error("Not connected");

            }

            var account = web3.eth.accounts[0];
            var accountInterval = setInterval(function() {
              if (web3.eth.accounts[0] !== account) {
                account = web3.eth.accounts[0];
                document.getElementById("address").innerHTML = account;
              }
            }, 100);

        });

    </script>
</body>
</html>

3. Auto-reload after switching account

The solution right now is a basic setInterval function

enter image description here

Greg Jeanmart
  • 7,207
  • 2
  • 19
  • 35
  • thanks for the answer. But, don't you think we're setting the account as account[0]. Assume we switch to account[1] in MetaMask, then how web3 (in .js file) can detect it and set account=account[1]? Am I right that your answer explains: how we can set user's account to account[0], but it doesn't show how we can get the user's current address? (assume we manually set the account to account[1] in MetaMasK browser extension.). Thanks – Aydin Sep 11 '17 at 19:57
  • I don't know if you have seen the update. But the array always contains one element which the current metamask address. – Greg Jeanmart Sep 11 '17 at 19:59
  • To pull a change. A setInterval function does the job – Greg Jeanmart Sep 11 '17 at 20:00
  • I am using a newer version of web 3 and web3.eth.accounts[0] is giving me undefined instead of the address of the account – Zeeshan Ahmad Khalil Aug 05 '19 at 09:45
  • 1
    The web3.eth.getAccounts() is giving the addresses of all the accounts – Zeeshan Ahmad Khalil Aug 05 '19 at 09:53
  • @ZeeshanAhmadKhalil web3.eth.getAccounts() now gives me "Method not found" error... – Jim Aug 29 '21 at 06:17
  • @Jim I was using web3^1.0.0-beta.55. The current version is web3^1.5.2. Check your web 3.0 version in package.json, see their documentation and find the function against your own version to get all the accounts. – Zeeshan Ahmad Khalil Aug 29 '21 at 11:12
8

var account = web3.currentProvider.selectedAddress

*for web3 1.2.0

Bruno Silva
  • 81
  • 1
  • 3
2

web3.currentProvider.selectedAddress is deprecated

MetaMask no longer injects web3 so web3.eth.accounts[0] and so on won't work.

See https://docs.metamask.io/guide/provider-migration.html#replacing-window-web3

You should migrate to window.ethereum and use it for all operations.

But window.ethereum.selectedAddress is deprecated too.

Correct way is await window.ethereum.request({ method: 'eth_accounts' })

See https://docs.metamask.io/guide/ethereum-provider.html#legacy-properties

But if you are using web3.js directly, like from nodejs, then you can do this:

const accounts = await web3.eth.getAccounts();
console.log(accounts[0]);
Jeremy Then
  • 4,599
  • 3
  • 5
  • 28
Andrej
  • 121
  • 4
2

If the user is using MetaMask: MetaMask has said that it will deprecate injecting web3 into the global object. However they have replaced this with an ethereum object which is equivalent to web3.currentProvider.

Since 2018, it has become necessary to request permission to get the current user's account address, which can be done by making a call to ethereum.enable(). The call to enable will return a promise that will resolve to an array of addresses containing the current address, and will also populate the selectedAddress property of the ethereum object:

let _web3:Web3;
const ethereum = (window as any).ethereum;
if (ethereum) {
    if (!ethereum.selectedAddress) {
        await ethereum.enable(); // <<< ask for permission
    }
    userAccount = ethereum.selectedAddress;
    _web3 = new Web3(ethereum);
}   
else {
   ...< connect to local rpc >
}
return _web3;

When the user changes accounts on MetaMask, that should ripple through the currentProvider which, i believe, causes a page refresh.

WeezyKrush
  • 121
  • 2
0

Just use

var acc = web3.currentProvider.selectedAddress;
Martin Tonev
  • 121
  • 6