【问题标题】:How to Implement Metamask EventEmitter to Angular?如何将 Metamask EventEmitter 实现到 Angular?
【发布时间】:2021-12-18 11:04:08
【问题描述】:

在 Metamask Provider 中有这样的 EventEmitter

ethereum.on('accountsChange', (accounts) => console.log(accounts))

如何实现这个到角度组件?当我尝试像这样将它放在组件构造函数中时

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  currentAccount: string;

  constructor() {
    ethereum.on('accountsChange', (accounts) => {
      console.log(accounts);
      this.currentAccount = accounts[0];
    })
  }

控制台没有记录任何东西,currentAccount 没有改变。

【问题讨论】:

    标签: angular ethereum eventemitter metamask


    【解决方案1】:

    您需要将事件附加到窗口对象,并在组件装饰器之前声明它。

    declare var window: any;
    
    // then
    window.ethereum.on('accountsChange', (accounts) => {
          console.log(accounts);
          this.currentAccount = accounts[0];
    })
    

    【讨论】:

    • 组件不是已经知道窗口对象吗?为什么我们必须显式声明它?
    • 必须为其分配引用才能在 Angular 中正常工作
    【解决方案2】:

    经过漫长的兔子洞之旅,这是我解决问题的方法,希望它也对你有用(链接和参考在最后):

    起初,我尝试使用 window.etherem.on('accountsChange'...),但从未让它在 Angular 12 中正常工作。我能够让它在 javascript 中工作,但在我们的案例中这不是一个选项。

    在我的例子中,我需要监听用户在 Metamask 浏览器扩展中所做的帐户更改,并在我们的网络应用程序中更新帐户。最后,我选择了仅使用“ethers”的方法,该方法有效,并且还具有节省空间的额外好处,因为我们的应用程序当前使用它们的库。

    元掩码组件

    import {Component, OnInit, OnDestroy, Renderer2} from '@angular/core';
    import {ethers} from 'ethers';
    ...
    
    export class Metamask Component implements OnInit, OnDestroy {
    account: string;
    selectedAccount = [];
    ethereum: any;
    
    constructor(private renderer: Renderer2) {
    this.ethereum = new ethers.providers.Web3Provider((<any>window).ethereum, 'any'); }
    
     async ngOnInit() {
      this.connectAccount().catch(error => {
        console.error('Error in connectAccount', error); });
    
      this.listener();
     }
    
    ngOnDestroy() {
      this.listener();
     }
    }
    
    async connectAccount() {
       this.selectedAccount = this.ethereum.send('eth_requestAccounts', [])
       .then((resolve: any) => {this.account = resolve[0]})
       .catch((error: any) => {console.error('Error', error)});
    }
    
    listener() {
      this.renderer.listen('window', 'focus', event => {
        this.selectedAccount = this.ethereum.send('eth_requestAccounts', []).then((resolve: any) => {
        this.account = resolve[0]
        }).catch((error: any) => {
        console.error('Error', error);
        });
      });
     }
    
    }
    

    元掩码模板

    &lt;div&gt;{{this.account}}&lt;/div&gt;

    应用组件模板

    ...
    <app-metamask></app-metamask>
    ...
    

    我使用的链接和参考资料

    How to properly add document.addEventListener to Angular2? https://docs.ethers.io/v5/api/providers/other/#Web3Provider https://eips.ethereum.org/EIPS/eip-1193#user-account-exposure-and-account-changes;

    在我们的例子中,我不得不放弃 @metamask/providers 方法,因为我无法让 window.ethereum.on('accountsChanged...) 一致地识别 Angular12 中的变化。我假设问题与 Angular 更改检测如何处理主机模板有关,但我对此没有确定的答案。此外,我在访问 window.ethereum.selectedAccount 时遇到问题,每次用户在 Metamask 扩展中选择一个新帐户时都会更新,可能是出于同样的原因。附带说明一下,我在使用 Chrome 开发工具时确实遇到了一些问题,但是一旦我关闭了这些工具并在常规浏览器页面中进行了测试,上述工作对我来说就像预期的那样。

    这是一个稍微简化的版本,它只监听更改并在发生更改时更新帐户字符串。它让我再次前进,我希望它对你也有同样的作用。

    【讨论】:

      猜你喜欢
      • 2021-07-25
      • 2023-02-13
      • 2022-06-23
      • 2023-04-01
      • 2018-09-28
      • 1970-01-01
      • 2017-04-21
      • 1970-01-01
      • 2020-04-08
      相关资源
      最近更新 更多