Skip to content

Commit

Permalink
ALL-2835 - Extension Ecosystem enabler
Browse files Browse the repository at this point in the history
  • Loading branch information
Smrecz committed Sep 22, 2023
1 parent 0a8582d commit 2ad11fe
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 32 deletions.
12 changes: 12 additions & 0 deletions src/service/tatum/tatum.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Network } from '../../dto/Network'
import { TatumSdkContainer, TatumSdkExtension } from "./tatum";

export interface TatumConfig {
/**
Expand Down Expand Up @@ -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',
Expand Down
107 changes: 75 additions & 32 deletions src/service/tatum/tatum.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -11,17 +11,57 @@ 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<void>;
destroy(): void;
}

export interface ITatumSdkChain {
extension<T extends TatumSdkExtension>(type: new (tatumSdkContainer: TatumSdkContainer, ...args: unknown[]) => T): T
}

export abstract class TatumSdkChain implements ITatumSdkChain {
protected constructor(readonly id: string) { }

extension<T extends TatumSdkExtension>(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<T>(type: Constructable<T>): T;
get<T>(type: AbstractConstructable<T>): T;
get<T>(id: string): T;
get<T>(id: DiToken<T>): T;
get<T>(id: ServiceIdentifier<T>): T;
}

export class TatumSdkContainer implements ITatumSdkContainer {
constructor(private readonly containerInstance: ContainerInstance) {

}

get<T>(typeOrId: Constructable<T> | AbstractConstructable<T> | string | DiToken<T> | ServiceIdentifier<T>): T {
return this.containerInstance.get(typeOrId);
}
}
export class BaseTatumSdk extends TatumSdkChain {
notification: Notification
nft: Nft
token: Token
address: Address
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)
Expand All @@ -39,10 +79,6 @@ export abstract class BaseUtxoClass extends BaseTatumSdk {
this.rpc = Utils.getRpc<UtxoBasedRpcSuite>(id, Container.of(id).get(CONFIG))
this.fee = Container.of(id).get(FeeUtxo)
}

destroy(): void {
this.rpc.destroy()
}
}

export abstract class BaseEvmClass extends BaseTatumSdk {
Expand All @@ -52,10 +88,6 @@ export abstract class BaseEvmClass extends BaseTatumSdk {
super(id)
this.rpc = Utils.getRpc<EvmBasedRpcSuite>(id, Container.of(id).get(CONFIG))
}

destroy(): void {
this.rpc.destroy()
}
}

export class Ethereum extends BaseEvmClass {
Expand Down Expand Up @@ -102,23 +134,15 @@ export class Xrp extends BaseTatumSdk {
super(id)
this.rpc = Utils.getRpc<XrpRpcSuite>(id, Container.of(id).get(CONFIG))
}

destroy(): void {
this.rpc.destroy()
}
}
export class Solana extends BaseTatumSdk {
rpc: SolanaRpcSuite
constructor(id: string) {
super(id)
this.rpc = Utils.getRpc<SolanaRpcSuite>(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
Expand All @@ -127,28 +151,26 @@ 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)
this.address = Container.of(id).get(AddressTron)
this.rates = Container.of(id).get(Rates)
this.rpc = Utils.getRpc<TronRpcSuite>(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)
}
}

Expand All @@ -159,7 +181,7 @@ export class TatumSDK {
* Default configuration is used if no configuration is provided.
* @param config
*/
public static async init<T>(config: TatumConfig): Promise<T> {
public static async init<T extends ITatumSdkChain>(config: TatumConfig): Promise<T> {
const defaultConfig: Partial<TatumConfig> = {
version: ApiVersion.V4,
retryCount: 1,
Expand All @@ -182,9 +204,30 @@ export class TatumSDK {
await loadBalancer.init()
}

await this.configureExtensions(config, id)

return Utils.getClient<T>(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 = ''
Expand Down

0 comments on commit 2ad11fe

Please sign in to comment.