-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: add new analytics package, leather-io/issues#345
- Loading branch information
Showing
20 changed files
with
2,281 additions
and
607 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
nodejs 20.12.2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
SEGMENT_API_KEY='<your-segment-api-key>' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
extends: | ||
- '@leather.io/eslint-config' | ||
- universe/native | ||
parserOptions: | ||
project: ./tsconfig.json | ||
ignorePatterns: | ||
- .eslintrc.js | ||
- '*.js' | ||
rules: | ||
import/order: 0 | ||
no-void: 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# build | ||
.tsup | ||
# debug | ||
npm-debug.* | ||
yarn-debug.* | ||
yarn-error.* | ||
|
||
# macOS | ||
.DS_Store | ||
*.pem | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
dist-web/ | ||
dist-native/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# @leather/analytics | ||
|
||
This package provides a client for sending analytics events to various analytics services. Currently, it supports Segment but could be extended to support other services in the future. | ||
|
||
## Installation | ||
|
||
```bash | ||
pnpm install @leather/analytics | ||
``` | ||
|
||
## Usage | ||
|
||
Before making any analytics calls, you must configure the analytics client with your write key. | ||
|
||
```ts | ||
import { configureAnalyticsClient } from '@leather/analytics'; | ||
|
||
configureAnalyticsClient({ | ||
writeKey: 'YOUR_WRITE_KEY', | ||
defaultProperties: { | ||
platform: 'web', | ||
}, | ||
}); | ||
``` | ||
|
||
Now you can make analytics calls. | ||
|
||
```ts | ||
import { analyticsClient } from '@leather/analytics'; | ||
|
||
analyticsClient.track('My Event', { | ||
property: 'value', | ||
}); | ||
``` | ||
|
||
You can also inject your own analytics client if you are using a custom analytics service or want to use a stubbed client for testing. | ||
|
||
````ts | ||
import { configureAnalyticsClient } from '@leather/analytics'; | ||
|
||
configureAnalyticsClient({ | ||
client: myAnalyticsClient, | ||
}); | ||
|
||
## Development | ||
|
||
```bash | ||
pnpm build | ||
```` | ||
or | ||
```bash | ||
pnpm build:watch | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
{ | ||
"name": "@leather.io/analytics", | ||
"author": "leather.io", | ||
"description": "Analytics package for Leather using Segment", | ||
"version": "0.0.1", | ||
"license": "MIT", | ||
"type": "module", | ||
"scripts": { | ||
"build": "pnpm build:native && pnpm build:web", | ||
"build:native": "tsup --config tsup.config.native.ts", | ||
"build:watch": "concurrently \"pnpm build:native --watch\" \"pnpm build:web --watch\" ", | ||
"build:web": "tsup --config tsup.config.web.ts", | ||
"format": "prettier . --write \"src/**/*.ts\" --ignore-path ../../.prettierignore", | ||
"format:check": "prettier . --check \"src/**/*.ts\" --ignore-path ../../.prettierignore", | ||
"lint": "eslint . --ignore-path ../../.eslintignore", | ||
"lint:fix": "eslint . --fix --ignore-path ../../.eslintignore", | ||
"typecheck": "tsc --noEmit --project ./tsconfig.json" | ||
}, | ||
"files": [ | ||
"dist-web", | ||
"dist-native" | ||
], | ||
"exports": { | ||
".": { | ||
"import": "./dist-web/src/index.web.js", | ||
"require": "./dist-web/src/index.web.js", | ||
"types": "./dist-web/src/index.web.d.ts" | ||
}, | ||
"./native": { | ||
"import": "./dist-native/index.native.js", | ||
"require": "./dist-native/index.native.js", | ||
"types": "./dist-native/index.native.d.ts" | ||
} | ||
}, | ||
"devDependencies": { | ||
"@leather.io/eslint-config": "workspace:*", | ||
"@types/node": "20.14.0", | ||
"concurrently": "8.2.2", | ||
"eslint": "8.53.0", | ||
"eslint-config-universe": "12.0.0", | ||
"prettier": "3.3.3", | ||
"tsup": "8.1.0", | ||
"typescript": "5.5.4" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"dependencies": { | ||
"@segment/analytics-next": "1.73.0", | ||
"@segment/analytics-react-native": "2.19.5" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import { AnalyticsClientConfig, GenericAnalyticsClient, JsonMap } from '../utils/types.shared'; | ||
|
||
export type AnalyticsClientOptions = Pick< | ||
AnalyticsClientConfig, | ||
'defaultProperties' | 'defaultTraits' | ||
>; | ||
|
||
export class AnalyticsClient<T extends GenericAnalyticsClient> { | ||
constructor( | ||
private readonly client: T, | ||
private readonly options: AnalyticsClientOptions | ||
) { | ||
this.client = client; | ||
this.options = options; | ||
} | ||
|
||
private async track(event: string, properties?: JsonMap) { | ||
return this.client.track(event, { ...properties, ...this.options.defaultProperties }); | ||
} | ||
|
||
public async screen(name: string, properties?: JsonMap) { | ||
return this.client.screen(name, { ...properties, ...this.options.defaultProperties }); | ||
} | ||
|
||
public async group(groupId: string, traits?: JsonMap) { | ||
return this.client.group(groupId, { ...traits, ...this.options.defaultTraits }); | ||
} | ||
|
||
public async identify(userId: string, traits?: JsonMap) { | ||
return this.client.identify(userId, { ...traits, ...this.options.defaultTraits }); | ||
} | ||
|
||
private errorToJsonMap(error: Error) { | ||
return { | ||
errorMessage: error.message, | ||
errorName: error.name, | ||
}; | ||
} | ||
|
||
// TODO: replace view_transaction_confirmation with this method call. | ||
public async trackViewTransactionConfirmation(properties: { symbol: string }) { | ||
return this.track('Transaction Confirmation Viewed', properties); | ||
} | ||
// TODO: replace ordinals_dot_com_unavailable with this method call. | ||
public async trackOrdinalsDotComUnavailable(properties: { error: Error }) { | ||
return this.track('Ordinals.com Unavailable', this.errorToJsonMap(properties.error)); | ||
} | ||
// TODO: replace select_maximum_amount_for_send with this method call. | ||
public async trackSelectMaximumAmountForSend() { | ||
return this.track('Send Amount Selected', { | ||
maximum: true, | ||
}); | ||
} | ||
// TODO: replace copy_recipient_bns_address_to_clipboard with this method call. | ||
public async trackCopyToClipboard(properties: { value: 'thing' | 'other-thing' }) { | ||
return this.track('Copy To Clipboard', { | ||
value: properties.value, | ||
}); | ||
} | ||
// TODO: replace broadcast_transaction with this method call. | ||
public async trackBroadcastTransaction(properties: { symbol: string }) { | ||
return this.track('Broadcast Transaction', properties); | ||
} | ||
// TODO: replace broadcast_btc_error with this method call. | ||
public async trackBroadcastBtcError(properties: { error: Error; symbol: string }) { | ||
const { error, ...rest } = properties; | ||
return this.track('Broadcast Transaction Error', { | ||
...this.errorToJsonMap(properties.error), | ||
...rest, | ||
}); | ||
} | ||
// TODO: replace request_signature_cancel with this method call. | ||
public async trackRequestSignatureCancel() { | ||
return this.track('Request Signature Canceled'); | ||
} | ||
// TODO: replace view_transaction_signing with this method call. | ||
public async trackViewTransactionSigning() { | ||
return this.track('Transaction Signing Viewed'); | ||
} | ||
// TODO: replace submit_fee_for_transaction with this method call. | ||
public async trackSubmitFeeForTransaction(properties: { | ||
calculation: string; | ||
fee: number | string; | ||
type: string; | ||
}) { | ||
return this.track('Transaction Fee Submitted', properties); | ||
} | ||
// TODO: replace request_update_profile_submit with this method call. | ||
// TODO: replace request_update_profile_cancel with this method call. | ||
public async trackRequestUpdateProfileSubmit(properties: { requestType: 'update' | 'cancel' }) { | ||
return this.track('Update Profile Requested', properties); | ||
} | ||
// TODO: replace non_compliant_entity_detected with this method call. | ||
public async trackNonCompliantEntityDetected(properties?: { address?: string }) { | ||
return this.track('Non Compliant Entity Detected', properties); | ||
} | ||
// TODO: replace requesting_origin_tab_closed_with_pending_action with this method call. | ||
public async trackRequestingOriginTabClosed(properties?: { status: 'action_pending' }) { | ||
return this.track('Origin Tab Closed Requested', properties); | ||
} | ||
// TODO: replace successfully_added_native_segwit_tx_hex_to_ledger_tx with this method call. | ||
// TODO: replace failed_to_add_native_segwit_tx_hex_to_ledger_tx with this method call. | ||
public async trackNativeSegwitTxHexToLedgerTx(properties: { success: boolean }) { | ||
return this.track('Native Segwit Transaction Hex to Ledger', properties); | ||
} | ||
// TODO: replace psbt_sign_request_p2tr_missing_taproot_internal_key with this method call. | ||
public async trackPsbtSignRequest(properties: { status: 'missing_taproot_internal_key' }) { | ||
return this.track('PSBT Sign Request', properties); | ||
} | ||
// TODO: replace ledger_nativesegwit_add_nonwitnessutxo with this method call. | ||
// TODO: replace ledger_nativesegwit_skip_add_nonwitnessutxo with this method call. | ||
public async trackLedgerNativesegwitAddNonwitnessUtxo(properties: { | ||
action: 'add_nonwitness_utxo' | 'skip_add_nonwitness_utxo'; | ||
}) { | ||
return this.track('Ledger Native Segwit UTXO Updated', properties); | ||
} | ||
// TODO: replace redux_persist_migration_to_no_serialization with this method call. | ||
public async trackReduxPersistMigrationToNoSerialization() { | ||
return this.track('Redux Persist to No Serialization Migrated'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { createClient } from '@segment/analytics-react-native'; | ||
import { AnalyticsClientConfig, GenericAnalyticsClient } from 'src/utils/types.shared'; | ||
|
||
import { AnalyticsClient } from './client/client'; | ||
|
||
let analyticsClient: AnalyticsClient<GenericAnalyticsClient>; | ||
|
||
/** | ||
* Configures the analytics client for the native environment. Must be called before any analytics functions are used. | ||
* @param {AnalyticsClientConfig} config - The configuration for the analytics client. | ||
* @returns {AnalyticsClient<SegmentClient>} The configured analytics client. | ||
*/ | ||
const configureAnalyticsClient = ({ | ||
writeKey, | ||
defaultProperties, | ||
client, | ||
}: AnalyticsClientConfig) => { | ||
const nativeClient = | ||
client ?? | ||
createClient({ | ||
writeKey, | ||
}); | ||
|
||
analyticsClient = new AnalyticsClient(nativeClient, { defaultProperties }); | ||
|
||
return analyticsClient; | ||
}; | ||
|
||
export { analyticsClient, configureAnalyticsClient }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { AnalyticsBrowser } from '@segment/analytics-next'; | ||
import { AnalyticsClientConfig, GenericAnalyticsClient } from 'src/utils/types.shared'; | ||
|
||
import { AnalyticsClient } from './client/client'; | ||
|
||
let analyticsClient: AnalyticsClient<GenericAnalyticsClient>; | ||
|
||
/** | ||
* Configures the analytics client for the web environment. Must be called before any analytics functions are used. | ||
* @param {AnalyticsClientConfig} config - The configuration for the analytics client. | ||
* @returns {AnalyticsClient<AnalyticsBrowser>} The configured analytics client. | ||
*/ | ||
const configureAnalyticsClient = ({ | ||
client, | ||
writeKey, | ||
defaultProperties, | ||
}: AnalyticsClientConfig) => { | ||
const webClient = client ?? AnalyticsBrowser.load({ writeKey }); | ||
|
||
analyticsClient = new AnalyticsClient(webClient, { defaultProperties }); | ||
|
||
return analyticsClient; | ||
}; | ||
|
||
export { analyticsClient, configureAnalyticsClient }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { AnalyticsBrowser } from '@segment/analytics-next/dist/types/browser'; | ||
import { SegmentClient } from '@segment/analytics-react-native/lib/typescript/src/analytics'; | ||
|
||
export interface DefaultProperties { | ||
platform: 'web' | 'extension' | 'mobile'; | ||
} | ||
|
||
export interface AnalyticsClientConfig { | ||
writeKey: string; | ||
client: GenericAnalyticsClient; | ||
defaultProperties: DefaultProperties; | ||
defaultTraits?: Record<string, JsonValue>; | ||
} | ||
|
||
export interface AnalyticsClientInterface { | ||
track: (event: string, properties?: JsonMap) => Promise<void>; | ||
screen: (name: string, properties?: JsonMap) => Promise<void>; | ||
group: (groupId: string, traits?: JsonMap) => Promise<void>; | ||
identify: (userId: string, traits?: JsonMap) => Promise<void>; | ||
} | ||
|
||
export type GenericAnalyticsClient = SegmentClient | AnalyticsBrowser | AnalyticsClientInterface; | ||
|
||
export type JsonValue = boolean | number | string | null | JsonList | JsonMap | undefined; | ||
|
||
export interface JsonMap { | ||
[key: string]: JsonValue; | ||
[index: number]: JsonValue; | ||
} | ||
|
||
export type JsonList = JsonValue[]; |
Oops, something went wrong.