Skip to content

Commit

Permalink
Feature/tatum logger (#1042)
Browse files Browse the repository at this point in the history
* ALL-3453: tatum logger module init

* ALL-3453: add logging support

* ALL-3453: access logger via tatumsdk container

* ALL-3453: add faucet info log to metamask wallet provider

* ALL-3453: replace console logs with logger logs

* ALL-3453: tweak missing API key log

* ALL-3453: add logger test suite

* ALL-3453: fix circular dependencies, cr feedback

* ALL-3453: bump version, update dependencies (#1042)

* ALL-3453: fix missing apikey warning condition

---------

Co-authored-by: Filip KaΕ‘tovskΓ½ <[email protected]>
  • Loading branch information
filipkastovsky and Filip KaΕ‘tovskΓ½ authored Jan 8, 2024
1 parent 99129cc commit 972925f
Show file tree
Hide file tree
Showing 29 changed files with 1,662 additions and 953 deletions.
278 changes: 273 additions & 5 deletions CHANGELOG.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tatumio/tatum",
"version": "4.1.37",
"version": "4.2.0",
"description": "Tatum JS SDK",
"author": "Tatum",
"repository": "https://github.com/tatumio/tatum-js",
Expand Down Expand Up @@ -30,6 +30,7 @@
},
"dependencies": {
"bignumber.js": "^9.1.1",
"chalk": "^4.1.2",
"reflect-metadata": "^0.1.13",
"typedi": "^0.10.0"
},
Expand Down
29 changes: 29 additions & 0 deletions src/e2e/tatum.logger.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Network } from '../dto'
import { Ethereum, TatumSDK } from '../service'
import { Logger } from '../service/logger/logger.types'

describe('Logger', () => {
let logger: Logger

beforeEach(() => {
logger = {
trace: jest.fn(),
debug: jest.fn(),
error: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
}
})

it('should warn on missing API key', async () => {
const tatum = await TatumSDK.init<Ethereum>({
network: Network.ETHEREUM_SEPOLIA,
logger,
})
await tatum.destroy()

expect(logger.warn).toHaveBeenCalledWith(
'API key not provided - only a subset of SDK features will be enabled. Generate an API Key by accessing your Dashboard: https://co.tatum.io/signup',
)
})
})
8 changes: 7 additions & 1 deletion src/service/extensions/tatumsdk.container.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { ContainerInstance } from 'typedi'
import { CONFIG, Utils } from '../../util'
import { CONFIG, LOGGER, Utils } from '../../util'
import { Logger } from '../logger/logger.types'
import { TatumConfig } from '../tatum'
import { ServiceConstructor } from './tatumsdk.extensions.dto'

export interface ITatumSdkContainer {
get<T>(type: ServiceConstructor<T>): T
getRpc<T>(): T
getConfig(): TatumConfig
getLogger(): Logger
}

export class TatumSdkContainer implements ITatumSdkContainer {
Expand All @@ -23,4 +25,8 @@ export class TatumSdkContainer implements ITatumSdkContainer {
getConfig(): TatumConfig {
return this.containerInstance.get(CONFIG)
}

getLogger(): Logger {
return this.containerInstance.get(LOGGER)
}
}
11 changes: 10 additions & 1 deletion src/service/faucet/faucet.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Container, Service } from 'typedi'

import { TatumConnector } from '../../connector/tatum.connector'
import { CONFIG, ErrorUtils, ResponseDto } from '../../util'
import { CONFIG, ErrorUtils, LOGGER, ResponseDto } from '../../util'
import { Network, TatumConfig } from '../tatum'

import { Logger } from '../logger/logger.types'
import { TxIdResponse } from './faucet.dto'

@Service({
Expand All @@ -15,13 +16,21 @@ import { TxIdResponse } from './faucet.dto'
export class Faucet {
private readonly connector: TatumConnector
private readonly config: TatumConfig
private readonly logger: Logger

constructor(private readonly id: string) {
this.connector = Container.of(this.id).get(TatumConnector)
this.config = Container.of(this.id).get(CONFIG)
this.logger = Container.of(this.id).get(LOGGER)
}

async fund(address: string): Promise<ResponseDto<TxIdResponse>> {
if (!this.config.apiKey?.v4) {
this.logger.warn(
'Unable to make Faucet calls, get an api key to successfully use this feature: https://co.tatum.io/signup',
)
}

const chain = this.convertToFaucetChain(this.config.network)

return ErrorUtils.tryFail(async () => {
Expand Down
1 change: 1 addition & 0 deletions src/service/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './address'
export * from './extensions'
export * from './fee'
export * from './logger'
export * from './nft'
export * from './notification'
export * from './rpc'
Expand Down
5 changes: 5 additions & 0 deletions src/service/logger/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './logger.development'
export * from './logger.development.browser'
export * from './logger.production'
export * from './logger.quiet'
export * from './logger.types'
121 changes: 121 additions & 0 deletions src/service/logger/logger.development.browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { EnvUtils } from '../../util/env'
import { LogLevel, Logger } from './logger.types'

interface TatumDevelopmentBrowserLoggerOptions {
welcome: boolean
level: LogLevel
}

type BrowserFormattedMessage = [template: string, ...styles: string[]]

export class TatumDevelopmentBrowserLogger implements Logger {
private static readonly DISABLE_WELCOME = '__TTM_DISABLE_WELCOME__'
private static isWelcomeDisabled(): boolean {
if (!EnvUtils.isBrowser()) return false
const anyWindow = window as unknown as { __TTM_DISABLE_WELCOME__: boolean }
return anyWindow[TatumDevelopmentBrowserLogger.DISABLE_WELCOME]
}

private static disableWelcome(): void {
if (!EnvUtils.isBrowser()) return
const anyWindow = window as unknown as { __TTM_DISABLE_WELCOME__: boolean }
anyWindow[TatumDevelopmentBrowserLogger.DISABLE_WELCOME] = true
}

private readonly options: TatumDevelopmentBrowserLoggerOptions
private readonly logger = console

private readonly _DEBUG: BrowserFormattedMessage = ['%c Debug %c ', bgGray, initial]
private readonly _INFO: BrowserFormattedMessage = ['%c Info %c ', bgBlue, initial]
private readonly _WARN: BrowserFormattedMessage = ['%c Warn %c ', bgYellowStrong, initial]
private readonly _ERROR: BrowserFormattedMessage = ['%c Error %c ', bgRedStrong, initial]
private readonly _TATUM: BrowserFormattedMessage = ['%c Tatum %c ', bgGradient, initial]

constructor(options: Partial<TatumDevelopmentBrowserLoggerOptions> = {}) {
const defaultOptions: TatumDevelopmentBrowserLoggerOptions = {
welcome: EnvUtils.isDevelopment() && !TatumDevelopmentBrowserLogger.isWelcomeDisabled(),
level: LogLevel.INFO,
}

this.options = { ...defaultOptions, ...options }

if (this.options.welcome) {
this.welcome()
TatumDevelopmentBrowserLogger.disableWelcome()
}
}

private join(...messages: BrowserFormattedMessage[]): BrowserFormattedMessage {
return messages.reduce(
(acc, curr) => {
acc[0] += curr[0]
acc.push(...curr.slice(1))
return acc
},
[''],
)
}

private welcome(): void {
this.logger.log(
...this.join(this._TATUM, WELCOME_MESSAGES[Math.floor(Math.random() * WELCOME_MESSAGES.length)]),
)
}

trace(...args: unknown[]): void {
if (this.options.level > LogLevel.TRACE) return
this.logger.trace(...args)
}

debug(...args: unknown[]): void {
if (this.options.level > LogLevel.DEBUG) return
this.logger.debug(...this._DEBUG, ...args)
}

info(...args: unknown[]): void {
if (this.options.level > LogLevel.INFO) return
this.logger.info(...this._INFO, ...args)
}

warn(...args: unknown[]): void {
if (this.options.level > LogLevel.WARN) return
this.logger.warn(...this._WARN, ...args)
}

error(...args: unknown[]): void {
if (this.options.level > LogLevel.ERROR) return
this.logger.error(...this._ERROR, ...args)
}
}

const bgGradient =
'color: white; font-weight: bold; background-image: linear-gradient(126deg,#513bff 9%,#89ffca 97%);'

const initial = 'color: inherit; font-weight: inherit;'
const initialStrong = 'color: inherit; font-weight: bold;'
const green = 'color: rgb(137, 255, 202);'

const bgRedStrong = 'color: white; background-color: rgb(238, 52, 52); font-weight: bold;'
const bgYellowStrong = 'color: white; background-color: rgb(255, 140, 0); font-weight: bold;'
const bgBlue = 'color: white; background-color: rgb(81, 59, 255);'
const bgGray = 'color: white; background-color: rgb(158, 158, 158);'

const WELCOME = 'Hi! πŸ‘‹ Welcome to Tatum, the Javascript SDK for Web3.'

const BOLD = [initialStrong, initial]

const WELCOME_MESSAGES: BrowserFormattedMessage[] = [
[
`%c${WELCOME}%c\nVisit our docs to see how Tatum will help you launch projects fast: https://co.tatum.io/docs`,
...BOLD,
],
[`%c${WELCOME}%c\nKick start by making your first RPC call: https://co.tatum.io/start`, ...BOLD],
[`%c${WELCOME}%c\nSee what apps you can build with Tatum: https://co.tatum.io/apps`, ...BOLD],
[
`%c${WELCOME}%c\n%cFREE Testnet Tokens%c: Explore %cTatum Faucets%c available for over 5 chains: https://co.tatum.io/faucets`,
...BOLD,
...BOLD,
green,
initial,
],
]
Loading

0 comments on commit 972925f

Please sign in to comment.