Skip to content

Commit

Permalink
refine defid module from 2 objects ocean & blockchain -> 1 object (oc…
Browse files Browse the repository at this point in the history
…ean + blockchain)
  • Loading branch information
canonbrother committed Jan 25, 2024
1 parent e593410 commit e17804e
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 94 deletions.
143 changes: 126 additions & 17 deletions apps/whale-api/src/e2e.defid.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { v4 as uuidv4 } from 'uuid'
import fs from 'fs'
import { ChildProcess, spawn } from 'child_process'
import { RegTestFoundationKeys } from '@defichain/jellyfish-network'
import { MasterNodeRegTestContainer } from '@defichain/testcontainers/dist/index'
import { ApiPagedResponse } from './module.api/_core/api.paged.response'

import { AddressToken, AddressHistory } from '@defichain/whale-api-client/dist/api/address'
Expand Down Expand Up @@ -39,10 +38,9 @@ import { TokenData } from '@defichain/whale-api-client/dist/api/tokens'
import { Transaction } from './module.model/transaction'
import { TransactionVin } from './module.model/transaction.vin'
import { TransactionVout } from './module.model/transaction.vout'
import { DeFiDRpcError, waitForCondition } from '@defichain/testcontainers'

const PORT = 3002
const ENDPOINT = `http://127.0.0.1:${PORT}`
const SPAWNING_TIME = 120_000
const SPAWNING_TIME = 180_000

export interface OceanListQuery {
size: number
Expand All @@ -61,15 +59,17 @@ export interface OceanProposalQuery {
}

class DefidOceanApi {
endpoint = 'http://127.0.0.1:3002'

async get (path: string): Promise<any> {
const res = await fetch(`${ENDPOINT}${path}`, {
const res = await fetch(`${this.endpoint}${path}`, {
method: 'GET'
})
return await res.json()
}

async post (path: string, data?: any): Promise<any> {
const res = await fetch(`${ENDPOINT}${path}`, {
const res = await fetch(`${this.endpoint}${path}`, {
method: 'POST',
body: JSON.stringify(data)
})
Expand Down Expand Up @@ -344,12 +344,8 @@ export class DTransactionController extends DefidOceanController {
}
}

export class DefidBin {
tmpDir: string = `/tmp/${uuidv4()}`
binary: ChildProcess | null = null

public constructor (
readonly container: MasterNodeRegTestContainer,
export class DefidOcean {
constructor (
readonly addressController: DAddressController,
readonly blockController: DBlockController,
readonly feeController: DFeeController,
Expand All @@ -364,6 +360,98 @@ export class DefidBin {
readonly tokenController: DTokenController
) {
}
}

export class DefidRpc {
rpcUrl = 'http://test:[email protected]:19554'

getCachedRpcUrl (): string {
return this.rpcUrl
}

async call (method: string, params: any = []): Promise<any> {
const body = JSON.stringify({
jsonrpc: '1.0',
id: Math.floor(Math.random() * 100000000000000),
method: method,
params: params
})

const text = await this.post(body)
const {
result,
error
} = JSON.parse(text)

if (error !== undefined && error !== null) {
throw new DeFiDRpcError(error)
}

return result
}

async post (body: string): Promise<string> {
const response = await fetch(this.rpcUrl, {
method: 'POST',
body: body
})
return await response.text()
}

async generate (
nblocks: number,
address?: string | undefined,
maxTries: number = 1000000
): Promise<void> {
if (address === undefined) {
address = await this.call('getnewaddress')
}
for (let minted = 0, tries = 0; minted < nblocks && tries < maxTries; tries++) {
const result = await this.call('generatetoaddress', [1, address, 1])
if (result === 1) {
minted += 1
}
}
}

async waitForBlockHeight (height: number, timeout = 590000): Promise<void> {
return await waitForCondition(async () => {
const count = await this.getBlockCount()
if (count > height) {
return true
}
await this.generate(1)
return false
}, timeout, 100, 'waitForBlockHeight')
}

async getNewAddress (label: string = '', addressType: 'legacy' | 'p2sh-segwit' | 'bech32' | 'eth' | string = 'bech32'): Promise<string> {
return await this.call('getnewaddress', [label, addressType])
}

async getBlockCount (): Promise<number> {
return await this.call('getblockcount', [])
}
}

export class DefidBin {
tmpDir: string = `/tmp/${uuidv4()}`
binary: ChildProcess | null = null
rpc = new DefidRpc()
ocean = new DefidOcean(
new DAddressController(),
new DBlockController(),
new DFeeController(),
new DGovernanceController(),
new DMasternodeController(),
new DOracleController(),
new DPoolPairController(),
new DPriceController(),
new DRawTxController(),
new DStatsController(),
new DTransactionController(),
new DTokenController()
)

async start (): Promise<void> {
fs.mkdirSync(this.tmpDir)
Expand All @@ -375,7 +463,6 @@ export class DefidBin {
const args = [
`-datadir=${this.tmpDir}`,
'-regtest',
'-oceanarchive',
'-printtoconsole',
'-gen=0',
'-rpcuser=test',
Expand All @@ -389,7 +476,8 @@ export class DefidBin {
'-txnotokens=0',
'-logtimemicros',
'-txindex=1',
'-acindex=1'
'-acindex=1',
'-oceanarchive'
]

const extraArgs = [
Expand Down Expand Up @@ -443,8 +531,9 @@ export class DefidBin {
await new Promise((resolve) => setTimeout(resolve, 1000))

try {
const res = await this.blockController.get('0')
console.log('[DefidBin.start()] blockController.get res: ', res)
// TODO(canonbrother): blockController.get(0)
const res = await this.ocean.blockController.list({ size: 1 })
console.log('[DefidBin.start()] blockController.list res: ', res)
} catch (err) {
console.log('[DefidBin.start()] blockController.get err: ', err)
}
Expand All @@ -454,7 +543,9 @@ export class DefidBin {
binary.stderr.off('data', onData)
binary.stdout.off('data', onData)

// import privkey
await this.rpc.call('importprivkey', [RegTestFoundationKeys[1].owner.privKey])
await this.rpc.call('importprivkey', [RegTestFoundationKeys[1].operator.privKey])

// setgov
// generate(2)

Expand All @@ -468,4 +559,22 @@ export class DefidBin {

this.binary = binary
}

async stop (): Promise<void> {
const interval = setInterval(() => {
if (this.binary?.pid !== undefined && !this.isRunning(this.binary?.pid)) {
clearInterval(interval)
fs.rmdirSync(this.tmpDir, { recursive: true })
}
}, 500)
this.binary?.kill()
}

private isRunning (pid: number): boolean {
try {
return process.kill(pid, 0)
} catch (err: any) {
return err.code === 'EPERM'
}
}
}
77 changes: 11 additions & 66 deletions apps/whale-api/src/e2e.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import fs from 'fs'
import { Test, TestingModule } from '@nestjs/testing'
import { AppModule } from './app.module'
import { ConfigService } from '@nestjs/config'
Expand All @@ -11,21 +10,7 @@ import waitForExpect from 'wait-for-expect'
import { addressToHid } from './module.api/address.controller'
import { ScriptAggregationMapper } from './module.model/script.aggregation'
import { TestingGroup } from '@defichain/jellyfish-testing'
import {
DefidBin,
DAddressController,
DBlockController,
DFeeController,
DGovernanceController,
DMasternodeController,
DOracleController,
DPoolPairController,
DPriceController,
DStatsController,
DTransactionController,
DTokenController,
DRawTxController
} from './e2e.defid.module'
import { DefidBin } from './e2e.defid.module'

/**
* Configures an end-to-end testing app integrated with all modules.
Expand All @@ -35,29 +20,7 @@ import {
* @param {MasterNodeRegTestContainer} container to provide defid client
* @return Promise<NestFastifyApplication> with initialization
*/
export async function createTestingApp (container: MasterNodeRegTestContainer): Promise<NestFastifyApplication>
export async function createTestingApp (container: MasterNodeRegTestContainer): Promise<DefidBin>
export async function createTestingApp (container: MasterNodeRegTestContainer): Promise<NestFastifyApplication | DefidBin> {
if (process.env.DEFID !== undefined) {
const defid = new DefidBin(
container,
new DAddressController(),
new DBlockController(),
new DFeeController(),
new DGovernanceController(),
new DMasternodeController(),
new DOracleController(),
new DPoolPairController(),
new DPriceController(),
new DRawTxController(),
new DStatsController(),
new DTransactionController(),
new DTokenController()
)
await defid.start()
return defid
}

export async function createTestingApp (container: MasterNodeRegTestContainer): Promise<NestFastifyApplication> {
const url = await container.getCachedRpcUrl()
const module = await createTestingModule(url)

Expand All @@ -76,21 +39,11 @@ export async function createTestingApp (container: MasterNodeRegTestContainer):
* @param {MasterNodeRegTestContainer | TestingGroup} container to provide defid client
* @param {NestFastifyApplication} app to close
*/
export async function stopTestingApp (container: MasterNodeRegTestContainer | TestingGroup, app: NestFastifyApplication | DefidBin): Promise<void> {
export async function stopTestingApp (container: MasterNodeRegTestContainer | TestingGroup, app: NestFastifyApplication): Promise<void> {
try {
if (app instanceof DefidBin) {
const interval = setInterval(() => {
if (app.binary?.pid !== undefined && !isRunning(app.binary?.pid)) {
clearInterval(interval)
fs.rmdirSync(app.tmpDir, { recursive: true })
}
}, 500)
app.binary?.kill()
} else {
const indexer = app.get(RPCBlockProvider)
await indexer.stop()
await app.close()
}
const indexer = app.get(RPCBlockProvider)
await indexer.stop()
await app.close()
} finally {
await new Promise((resolve) => {
// Wait 2000ms between indexer cycle time to prevent database error
Expand All @@ -105,14 +58,6 @@ export async function stopTestingApp (container: MasterNodeRegTestContainer | Te
}
}

function isRunning (pid: number): boolean {
try {
return process.kill(pid, 0)
} catch (err: any) {
return err.code === 'EPERM'
}
}

async function createTestingModule (url: string): Promise<TestingModule> {
return await Test.createTestingModule({
imports: [AppModule.forRoot('memory')]
Expand Down Expand Up @@ -141,16 +86,16 @@ export async function waitForIndexedHeightLatest (app: NestFastifyApplication, c
export async function waitForIndexedHeight (app: NestFastifyApplication | DefidBin, height: number, timeout: number = 30000): Promise<void> {
if (app instanceof DefidBin) {
await waitForExpect(async () => {
// TODO(): maybe get index from DefidBin
const count = await app.container.getBlockCount()
await expect(count).toBeGreaterThan(height)
await await app.container.generate(1)
// TODO(canonbrother): ocean getblockcount
// const count = await app.ocean.getBlockCount()
// expect(count).toBeGreaterThan(height)
// await app.rpc.generate(1)
}, timeout)
} else {
const blockMapper = app.get(BlockMapper)
await waitForExpect(async () => {
const block = await blockMapper.getHighest()
await expect(block?.height).toBeGreaterThan(height)
expect(block?.height).toBeGreaterThan(height)
}, timeout)
}
await new Promise((resolve) => setTimeout(resolve, 1000))
Expand Down
33 changes: 22 additions & 11 deletions apps/whale-api/src/module.api/block.controller.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,33 @@ import { MasterNodeRegTestContainer } from '@defichain/testcontainers'
import { NestFastifyApplication } from '@nestjs/platform-fastify'
import { createTestingApp, stopTestingApp, waitForIndexedHeight } from '../e2e.module'
import { JsonRpcClient } from '@defichain/jellyfish-api-jsonrpc'
import { DBlockController, DefidBin } from '../e2e.defid.module'
import { DBlockController, DefidBin, DefidRpc } from '../e2e.defid.module'

const container = new MasterNodeRegTestContainer()
let app: NestFastifyApplication | DefidBin
let container: MasterNodeRegTestContainer | DefidRpc
let controller: BlockController | DBlockController
let client: JsonRpcClient

beforeAll(async () => {
await container.start()
await container.waitForBlockHeight(101)
if (process.env.DEFID !== undefined) {
app = new DefidBin()
await app.start()
container = app.rpc
controller = app.ocean.blockController
await container.waitForBlockHeight(101)
// await waitForIndexedHeight(app, 100)
client = new JsonRpcClient(container.getCachedRpcUrl())
} else {
container = new MasterNodeRegTestContainer()
await container.start()
await container.waitForBlockHeight(101)

app = await createTestingApp(container)
app = await createTestingApp(container)

await waitForIndexedHeight(app, 100)
if (app instanceof DefidBin) {
controller = app.blockController
} else {
await waitForIndexedHeight(app, 100)
controller = app.get(BlockController)
client = new JsonRpcClient(await container.getCachedRpcUrl())
}
client = new JsonRpcClient(await container.getCachedRpcUrl())

const address = await container.getNewAddress()
for (let i = 0; i < 4; i += 1) {
Expand All @@ -34,7 +41,11 @@ beforeAll(async () => {
})

afterAll(async () => {
await stopTestingApp(container, app)
if (process.env.DEFID !== undefined) {
await (app as DefidBin).stop()
return
}
await stopTestingApp(container as MasterNodeRegTestContainer, app as NestFastifyApplication)
})

describe('get', () => {
Expand Down

0 comments on commit e17804e

Please sign in to comment.