From 389c4de125459a07d56ec7747beb9035d7ac3d4a Mon Sep 17 00:00:00 2001
From: Nik <2661899+CodeSchwert@users.noreply.github.com>
Date: Fri, 22 Sep 2023 11:33:05 +1200
Subject: [PATCH] [DX-2335] feat: Send checkout widgets version to analytics
service (#873)
---
.github/CODEOWNERS | 1 +
.../workflows/build-lint-typecheck-test.yaml | 3 +
package.json | 1 +
packages/checkout/widgets-lib/package.json | 1 +
.../src/widgets/ImmutableWebComponent.tsx | 3 +
packages/internal/analytics/.eslintrc | 8 ++
packages/internal/analytics/README.md | 7 ++
packages/internal/analytics/jest.config.ts | 17 +++
packages/internal/analytics/package.json | 41 +++++++
packages/internal/analytics/rollup.config.js | 10 ++
packages/internal/analytics/src/index.ts | 1 +
.../checkout-widgets-test/README.md | 49 ++++++++
.../checkout-widgets-test/index.html | 11 ++
.../analytics/src/version-check/index.ts | 1 +
.../src/version-check/localStorage.test.ts | 46 ++++++++
.../src/version-check/localStorage.ts | 57 +++++++++
.../src/version-check/versionCheck.test.ts | 60 ++++++++++
.../src/version-check/versionCheck.ts | 94 +++++++++++++++
packages/internal/analytics/tsconfig.json | 111 ++++++++++++++++++
sdk/package.json | 1 +
yarn.lock | 19 +++
21 files changed, 542 insertions(+)
create mode 100644 packages/internal/analytics/.eslintrc
create mode 100644 packages/internal/analytics/README.md
create mode 100644 packages/internal/analytics/jest.config.ts
create mode 100644 packages/internal/analytics/package.json
create mode 100644 packages/internal/analytics/rollup.config.js
create mode 100644 packages/internal/analytics/src/index.ts
create mode 100644 packages/internal/analytics/src/version-check/checkout-widgets-test/README.md
create mode 100644 packages/internal/analytics/src/version-check/checkout-widgets-test/index.html
create mode 100644 packages/internal/analytics/src/version-check/index.ts
create mode 100644 packages/internal/analytics/src/version-check/localStorage.test.ts
create mode 100644 packages/internal/analytics/src/version-check/localStorage.ts
create mode 100644 packages/internal/analytics/src/version-check/versionCheck.test.ts
create mode 100644 packages/internal/analytics/src/version-check/versionCheck.ts
create mode 100644 packages/internal/analytics/tsconfig.json
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 3c6c8f0bd0..14620ec1c7 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,6 +1,7 @@
/sdk @immutable/developer-experience
/packages/immutablex_client @immutable/developer-experience
/packages/config @immutable/developer-experience
+/packages/internal/analytics @immutable/developer-experience
/packages/internal/generated-clients @immutable/developer-experience
/packages/internal/toolkit @immutable/wallets
/packages/internal/cryptofiat @immutable/wallets
diff --git a/.github/workflows/build-lint-typecheck-test.yaml b/.github/workflows/build-lint-typecheck-test.yaml
index c320b82cb2..ab02a08f9d 100644
--- a/.github/workflows/build-lint-typecheck-test.yaml
+++ b/.github/workflows/build-lint-typecheck-test.yaml
@@ -49,6 +49,9 @@ jobs:
- name: Install dependencies
run: yarn install --immutable
+ - name: Build
+ run: yarn build
+
- name: Test
run: yarn test
diff --git a/package.json b/package.json
index dcd94b82d6..cb53bc9371 100644
--- a/package.json
+++ b/package.json
@@ -66,6 +66,7 @@
"packages/provider",
"packages/provider/src/sample-app",
"packages/orderbook",
+ "packages/internal/analytics",
"packages/internal/contracts",
"packages/internal/toolkit",
"packages/internal/cryptofiat",
diff --git a/packages/checkout/widgets-lib/package.json b/packages/checkout/widgets-lib/package.json
index 58554676b1..e8c8824d97 100644
--- a/packages/checkout/widgets-lib/package.json
+++ b/packages/checkout/widgets-lib/package.json
@@ -17,6 +17,7 @@
"@biom3/design-tokens": "0.2.4-beta",
"@biom3/react": "^0.9.17-beta",
"@ethersproject/providers": "^5.7.2",
+ "@imtbl/analytics": "0.0.0",
"@imtbl/bridge-sdk": "0.0.0",
"@imtbl/checkout-sdk": "0.0.0",
"@imtbl/checkout-widgets": "0.0.0",
diff --git a/packages/checkout/widgets-lib/src/widgets/ImmutableWebComponent.tsx b/packages/checkout/widgets-lib/src/widgets/ImmutableWebComponent.tsx
index f170d4ba1f..16050ff224 100644
--- a/packages/checkout/widgets-lib/src/widgets/ImmutableWebComponent.tsx
+++ b/packages/checkout/widgets-lib/src/widgets/ImmutableWebComponent.tsx
@@ -1,5 +1,6 @@
import ReactDOM from 'react-dom/client';
import { Web3Provider } from '@ethersproject/providers';
+import { sdkVersionCheck, sdkVersion } from '@imtbl/analytics';
import { Checkout } from '@imtbl/checkout-sdk';
import { Passport } from '@imtbl/passport';
import { StrongCheckoutWidgetsConfig, withDefaultWidgetConfigs } from '../lib/withDefaultWidgetConfig';
@@ -44,6 +45,8 @@ export abstract class ImmutableWebComponent extends HTMLElement {
const widgetConfig = this.getAttribute('widgetconfig') || undefined;
this.widgetConfig = this.parseWidgetConfig(widgetConfig);
this.updateCheckout();
+ // Leave version at the end so the widgets will load even if the next call fails
+ sdkVersionCheck('checkout-widgets', sdkVersion);
}
private parseWidgetConfig(widgetsConfig?: string): StrongCheckoutWidgetsConfig {
diff --git a/packages/internal/analytics/.eslintrc b/packages/internal/analytics/.eslintrc
new file mode 100644
index 0000000000..9b6c8a5aef
--- /dev/null
+++ b/packages/internal/analytics/.eslintrc
@@ -0,0 +1,8 @@
+{
+ "extends": ["../../../.eslintrc"],
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "project": "./tsconfig.json",
+ "tsconfigRootDir": "."
+ }
+}
diff --git a/packages/internal/analytics/README.md b/packages/internal/analytics/README.md
new file mode 100644
index 0000000000..6a6b1f22d9
--- /dev/null
+++ b/packages/internal/analytics/README.md
@@ -0,0 +1,7 @@
+# Analytics
+
+Internal analytics package,
+
+## Version Check
+
+The version check is a simple function that checks the current version of the SDK.
diff --git a/packages/internal/analytics/jest.config.ts b/packages/internal/analytics/jest.config.ts
new file mode 100644
index 0000000000..db762b107d
--- /dev/null
+++ b/packages/internal/analytics/jest.config.ts
@@ -0,0 +1,17 @@
+import type { Config } from 'jest';
+
+const config: Config = {
+ clearMocks: true,
+ coverageProvider: 'v8',
+ moduleDirectories: ['node_modules', 'src'],
+ testEnvironment: 'jsdom',
+ transform: {
+ '^.+\\.(t|j)sx?$': '@swc/jest',
+ },
+ transformIgnorePatterns: [],
+ testEnvironmentOptions: {
+ url: 'http://localhost',
+ },
+};
+
+export default config;
diff --git a/packages/internal/analytics/package.json b/packages/internal/analytics/package.json
new file mode 100644
index 0000000000..b696fbc7d0
--- /dev/null
+++ b/packages/internal/analytics/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "@imtbl/analytics",
+ "description": "Analytics module for Immutable SDK",
+ "version": "0.0.0",
+ "author": "Immutable",
+ "bugs": "https://github.com/immutable/ts-immutable-sdk/issues",
+ "dependencies": {
+ "axios": "^1.3.5"
+ },
+ "devDependencies": {
+ "@rollup/plugin-typescript": "^11.0.0",
+ "@swc/jest": "^0.2.24",
+ "@types/jest": "^29.4.3",
+ "eslint": "^8.40.0",
+ "http-server": "^14.1.1",
+ "jest": "^29.4.3",
+ "jest-environment-jsdom": "^29.4.3",
+ "rollup": "^3.17.2",
+ "typescript": "^4.9.5"
+ },
+ "engines": {
+ "node": ">=16.11.0"
+ },
+ "files": [
+ "dist"
+ ],
+ "homepage": "https://github.com/immutable/ts-immutable-sdk#readme",
+ "main": "dist/index.js",
+ "private": true,
+ "repository": "immutable/ts-immutable-sdk.git",
+ "scripts": {
+ "build": "NODE_ENV=production rollup --config rollup.config.js",
+ "lint": "eslint ./src --ext .ts,.jsx,.tsx --max-warnings=0",
+ "start:checkout-js-server": "http-server -p 8080 -c-1 ../../../sdk/dist",
+ "start:checkout-web-server": "http-server -p 8081 -c-1 ./src/version-check/checkout-widgets-test",
+ "test": "jest",
+ "typecheck": "tsc --noEmit --jsx preserve"
+ },
+ "type": "module",
+ "types": "dist/index.d.ts"
+}
diff --git a/packages/internal/analytics/rollup.config.js b/packages/internal/analytics/rollup.config.js
new file mode 100644
index 0000000000..16a7d58d7e
--- /dev/null
+++ b/packages/internal/analytics/rollup.config.js
@@ -0,0 +1,10 @@
+import typescript from '@rollup/plugin-typescript';
+
+export default {
+ input: 'src/index.ts',
+ output: {
+ dir: 'dist',
+ format: 'es',
+ },
+ plugins: [typescript()],
+};
diff --git a/packages/internal/analytics/src/index.ts b/packages/internal/analytics/src/index.ts
new file mode 100644
index 0000000000..04b08a9a2e
--- /dev/null
+++ b/packages/internal/analytics/src/index.ts
@@ -0,0 +1 @@
+export { sdkVersionCheck, sdkVersion } from './version-check';
diff --git a/packages/internal/analytics/src/version-check/checkout-widgets-test/README.md b/packages/internal/analytics/src/version-check/checkout-widgets-test/README.md
new file mode 100644
index 0000000000..13ffd344f1
--- /dev/null
+++ b/packages/internal/analytics/src/version-check/checkout-widgets-test/README.md
@@ -0,0 +1,49 @@
+# Checkout Widgets (Manual) Test Site
+
+This is a manual test site for the checkout widgets. It is used to test the `sdkVersionCheck` function called by checkout widgets in a local environment.
+
+The run the site, you need to start a local web server to host the built JS bundle, and another web server to host the test website.
+
+## Usage
+
+1. Update the target endpoint the checkout bundle will send version check requests to.
+
+ - Find the `packages/internal/analytics/version-check/versionCheck.ts` file.
+ - Update the `imtblApi` variable (near the top of the file) to point to the endpoint you want to send the version check requests to.
+ - Suggest using something like `https://webhook.site/` or a local webserver setup to log requests.
+
+2. Build the SDK:
+
+ ```bash
+ # from the root of the SDK repo
+ yarn build
+ ```
+
+2. Start the JS bundle server:
+
+ ```bash
+ # in the packages/internal/analytics directory start the JS server
+ start:checkout-js-server
+ ```
+
+3. Open a browser and navigate to `http://127.0.0.1:8080/browser/checkout.js` to confirm the JS bundle is hosted correctly.
+
+ - Search for `"checkout-widgets","0.0.0"` in the JS bundle to confirm the version number is correct.
+ - It should be `0.0.0` because the version number for the SDK is not updated in the `package.json` file.
+
+4. Start a web server to host the built JS bundle:
+
+ ```bash
+ # in the packages/internal/analytics directory
+ start:checkout-web-server
+ ```
+
+5. Open a browser and navigate to `http://127.0.0.1:8081/` to confirm the test site is hosted correctly.
+
+ - You should see a title that says `Welcome to the Checkout Widgets Test Page` and the `Connect a wallet` widget loaded on the page.
+
+6. Check the version check request was sent to the endpoint you configured in step 2.
+
+## Cleanup
+
+Remember to revert the changes to the `packages/internal/analytics/version-check/versionCheck.ts` file.
diff --git a/packages/internal/analytics/src/version-check/checkout-widgets-test/index.html b/packages/internal/analytics/src/version-check/checkout-widgets-test/index.html
new file mode 100644
index 0000000000..0f85ae0abc
--- /dev/null
+++ b/packages/internal/analytics/src/version-check/checkout-widgets-test/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Checkout Widgets
+
+
+
+ Welcome to the Checkout Widgets Test Page
+
+
+
\ No newline at end of file
diff --git a/packages/internal/analytics/src/version-check/index.ts b/packages/internal/analytics/src/version-check/index.ts
new file mode 100644
index 0000000000..08a29e0b28
--- /dev/null
+++ b/packages/internal/analytics/src/version-check/index.ts
@@ -0,0 +1 @@
+export { sdkVersionCheck, sdkVersion } from './versionCheck';
diff --git a/packages/internal/analytics/src/version-check/localStorage.test.ts b/packages/internal/analytics/src/version-check/localStorage.test.ts
new file mode 100644
index 0000000000..c0e18802e0
--- /dev/null
+++ b/packages/internal/analytics/src/version-check/localStorage.test.ts
@@ -0,0 +1,46 @@
+import {
+ deleteItem,
+ getItem,
+ setItem,
+} from './localStorage';
+
+beforeEach(() => {
+ global.localStorage.clear();
+});
+
+describe('getItem', () => {
+ test('it should not return a value that does not exist', () => {
+ const value = getItem('test');
+ expect(value).toBe(undefined);
+ });
+ test('it should return a string value when stored', () => {
+ global.localStorage.setItem('__IMX-test', 'some value');
+ expect(getItem('test')).toBe('some value');
+ });
+});
+
+describe('setItem', () => {
+ test('it should store items in a namespaced key', () => {
+ setItem('test', 1);
+ expect(global.localStorage.getItem('__IMX-test')).toBe('1');
+ });
+
+ test('it should serialise an object accurately when storing', () => {
+ const returnVal = setItem('test', { a: 1, b: 'hello' });
+ expect(global.localStorage.getItem('__IMX-test')).toBe(
+ JSON.stringify({ a: 1, b: 'hello' }),
+ );
+ expect(returnVal).toBe(true);
+ });
+});
+
+describe('deleteItem', () => {
+ test('should remove item that is stored', () => {
+ global.localStorage.setItem('__IMX-test', 'test');
+ deleteItem('test');
+ expect(global.localStorage.getItem('__IMX--test')).toBeNull();
+ });
+ test('should do nothing if key not stored', () => {
+ expect(() => global.localStorage.getItem('__IMX-random')).not.toThrow();
+ });
+});
diff --git a/packages/internal/analytics/src/version-check/localStorage.ts b/packages/internal/analytics/src/version-check/localStorage.ts
new file mode 100644
index 0000000000..6f44e46e6a
--- /dev/null
+++ b/packages/internal/analytics/src/version-check/localStorage.ts
@@ -0,0 +1,57 @@
+/**
+ * Abstraction on localstorage
+ */
+
+const localStoragePrefix = '__IMX-';
+
+const hasLocalstorage = () => typeof window !== 'undefined' && window.localStorage;
+
+const parseItem = (payload: string | null) => {
+ // Try to parse, if can't be parsed assume string
+ // and return string
+ if (!payload) return undefined;
+
+ try {
+ return JSON.parse(payload);
+ } catch (error) {
+ return payload;
+ }
+};
+
+const serialiseItem = (payload: any) => {
+ if (typeof payload === 'string') {
+ return payload;
+ }
+ return JSON.stringify(payload);
+};
+
+/**
+ * GenKey will take into account the namespace
+ * as well as if being run in the Link, it will tap into the link
+ * @param {string} key
+ * @returns key
+ */
+const genKey = (key: string) => `${localStoragePrefix}${key}`;
+
+export const getItem = (key: string): any => {
+ if (hasLocalstorage()) {
+ return parseItem(window.localStorage.getItem(genKey(key)));
+ }
+ return undefined;
+};
+
+export const setItem = (key: string, payload: any): boolean => {
+ if (hasLocalstorage()) {
+ window.localStorage.setItem(genKey(key), serialiseItem(payload));
+ return true;
+ }
+ return false;
+};
+
+export const deleteItem = (key: string): boolean => {
+ if (hasLocalstorage()) {
+ window.localStorage.removeItem(genKey(key));
+ return true;
+ }
+ return false;
+};
diff --git a/packages/internal/analytics/src/version-check/versionCheck.test.ts b/packages/internal/analytics/src/version-check/versionCheck.test.ts
new file mode 100644
index 0000000000..914eb7af28
--- /dev/null
+++ b/packages/internal/analytics/src/version-check/versionCheck.test.ts
@@ -0,0 +1,60 @@
+import axios from 'axios';
+import { sdkVersionCheck } from './versionCheck';
+
+jest.mock('axios');
+
+describe('sdkVersionCheck', () => {
+ test('should now throw errors', () => {
+ expect(() => sdkVersionCheck('test-package', '1.0.0')).not.toThrow();
+ expect(() => sdkVersionCheck()).not.toThrow();
+ });
+
+ test('should send request to analytics API', () => {
+ const defaultApi = 'https://api.x.immutable.com';
+ const defaultVersionApi = '/v1/check';
+
+ sdkVersionCheck();
+
+ expect(axios.get).toHaveBeenCalledTimes(1);
+ expect(axios.get).toHaveBeenCalledWith(expect.stringContaining(`${defaultApi}${defaultVersionApi}`));
+ });
+
+ test('should include SDK version', () => {
+ const defaultApi = 'https://api.x.immutable.com';
+ const defaultVersionApi = '/v1/check';
+ const sdkVersion = '__SDK_VERSION__';
+ const expectedUrl = `${defaultApi}${defaultVersionApi}`;
+ const expectedQueryParams = `?version=imtbl-sdk-${sdkVersion}`;
+
+ sdkVersionCheck();
+
+ expect(axios.get).toHaveBeenCalledTimes(1);
+ expect(axios.get).toHaveBeenCalledWith(expect.stringContaining(`${expectedUrl}${expectedQueryParams}`));
+ });
+
+ test('should send details query parameter', () => {
+ sdkVersionCheck();
+
+ expect(axios.get).toHaveBeenCalledTimes(1);
+ expect(axios.get).toHaveBeenCalledWith(expect.stringContaining('&details='));
+ });
+
+ test('should not send id query parameters if runtimeId is not set', () => {
+ sdkVersionCheck();
+
+ expect(axios.get).toHaveBeenCalledTimes(1);
+ expect(axios.get).toHaveBeenCalledWith(expect.not.stringContaining('&id='));
+ });
+
+ test('should send app name and version number', () => {
+ const sdkVersion = '__SDK_VERSION__';
+ const packageName = 'test-package';
+ const packageVersion = '1.0.0';
+ const expectedQueryParams = `?version=imtbl-sdk-${sdkVersion},${packageName}-${packageVersion}`;
+
+ sdkVersionCheck(packageName, packageVersion);
+
+ expect(axios.get).toHaveBeenCalledTimes(1);
+ expect(axios.get).toHaveBeenCalledWith(expect.stringContaining(`${expectedQueryParams}`));
+ });
+});
diff --git a/packages/internal/analytics/src/version-check/versionCheck.ts b/packages/internal/analytics/src/version-check/versionCheck.ts
new file mode 100644
index 0000000000..b74b51c1dc
--- /dev/null
+++ b/packages/internal/analytics/src/version-check/versionCheck.ts
@@ -0,0 +1,94 @@
+import axios from 'axios';
+import { getItem, setItem } from './localStorage';
+
+export const imtblApi = process.env.IMTBL_API || 'https://api.x.immutable.com';
+export const versionApi = process.env.VERSION_API || '/v1/check';
+export const sdkVersion = '__SDK_VERSION__';
+
+const getReferrer = () => {
+ if (typeof window === 'undefined') {
+ return '';
+ }
+ if (
+ window.location.ancestorOrigins
+ && window.location.ancestorOrigins.length > 0
+ ) {
+ return new URL(window.location.ancestorOrigins[0]).hostname;
+ }
+
+ return document.referrer ? new URL(window.document.referrer).hostname : '';
+};
+
+const runtimeHost = () => {
+ if (typeof window === 'undefined') {
+ return '';
+ }
+ if (window.opener || window.parent !== window) {
+ return getReferrer();
+ }
+ return new URL(window.location.href).hostname;
+};
+
+const sdkRuntimeDetails = () => {
+ if (typeof window === 'undefined') {
+ return btoa(JSON.stringify({ browser: 'nodejs' }));
+ }
+
+ const idVal = JSON.stringify({
+ browser: window.navigator.userAgent,
+ domain: runtimeHost(),
+ tz: Intl.DateTimeFormat().resolvedOptions().timeZone,
+ screen: `${window.screen.width}x${window.screen.height}`,
+ });
+
+ return btoa(idVal);
+};
+
+const useRuntimeId = (runtimeId?: string) => {
+ // only run on browser
+ if (typeof window === 'undefined') {
+ return '';
+ }
+ const runtimeKey = 'runtimeid';
+ if (runtimeId) {
+ setItem(runtimeKey, runtimeId);
+ }
+ return getItem(runtimeKey) || '';
+};
+
+export const sdkVersionCheck = (appName?: string, appVersion?: string) => {
+ try {
+ const existingRuntimeId = useRuntimeId();
+ const runtimeDetails = sdkRuntimeDetails();
+ const versionParam = appName && appVersion
+ ? `version=imtbl-sdk-${sdkVersion},${appName}-${appVersion}`
+ : `version=imtbl-sdk-${sdkVersion}`;
+
+ const idParam = `id=${existingRuntimeId}`;
+ const detailsParam = `details=${runtimeDetails}`;
+
+ let versionCheckUrl = `${imtblApi}${versionApi}?${versionParam}&${detailsParam}`;
+ if (existingRuntimeId) {
+ versionCheckUrl += `&${idParam}`;
+ }
+
+ axios
+ .get(versionCheckUrl)
+ .then((response) => {
+ const { ok, message, runtimeId } = response.data;
+ if (!ok) {
+ // eslint-disable-next-line no-console
+ console.warn(
+ `Immutable SDK: ${message}\n\nPlease update the SDK to the latest version.`,
+ );
+ }
+ if (runtimeId) {
+ useRuntimeId(runtimeId);
+ }
+ })
+ .catch(() => {});
+ } catch (_) {
+ // eslint-disable-next-line no-console
+ console.warn('Immutable SDK: Unable to check for latest version.');
+ }
+};
diff --git a/packages/internal/analytics/tsconfig.json b/packages/internal/analytics/tsconfig.json
new file mode 100644
index 0000000000..db5668e055
--- /dev/null
+++ b/packages/internal/analytics/tsconfig.json
@@ -0,0 +1,111 @@
+{
+ "compilerOptions": {
+ /* Visit https://aka.ms/tsconfig to read more about this file */
+
+ /* Projects */
+ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
+ // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
+
+ /* Language and Environment */
+ "target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+ // "jsx": "preserve", /* Specify what JSX code is generated. */
+ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
+ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+ // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
+ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
+
+ /* Modules */
+ "module": "esnext", /* Specify what module code is generated. */
+ // "rootDir": "./src", /* Specify the root folder within your source files. */
+ "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
+ "baseUrl": "./src", /* Specify the base directory to resolve non-relative module names. */
+ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
+ "rootDirs": ["src"], /* Allow multiple folders to be treated as one when resolving modules. */
+ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
+ // "types": [], /* Specify type package names to be included without being referenced in a source file. */
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
+ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "resolveJsonModule": true, /* Enable importing .json files. */
+ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
+
+ /* JavaScript Support */
+ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
+ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+
+ /* Emit */
+ "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
+ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+ "outDir": "./dist", /* Specify an output folder for all emitted files. */
+ "removeComments": false, /* Disable emitting comments. */
+ // "noEmit": true, /* Disable emitting files from a compilation. */
+ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
+ // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+ // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
+ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
+ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+ /* Interop Constraints */
+ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
+ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
+ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
+
+ /* Type Checking */
+ "strict": true, /* Enable all strict type-checking options. */
+ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
+ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
+ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
+ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
+ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
+ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
+ // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
+ // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
+
+ /* Completeness */
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
+ "skipLibCheck": true, /* Skip type checking all .d.ts files. */
+
+ /* Advanced */
+ // "noEmit": true,
+ // "allowJs": false,
+ // "allowSyntheticDefaultImports": true,
+ // "resolveJsonModule": true,
+ },
+ "include": ["src"],
+ "exclude": ["dist", "jest.config.js", "node_modules"]
+}
diff --git a/sdk/package.json b/sdk/package.json
index f1b0b81962..095bd22286 100644
--- a/sdk/package.json
+++ b/sdk/package.json
@@ -27,6 +27,7 @@
"oidc-client-ts": "^2.2.1"
},
"devDependencies": {
+ "@imtbl/analytics": "0.0.0",
"@imtbl/blockchain-data": "0.0.0",
"@imtbl/checkout-sdk": "0.0.0",
"@imtbl/checkout-widgets": "0.0.0",
diff --git a/yarn.lock b/yarn.lock
index c02f201582..933d58a7ab 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3004,6 +3004,23 @@ __metadata:
languageName: node
linkType: hard
+"@imtbl/analytics@0.0.0, @imtbl/analytics@workspace:packages/internal/analytics":
+ version: 0.0.0-use.local
+ resolution: "@imtbl/analytics@workspace:packages/internal/analytics"
+ dependencies:
+ "@rollup/plugin-typescript": ^11.0.0
+ "@swc/jest": ^0.2.24
+ "@types/jest": ^29.4.3
+ axios: ^1.3.5
+ eslint: ^8.40.0
+ http-server: ^14.1.1
+ jest: ^29.4.3
+ jest-environment-jsdom: ^29.4.3
+ rollup: ^3.17.2
+ typescript: ^4.9.5
+ languageName: unknown
+ linkType: soft
+
"@imtbl/blockchain-data@0.0.0, @imtbl/blockchain-data@workspace:packages/blockchain-data/sdk":
version: 0.0.0-use.local
resolution: "@imtbl/blockchain-data@workspace:packages/blockchain-data/sdk"
@@ -3124,6 +3141,7 @@ __metadata:
"@biom3/design-tokens": 0.2.4-beta
"@biom3/react": ^0.9.17-beta
"@ethersproject/providers": ^5.7.2
+ "@imtbl/analytics": 0.0.0
"@imtbl/bridge-sdk": 0.0.0
"@imtbl/checkout-sdk": 0.0.0
"@imtbl/checkout-widgets": 0.0.0
@@ -3772,6 +3790,7 @@ __metadata:
"@ethersproject/abstract-signer": ^5.7.0
"@ethersproject/providers": ^5.7.2
"@ethersproject/wallet": ^5.7.0
+ "@imtbl/analytics": 0.0.0
"@imtbl/blockchain-data": 0.0.0
"@imtbl/checkout-sdk": 0.0.0
"@imtbl/checkout-widgets": 0.0.0