@crossmint/client-sdk-smart-wallet 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/index.cjs +4 -4
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +53 -70
  4. package/dist/index.d.ts +53 -70
  5. package/dist/index.js +4 -4
  6. package/dist/index.js.map +1 -1
  7. package/package.json +9 -4
  8. package/src/SmartWalletSDK.ts +10 -7
  9. package/src/api/CrossmintWalletService.test.ts +2 -1
  10. package/src/api/CrossmintWalletService.ts +21 -7
  11. package/src/blockchain/wallets/EVMSmartWallet.ts +7 -9
  12. package/src/blockchain/wallets/account/cache.test.ts +67 -0
  13. package/src/blockchain/wallets/account/cache.ts +43 -0
  14. package/src/blockchain/wallets/account/config.test.ts +103 -0
  15. package/src/blockchain/wallets/account/config.ts +71 -15
  16. package/src/blockchain/wallets/account/creator.ts +18 -14
  17. package/src/blockchain/wallets/account/eoa.ts +10 -9
  18. package/src/blockchain/wallets/account/passkey.ts +11 -12
  19. package/src/blockchain/wallets/account/strategy.ts +2 -2
  20. package/src/blockchain/wallets/clientDecorator.ts +4 -5
  21. package/src/blockchain/wallets/service.ts +20 -15
  22. package/src/error/processor.ts +4 -3
  23. package/src/services/index.ts +1 -0
  24. package/src/services/logger.ts +6 -0
  25. package/src/types/internal.ts +29 -23
  26. package/src/utils/constants.ts +0 -4
  27. package/src/utils/helpers.ts +0 -8
  28. package/src/utils/test.ts +24 -0
  29. package/src/api/APIErrorService.ts +0 -78
  30. package/src/api/BaseCrossmintService.ts +0 -81
  31. package/src/services/logging/BrowserLoggerInterface.ts +0 -5
  32. package/src/services/logging/ConsoleProvider.ts +0 -15
  33. package/src/services/logging/DatadogProvider.ts +0 -39
  34. package/src/services/logging/index.ts +0 -16
  35. package/src/utils/log.ts +0 -49
@@ -1,5 +1,5 @@
1
- import { AccountAndSigner, WalletCreationParams } from "../../../types/internal";
1
+ import { AccountAndSigner, WalletCreationContext } from "../../../types/internal";
2
2
 
3
3
  export interface AccountCreationStrategy {
4
- create(params: WalletCreationParams): Promise<AccountAndSigner>;
4
+ create(params: WalletCreationContext): Promise<AccountAndSigner>;
5
5
  }
@@ -4,9 +4,8 @@ import { stringify } from "viem";
4
4
 
5
5
  import { SmartWalletError } from "../../error";
6
6
  import { ErrorProcessor } from "../../error/processor";
7
- import { logInfo } from "../../services/logging";
7
+ import { scwLogger } from "../../services";
8
8
  import { usesGelatoBundler } from "../../utils/blockchain";
9
- import { logPerformance } from "../../utils/log";
10
9
  import { SmartWalletChain } from "../chains";
11
10
 
12
11
  const transactionMethods = [
@@ -38,7 +37,7 @@ function isSignMethod(method: string): method is SignMethod {
38
37
  * - Automatic formatting of transactions for Gelato bundler compatibility.
39
38
  * */
40
39
  export class ClientDecorator {
41
- constructor(private readonly errorProcessor: ErrorProcessor) {}
40
+ constructor(private readonly errorProcessor: ErrorProcessor, protected logger = scwLogger) {}
42
41
 
43
42
  public decorate<Client extends SmartAccountClient<EntryPoint>>({
44
43
  crossmintChain,
@@ -60,7 +59,7 @@ export class ClientDecorator {
60
59
  }
61
60
 
62
61
  return (...args: any[]) =>
63
- logPerformance(`CrossmintSmartWallet.${prop}`, () =>
62
+ this.logger.logPerformance(`CrossmintSmartWallet.${prop}`, () =>
64
63
  this.execute(target, prop, originalMethod, args, crossmintChain)
65
64
  );
66
65
  },
@@ -76,7 +75,7 @@ export class ClientDecorator {
76
75
  crossmintChain: SmartWalletChain
77
76
  ) {
78
77
  try {
79
- logInfo(`[CrossmintSmartWallet.${prop}] - params: ${stringify(args)}`);
78
+ this.logger.log(`[CrossmintSmartWallet.${prop}] - params: ${stringify(args)}`);
80
79
  const processed = isTxnMethod(prop) ? this.processTxnArgs(prop, crossmintChain, args) : args;
81
80
  return await originalMethod.call(target, ...processed);
82
81
  } catch (error: any) {
@@ -12,7 +12,7 @@ import { CURRENT_VERSION, ZERO_DEV_TYPE } from "../../utils/constants";
12
12
  import { equalsIgnoreCase } from "../../utils/helpers";
13
13
  import { type SmartWalletChain, getBundlerRPC, viemNetworks } from "../chains";
14
14
  import { EVMSmartWallet } from "./EVMSmartWallet";
15
- import type { AccountConfigFacade } from "./account/config";
15
+ import type { AccountConfigService } from "./account/config";
16
16
  import type { AccountCreator } from "./account/creator";
17
17
  import type { ClientDecorator } from "./clientDecorator";
18
18
  import { paymasterMiddleware, usePaymaster } from "./paymaster";
@@ -20,7 +20,7 @@ import { paymasterMiddleware, usePaymaster } from "./paymaster";
20
20
  export class SmartWalletService {
21
21
  constructor(
22
22
  private readonly crossmintService: CrossmintWalletService,
23
- private readonly accountConfigFacade: AccountConfigFacade,
23
+ private readonly accountConfigService: AccountConfigService,
24
24
  private readonly accountCreator: AccountCreator,
25
25
  private readonly clientDecorator: ClientDecorator
26
26
  ) {}
@@ -30,28 +30,24 @@ export class SmartWalletService {
30
30
  chain: SmartWalletChain,
31
31
  walletParams: WalletParams
32
32
  ): Promise<EVMSmartWallet> {
33
- const { entryPointVersion, kernelVersion, existingSignerConfig, smartContractWalletAddress, userId } =
34
- await this.accountConfigFacade.get(user, chain);
33
+ const {
34
+ config: { entryPointVersion, kernelVersion, existing, userWithId },
35
+ cached,
36
+ } = await this.accountConfigService.get(user, chain);
37
+
35
38
  const publicClient = createPublicClient({ transport: http(getBundlerRPC(chain)) });
36
39
 
37
40
  const { account, signerConfig } = await this.accountCreator.get({
38
41
  chain,
39
42
  walletParams,
40
43
  publicClient,
41
- user: { ...user, id: userId },
42
- entryPoint: {
43
- version: entryPointVersion,
44
- address: entryPointVersion === "v0.6" ? ENTRYPOINT_ADDRESS_V06 : ENTRYPOINT_ADDRESS_V07,
45
- },
44
+ user: userWithId,
45
+ entryPoint: entryPointVersion === "v0.6" ? ENTRYPOINT_ADDRESS_V06 : ENTRYPOINT_ADDRESS_V07,
46
46
  kernelVersion,
47
- existingSignerConfig,
47
+ existing,
48
48
  });
49
49
 
50
- if (smartContractWalletAddress != null && !equalsIgnoreCase(smartContractWalletAddress, account.address)) {
51
- throw new UserWalletAlreadyCreatedError(userId);
52
- }
53
-
54
- if (existingSignerConfig == null) {
50
+ if (existing == null) {
55
51
  await this.crossmintService.idempotentCreateSmartWallet(user, {
56
52
  type: ZERO_DEV_TYPE,
57
53
  smartContractWalletAddress: account.address,
@@ -64,6 +60,15 @@ export class SmartWalletService {
64
60
  });
65
61
  }
66
62
 
63
+ if (!cached) {
64
+ this.accountConfigService.cache({
65
+ entryPointVersion,
66
+ kernelVersion,
67
+ user: userWithId,
68
+ existing: { address: account.address, signerConfig },
69
+ });
70
+ }
71
+
67
72
  const kernelAccountClient: SmartWalletClient = createKernelAccountClient({
68
73
  account,
69
74
  chain: viemNetworks[chain],
@@ -1,11 +1,12 @@
1
1
  import { BaseError, stringify } from "viem";
2
2
 
3
+ import { SDKLogger } from "@crossmint/client-sdk-base";
4
+
3
5
  import { SmartWalletError } from ".";
4
- import { DatadogProvider } from "../services/logging/DatadogProvider";
5
6
  import { SDK_VERSION } from "../utils/constants";
6
7
 
7
8
  export class ErrorProcessor {
8
- constructor(private readonly logger: DatadogProvider) {}
9
+ constructor(private readonly logger: SDKLogger) {}
9
10
 
10
11
  public map(error: unknown, fallback: SmartWalletError): SmartWalletError | BaseError {
11
12
  this.record(error);
@@ -24,7 +25,7 @@ export class ErrorProcessor {
24
25
 
25
26
  private record(error: unknown) {
26
27
  const message = error instanceof Error ? error.message : String(error);
27
- this.logger.logError(`Smart Wallet SDK Error: ${message}`, {
28
+ this.logger.error(`Smart Wallet SDK Error: ${message}`, {
28
29
  stack: error instanceof Error ? error.stack : undefined,
29
30
  name: error instanceof Error ? error.name : "UnknownError",
30
31
  details: stringify(error),
@@ -0,0 +1 @@
1
+ export * from "./logger";
@@ -0,0 +1,6 @@
1
+ import { SDKLogger, getBrowserLogger } from "@crossmint/client-sdk-base";
2
+
3
+ import { SCW_SERVICE } from "../utils/constants";
4
+
5
+ export const scwLogger = new SDKLogger(SCW_SERVICE);
6
+ export const scwDatadogLogger = new SDKLogger(SCW_SERVICE, getBrowserLogger(SCW_SERVICE, { onlyDatadog: true }));
@@ -2,7 +2,7 @@ import type { KernelSmartAccount } from "@zerodev/sdk";
2
2
  import type { SmartAccountClient } from "permissionless";
3
3
  import type { SmartAccount } from "permissionless/accounts";
4
4
  import type { EntryPoint } from "permissionless/types/entrypoint";
5
- import type { Chain, HttpTransport, PublicClient } from "viem";
5
+ import type { Address, Chain, HttpTransport, PublicClient } from "viem";
6
6
 
7
7
  import type { SmartWalletChain } from "../blockchain/chains";
8
8
  import type { EOASignerConfig, PasskeySignerConfig, SignerConfig } from "../blockchain/wallets/account/signer";
@@ -19,47 +19,53 @@ export function isSupportedEntryPointVersion(version: string): version is Suppor
19
19
  return SUPPORTED_ENTRYPOINT_VERSIONS.includes(version as any);
20
20
  }
21
21
 
22
- export interface WalletCreationParams {
22
+ export interface PreExistingWalletProperties {
23
+ signerConfig: SignerConfig;
24
+ address: Address;
25
+ }
26
+
27
+ export interface WalletCreationContext {
23
28
  user: UserParams & { id: string };
24
29
  chain: SmartWalletChain;
25
30
  publicClient: PublicClient<HttpTransport>;
26
31
  walletParams: WalletParams;
27
- entryPoint: { version: SupportedEntryPointVersion; address: EntryPoint };
32
+ entryPoint: EntryPoint;
28
33
  kernelVersion: SupportedKernelVersion;
29
- existingSignerConfig?: SignerConfig;
34
+ existing?: PreExistingWalletProperties;
30
35
  }
31
36
 
32
- export interface PasskeyCreationParams extends WalletCreationParams {
37
+ export interface PasskeyCreationContext extends WalletCreationContext {
33
38
  walletParams: WalletParams & { signer: PasskeySigner };
34
- existingSignerConfig?: PasskeySignerConfig;
39
+ existing?: { signerConfig: PasskeySignerConfig; address: Address };
35
40
  }
36
41
 
37
- export interface EOACreationParams extends WalletCreationParams {
42
+ export interface EOACreationContext extends WalletCreationContext {
38
43
  walletParams: WalletParams & { signer: EOASigner };
39
- existingSignerConfig?: EOASignerConfig;
44
+ existing?: { signerConfig: EOASignerConfig; address: Address };
40
45
  }
41
46
 
42
- export function isPasskeyCreationParams(params: WalletCreationParams): params is PasskeyCreationParams {
43
- const hasPasskeyWalletParams =
44
- "signer" in params.walletParams &&
45
- "type" in params.walletParams.signer &&
46
- params.walletParams.signer.type === "PASSKEY";
47
+ export function isPasskeyWalletParams(params: WalletParams): params is WalletParams & { signer: PasskeySigner } {
48
+ return "signer" in params && "type" in params.signer && params.signer.type === "PASSKEY";
49
+ }
47
50
 
48
- const signerIsPasskeyOrUndefined =
49
- params.existingSignerConfig == null || params.existingSignerConfig.type === "passkeys";
51
+ export function isPasskeyCreationContext(params: WalletCreationContext): params is PasskeyCreationContext {
52
+ const signerIsPasskeyOrUndefined = params.existing == null || params.existing.signerConfig.type === "passkeys";
50
53
 
51
- return hasPasskeyWalletParams && signerIsPasskeyOrUndefined;
54
+ return isPasskeyWalletParams(params.walletParams) && signerIsPasskeyOrUndefined;
52
55
  }
53
56
 
54
- export function isEOACreationParams(params: WalletCreationParams): params is EOACreationParams {
55
- const hasEOAWalletParams =
56
- "signer" in params.walletParams &&
57
- (("type" in params.walletParams.signer && params.walletParams.signer.type === "VIEM_ACCOUNT") ||
58
- ("request" in params.walletParams.signer && typeof params.walletParams.signer.request === "function"));
57
+ export function isEOAWalletParams(params: WalletParams): params is WalletParams & { signer: EOASigner } {
58
+ return (
59
+ "signer" in params &&
60
+ (("type" in params.signer && params.signer.type === "VIEM_ACCOUNT") ||
61
+ ("request" in params.signer && typeof params.signer.request === "function"))
62
+ );
63
+ }
59
64
 
60
- const signerIsEOAOrUndefined = params.existingSignerConfig == null || params.existingSignerConfig.type === "eoa";
65
+ export function isEOACreationContext(params: WalletCreationContext): params is EOACreationContext {
66
+ const signerIsEOAOrUndefined = params.existing == null || params.existing.signerConfig.type === "eoa";
61
67
 
62
- return hasEOAWalletParams && signerIsEOAOrUndefined;
68
+ return isEOAWalletParams(params.walletParams) && signerIsEOAOrUndefined;
63
69
  }
64
70
 
65
71
  export interface AccountAndSigner {
@@ -1,9 +1,5 @@
1
1
  export const ZERO_DEV_TYPE = "ZeroDev";
2
2
  export const CURRENT_VERSION = 0;
3
- export const DATADOG_CLIENT_TOKEN = "pub035be8a594b35be1887b6ba76c4029ca";
4
- export const CROSSMINT_DEV_URL = "http://localhost:3000/api";
5
- export const CROSSMINT_STG_URL = "https://staging.crossmint.com/api";
6
- export const CROSSMINT_PROD_URL = "https://www.crossmint.com/api";
7
3
  export const SCW_SERVICE = "SCW_SDK";
8
4
  export const SDK_VERSION = "0.1.0";
9
5
  export const API_VERSION = "2024-06-09";
@@ -1,11 +1,3 @@
1
- export function isLocalhost() {
2
- if (process.env.NODE_ENV === "test") {
3
- return false;
4
- }
5
-
6
- return window.location.origin.includes("localhost");
7
- }
8
-
9
1
  export function isEmpty(str: string | undefined | null): str is undefined | null {
10
2
  return !str || str.length === 0 || str.trim().length === 0;
11
3
  }
@@ -0,0 +1,24 @@
1
+ import { SmartWalletConfig } from "../types/service";
2
+
3
+ export const mockConfig: SmartWalletConfig = {
4
+ kernelVersion: "0.3.1",
5
+ entryPointVersion: "v0.7",
6
+ userId: "devlyn@paella.dev",
7
+ signers: [
8
+ {
9
+ signerData: {
10
+ entryPoint: "0x0000000071727De22E5E9d8BAf0edAc6f37da032",
11
+ validatorAddress: "0xbA45a2BFb8De3D24cA9D7F1B551E14dFF5d690Fd",
12
+ pubKeyX: "110311240024954100085667226472791468894960420468782293097673057837941382345525",
13
+ pubKeyY: "55639753423913323920634804373610812340711881298092778447611544058799129775494",
14
+ authenticatorIdHash: "0xb7f951026ad956257e41c16f5e6c1c8969968356c9a8a8df916fcceda53f5c6a",
15
+ authenticatorId: "u76dDdMEjTBgm68gbqfbaAlSoqE",
16
+ passkeyName: "devlyn@paella.dev",
17
+ validatorContractVersion: "0.0.2" as any,
18
+ domain: "localhost",
19
+ type: "passkeys",
20
+ },
21
+ },
22
+ ],
23
+ smartContractWalletAddress: "0x7EAf93269C06Af4236E08d16d5220Df5f964eD87",
24
+ };
@@ -1,78 +0,0 @@
1
- import {
2
- CrossmintServiceError,
3
- JWTDecryptionError,
4
- JWTExpiredError,
5
- JWTIdentifierError,
6
- JWTInvalidError,
7
- OutOfCreditsError,
8
- } from "@crossmint/client-sdk-base";
9
-
10
- import {
11
- AdminAlreadyUsedError,
12
- SmartWalletError,
13
- SmartWalletsNotEnabledError,
14
- UserWalletAlreadyCreatedError,
15
- } from "../error";
16
-
17
- export type CrossmintAPIErrorCodes =
18
- | "ERROR_JWT_INVALID"
19
- | "ERROR_JWT_DECRYPTION"
20
- | "ERROR_JWT_IDENTIFIER"
21
- | "ERROR_JWT_EXPIRED"
22
- | "ERROR_USER_WALLET_ALREADY_CREATED"
23
- | "ERROR_ADMIN_SIGNER_ALREADY_USED"
24
- | "ERROR_PROJECT_NONCUSTODIAL_WALLETS_NOT_ENABLED";
25
-
26
- export class APIErrorService {
27
- constructor(
28
- private errors: Record<CrossmintAPIErrorCodes, (apiResponse: any) => SmartWalletError> = {
29
- ERROR_JWT_INVALID: () => new JWTInvalidError(),
30
- ERROR_JWT_DECRYPTION: () => new JWTDecryptionError(),
31
- ERROR_JWT_EXPIRED: ({ expiredAt }: { expiredAt: string }) => new JWTExpiredError(new Date(expiredAt)),
32
- ERROR_JWT_IDENTIFIER: ({ identifierKey }: { identifierKey: string }) =>
33
- new JWTIdentifierError(identifierKey),
34
- ERROR_USER_WALLET_ALREADY_CREATED: ({ userId }: { userId: string }) =>
35
- new UserWalletAlreadyCreatedError(userId),
36
- ERROR_ADMIN_SIGNER_ALREADY_USED: () => new AdminAlreadyUsedError(),
37
- ERROR_PROJECT_NONCUSTODIAL_WALLETS_NOT_ENABLED: () => new SmartWalletsNotEnabledError(),
38
- }
39
- ) {}
40
-
41
- async throwErrorFromResponse({
42
- response,
43
- onServerErrorMessage,
44
- }: {
45
- response: Response;
46
- onServerErrorMessage: string;
47
- }) {
48
- if (response.ok) {
49
- return;
50
- }
51
-
52
- if (response.status >= 500) {
53
- throw new CrossmintServiceError(onServerErrorMessage, response.status);
54
- }
55
-
56
- if (response.status === 402) {
57
- throw new OutOfCreditsError();
58
- }
59
-
60
- try {
61
- const body = await response.json();
62
- const code = body.code as CrossmintAPIErrorCodes | undefined;
63
- if (code != null && this.errors[code] != null) {
64
- throw this.errors[code](body);
65
- }
66
- if (body.message != null) {
67
- throw new CrossmintServiceError(body.message, response.status);
68
- }
69
- } catch (e) {
70
- if (e instanceof SmartWalletError) {
71
- throw e;
72
- }
73
- console.error("Error parsing response", e);
74
- }
75
-
76
- throw new CrossmintServiceError(await response.text(), response.status);
77
- }
78
- }
@@ -1,81 +0,0 @@
1
- import { CrossmintServiceError } from "@crossmint/client-sdk-base";
2
- import { validateAPIKey } from "@crossmint/common-sdk-base";
3
-
4
- import { CROSSMINT_DEV_URL, CROSSMINT_PROD_URL, CROSSMINT_STG_URL } from "../utils/constants";
5
- import { logPerformance } from "../utils/log";
6
- import { APIErrorService } from "./APIErrorService";
7
-
8
- export abstract class BaseCrossmintService {
9
- public crossmintAPIHeaders: Record<string, string>;
10
- protected crossmintBaseUrl: string;
11
- protected apiErrorService: APIErrorService;
12
- private static urlMap: Record<string, string> = {
13
- development: CROSSMINT_DEV_URL,
14
- staging: CROSSMINT_STG_URL,
15
- production: CROSSMINT_PROD_URL,
16
- };
17
-
18
- constructor(apiKey: string) {
19
- const result = validateAPIKey(apiKey);
20
- if (!result.isValid) {
21
- throw new Error("API key invalid");
22
- }
23
- this.crossmintAPIHeaders = {
24
- accept: "application/json",
25
- "content-type": "application/json",
26
- "x-api-key": apiKey,
27
- };
28
- this.crossmintBaseUrl = this.getUrlFromEnv(result.environment);
29
- this.apiErrorService = new APIErrorService();
30
- }
31
-
32
- protected async fetchCrossmintAPI(
33
- endpoint: string,
34
- options: { body?: string; method: string } = { method: "GET" },
35
- onServerErrorMessage: string,
36
- authToken?: string
37
- ) {
38
- return logPerformance(
39
- "FETCH_CROSSMINT_API",
40
- async () => {
41
- const url = `${this.crossmintBaseUrl}/${endpoint}`;
42
- const { body, method } = options;
43
-
44
- let response: Response;
45
- try {
46
- response = await fetch(url, {
47
- body,
48
- method,
49
- headers: {
50
- ...this.crossmintAPIHeaders,
51
- ...(authToken != null && {
52
- Authorization: `Bearer ${authToken}`,
53
- }),
54
- },
55
- });
56
- } catch (error) {
57
- throw new CrossmintServiceError(`Error fetching Crossmint API: ${error}`);
58
- }
59
-
60
- if (!response.ok) {
61
- await this.apiErrorService.throwErrorFromResponse({
62
- response,
63
- onServerErrorMessage,
64
- });
65
- }
66
-
67
- return await response.json();
68
- },
69
- { endpoint }
70
- );
71
- }
72
-
73
- protected getUrlFromEnv(environment: string) {
74
- const url = BaseCrossmintService.urlMap[environment];
75
- if (!url) {
76
- console.log(" CrossmintService.urlMap: ", BaseCrossmintService.urlMap);
77
- throw new Error(`URL not found for environment: ${environment}`);
78
- }
79
- return url;
80
- }
81
- }
@@ -1,5 +0,0 @@
1
- export interface BrowserLoggerInterface {
2
- logInfo(message: string, context?: unknown): void;
3
- logError(message: string, context?: unknown): void;
4
- logWarn(message: string, context?: unknown): void;
5
- }
@@ -1,15 +0,0 @@
1
- import { BrowserLoggerInterface } from "./BrowserLoggerInterface";
2
-
3
- export class ConsoleProvider implements BrowserLoggerInterface {
4
- logInfo(message: string, context?: object) {
5
- console.log(message, context);
6
- }
7
-
8
- logError(message: string, context?: object) {
9
- console.error(message, context);
10
- }
11
-
12
- logWarn(message: string, context?: object) {
13
- console.warn(message, context);
14
- }
15
- }
@@ -1,39 +0,0 @@
1
- import { datadogLogs } from "@datadog/browser-logs";
2
-
3
- import { DATADOG_CLIENT_TOKEN, SCW_SERVICE } from "../../utils/constants";
4
- import { BrowserLoggerInterface } from "./BrowserLoggerInterface";
5
-
6
- export class DatadogProvider implements BrowserLoggerInterface {
7
- logInfo(message: string, context?: object) {
8
- log(message, "info", context);
9
- }
10
-
11
- logError(message: string, context?: object) {
12
- log(message, "error", context);
13
- }
14
-
15
- logWarn(message: string, context?: object) {
16
- log(message, "warn", context);
17
- }
18
- }
19
-
20
- function log(message: string, loggerType: "info" | "error" | "warn", contextParam?: object) {
21
- const _context = contextParam ? { ...contextParam, service: SCW_SERVICE } : { service: SCW_SERVICE };
22
-
23
- init();
24
- datadogLogs.logger[loggerType](message, _context);
25
- }
26
-
27
- function init() {
28
- const isDatadogInitialized = datadogLogs.getInternalContext() != null;
29
- if (isDatadogInitialized) {
30
- return;
31
- }
32
-
33
- datadogLogs.init({
34
- clientToken: DATADOG_CLIENT_TOKEN,
35
- site: "datadoghq.com",
36
- forwardErrorsToLogs: false,
37
- sampleRate: 100,
38
- });
39
- }
@@ -1,16 +0,0 @@
1
- import { isClient } from "../../utils/environment";
2
- import { isLocalhost } from "../../utils/helpers";
3
- import { ConsoleProvider } from "./ConsoleProvider";
4
- import { DatadogProvider } from "./DatadogProvider";
5
-
6
- function getBrowserLogger() {
7
- if (isClient() && isLocalhost()) {
8
- return new ConsoleProvider();
9
- }
10
-
11
- return new DatadogProvider();
12
- }
13
-
14
- const { logInfo, logWarn, logError } = getBrowserLogger();
15
-
16
- export { logInfo, logWarn, logError };
package/src/utils/log.ts DELETED
@@ -1,49 +0,0 @@
1
- import { logError, logInfo } from "../services/logging";
2
- import { SCW_SERVICE } from "./constants";
3
-
4
- export async function logPerformance<T>(name: string, cb: () => Promise<T>, extraInfo?: object) {
5
- const start = new Date().getTime();
6
- const result = await cb();
7
- const durationInMs = new Date().getTime() - start;
8
- const args = { durationInMs, ...extraInfo };
9
- logInfo(`[${SCW_SERVICE} - ${name} - TIME] - ${beautify(args)}`, { args });
10
- return result;
11
- }
12
-
13
- function beautify(json: any) {
14
- try {
15
- return json != null ? JSON.stringify(json, null, 2) : json;
16
- } catch (error) {
17
- return stringifyAvoidingCircular(json);
18
- }
19
- }
20
-
21
- function stringifyAvoidingCircular(json: any) {
22
- // stringify an object, avoiding circular structures
23
- // https://stackoverflow.com/a/31557814
24
- const simpleObject: { [key: string]: any } = {};
25
- for (const prop in json) {
26
- if (!Object.prototype.hasOwnProperty.call(json, prop)) {
27
- continue;
28
- }
29
- if (typeof json[prop] == "object") {
30
- continue;
31
- }
32
- if (typeof json[prop] == "function") {
33
- continue;
34
- }
35
- simpleObject[prop] = json[prop];
36
- }
37
- return JSON.stringify(simpleObject, null, 2); // returns cleaned up JSON
38
- }
39
-
40
- export function errorToJSON(error: Error | unknown) {
41
- const errorToLog = error instanceof Error ? error : { message: "Unknown error", name: "Unknown error" };
42
-
43
- if (!(errorToLog instanceof Error) && (errorToLog as any).constructor?.name !== "SyntheticBaseEvent") {
44
- logError("ERROR_TO_JSON_FAILED", { error: errorToLog });
45
- throw new Error("[errorToJSON] err is not instanceof Error nor SyntheticBaseEvent");
46
- }
47
-
48
- return JSON.parse(JSON.stringify(errorToLog, Object.getOwnPropertyNames(errorToLog)));
49
- }