From 2ad11feca67c778a165b4c0a722535c5cd06649f Mon Sep 17 00:00:00 2001 From: Smrecz Date: Fri, 22 Sep 2023 11:25:44 +0200 Subject: [PATCH] ALL-2835 - Extension Ecosystem enabler --- src/service/tatum/tatum.dto.ts | 12 ++++ src/service/tatum/tatum.ts | 107 +++++++++++++++++++++++---------- 2 files changed, 87 insertions(+), 32 deletions(-) diff --git a/src/service/tatum/tatum.dto.ts b/src/service/tatum/tatum.dto.ts index 6157f75eca..83c80b767e 100644 --- a/src/service/tatum/tatum.dto.ts +++ b/src/service/tatum/tatum.dto.ts @@ -1,4 +1,5 @@ import { Network } from '../../dto/Network' +import { TatumSdkContainer, TatumSdkExtension } from "./tatum"; export interface TatumConfig { /** @@ -61,8 +62,19 @@ export interface TatumConfig { */ oneTimeLoadBalancing?: boolean } + + configureExtensions?: ExtensionConstructorOrConfig[] } +type ExtensionConstructor = new (tatumSdkContainer: TatumSdkContainer, ...args: unknown[]) => TatumSdkExtension; + +type ExtensionWithConfig = { + type: ExtensionConstructor; + config: unknown; +}; + +type ExtensionConstructorOrConfig = ExtensionConstructor | ExtensionWithConfig; + export enum ApiVersion { V3 = 'V3', V4 = 'V4', diff --git a/src/service/tatum/tatum.ts b/src/service/tatum/tatum.ts index 18478fac7b..01de250df8 100644 --- a/src/service/tatum/tatum.ts +++ b/src/service/tatum/tatum.ts @@ -1,4 +1,4 @@ -import { Container, Service } from 'typedi' +import { Container, ContainerInstance, Service, ServiceIdentifier, Token as DiToken } from 'typedi' import { isLoadBalancerNetwork } from '../../dto' import { EvmBasedRpcSuite, SolanaRpcSuite, TronRpcSuite, UtxoBasedRpcSuite, XrpRpcSuite } from '../../dto/rpc' import { CONFIG, Constant, Utils } from '../../util' @@ -11,8 +11,47 @@ import { LoadBalancer } from '../rpc/generic/LoadBalancer' import { Token } from '../token' import { WalletProvider } from '../walletProvider' import { ApiVersion, TatumConfig } from './tatum.dto' +import { Constructable } from "typedi/types/types/constructable.type"; +import { AbstractConstructable } from "typedi/types/types/abstract-constructable.type"; -export class BaseTatumSdk { +export interface TatumSdkExtension { + init(...args: unknown[]): Promise; + destroy(): void; +} + +export interface ITatumSdkChain { + extension(type: new (tatumSdkContainer: TatumSdkContainer, ...args: unknown[]) => T): T +} + +export abstract class TatumSdkChain implements ITatumSdkChain { + protected constructor(readonly id: string) { } + + extension(type: new (tatumSdkContainer: TatumSdkContainer, ...args: unknown[]) => T): T { + return Container.of(this.id).get(type); + } + + destroy(): void { + Container.of(this.id).reset( {strategy: 'resetServices' }) + } +} +interface ITatumSdkContainer { + get(type: Constructable): T; + get(type: AbstractConstructable): T; + get(id: string): T; + get(id: DiToken): T; + get(id: ServiceIdentifier): T; +} + +export class TatumSdkContainer implements ITatumSdkContainer { + constructor(private readonly containerInstance: ContainerInstance) { + + } + + get(typeOrId: Constructable | AbstractConstructable | string | DiToken | ServiceIdentifier): T { + return this.containerInstance.get(typeOrId); + } +} +export class BaseTatumSdk extends TatumSdkChain { notification: Notification nft: Nft token: Token @@ -20,8 +59,9 @@ export class BaseTatumSdk { walletProvider: WalletProvider rates: Rates - constructor(private readonly id: string) { - this.notification = Container.of(this.id).get(Notification) + constructor(id: string) { + super(id) + this.notification = Container.of(id).get(Notification) this.nft = Container.of(id).get(Nft) this.token = Container.of(id).get(Token) this.walletProvider = Container.of(id).get(WalletProvider) @@ -39,10 +79,6 @@ export abstract class BaseUtxoClass extends BaseTatumSdk { this.rpc = Utils.getRpc(id, Container.of(id).get(CONFIG)) this.fee = Container.of(id).get(FeeUtxo) } - - destroy(): void { - this.rpc.destroy() - } } export abstract class BaseEvmClass extends BaseTatumSdk { @@ -52,10 +88,6 @@ export abstract class BaseEvmClass extends BaseTatumSdk { super(id) this.rpc = Utils.getRpc(id, Container.of(id).get(CONFIG)) } - - destroy(): void { - this.rpc.destroy() - } } export class Ethereum extends BaseEvmClass { @@ -102,10 +134,6 @@ export class Xrp extends BaseTatumSdk { super(id) this.rpc = Utils.getRpc(id, Container.of(id).get(CONFIG)) } - - destroy(): void { - this.rpc.destroy() - } } export class Solana extends BaseTatumSdk { rpc: SolanaRpcSuite @@ -113,12 +141,8 @@ export class Solana extends BaseTatumSdk { super(id) this.rpc = Utils.getRpc(id, Container.of(id).get(CONFIG)) } - - destroy(): void { - this.rpc.destroy() - } } -export class Tron { +export class Tron extends TatumSdkChain { notification: Notification nft: Nft token: Token @@ -127,8 +151,9 @@ export class Tron { rates: Rates rpc: TronRpcSuite - constructor(private readonly id: string) { - this.notification = Container.of(this.id).get(Notification) + constructor(id: string) { + super(id) + this.notification = Container.of(id).get(Notification) this.nft = Container.of(id).get(Nft) this.token = Container.of(id).get(Token) this.walletProvider = Container.of(id).get(WalletProvider) @@ -136,19 +161,16 @@ export class Tron { this.rates = Container.of(id).get(Rates) this.rpc = Utils.getRpc(id, Container.of(id).get(CONFIG)) } - - destroy(): void { - this.rpc.destroy() - } } -export class Tezos { +export class Tezos extends TatumSdkChain { notification: Notification address: AddressTezos - constructor(private readonly id: string) { - this.notification = Container.of(this.id).get(Notification) - this.address = Container.of(this.id).get(AddressTezos) + constructor(id: string) { + super(id) + this.notification = Container.of(id).get(Notification) + this.address = Container.of(id).get(AddressTezos) } } @@ -159,7 +181,7 @@ export class TatumSDK { * Default configuration is used if no configuration is provided. * @param config */ - public static async init(config: TatumConfig): Promise { + public static async init(config: TatumConfig): Promise { const defaultConfig: Partial = { version: ApiVersion.V4, retryCount: 1, @@ -182,9 +204,30 @@ export class TatumSDK { await loadBalancer.init() } + await this.configureExtensions(config, id) + return Utils.getClient(id, mergedConfig.network) } + private static async configureExtensions(config: TatumConfig, id: string) { + for (const extensionConfig of config?.configureExtensions ?? []) { + let type: new (container: TatumSdkContainer, ...args: unknown[]) => TatumSdkExtension + const args: unknown[] = [] + + if ('type' in extensionConfig) { + type = extensionConfig.type + args.push(extensionConfig.config) + } else { + type = extensionConfig + } + + const containerInstance = new TatumSdkContainer(Container.of(id)) + const instance = new type(containerInstance, ...args) + await instance.init(...args) + Container.of(id).set(type, instance) + } + } + private static generateRandomString() { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' let result = ''