Ethereum and Angular — Part 4:
NRGX (last part)
Last part of the article “Ethereum and Angular”. Read the previous parts :
- Part 1 : Create a Dapp
- Part 2 : Component
- Part 3 : NGRX
You can find the source code here :
https://github.com/B2-Expand/angular-ethereum-boilerplate
Effects
In the last article we coded eth.reducers.ts
to change the state of the application. We changed accounts
with the GetAccountsSuccess
action, but we don’t know yet when this action is used, nor how it has access get these accounts.
The effects, or side effects, aim to retrieve information outside the application when certain actions are triggered. In our case we will search the list of accounts on the node usingEthService
when the action GetAccounts
is received by the store. Then we return this list via the GetAccountsSuccess
action.
Effects are injectable class methods that listen to the actions received by the blind. The first thing to note is the Actions
class injected into the constructor. It filters the actions received by the store according to its type thanks to theofType
method. This method can take one or more strings. Here we listen on the type GET_ACCOUNTS
.
Now let’s get our accounts with our service:
switchMap(() => this.eth.getAccounts())
Then we return a new action which contains the list of accounts and which will be taken into consideration by the reducer:
map((accounts: string[]) => new GetAccountsSuccess(accounts))
Finally we manage potential errors with catchError
. Note thatcatchError
expects an observable, that’s why we use of
:
catchError((err: any) => of(new EthError(err)))
Selectors
The selectors allow to listen on the changes of a data of the state. In our state we have two data:
- The list of Ethereum accounts
- The selected account.
So we create two selectors:
getAccounts
and getDefaultAccount
are two functions that simplify access to state data from a component.
Module
Let’s put everything together in our moduleethereum.module.ts
:
We have three more imports:
StoreModule.forRoot(reducers)
: Creates the store that interaction with the application state.EffectsModule.forRoot([EthEffects])
: Allows our effect to listen on the actions received by the store.environment.production ? [] : StoreDevtoolsModule.instrument()
: Enables Redux development tools when not in production mode.
Note:
Here we assume that the whole state is managed by the Ethereum module. Otherwise we would have use StoreModule.forFeature(‘eth’, ethReducers)
and StoreModule.forRoot(…)
would be used in app.module.ts
.
Component
Finally! Everything is set up, let’s return in our componentapp.component.ts
:
The whole logic of this component lies in ngOnInit
:
- We start to inform the store that we want to retrieve the accounts with the
GetAccounts()
action defined ineth.actions.ts
. - The action is taken into account by
EthEffects
, which calls the serviceAccountsService
before returning an actionGetAccountsSuccess
with the list of accounts (see:eth.effects.ts
). GetAccountsSuccess
is received in the store, it is the reducer’s turn to modify the state accordingly (see:eth.reducers.ts
).- Once the state is updated, the selector
getAccounts
informs the component of this modification using the store’sselect
method. - Each time the list of accounts is modified in the state, the component will be notified and will update its UI.
- BONUS: We can now use the
async
pipe to avoid having to manage the unsubscription of the observable!
There it is, it’s over! A little long just to display the list of accounts, I agree, but now the whole structure is ready. We only have to extend it to all web3 methods to take advantage of a structure based on observables, without having to worry aboutngZone
.
Congratulations to everyone who came to the end of this tutorial, I hope it helped you interact with Ethereum through Angular. I would be happy to answer your questions
You can find the source code here: https://github.com/B2-Expand/angular-ethereum-boilerplate
François Guezengar