From 22c81daee634f31708a7a09c6a5b3ed090d171e5 Mon Sep 17 00:00:00 2001 From: Fuxing Loh Date: Fri, 31 Dec 2021 15:35:16 +0800 Subject: [PATCH 1/3] feat(ocean-api): integrate playground with ocean-api --- .../modules/PlaygroundModule.test.ts | 48 +++++++++++++++ .../ocean-api/src/modules/PlaygroundModule.ts | 60 +++++++++++++++++++ apps/ocean-api/src/modules/RootModule.ts | 4 +- 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 apps/ocean-api/__tests__/modules/PlaygroundModule.test.ts create mode 100644 apps/ocean-api/src/modules/PlaygroundModule.ts diff --git a/apps/ocean-api/__tests__/modules/PlaygroundModule.test.ts b/apps/ocean-api/__tests__/modules/PlaygroundModule.test.ts new file mode 100644 index 0000000000..8d177bc94a --- /dev/null +++ b/apps/ocean-api/__tests__/modules/PlaygroundModule.test.ts @@ -0,0 +1,48 @@ +import { OceanApiTesting } from '../../testing/OceanApiTesting' +import waitForExpect from 'wait-for-expect' + +describe('regtest', () => { + const apiTesting = OceanApiTesting.create() + + beforeEach(async () => { + apiTesting.playgroundEnable(false) + await apiTesting.start() + }) + + afterEach(async () => { + await apiTesting.stop() + }) + + it('block count should not increment', async () => { + const initial = await apiTesting.rpc.blockchain.getBlockCount() + + await new Promise((resolve) => { + setTimeout(_ => resolve(0), 5000) + }) + + const next = await apiTesting.rpc.blockchain.getBlockCount() + expect(next).toStrictEqual(initial) + }) +}) + +describe('playground', () => { + const apiTesting = OceanApiTesting.create() + + beforeEach(async () => { + apiTesting.playgroundEnable(true) + await apiTesting.start() + }) + + afterEach(async () => { + await apiTesting.stop() + }) + + it('block count should increment', async () => { + const initial = await apiTesting.rpc.blockchain.getBlockCount() + + await waitForExpect(async () => { + const next = await apiTesting.rpc.blockchain.getBlockCount() + expect(next).toBeGreaterThan(initial) + }) + }) +}) diff --git a/apps/ocean-api/src/modules/PlaygroundModule.ts b/apps/ocean-api/src/modules/PlaygroundModule.ts new file mode 100644 index 0000000000..d9859fc2ce --- /dev/null +++ b/apps/ocean-api/src/modules/PlaygroundModule.ts @@ -0,0 +1,60 @@ +import { Injectable, Logger, Module } from '@nestjs/common' +import { ConfigService } from '@nestjs/config' +import { Interval, ScheduleModule } from '@nestjs/schedule' +import { BotLogger, Playground } from '@defichain/playground' +import { ApiClient } from '@defichain/jellyfish-api-core' + +/** + * Provide a PlaygroundRunner when PLAYGROUND_ENABLE is enabled. + */ +@Module({ + imports: [ + ScheduleModule.forRoot() + ], + providers: [ + { + provide: 'PLAYGROUND_RUNNER', + useFactory: (configService: ConfigService, apiClient: ApiClient): PlaygroundRunner | undefined => { + if (configService.get('PLAYGROUND_ENABLE') === true) { + return new PlaygroundRunner(apiClient) + } + return undefined + }, + inject: [ConfigService, ApiClient] + } + ] +}) +export class PlaygroundModule { +} + +/** + * Universal logger for playground using NestJS logger. + */ +class PlaygroundLogger implements BotLogger { + private readonly logger = new Logger(PlaygroundLogger.name) + + info (action: string, message: string): void { + this.logger.log(`${action} ${message}`) + } +} + +@Injectable() +class PlaygroundRunner { + constructor ( + private readonly apiClient: ApiClient, + private readonly logger: PlaygroundLogger = new PlaygroundLogger(), + private readonly playground: Playground = new Playground(apiClient, logger) + ) { + } + + async onApplicationBootstrap (): Promise { + this.logger.info('onApplicationBootstrap', 'Bootstrapping') + await this.playground.bootstrap() + this.logger.info('onApplicationBootstrap', 'Bootstrapped') + } + + @Interval(3000) + async cycle (): Promise { + await this.playground.cycle() + } +} diff --git a/apps/ocean-api/src/modules/RootModule.ts b/apps/ocean-api/src/modules/RootModule.ts index 7dfc8ee47c..886f47fdbb 100644 --- a/apps/ocean-api/src/modules/RootModule.ts +++ b/apps/ocean-api/src/modules/RootModule.ts @@ -4,6 +4,7 @@ import { ConfigModule } from '@nestjs/config' import { ControllerModule } from './ControllerModule' import { BlockchainCppModule } from './BlockchainCppModule' import { ActuatorModule } from './ActuatorModule' +import { PlaygroundModule } from './PlaygroundModule' @Module({ imports: [ @@ -14,7 +15,8 @@ import { ActuatorModule } from './ActuatorModule' }), ActuatorModule, BlockchainCppModule, - ControllerModule + ControllerModule, + PlaygroundModule ] }) export class RootModule { From 7a3ab909b7dfac17298c45295a147295e49c58b8 Mon Sep 17 00:00:00 2001 From: Fuxing Loh Date: Fri, 31 Dec 2021 15:47:45 +0800 Subject: [PATCH 2/3] automatically error if playground is configured on non regtest setup --- apps/ocean-api/src/modules/PlaygroundModule.ts | 11 ++++++++--- apps/ocean-api/src/modules/RootModule.ts | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/ocean-api/src/modules/PlaygroundModule.ts b/apps/ocean-api/src/modules/PlaygroundModule.ts index d9859fc2ce..7ded526ee6 100644 --- a/apps/ocean-api/src/modules/PlaygroundModule.ts +++ b/apps/ocean-api/src/modules/PlaygroundModule.ts @@ -15,10 +15,15 @@ import { ApiClient } from '@defichain/jellyfish-api-core' { provide: 'PLAYGROUND_RUNNER', useFactory: (configService: ConfigService, apiClient: ApiClient): PlaygroundRunner | undefined => { - if (configService.get('PLAYGROUND_ENABLE') === true) { - return new PlaygroundRunner(apiClient) + if (configService.get('PLAYGROUND_ENABLE') === false) { + return undefined } - return undefined + + if (configService.get('API_NETWORK') !== 'regtest') { + throw new Error('PLAYGROUND_ENABLE:true is only allowed on API_NETWORK:regtest') + } + + return new PlaygroundRunner(apiClient) }, inject: [ConfigService, ApiClient] } diff --git a/apps/ocean-api/src/modules/RootModule.ts b/apps/ocean-api/src/modules/RootModule.ts index 886f47fdbb..fcff8a57d5 100644 --- a/apps/ocean-api/src/modules/RootModule.ts +++ b/apps/ocean-api/src/modules/RootModule.ts @@ -27,7 +27,7 @@ function ENV_VALIDATION_SCHEMA (): any { NODE_ENV: Joi.string().valid('production', 'test').default('test'), PORT: Joi.number().default(3000), API_VERSION: Joi.string().regex(/^v[0-9]+(\.[0-9]+)?$/).default('v1'), - API_NETWORK: Joi.string().valid('regtest', 'testnet', 'mainnet', 'playground').default('regtest'), + API_NETWORK: Joi.string().valid('regtest', 'testnet', 'mainnet').default('regtest'), PLAYGROUND_ENABLE: Joi.boolean() }) } From 142779bff162e85aa46f662817f111584891e315 Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:31:03 +0800 Subject: [PATCH 3/3] Apply suggestions from code review --- apps/ocean-api/__tests__/modules/PlaygroundModule.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ocean-api/__tests__/modules/PlaygroundModule.test.ts b/apps/ocean-api/__tests__/modules/PlaygroundModule.test.ts index 8d177bc94a..1fc7b22134 100644 --- a/apps/ocean-api/__tests__/modules/PlaygroundModule.test.ts +++ b/apps/ocean-api/__tests__/modules/PlaygroundModule.test.ts @@ -13,7 +13,7 @@ describe('regtest', () => { await apiTesting.stop() }) - it('block count should not increment', async () => { + it('should not increment block count', async () => { const initial = await apiTesting.rpc.blockchain.getBlockCount() await new Promise((resolve) => { @@ -37,7 +37,7 @@ describe('playground', () => { await apiTesting.stop() }) - it('block count should increment', async () => { + it('should increment block count', async () => { const initial = await apiTesting.rpc.blockchain.getBlockCount() await waitForExpect(async () => {