Web3js

您如何在 MetaMask 以外的 Web3 瀏覽器上找到乙太坊提供商?

  • January 6, 2020

MetaMask 目前提供以下方式來為其即將到來的 2020 年重大變革尋找供應商:

// Running on the page, in the browser
// This API will go live in Q1 2020
// It will be the only API available after a 6-week deprecation period

if (!ethereum || !ethereum.isMetaMask) {
 throw new Error('Please install MetaMask.')
}

/*********************************************************/
/* Handle chain (network) and chainChanged, per EIP 1193 */
/*********************************************************/

let currentChainId = null
ethereum.send('eth_chainId')
 .then(handleChainChanged)
 .catch(err => console.error(err)) // This should never happen

ethereum.on('chainChanged', handleChainChanged)

function handleChainChanged (chainId) {

 if (currentChainId !== chainId) {

   currentChainId = chainId
   // Run any other necessary logic...
 }
}

/**********************************************************/
/* Handle user accounts and accountsChanged, per EIP 1193 */
/**********************************************************/

let currentAccount = null
ethereum.send('eth_accounts')
 .then(handleAccountsChanged)
 .catch(err => {
   // In the future, maybe in 2020, this will return a 4100 error if
   // the user has yet to connect
   if (err.code === 4100) { // EIP 1193 unauthorized error
     console.log('Please connect to MetaMask.')
   } else {
     console.error(err)
   }
 })

// Note that this event is emitted on page load.
// If the array of accounts is non-empty, you're already
// connected.
ethereum.on('accountsChanged', handleAccountsChanged)

// For now, 'eth_accounts' will continue to always return an array
function handleAccountsChanged (accounts) {

 if (accounts.length === 0) {

   // MetaMask is locked or the user has not connected any accounts
   console.log('Please connect to MetaMask.')

 } else if (accounts[0] !== currentAccount) {

   currentAccount = accounts[0]
   // Run any other necessary logic...
 }
}

/***********************************/
/* Handle connecting, per EIP 1102 */
/***********************************/

// You should only attempt to connect in response to user interaction,
// such as a button click. Otherwise, you're popup-spamming the user
// like it's 1999.
// If you can't retrieve the user's account(s), you should encourage the user
// to initiate a connection attempt.
document.getElementById('connectButton', connect)

function connect () {

 // This is equivalent to ethereum.enable()
 ethereum.send('eth_requestAccounts')
   .then(handleAccountsChanged)
   .catch(err => {
     if (err.code === 4001) { // EIP 1193 userRejectedRequest error
       console.log('Please connect to MetaMask.')
     } else {
       console.error(err)
     }
   })
}

我正在努力讓我的前端辨識不是 MetaMask 的 web3.js 提供程序。上面的程式碼在目前版本的 MetaMask 上完美執行,但在任何其他 Web3 瀏覽器中都無法執行。如果我注入我自己的 web3.js,我會得到 Can't find variable: Web3MetaMask Can't find variable: ethereum的文件非常混亂,特別是考慮到它仍然注入 v0.2 的 web3.js,同時迫使你很快完全改變你找到提供者的方式。我什至不知道上面的程式碼是針對哪個版本的 web3.js,1.2 還是 2.0。從他們所有令人費解的新聞稿和部落格中都不清楚,這些新聞稿和部落格似乎來自團隊中的另一個人。

如何使上述程式碼適用於其他 web3.js 瀏覽器,如 Cipher 或 Parity?

目前我使用 v0.2 執行此操作:

if (typeof web3 !== 'undefined') {
   console.log('Web3 Detected! ' + web3.currentProvider.constructor.name)
   window.web3 = new Web3(web3.currentProvider);
   web3.eth.defaultAccount = web3.eth.accounts[0];
} else {
   console.log('No Web3 Detected, Using HTTP Provider')
   web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/v3/xxxxxxx"));
   alert("You are not logged into a Web 3.0 enabled wallet such as MetaMask. You will be able to see the current status of the contract via Infura Web 3.0 services, but you will not be able to interact with the Dapp. Please login to a Web 3.0 wallet and refresh the page to use all functions.");
}

請參閱 Status 文件中的本教程和範例。https://status.im/developer_tools/run_on_status/eip-1102.html

這個想法是保持向後兼容性,同時在瀏覽器/元遮罩/等支持時引入和支持 EIP-1102。換句話說,在不破壞現有提供商支持的情況下添加 EIP-1102。

它查找 EIP-1102,如果不存在,則通過其他方法回退。這為使用者提供了與 MetaMask/Status 和 EIP-1102、遺留注入提供程序或他們自己的節點一起使用的選項和 UI。

請原諒範例應用程序的粗魯。有意避免混淆完成此任務的要點。出於這個原因,除了舊的 jQuery 將某些東西放在螢幕上之外,沒有使用任何外觀問題或前端框架。

const Web3 = require("web3");
const $ = require("jquery");

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

   if (typeof ethereum !== 'undefined') {
       // Supports EIP-1102 injected Ethereum providers.
       window.web3 = new Web3(ethereum);
   } else if (typeof web3 !== 'undefined') {
       // Supports legacy injected Ethereum providers.
       window.web3 = new Web3(web3.currentProvider);
   } else {
       // Your preferred fallback.
       window.web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); 
   }

   try {
       $("#connected").html(`You are connected to network ${await window.web3.eth.net.getId()}`);
   } catch(error) {
       $("#connected").html(`You are have no access to Ethereum: ${error}`);
   }

   $("#otherAddress").change(async function() {
       try {
           $("#otherBalance").html(await window.web3.eth.getBalance($(this).val()));
       } catch(error) {
           $("#otherBalance").html(error);
       }
   });

   const displayMyAccounts = accounts => {
       try {
           if (accounts.length == 0) {
               $("#myAddresses").html("<tr><td colspan='2'>You have no addresses</td></tr>");
           } else {
               $("#myAddresses").html("");
               accounts.forEach(async myAddress => $("#myAddresses").append(`<tr>
                       <td>${myAddress}</td>
                       <td>${await window.web3.eth.getBalance(myAddress)}</td>
                   </tr>`)
               );
           }
       } catch(error) {
           $("#myAddresses").html(error);
       }
   };

   if (typeof ethereum !== 'undefined') {
       $("#allowMyAddresses").click(async () => {
           try {
               displayMyAccounts(await ethereum.enable());
           } catch(error) {
               $("#allowStatus").html("You did not allow to access your addresses");
           }
       });
   } else {
       try {
           displayMyAccounts(await window.web3.eth.getAccounts());
       } catch(error) {
           $("#myAddresses").html(`Failed to get your addresses: ${error}`);
       }        
   }

});
  • 一個新的教程解釋了發生了什麼。它可能比在這裡重新散列更清楚(感謝回饋):https ://status.im/developer_tools/run_on_status/eip-1102.html
  • 帶和不帶 EIP-1102 的範常式式碼(注意教程中描述的分支):https ://github.com/b9lab/eip-1102-example 。“injected-web3”意味著看起來很熟悉,“eip-1102-injected”意味著解決方案,而差異意味著具有指導意義。

為清楚起見,本教程所說的“在 Status 中”,您可以將其解釋為“在帶有 Status、MetaMask 或任何其他支持 EIP-1102 的配置的瀏覽器中”。該範例使用 MetaMask 進行了測試。當然,關於導航到權限的提示會有所不同,但要點是相同的,因為 EIP-1102 對權限的流程和表示很清楚。

希望能幫助到你。

引用自:https://ethereum.stackexchange.com/questions/78660