I am new to NestJS and I did not find any clear instruction to do what I need to.
I wanted to build my backend using NestJS which I have never used before but only heard good things about. So the backend server I am going to build will be using a 3rd party module called ccxt from npmjs. In a normal node app, I would just create a random class for example CryptoManager, import the ccxt module and write some functions that are running on set intervals or whatever. Then I would create a controller class that instantiates an object of that CryptoManager class and from there on I can return it's responses.
But how am I supposed to do this with NestJS? What do I have to do, in order to have a custom class that is running background tasks available in other nest controllers / services and so on?
This class is just supposed to execute 3rd party (ccxt) module functions and store results in a database.But I want to be able to execute this classes methods from all points in the nestjs app (from all modules).
I hope my question is clear, if not please let me know.
You'll need a combination of Modules and Providers to do this the "nest way", and then you can use dependency injection throughout your app.
Generally speaking, the way that you'd approach adding 3rd party libraries is the following:
providers array.Inside crypto-manager.module.ts
import { DynamicModule, Module, Provider } from '@nestjs/common';
import { CryptoManagerService } from './crypto-manager.service';
import * as ccxt from 'ccxt';
// Add any config options you need, like API keys, etc
export interface CryptoManagerModuleOptions {
global?: boolean;
}
export const KRAKEN_CLIENT_TOKEN = 'KRAKEN_CLIENT_TOKEN';
export class CryptoManagerModule {
static forRoot(options: CryptoManagerModuleOptions): DynamicModule {
// An example of injecting a single class of ccxt. Note this is only available
// within this module.
const krakenProvider: Provider = {
provide: KRAKEN_CLIENT_TOKEN,
useValue: new ccxt.kraken(),
};
return {
module: CryptoManagerModule,
providers: [krakenProvider, CryptoManagerService],
// Exports can be @Inject()'ed to other files, and if global
// is set, then forRoot only needs to be called in the AppModule
exports: [CryptoManagerService],
global: options.global,
};
}
}
Inside crypto-manager.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { KRAKEN_CLIENT_TOKEN } from './crypto-manager.module';
import { kraken } from 'ccxt';
@Injectable()
export class CryptoManagerService {
constructor(@Inject(KRAKEN_CLIENT_TOKEN) private kraken: kraken) {}
loadKrakenMarkets() {
return this.kraken.loadMarkets();
}
}
Inside app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CryptoManagerModule } from './crypto-manager/crypto-manager.module';
@Module({
controllers: [AppController],
providers: [AppService],
// Make sure to call forRoot
imports: [CryptoManagerModule.forRoot({ global: true })],
})
export class AppModule {}
And lastly, an example of it being used inside of app.service.ts. I haven't done anything special to this file, you'll just see the result logged to the console.
import { Inject, Injectable } from '@nestjs/common';
import { CryptoManagerService } from './crypto-manager/crypto-manager.service';
@Injectable()
export class AppService {
constructor(private cryptoManagerService: CryptoManagerService) {}
getHello(): string {
this.cryptoManagerService.loadKrakenMarkets().then(console.log);
return 'Hello World!';
}
}
Doing it this way allows you to easily mock out kraken when it comes time to test, allows you to pass configuration variables in the forRoot in case you want to reuse this across projects, and is a pattern that is widespread in the Nest community already.
I have created nestjs-ccxt a NestJS CCXT module wrapper for that purpose https://www.npmjs.com/package/nestjs-ccxt
First import the CcxtModule as any other module
import { CcxtModule } from 'nestjs-ccxt';
@Module({
imports: [CcxtModule.forRoot({ ... })],
})
export class AppModule {}
Next in your service inject the CcxtService using normal constructor injection.
@Injectable()
export class ExchangeService {
constructor(private ccxtService: CcxtService) {}
async getBtcUsdtTicker() {
const client = await this.ccxtService.getClient('binance');
const ticker = await client.fetchTicker('BTC/USDT');
return ticker;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With