From 28e6083b842eafaaa3d65979fa6380b4b0abd9d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Oliv=C3=A9?= Date: Fri, 11 Oct 2024 15:56:17 +0200 Subject: [PATCH] feat: added export state log feature (#841) --- packages/custodyController/src/custody.ts | 39 ++++++++++++++++++- packages/custodyKeyring/src/CustodyKeyring.ts | 8 ++++ .../custodyKeyring/src/constants/index.ts | 1 + packages/sdk/src/classes/MMISDK.ts | 11 +++++- packages/sdk/src/constants/constants.ts | 1 + .../sdk/src/custodianApi/eca3/ECA3Client.ts | 23 ++++++++++- .../src/custodianApi/eca3/ECA3CustodianApi.ts | 14 +++++-- .../eca3/util/json-rpc-call.test.ts | 4 +- .../custodianApi/eca3/util/json-rpc-call.ts | 25 +++++++++++- .../custodianApi/json-rpc/JsonRpcClient.ts | 23 ++++++++++- .../json-rpc/JsonRpcCustodianApi.ts | 11 +++++- .../json-rpc/util/json-rpc-call.test.ts | 4 +- .../json-rpc/util/json-rpc-call.ts | 25 +++++++++++- packages/sdk/src/index.ts | 1 + packages/types/src/IApiCallLogEntry.ts | 9 +++++ packages/types/src/index.ts | 1 + 16 files changed, 182 insertions(+), 18 deletions(-) create mode 100644 packages/types/src/IApiCallLogEntry.ts diff --git a/packages/custodyController/src/custody.ts b/packages/custodyController/src/custody.ts index 2f110501..42d72a09 100644 --- a/packages/custodyController/src/custody.ts +++ b/packages/custodyController/src/custody.ts @@ -1,5 +1,5 @@ import { CUSTODIAN_TYPES } from "@metamask-institutional/custody-keyring"; -import { ITransactionStatusMap } from "@metamask-institutional/types"; +import { IApiCallLogEntry, ITransactionStatusMap } from "@metamask-institutional/types"; import { ObservableStore } from "@metamask/obs-store"; import { CustodyAccountDetails } from "./types"; @@ -16,8 +16,9 @@ import { toChecksumHexAddress } from "./utils"; */ export class CustodyController { public store; - + private readonly MAX_LOG_ENTRIES = 500; public captureException: (e: Error) => void; + /** * Creates a new controller instance * @@ -29,12 +30,46 @@ export class CustodyController { this.store = new ObservableStore({ custodyAccountDetails: {} as { [key: string]: CustodyAccountDetails }, custodianConnectRequest: {}, + apiRequestLogs: [], ...initState, }); this.captureException = captureException; } + storeApiCallLog(apiLogEntry: IApiCallLogEntry): void { + const { apiRequestLogs } = this.store.getState(); + + const updatedApiRequestLogs = apiRequestLogs ? [...apiRequestLogs] : []; + + if (updatedApiRequestLogs.length >= this.MAX_LOG_ENTRIES) { + updatedApiRequestLogs.shift(); + } + + updatedApiRequestLogs.push(apiLogEntry); + + this.store.updateState({ apiRequestLogs: updatedApiRequestLogs }); + } + + sanitizeAndLogApiCall(apiLogEntry: IApiCallLogEntry): void { + const { id, method, endpoint, success, timestamp, errorMessage, responseData } = apiLogEntry; + + const sanitizedEntry: IApiCallLogEntry = { + id, + method, + endpoint, + success, + timestamp, + responseData: success ? responseData : undefined, + }; + + if (!success && errorMessage) { + sanitizedEntry.errorMessage = errorMessage; + } + + this.storeApiCallLog(sanitizedEntry); + } + storeCustodyStatusMap(custody: string, custodyStatusMap: ITransactionStatusMap): void { try { const { custodyStatusMaps } = this.store.getState(); diff --git a/packages/custodyKeyring/src/CustodyKeyring.ts b/packages/custodyKeyring/src/CustodyKeyring.ts index 88ebf5e7..f8a993ac 100644 --- a/packages/custodyKeyring/src/CustodyKeyring.ts +++ b/packages/custodyKeyring/src/CustodyKeyring.ts @@ -5,6 +5,7 @@ import { AddressType, AuthDetails, AuthTypes, + IApiCallLogEntry, ICustodianAccount, ICustodianTransactionLink, ICustodianType, @@ -25,6 +26,7 @@ import crypto from "crypto"; import { EventEmitter } from "events"; import { + API_REQUEST_LOG_EVENT, DEFAULT_MAX_CACHE_AGE, INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, REFRESH_TOKEN_CHANGE_EVENT, @@ -249,6 +251,10 @@ export abstract class CustodyKeyring extends EventEmitter { this.emit(INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, event); // Propagate the event to the extension where it calls for the keyrings to be persisted } + emitApiRequestLogEvent(event: IApiCallLogEntry): void { + this.emit(API_REQUEST_LOG_EVENT, event); + } + createAuthDetails(token: string): AuthDetails { let authDetails: AuthDetails; @@ -287,6 +293,8 @@ export abstract class CustodyKeyring extends EventEmitter { this.handleInteractiveRefreshTokenChangeEvent(event), ); + sdk.on(API_REQUEST_LOG_EVENT, (event: IApiCallLogEntry) => this.emitApiRequestLogEvent(event)); + this.sdkList.push({ sdk, hash, diff --git a/packages/custodyKeyring/src/constants/index.ts b/packages/custodyKeyring/src/constants/index.ts index 29d80bc8..5c1803c6 100644 --- a/packages/custodyKeyring/src/constants/index.ts +++ b/packages/custodyKeyring/src/constants/index.ts @@ -1,3 +1,4 @@ export const DEFAULT_MAX_CACHE_AGE = 60; export const REFRESH_TOKEN_CHANGE_EVENT = "refresh_token_change"; export const INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT = "interactive_replacement_token_change"; +export const API_REQUEST_LOG_EVENT = "API_REQUEST_LOG_EVENT"; diff --git a/packages/sdk/src/classes/MMISDK.ts b/packages/sdk/src/classes/MMISDK.ts index 4e108060..a3759b9d 100644 --- a/packages/sdk/src/classes/MMISDK.ts +++ b/packages/sdk/src/classes/MMISDK.ts @@ -2,6 +2,7 @@ import { SimpleCache } from "@metamask-institutional/simplecache"; import { AuthDetails, AuthTypes, + IApiCallLogEntry, ICustodianTransactionLink, IEIP1559TxParams, ILegacyTXParams, @@ -16,7 +17,11 @@ import { CustodianApiConstructor, ICustodianApi } from "src/interfaces/ICustodia import { SignedMessageMetadata } from "src/types/SignedMessageMetadata"; import { SignedTypedMessageMetadata } from "src/types/SignedTypedMessageMetadata"; -import { INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, REFRESH_TOKEN_CHANGE_EVENT } from "../constants/constants"; +import { + API_REQUEST_LOG_EVENT, + INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, + REFRESH_TOKEN_CHANGE_EVENT, +} from "../constants/constants"; import { IEthereumAccount } from "../interfaces/IEthereumAccount"; import { IEthereumAccountCustodianDetails } from "../interfaces/IEthereumAccountCustodianDetails"; import { MessageTypes, TypedMessage } from "../interfaces/ITypedMessage"; @@ -49,6 +54,10 @@ export class MMISDK extends EventEmitter { this.custodianApi.on(INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, event => { this.emit(INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, event); }); + + this.custodianApi.on(API_REQUEST_LOG_EVENT, (event: IApiCallLogEntry) => { + this.emit(API_REQUEST_LOG_EVENT, event); + }); } // Do an in-situ replacement of the auth details diff --git a/packages/sdk/src/constants/constants.ts b/packages/sdk/src/constants/constants.ts index d9fb5c24..142258bb 100644 --- a/packages/sdk/src/constants/constants.ts +++ b/packages/sdk/src/constants/constants.ts @@ -1,3 +1,4 @@ export const REFRESH_TOKEN_CHANGE_EVENT = "refresh_token_change"; export const INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT = "interactive_replacement_token_change"; export const DEFAULT_MAX_CACHE_AGE = 60; +export const API_REQUEST_LOG_EVENT = "API_REQUEST_LOG_EVENT"; diff --git a/packages/sdk/src/custodianApi/eca3/ECA3Client.ts b/packages/sdk/src/custodianApi/eca3/ECA3Client.ts index f9470258..eaea5432 100644 --- a/packages/sdk/src/custodianApi/eca3/ECA3Client.ts +++ b/packages/sdk/src/custodianApi/eca3/ECA3Client.ts @@ -3,7 +3,11 @@ import { IRefreshTokenChangeEvent } from "@metamask-institutional/types"; import crypto from "crypto"; import { EventEmitter } from "events"; -import { INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, REFRESH_TOKEN_CHANGE_EVENT } from "../../constants/constants"; +import { + API_REQUEST_LOG_EVENT, + INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, + REFRESH_TOKEN_CHANGE_EVENT, +} from "../../constants/constants"; import { JsonRpcResult } from "./interfaces/JsonRpcResult"; import { JsonRpcCreateTransactionPayload } from "./rpc-payloads/JsonRpcCreateTransactionPayload"; import { JsonRpcGetSignedMessageByIdPayload } from "./rpc-payloads/JsonRpcGetSignedMessageByIdPayload"; @@ -38,7 +42,7 @@ export class ECA3Client extends EventEmitter { constructor(private apiBaseUrl: string, private refreshToken: string, private refreshTokenUrl: string) { super(); - this.call = factory(`${apiBaseUrl}/v3/json-rpc`); + this.call = factory(`${this.apiBaseUrl}/v3/json-rpc`, this.emit.bind(this)); this.cache = new SimpleCache(); } @@ -132,8 +136,23 @@ export class ECA3Client extends EventEmitter { this.emit(REFRESH_TOKEN_CHANGE_EVENT, payload); } + this.emit(API_REQUEST_LOG_EVENT, { + method: "POST", + endpoint: this.refreshTokenUrl, + success: response.ok, + timestamp: new Date().toISOString(), + errorMessage: response.ok ? undefined : responseJson.message, + }); + return responseJson.access_token; } catch (error) { + this.emit(API_REQUEST_LOG_EVENT, { + method: "POST", + endpoint: this.refreshTokenUrl, + success: false, + timestamp: new Date().toISOString(), + errorMessage: error.message, + }); throw new Error(`Error getting the Access Token: ${error}`); } } diff --git a/packages/sdk/src/custodianApi/eca3/ECA3CustodianApi.ts b/packages/sdk/src/custodianApi/eca3/ECA3CustodianApi.ts index 2778853f..ffa0471a 100644 --- a/packages/sdk/src/custodianApi/eca3/ECA3CustodianApi.ts +++ b/packages/sdk/src/custodianApi/eca3/ECA3CustodianApi.ts @@ -1,6 +1,7 @@ import { SimpleCache } from "@metamask-institutional/simplecache"; import { AuthTypes, + IApiCallLogEntry, ICustodianTransactionLink, IEIP1559TxParams, ILegacyTXParams, @@ -11,12 +12,14 @@ import { } from "@metamask-institutional/types"; import { EventEmitter } from "events"; import { SignedMessageMetadata } from "src/types/SignedMessageMetadata"; -import { SignedMessageParams } from "src/types/SignedMessageParams"; import { SignedTypedMessageMetadata } from "src/types/SignedTypedMessageMetadata"; -import { SignedTypedMessageParams } from "src/types/SignedTypedMessageParams"; import { AccountHierarchyNode } from "../../classes/AccountHierarchyNode"; -import { INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, REFRESH_TOKEN_CHANGE_EVENT } from "../../constants/constants"; +import { + API_REQUEST_LOG_EVENT, + INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, + REFRESH_TOKEN_CHANGE_EVENT, +} from "../../constants/constants"; import { ICustodianApi } from "../../interfaces/ICustodianApi"; import { IEthereumAccount } from "../../interfaces/IEthereumAccount"; import { IEthereumAccountCustodianDetails } from "../../interfaces/IEthereumAccountCustodianDetails"; @@ -25,7 +28,6 @@ import { CreateTransactionMetadata } from "../../types/CreateTransactionMetadata import { ECA3Client } from "./ECA3Client"; import { JsonRpcTransactionParams } from "./rpc-payloads/JsonRpcCreateTransactionPayload"; import { JsonRpcReplaceTransactionParams } from "./rpc-payloads/JsonRpcReplaceTransactionPayload"; -import { JsonRpcListAccountsSignedResponse } from "./rpc-responses/JsonRpcListAccountsSignedResponse"; import { hexlify } from "./util/hexlify"; import { mapStatusObjectToStatusText } from "./util/mapStatusObjectToStatusText"; @@ -55,6 +57,10 @@ export class ECA3CustodianApi extends EventEmitter implements ICustodianApi { this.client.on(INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, event => { this.emit(INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, event); }); + + this.client.on(API_REQUEST_LOG_EVENT, (event: IApiCallLogEntry) => { + this.emit(API_REQUEST_LOG_EVENT, event); + }); } getAccountHierarchy(): Promise { diff --git a/packages/sdk/src/custodianApi/eca3/util/json-rpc-call.test.ts b/packages/sdk/src/custodianApi/eca3/util/json-rpc-call.test.ts index 457713b7..5789de1c 100644 --- a/packages/sdk/src/custodianApi/eca3/util/json-rpc-call.test.ts +++ b/packages/sdk/src/custodianApi/eca3/util/json-rpc-call.test.ts @@ -13,7 +13,7 @@ describe("json-rpc-call", () => { describe("json-rpc-call", () => { it("should call the JSON RPC endpoint with the appropriate method and parameters", async () => { fetchMock.mockResponseOnce(JSON.stringify({ result: "test" })); - const call = factory("http://test/json-rpc"); + const call = factory("http://test/json-rpc", jest.fn()); await call("test", { some: "parameter" }, "access_token"); @@ -37,7 +37,7 @@ describe("json-rpc-call", () => { }), ); - const call = factory("http://test/json-rpc"); + const call = factory("http://test/json-rpc", jest.fn()); await expect(call("test", { some: "parameter" }, "access_token")).rejects.toThrow("Test error"); }); diff --git a/packages/sdk/src/custodianApi/eca3/util/json-rpc-call.ts b/packages/sdk/src/custodianApi/eca3/util/json-rpc-call.ts index 39c7b0dc..ffe58fff 100644 --- a/packages/sdk/src/custodianApi/eca3/util/json-rpc-call.ts +++ b/packages/sdk/src/custodianApi/eca3/util/json-rpc-call.ts @@ -1,7 +1,10 @@ +import { IApiCallLogEntry } from "@metamask-institutional/types"; + +import { API_REQUEST_LOG_EVENT } from "../../../constants/constants"; import { JsonRpcError } from "../interfaces/JsonRpcError"; import { JsonRpcResult } from "../interfaces/JsonRpcResult"; -export default function (jsonRpcEndpoint: string) { +export default function (jsonRpcEndpoint: string, emit: (eventName: string, eventData: IApiCallLogEntry) => void) { let requestId = 0; return async function jsonRpcCall(method: string, params: T1, accessToken: string): Promise { @@ -30,6 +33,16 @@ export default function (jsonRpcEndpoint: string) { responseJson = await response.json(); + emit(API_REQUEST_LOG_EVENT, { + id: requestId, + method, + endpoint: jsonRpcEndpoint, + success: !responseJson.error, + timestamp: new Date().toISOString(), + errorMessage: responseJson.error ? responseJson.error.message : undefined, + responseData: responseJson.result, + }); + if ((responseJson as JsonRpcError).error) { console.log("JSON-RPC <", method, requestId, responseJson, jsonRpcEndpoint); throw new Error((responseJson as JsonRpcError).error.message); @@ -42,6 +55,16 @@ export default function (jsonRpcEndpoint: string) { console.log("JSON-RPC <", method, requestId, e, jsonRpcEndpoint); + emit(API_REQUEST_LOG_EVENT, { + id: requestId, + method, + endpoint: jsonRpcEndpoint, + success: false, + timestamp: new Date().toISOString(), + errorMessage: e.message, + responseData: null, + }); + throw e; } diff --git a/packages/sdk/src/custodianApi/json-rpc/JsonRpcClient.ts b/packages/sdk/src/custodianApi/json-rpc/JsonRpcClient.ts index a875e14e..df71a1dd 100644 --- a/packages/sdk/src/custodianApi/json-rpc/JsonRpcClient.ts +++ b/packages/sdk/src/custodianApi/json-rpc/JsonRpcClient.ts @@ -3,7 +3,11 @@ import { IRefreshTokenChangeEvent } from "@metamask-institutional/types"; import crypto from "crypto"; import { EventEmitter } from "events"; -import { INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, REFRESH_TOKEN_CHANGE_EVENT } from "../../constants/constants"; +import { + API_REQUEST_LOG_EVENT, + INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, + REFRESH_TOKEN_CHANGE_EVENT, +} from "../../constants/constants"; import { JsonRpcResult } from "./interfaces/JsonRpcResult"; import { JsonRpcCreateTransactionPayload } from "./rpc-payloads/JsonRpcCreateTransactionPayload"; import { JsonRpcGetSignedMessageByIdPayload } from "./rpc-payloads/JsonRpcGetSignedMessageByIdPayload"; @@ -33,7 +37,7 @@ export class JsonRpcClient extends EventEmitter { constructor(private apiBaseUrl: string, private refreshToken: string, private refreshTokenUrl: string) { super(); - this.call = factory(`${apiBaseUrl}/v1/json-rpc`); + this.call = factory(`${this.apiBaseUrl}/v1/json-rpc`, this.emit.bind(this)); this.cache = new SimpleCache(); } @@ -127,8 +131,23 @@ export class JsonRpcClient extends EventEmitter { this.emit(REFRESH_TOKEN_CHANGE_EVENT, payload); } + this.emit(API_REQUEST_LOG_EVENT, { + method: "POST", + endpoint: this.refreshTokenUrl, + success: response.ok, + timestamp: new Date().toISOString(), + errorMessage: response.ok ? undefined : responseJson.message, + }); + return responseJson.access_token; } catch (error) { + this.emit(API_REQUEST_LOG_EVENT, { + method: "POST", + endpoint: this.refreshTokenUrl, + success: false, + timestamp: new Date().toISOString(), + errorMessage: error.message, + }); throw new Error(`Error getting the Access Token: ${error}`); } } diff --git a/packages/sdk/src/custodianApi/json-rpc/JsonRpcCustodianApi.ts b/packages/sdk/src/custodianApi/json-rpc/JsonRpcCustodianApi.ts index 6d125703..4c479b84 100644 --- a/packages/sdk/src/custodianApi/json-rpc/JsonRpcCustodianApi.ts +++ b/packages/sdk/src/custodianApi/json-rpc/JsonRpcCustodianApi.ts @@ -1,6 +1,7 @@ import { SimpleCache } from "@metamask-institutional/simplecache"; import { AuthTypes, + IApiCallLogEntry, ICustodianTransactionLink, IEIP1559TxParams, ILegacyTXParams, @@ -12,7 +13,11 @@ import { import { EventEmitter } from "events"; import { AccountHierarchyNode } from "../../classes/AccountHierarchyNode"; -import { INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, REFRESH_TOKEN_CHANGE_EVENT } from "../../constants/constants"; +import { + API_REQUEST_LOG_EVENT, + INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, + REFRESH_TOKEN_CHANGE_EVENT, +} from "../../constants/constants"; import { ICustodianApi } from "../../interfaces/ICustodianApi"; import { IEthereumAccount } from "../../interfaces/IEthereumAccount"; import { IEthereumAccountCustodianDetails } from "../../interfaces/IEthereumAccountCustodianDetails"; @@ -49,6 +54,10 @@ export class JsonRpcCustodianApi extends EventEmitter implements ICustodianApi { this.client.on(INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, event => { this.emit(INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, event); }); + + this.client.on(API_REQUEST_LOG_EVENT, (event: IApiCallLogEntry) => { + this.emit(API_REQUEST_LOG_EVENT, event); + }); } getAccountHierarchy(): Promise { diff --git a/packages/sdk/src/custodianApi/json-rpc/util/json-rpc-call.test.ts b/packages/sdk/src/custodianApi/json-rpc/util/json-rpc-call.test.ts index 457713b7..5789de1c 100644 --- a/packages/sdk/src/custodianApi/json-rpc/util/json-rpc-call.test.ts +++ b/packages/sdk/src/custodianApi/json-rpc/util/json-rpc-call.test.ts @@ -13,7 +13,7 @@ describe("json-rpc-call", () => { describe("json-rpc-call", () => { it("should call the JSON RPC endpoint with the appropriate method and parameters", async () => { fetchMock.mockResponseOnce(JSON.stringify({ result: "test" })); - const call = factory("http://test/json-rpc"); + const call = factory("http://test/json-rpc", jest.fn()); await call("test", { some: "parameter" }, "access_token"); @@ -37,7 +37,7 @@ describe("json-rpc-call", () => { }), ); - const call = factory("http://test/json-rpc"); + const call = factory("http://test/json-rpc", jest.fn()); await expect(call("test", { some: "parameter" }, "access_token")).rejects.toThrow("Test error"); }); diff --git a/packages/sdk/src/custodianApi/json-rpc/util/json-rpc-call.ts b/packages/sdk/src/custodianApi/json-rpc/util/json-rpc-call.ts index 39c7b0dc..ffe58fff 100644 --- a/packages/sdk/src/custodianApi/json-rpc/util/json-rpc-call.ts +++ b/packages/sdk/src/custodianApi/json-rpc/util/json-rpc-call.ts @@ -1,7 +1,10 @@ +import { IApiCallLogEntry } from "@metamask-institutional/types"; + +import { API_REQUEST_LOG_EVENT } from "../../../constants/constants"; import { JsonRpcError } from "../interfaces/JsonRpcError"; import { JsonRpcResult } from "../interfaces/JsonRpcResult"; -export default function (jsonRpcEndpoint: string) { +export default function (jsonRpcEndpoint: string, emit: (eventName: string, eventData: IApiCallLogEntry) => void) { let requestId = 0; return async function jsonRpcCall(method: string, params: T1, accessToken: string): Promise { @@ -30,6 +33,16 @@ export default function (jsonRpcEndpoint: string) { responseJson = await response.json(); + emit(API_REQUEST_LOG_EVENT, { + id: requestId, + method, + endpoint: jsonRpcEndpoint, + success: !responseJson.error, + timestamp: new Date().toISOString(), + errorMessage: responseJson.error ? responseJson.error.message : undefined, + responseData: responseJson.result, + }); + if ((responseJson as JsonRpcError).error) { console.log("JSON-RPC <", method, requestId, responseJson, jsonRpcEndpoint); throw new Error((responseJson as JsonRpcError).error.message); @@ -42,6 +55,16 @@ export default function (jsonRpcEndpoint: string) { console.log("JSON-RPC <", method, requestId, e, jsonRpcEndpoint); + emit(API_REQUEST_LOG_EVENT, { + id: requestId, + method, + endpoint: jsonRpcEndpoint, + success: false, + timestamp: new Date().toISOString(), + errorMessage: e.message, + responseData: null, + }); + throw e; } diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 6f8c34a5..346990a4 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -8,6 +8,7 @@ export { ICustodianApi } from "./interfaces/ICustodianApi"; export { REFRESH_TOKEN_CHANGE_EVENT, INTERACTIVE_REPLACEMENT_TOKEN_CHANGE_EVENT, + API_REQUEST_LOG_EVENT, DEFAULT_MAX_CACHE_AGE, } from "./constants/constants"; diff --git a/packages/types/src/IApiCallLogEntry.ts b/packages/types/src/IApiCallLogEntry.ts new file mode 100644 index 00000000..1dfe1da0 --- /dev/null +++ b/packages/types/src/IApiCallLogEntry.ts @@ -0,0 +1,9 @@ +export interface IApiCallLogEntry { + id?: number; + method: string; + endpoint: string; + success: boolean; + timestamp: string; + errorMessage?: string; + responseData?: any; +} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 5051f706..6a8ad88c 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -16,6 +16,7 @@ export { ITransactionStatusMap } from "./ITransactionStatusMap"; export { ICustodianAccount, IExtensionCustodianAccount } from "./ICustodianAccount"; export { IRefreshTokenChangeEvent } from "./IRefreshTokenChangeEvent"; export { IInteractiveRefreshTokenChangeEvent } from "./IInteractiveRefreshTokenChangeEvent"; +export { IApiCallLogEntry } from "./IApiCallLogEntry"; // Enums export { AuthTypes } from "./enum/AuthTypes";