Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nestjs - What is the right approach to have custom classes using 3rd party libraries available

Tags:

node.js

nestjs

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.

like image 242
user16780074 Avatar asked Jan 20 '26 22:01

user16780074


2 Answers

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:

  1. Create a module to wrap your library, like "CryptoManagerModule".
  2. Create a custom provider that provides the CCXT library, and add this to your providers array.
  3. Create a service, "CryptoManagerService", and inject CCXT into the constructor.
  4. Export the "CryptoManagerService" from your module, so that you can inject it into the rest of your app.
  5. (Optionally) mark your module as "global", so that you only need to configure the module once in the AppModule to make it available to all other modules.

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.

like image 190
HMilbradt Avatar answered Jan 23 '26 12:01

HMilbradt


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;
  }
}
like image 35
fasenderos Avatar answered Jan 23 '26 11:01

fasenderos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!