如何将Metamask EventEmitter实现为Angular



在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也没有更改。

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

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

经过一次漫长的兔子洞之旅,以下是我如何解决我们的问题,希望它也能为你工作(链接和参考资料在最后(:

起初,我尝试使用window.etherem.on('accountsChange'...),但始终无法在Angular 12中正常工作。我能够在javascript中工作,但在我们的情况下,这不是一个选项。

在我的情况下,我需要在Metamask浏览器扩展中听取用户的帐户更改,并在我们的网络应用程序中更新帐户。最后,我选择了一种只使用"以太"的方法,这种方法很有效,而且由于我们的应用程序目前正在使用它们的库,还节省了空间。

Metamask组件

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);
});
});
}
}

Metamask模板

<div>{{this.account}}</div>

应用程序组件模板

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

链接&我使用的参考资料

如何将document.addEventListener正确添加到Angular2?https://docs.ethers.io/v5/api/providers/other/#Web3Providerhttps://eips.ethereum.org/EIPS/eip-1193#user-账户风险敞口和账户变更;

在我们的案例中,我不得不放弃@metamask/providers的方法,因为我无法在('accountsChanged…(上获得window.ethereum.以始终识别Angular12的变化。我假设这个问题与角度变化检测如何处理宿主模板有关,但我对此没有结论性的答案。此外,我在访问window.ethereum.selectedAccount时遇到了问题,每次用户在Metamask扩展中选择新帐户时,该帐户都会更新,原因可能相同。顺便说一句,我在Chrome开发工具中使用它时确实遇到了一些问题,但一旦我关闭了这些工具并在常规浏览器页面中进行了测试,上述功能就如我所期望的那样发挥了作用

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

很简单,只需要调用"ChangeDetectorRef";并将自动检测的变化

import { ChangeDetectorRef } from '@angular/core';
...
constructor(
public cRef: ChangeDetectorRef
) {
ethereum.on('accountsChange', (accounts) => {
console.log(accounts);
this.currentAccount = accounts[0];
this.cRef.detectChanges();
})
}

完成了!

以上内容对我有效,我希望对你也有效。

最新更新