npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ngeth/ethers-angular

v0.0.26

Published

``` npm install @ngeth/ethers-core @ngeth/ethers-angular ethers ```

Downloads

10

Readme

Angular toolkit for ethers

Getting Started

npm install @ngeth/ethers-core @ngeth/ethers-angular ethers

In the app.module.ts add the providers:

import { ngEthersProviders, EthersModule } from '@ngeth/ethers-angular';
import { InjectedProviders } form '@ngeth/ethers-core';

@NgModule({
  // Use EthersModule only for the pipes, directive or components
  imports: [BrowserModule, EthersModule],
  providers: [ngEthersProviders(InjectedProviders)]
})

This will exposes the NgERC1193 provider

Use it in a component:

import { NgERC1193 } from '@ngeth/ethers-angular';
@Component({
  template: `
    <p *ngIf="account$ | async as account; else noAccount">{{ account | address }}</p>
    <ng-template #noAccount>
      <button (click)="connect()">Connect your wallet</button>
    </ng-template>
  `
})
export class AppComponent {
  account$ = this.erc1193.account$;
  constructor(private erc1193: NgERC1193) {}
  connect() {
    this.erc1193.enable();
  }
}

Install

Standalone

npm install @ngeth/ethers-core @ngeth/ethers-angular ethers

With @ngeth/hardhat

npx nx @ngeth/hardhat:ng-add --outputType angular

Contract

ngContract

You can wrap any contract generated by @ngeth/hardhat with the ngContract mixin :

import { Signer } from '@ethersproject/abstract-signer';
import { ngContract } from '@ngeth/ethers-angular';

@Injectable({ providedIn: 'root' })
export class MyERC721 extends ngContract(ERC721) {
  // Use `ngEthersProviders` to inject the Signer. See how below
  constructor(signer: Signer) {
    super(addresses.hardhat.ERC721, signer);
  }

  tokensOwnedBy(address: string): Observable<BigNumber[]> {
    const receivedFilter = this.filters.Transfer(undefined, address);
    const sentFilter = this.filters.Transfer(address);
    return combineLatest([
      this.from(receivedFilter),
      this.from(sentFilter),
    ]).pipe(
      map(([received, sent]) => erc721Tokens(received, sent))
    );
  }
}

The ngContract wrap the events from ethers inside as Observable with the from method. Every observable is cached and multicasted.

Now you can inject it in your component:

import { Signer } from '@ethersproject/abstract-signer';
import {} from '@ngeth/ethers-core';

@Component({})
export class AppComponent {
  myTokens$: Observable<BigNumber[]>;
  constructor(private signer: Signer, private erc721: MyERC721) {}
  async ngOnInit() {
    const address = await this.signer.getAddress();
    this.myTokens$ = this.erc721.tokensOwnedBy(address);
  }
}

Providers

ngEthersProviders

Utils function to bind the Provider & Signer to the NgERC1193 wallet manager

import { InjectedProviders } form '@ngeth/ethers-core';
...
providers: [
  ngEthersProviders(InjectedProviders)
]

NgERC1193

The NgERC1193 manages the signers and providers. It's an extension of the ERC1193 for @ngeth/ethers-core with observable/zone helpers for angular. You can inject an ERC1193 with ngEthersProviders.

Select an ERC1193 You can create your own ERC1193 wallet manager or use an existing one. In this example we'll use the InjectedProviders from @ngeth/ethers-core. This will provide access to the ethereum providers in the browser (MetaMask and Coinbase).

import { ngEthersProviders } from '@ngeth/ethers-angular';
import { InjectedProviders } form '@ngeth/ethers-core';

@NgModule({
  providers: [ngEthersProviders(InjectedProviders)]
})

Then you can access it like that:

@Component({...})
export class AppComponent {
  account$ = this.erc1193.account$;
  constructor(private erc1193: NgERC1193) {}
  connect() {
    this.erc1193.enable();
  }
  async changeChain(chainId: string) {
    await this.erc1193.addChain(chainId);
    await this.erc1193.switchChain(chainId);
  }
}

Extends it If you want to extends the NgERC1193 class you can use the mixin ngErc1193. It'll wrap an existing ERC1193 class with NgERC1193. Here is an example with a custom wallet selector using @angular/material.

@Injectable({ providedIn: 'root' })
export class MyInjectedERC1193 extends ngErc1193(InjectedProviders) {
  constructor(private dialog: MatDialog) {
    super();
  }

  protected override async getWallet() {
    if (!this.wallets.length) return;
    if (this.wallets.length === 1) return this.wallets[0];
    const ref = this.dialog.open(SelectWalletComponent, { labels: this.wallets.map(w => w.label) });
    const label = await firstValueFrom(ref.afterClosed());
    return this.wallets.find(w => w.label === label);
  }
}

Now you can inject it as any other Injectable class:

@Component({...})
export class AppComponent {
  constructor(private erc1193: MyInjectedERC1193) {}
}

Note: If you want to inject the Provider or Signer you'll still need to use the ngEthersProviders in the providers list.

@NgModule({
  providers: [ngEthersProviders(MyInjectedERC1193)]
})

SUPPORTED_CHAINS

Specify a list of supported chain for the application. If value is "*", all chains are supported

{ provide: SUPPORTED_CHAINS, useValue: [1] }

CUSTOM_CHAINS

Add a list of custom chains for the ChainManager. Useful for local development with hardhat for example

{ provide: CUSTOM_CHAINS, useValue: { '0x1234': { name: 'Custom Chain', chain: 'ETH',... } } }

rpcProvider

Utils function to set the ethers.js's Provider as injectable dependancy

providers: [rpcProvider()]

EthersModule

Provides useful components & pipes for an angular web3 project

@NgModule({
  imports: [EthersModule]
})

Components

eth-blocky

A blocky stuled representation of an address

<eth-blocky address="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"></eth-blocky>

Directives

input[type="ethAddress"]

A ControlValueAccessor for ethereum addresses

<input type="ethAddress" [formControl]="control" />

input[type="ether"]

A ControlValueAccessor to transform an ether value into a BigNumber of wei

<input type="ether" [formControl]="control" />

Pipes

address

Checksum & format an ethereum address

<!-- 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 -->
<p>{{ account | address }}</p>
<!-- 0xf39F...2266 -->
<p>{{ account | address:'short' }}</p>

bignumber

Transform a bignumber-like value into a string

<p>{{ gasUsed | bignumber }}</p>

ether

Transform a bignumber-like value into a ether string using the ether symbol

<p>{{ price | ether }}</p>

ethCurrency

Transform a bignumber-like value into a the native currency of a chain. It'll default to the current chain if not chainId is specified.

<!-- Use the current selected chain -->
<p>{{ price | ethCurrency | async }}</p>
<!-- Support number or hex chainID -->
<p>{{ price | ethCurrency:1 | async }}</p>
<p>{{ price | ethCurrency:'0x01' | async }}</p>

This is an async pipe because it relies on the chain metadata.

chain

Get the chain metadata of a chainId

<menu>
  <ng-container *ngFor="let chainId of availableChainIds">
    <li *ngIf="chainId | chain | async as chain">
      <button (click)="select(chainId)">{{ chain.name }}</button>
    <li>
  </ng-container>
</menu>

explore

Link to the block explorer search of a specific chain

<ng-container *ngIf="chainId$ | async as chainId">
  <article *ngIf="chainId | chain | async as chain">
    <a [href]="account | explorer:chain">
      <eth-blocky [address]="account"></eth-blocky>
      <h3>{{ account | address }}</h3>
    </a>
  </article>
</ng-container>

Guards

HasInjectedProviderGuard

Check if the user has an injected provided by looking at window.ethereum

  • Redirect to /no-injected-provider
  • Custom redirect: data.hasInjectedProviderRedirect
{
  path: 'account',
  canActivate: [HasInjectedProviderGuard],
  data: {
    hasInjectedProviderRedirect: '/get-provider'
  }
}

HasWalletGuard

Check if the user has an active erc1193 wallet selected. In the case of InjectedProviders it can be either MetaMask or Coinbase

  • Redirect to: /no-wallet
  • Custom redirect: data.hasWalletRedirect
{
  path: 'wallet',
  canActivate: [HasWalletGuard],
  data: {
    hasWalletRedirect: '/get-wallet'
  }
}

IsConnectedGuard

Check if the user has a connected account

  • Redirect to: /no-connected
  • Custom redirect: data.isConnectedRedirect
{
  path: 'wallet',
  canActivate: [IsConnectedGuard],
  data: {
    isConnectedRedirect: '/connect-to-metamask'
  }
}

HasSignerGuard

Check if the user has a connected account

  • Redirect to: /no-signer
  • Custom redirect: data.hasSignerRedirect
{
  path: 'wallet',
  canActivate: [IsConnectedGuard],
  data: {
    hasSignerRedirect: '/select-account'
  }
}

IsSupportedChainGuard

Check if the current user chain is supported by the application

  • Redirect to: /unsupported-chain
  • Custom redirect: data.isSupportedChainRedirect
@NgModule({
  imports: [
    RouterModule.forChild({
      path: '',
      canActivate: [IsSupportedChainGuard],
      data: {
        isSupportedChainRedirect: '/change-chain'
      }
    })
  ],
  providers: [
    { provide: SUPPORTED_CHAINS, useValue: [1] }
  ]
})