0

I'm trying to properly integrate Web3 with Angular 4 by creating a web3 service that needs to wait for the window to be loaded before it can check whether window.web3 was injected. And we should be able to query this service only after this was done. Here is the relevant code from Metamask's documentation excerpt:

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

  // Checking if Web3 has been injected by the browser (Mist/MetaMask)
  if (typeof web3 !== 'undefined') {
    // Use Mist/MetaMask's provider
    window.web3 = new Web3(web3.currentProvider);
  } else {
    console.log('No web3? You should consider trying MetaMask!')
    // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
    window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
  }

  // Now you can start your app & access web3 freely:
  startApp()

})

I found this other answer that seems to do what I want, but converting a Promise into an Observable.

How can I initialize an Angular4 service that wraps around this web3 object in such a way that any request to members of web3 will wait for it to be initialized?

Right now the code I'm using uses intervals but I don't like it as it feels very messy.

Sebastien
  • 3,583
  • 4
  • 43
  • 82

1 Answers1

0

After you bootstrap your main module you, you get an instance of your main module which contains the instance of the injector that angular will use to instantiate your providers. So, you can grab that instance and store it somewhere and later use it to instantiate providers.

Let's say you want to store your app's injector in app-injector.ts, so it would look like,

//app-injector.ts

import { Injector } from '@angular/core';

let appInjectorRef: Injector;

export const appInjector = (injector?: Injector): Injector => {
    if (!injector) {
        return appInjectorRef;
    }

    appInjectorRef = injector;

    return appInjectorRef;
};

and in your main module's bootstrap may look like,

platformBrowserDynamic()
  .bootstrapModule(TopLevelModule)
  .then((appRef: any) => {
    appInjector(appRef['injector']); // grab the injector instance and store.
  })
  .catch((err) => console.error(err));

Next, for example in your AppComponent you can do it like,

import {appInjector} from './app-injector';
export class AppComponent implements OnInit {
     private service: ServiceThatUsesWeb3;

     ngOnInit(): void {
        //.. do web3 instantiation stuffs.
        setTimeout(() => {
          service = appInjector().get(ServiceThatUsesWeb3);
          // use the service.
        });
     }
}

Please note that the setTimeout() is important otherwise appInjector() will return you undefined.

Anik
  • 2,692
  • 2
  • 22
  • 25