diff --git a/packages/testcontainers/__tests__/containers/WhaleApiContainer.test.ts b/packages/testcontainers/__tests__/containers/WhaleApiContainer.test.ts new file mode 100644 index 000000000..0953bdc07 --- /dev/null +++ b/packages/testcontainers/__tests__/containers/WhaleApiContainer.test.ts @@ -0,0 +1,39 @@ +import { NativeChainContainer, StartedNativeChainContainer } from '@defichain/testcontainers' +import { Network } from 'testcontainers' +import { + StartedWhaleApiContainer, + WhaleApiContainer +} from '@defichain/testcontainers/dist/containers/AppContainer/WhaleApiContainer' +import { WhaleApiClient } from '@defichain/whale-api-client' + +let defid: StartedNativeChainContainer +let whale: StartedWhaleApiContainer + +beforeAll(async () => { + const network = await new Network().start() + + defid = await new NativeChainContainer() + .withNetwork(network) + .withPreconfiguredRegtestMasternode() + .start() + + whale = await new WhaleApiContainer() + .withNetwork(network) + .withNativeChain(defid, network) + .start() +}) + +afterAll(async () => { + await whale.stop() + await defid.stop() +}) + +it('should waitForIndexedBlockHeight(100)', async () => { + await defid.waitFor.walletCoinbaseMaturity() + + const api = new WhaleApiClient(whale.getWhaleApiClientOptions()) + await whale.waitForIndexedBlockHeight(100) + + const blocks = await api.blocks.list(1) + expect(blocks[0].height).toBeGreaterThanOrEqual(100) +}) diff --git a/packages/testcontainers/src/containers/AppContainer/WhaleApiContainer.ts b/packages/testcontainers/src/containers/AppContainer/WhaleApiContainer.ts new file mode 100644 index 000000000..fdd0b48d4 --- /dev/null +++ b/packages/testcontainers/src/containers/AppContainer/WhaleApiContainer.ts @@ -0,0 +1,76 @@ +import { GenericContainer, StartedNetwork } from 'testcontainers' +import { AbstractStartedContainer } from 'testcontainers/dist/modules/abstract-started-container' +import { waitForCondition } from '../../utils' +import { StartedNativeChainContainer } from '../NativeChainContainer' +import fetch from 'cross-fetch' + +// eslint-disable-next-line +// @ts-ignore because `package.json` will always be available in the root of pnpm package +import packageJson from '../../../package.json' + +const WHALE_API_PORT = 3000 + +/** + * For local environment, `:latest` tag will be used as there isn't pipeline to automatically rebuild image locally. + */ +const WHALE_VERSION = packageJson.version === '0.0.0' ? 'latest' : packageJson.version + +export class WhaleApiContainer extends GenericContainer { + constructor (image: string = `ghcr.io/jellyfishsdk/whale-api:${WHALE_VERSION}`) { + super(image) + this.withExposedPorts(WHALE_API_PORT).withStartupTimeout(120_000) + } + + public withNativeChain ( + container: StartedNativeChainContainer, + network: StartedNetwork + ): this { + const ipAddress = container.getIpAddress(network.getName()) + this.withEnvironment({ + WHALE_DEFID_URL: `http://${container.rpcUser}:${container.rpcPassword}@${ipAddress}:19554/`, + WHALE_DATABASE_PROVIDER: 'level', + WHALE_DATABASE_LEVEL_LOCATION: '.level/index', + WHALE_NETWORK: 'regtest', + WHALE_VERSION: 'v0' + }) + return this + } + + public async start (): Promise { + return new StartedWhaleApiContainer(await super.start()) + } +} + +export class StartedWhaleApiContainer extends AbstractStartedContainer { + public getContainerPort (): number { + return WHALE_API_PORT + } + + public getPort (): number { + return this.getMappedPort(this.getContainerPort()) + } + + getEndpoint (): string { + return `http://localhost:${this.getPort()}` + } + + getWhaleApiClientOptions (): { url: string, version: 'v0', network: 'regtest' } { + return { + url: this.getEndpoint(), + version: 'v0', + network: 'regtest' + } + } + + async waitForIndexedBlockHeight (height: number, timeout: number = 590000): Promise { + const url = `${this.getEndpoint()}/v0/regtest/blocks?size=1` + + return await waitForCondition(async () => { + const response = await fetch(url, { + method: 'GET' + }) + const { data } = await response.json() + return data[0].height > height + }, timeout, 200, 'waitForIndexedBlockHeight') + } +} diff --git a/packages/testcontainers/src/index.ts b/packages/testcontainers/src/index.ts index 29748543f..52d2fa4fc 100644 --- a/packages/testcontainers/src/index.ts +++ b/packages/testcontainers/src/index.ts @@ -1,4 +1,4 @@ -import { MasterNodeKey as MNK, RegTestFoundationKeys } from '@defichain/jellyfish-network' +import { RegTestFoundationKeys } from '@defichain/jellyfish-network' export { DockerOptions } from 'dockerode' export { waitForCondition } from './utils' @@ -8,11 +8,6 @@ export { waitForCondition } from './utils' * @deprecated use `import { RegTestFoundationKeys } from '@defichain/jellyfish-network'` */ export const GenesisKeys = RegTestFoundationKeys -/** - * Moved to @defichain/jellyfish-network - * @deprecated use `import { MasterNodeKey } from '@defichain/jellyfish-network'` - */ -export type MasterNodeKey = MNK export * from './containers/DeFiDContainer' export * from './containers/MainNetContainer' @@ -26,6 +21,7 @@ export * from './utils' export * from './containers/RegTestContainer/LoanContainer' export * from './containers/AppContainer/WhaleSanityContainer' +export * from './containers/AppContainer/WhaleApiContainer' export * from './containers/NativeChainContainer' export * from './containers/NativeChainRpc'