Skip to content

Commit c3667f6

Browse files
mchappellwklos-iohkshawnbusuttilljagielagreatertomi
authored
feat: [LW-8901] paper wallet
* build: add paper wallet dependencies * chore: add paper wallet translations * feat(extension): add pgp utility functions * feat(extension): update posthog experiment provider and feature flag manager * docs: add paper wallet flow typings * feat(extension): add whitespace replacement utility function * feat(extension): add paper wallet pdf generation functionality * feat: update existing wallet flows * feat: add paper wallet creation flow * feat: add paper wallet restoration flow * feat(extension): add paper wallet regeneration from settings * fix: exclude wallet template file from sonarcloud as incorrectly identifies security risk * test(extension): add test ids to ChooseRecoveryMethod.tx * test(extension): update existing onboarding tests after paper wallet implementation * test(extension): update existing analytics tests after paper wallet implementation * test(extension): update existing 'add new wallet' tests after paper wallet implementation * fix: add optional chaining when fetching feature flag posthog properties * refactor(extension): remove duplication of pgp public key handler * fix(extension): wait for full scan before trying to decode message * feat(extension): update wallet ada balance calculation for paper wallet overview * feat(extension): implement paper wallet feature analytics * chore: use latest lace-ui-toolkit package * fix: correct styling for print icon when used in button * fix: correct missing pgp public key validation messages * feat(extension): update wallet overview to shown additional balances * feat: remove excess feature flag checks and align single timeline for mnemonics * fix(extension): use formatted name for paper wallet download * fix: save validation to state to avoid rechecking on component remount * fix: use correct analytics events for recovery method selection * fix: camera release when navigating between other screens * fixup! feat(extension): implement paper wallet feature analytics * fix: coalesce cta condition into memoised variable * fix: remove duplicate onClick handler for restoration method * fix(extension): correct video display * feat(extension): update wallet overview display * feat(extension): add additional constraint on additional public key data regex * fix(extension): use whitespace replacement with underscore for paper wallet filename * fix: display correct timeline step for save paper wallet stage * fix: clear validation and only validate file name if upload success * fix: reset validation and pgp info state on tab change * fix: reset pgp validation state on stage change * fix(core): update paper wallet info card border width * style: extract inline styling into classnames * feat(extension): add warning modal for paper wallet closure * fix(extension): display coingecko credit once loading complete * feat(extension): simplify pgp public key validation * refactor: update pdf base template * fix: remove pgp info on restoration * refactor: adjust styles for pgp text area * fix: scrub data * feat(extension): add exit warning modal for paper wallet settings drawer * feat(extension): add copy icon to restore wallet overview * test(extension): update pgp checks * feat(extension): update restoration success clear clipboard on paste * test(extension): fix github token for e2e-split and set default values for some outputs (#1344) * test(extension): set default values for env variables in e2e-split (#1345) * test(extension): fix preprod_env name in e2e-split (#1347) * test(extension): do not reuse artifacts for e2e split (#1348) * fix: improve shared wallet related ui (#1346) * test(extension): new test lw-9095 (#1317) * test(extension): fix cardano services url in e2e split (#1349) * fix(core): display reward account and deposit for info action proposal procedures (#1340) * test(extension): use split e2e for daily regression (#1352) * test(extension): test maintenance 7 aug 2023 (#1356) * E2e add lace build artifact reuse and cancelling job (#1354) * test(extension): add option to run e2e tests on all networks (#1351) * fix(core): replaces Math.Random with window.crypto.getRandomValues implementation in simple-cipher (#1357) * chore: drop console logging in production (#1358) * chore: update lace-ui-toolkit version * chore: bump lace-ui-toolkit to 1.13.0 * chore: bump lace-ui-toolkit to 1.14.0 * fix: send-transaction password input label * refactor: update paper wallet copy * fix: remove paper wallet drawer warning modal * fix: update save paper wallet instruction * fix: revert to pgp entry on move back step * feat: add pgp validation messages * refactor: address styles * refactor: media selector always on top * fix: create paper wallet copy * feat(extension): update posthog paper wallet analytic events * feat(extension): camera error analytics event * feat(extension): restore flow paper wallet events * feat(extension): invert checks for scanning qr code * feat(extension): update pgp copy * feat(extension): update qr code scanning * feat(extension): prevent generate paper wallet from popup settings * feat(extension): add distinction between international and US paper sizing * feat(extension): update scanning and ending stream * feat: update analytic events * feat(extension): add fallback if price information or utxo provider not responding * fix: correct merge issue * fix: add missing useSecrets changes * fix: submit name on paper wallet creation * fix: use password.value for paper wallet settings * fix: redirect to assets page after adding a new wallet --------- Co-authored-by: wklos-iohk <wojciech.klos@iohk.io> Co-authored-by: shawnbusuttil <shawn-buzu@hotmail.co.uk> Co-authored-by: Lukasz Jagiela <12641433+ljagiela@users.noreply.github.com> Co-authored-by: John Oshalusi <john.oshalusi@iohk.io> Co-authored-by: Janusz Janus <janusz.janus@iohk.io> Co-authored-by: Emir Hodzic <emir.hodzich@gmail.com> Co-authored-by: Angel Castillo <Angel.Castillo@iohk.io> Co-authored-by: Martynas Kazlauskas <martynas.kazlauskas@iohk.io> Co-authored-by: przemyslaw.wlodek <przem.wlodek.github@gmail.com>
1 parent b5d4ef7 commit c3667f6

File tree

96 files changed

+3908
-390
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+3908
-390
lines changed

apps/browser-extension-wallet/package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"@lace/core": "0.1.0",
5757
"@lace/staking": "0.1.0",
5858
"@lace/translation": "0.1.0",
59+
"@pdfme/generator": "^4.0.2",
5960
"@react-rxjs/core": "^0.9.8",
6061
"@react-rxjs/utils": "^0.9.5",
6162
"@vespaiach/axios-fetch-adapter": "^0.3.0",
@@ -73,12 +74,15 @@
7374
"graphql-tag": "2.12.5",
7475
"i18next": "^22.5.1",
7576
"intersection-observer-polyfill": "0.1.0",
77+
"jsqr": "^1.4.0",
7678
"lodash": "4.17.21",
7779
"node-abort-controller": "^3.1.1",
80+
"openpgp": "^5.11.2",
7881
"p-debounce": "^4.0.0",
7982
"pluralize": "^8.0.0",
8083
"posthog-js": "^1.68.4",
8184
"process": "^0.11.10",
85+
"qrcode": "^1.5.3",
8286
"react": "17.0.2",
8387
"react-dom": "17.0.2",
8488
"react-i18next": "^12.3.1",
@@ -93,9 +97,14 @@
9397
"devDependencies": {
9498
"@cardano-sdk/hardware-ledger": "0.11.0",
9599
"@emurgo/cardano-message-signing-asmjs": "1.0.1",
100+
"@openpgp/web-stream-tools": "0.0.11-patch-0",
101+
"@pdfme/common": "^4.0.2",
102+
"@pdfme/schemas": "^4.0.2",
96103
"@types/dotenv-webpack": "7.0.3",
97104
"@types/pluralize": "^0.0.29",
105+
"@types/qrcode": "^1",
98106
"@types/react-lottie": "^1.2.6",
107+
"@types/text-encoding-utf-8": "^1",
99108
"@types/uuid": "^8.3.4",
100109
"@types/w3c-web-hid": "^1.0.3",
101110
"@types/webextension-polyfill": "0.8.0",
@@ -105,6 +114,7 @@
105114
"fake-indexeddb": "3.1.3",
106115
"fork-ts-checker-webpack-plugin": "^7.2.1",
107116
"jest-webextension-mock": "^3.7.19",
117+
"text-encoding-utf-8": "^1.0.2",
108118
"tsconfig-paths-webpack-plugin": "3.5.2",
109119
"webassembly-loader-sw": "^1.1.0"
110120
}

apps/browser-extension-wallet/src/lib/scripts/types/storage.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { AuthorizedDappStorage } from '@src/types/dappConnector';
22
import type { Message } from './background-service';
33
import { ADAPrices } from './prices';
4+
import { ExperimentName } from '@providers/ExperimentsProvider/types';
45

56
export interface PendingMigrationState {
67
from: string;
@@ -28,7 +29,7 @@ export interface BackgroundStorage {
2829
fiatPrices?: { prices: ADAPrices; timestamp: number };
2930
userId?: string;
3031
usePersistentUserId?: boolean;
31-
experimentsConfiguration?: Record<string, string | boolean>;
32+
experimentsConfiguration?: Record<ExperimentName, string | boolean>;
3233
customSubmitTxUrl?: string;
3334
}
3435

apps/browser-extension-wallet/src/providers/AnalyticsProvider/analyticsTracker/events/multi-wallet.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,25 @@ const makeMultiWalletRestoreEvent = <E extends string>(eventSuffix: E) =>
99
`multiwallet | restore wallet revamp | ${eventSuffix}` as const;
1010
const makeMultiWalletHardwareEvent = <E extends string>(eventSuffix: E) =>
1111
`multiwallet | hardware wallet revamp | ${eventSuffix}` as const;
12+
const makePaperWalletOnboardingCreateEvent = <E extends string>(eventSuffix: E) =>
13+
`onboarding | new wallet revamp paper wallet | ${eventSuffix}` as const;
14+
const makePaperWalletOnboardingRestoreEvent = <E extends string>(eventSuffix: E) =>
15+
`onboarding | restore wallet revamp paper wallet | ${eventSuffix}` as const;
1216

1317
const multiWalletActions = {
1418
create: {
19+
CHOOSE_RECOVERY_MODE_MNEMONIC_CLICK: makePaperWalletOnboardingCreateEvent('choose mode | recovery phrase | click'),
20+
CHOOSE_RECOVERY_MODE_PAPER_CLICK: makePaperWalletOnboardingCreateEvent('choose mode | paper wallet | click'),
21+
CHOOSE_RECOVERY_MODE_NEXT_CLICK: makePaperWalletOnboardingCreateEvent('choose mode | next | click'),
22+
PGP_PUBLIC_KEY_PAGE_VIEW: makePaperWalletOnboardingCreateEvent('step: pgp key | pageview'),
23+
PGP_PUBLIC_KEY_NEXT_CLICK: makePaperWalletOnboardingCreateEvent('step: pgp key | next | click'),
24+
WALLET_SETUP_GENERATE_PAPER_WALLET_CLICK: makePaperWalletOnboardingCreateEvent(
25+
'step: wallet info | Generate paper wallet | click'
26+
),
27+
PAPER_WALLET_DOWNLOAD_PAGEVIEW: makePaperWalletOnboardingCreateEvent('step: download pdf | pageview'),
28+
DOWNLOAD_PAPER_WALLET_CLICK: makePaperWalletOnboardingCreateEvent('download pdf | download pdf | click'),
29+
PRINT_PAPER_WALLET_CLICK: makePaperWalletOnboardingCreateEvent('print pdf | print pdf | click'),
30+
PAPER_WALLET_COMPLETE_CLICK: makePaperWalletOnboardingCreateEvent('open wallet | open wallet | click'),
1531
SETUP_OPTION_CLICK: makeMultiWalletCreateEvent('create | click'),
1632
SAVE_RECOVERY_PHRASE_NEXT_CLICK: makeMultiWalletCreateEvent('save your recovery phrase | next | click'),
1733
ENTER_RECOVERY_PHRASE_NEXT_CLICK: makeMultiWalletCreateEvent('enter your recovery phrase | next | click'),
@@ -35,6 +51,18 @@ const multiWalletActions = {
3551
WALLET_ADDED: makeMultiWalletCreateEvent('added')
3652
},
3753
restore: {
54+
WALLET_SETUP_PAGEVIEW: makePaperWalletOnboardingCreateEvent('step: wallet info | pageview'),
55+
CHOOSE_RECOVERY_MODE_MNEMONIC_CLICK: makePaperWalletOnboardingRestoreEvent('choose mode | recovery phrase | click'),
56+
CHOOSE_RECOVERY_MODE_PAPER_CLICK: makePaperWalletOnboardingRestoreEvent('choose mode | paper wallet | click'),
57+
CHOOSE_RECOVERY_MODE_NEXT_CLICK: makePaperWalletOnboardingRestoreEvent('choose mode | next | click'),
58+
SCAN_QR_CODE_PAGEVIEW: makePaperWalletOnboardingRestoreEvent('step: scan qr code | pageview'),
59+
SCAN_QR_CODE_CAMERA_OK: makePaperWalletOnboardingRestoreEvent('step: scan qr code | camera ok'),
60+
SCAN_QR_CODE_CAMERA_ERROR: makePaperWalletOnboardingRestoreEvent('step: scan qr code | camera error'),
61+
SCAN_QR_CODE_READ_SUCCESS: makePaperWalletOnboardingRestoreEvent('step: scan qr code | read success'),
62+
SCAN_QR_CODE_READ_ERROR: makePaperWalletOnboardingRestoreEvent('step: scan qr code | read error'),
63+
WALLET_OVERVIEW_NEXT_CLICK: makePaperWalletOnboardingRestoreEvent('step: wallet overview | next | click'),
64+
ENTER_PGP_PRIVATE_KEY_PAGE_VIEW: makePaperWalletOnboardingRestoreEvent('step: pgp private key | pageview'),
65+
ENTER_PGP_PRIVATE_KEY_NEXT_CLICK: makePaperWalletOnboardingRestoreEvent('step: pgp private key | next | click'),
3866
SETUP_OPTION_CLICK: makeMultiWalletRestoreEvent('restore | click'),
3967
ENTER_WALLET: makeMultiWalletRestoreEvent("let's set up your new wallet | enter wallet | click"),
4068
ENTER_RECOVERY_PHRASE_NEXT_CLICK: makeMultiWalletRestoreEvent(' enter your recovery phrase | next | click'),

apps/browser-extension-wallet/src/providers/AnalyticsProvider/analyticsTracker/events/onboarding.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ const makeOnboardingHardwareEvent = <E extends string>(eventSuffix: E) =>
1313
`onboarding | hardware wallet revamp | ${eventSuffix}` as const;
1414
const makeForgotPasswordEvent = <E extends string>(eventSuffix: E) =>
1515
`unlock wallet | forgot password? | ${eventSuffix}` as const;
16+
const makePaperWalletOnboardingCreateEvent = <E extends string>(eventSuffix: E) =>
17+
`onboarding | new wallet revamp paper wallet | ${eventSuffix}` as const;
18+
const makePaperWalletOnboardingRestoreEvent = <E extends string>(eventSuffix: E) =>
19+
`onboarding | restore wallet revamp paper wallet | ${eventSuffix}` as const;
1620

1721
const onboardingActions = {
1822
onboarding: {
@@ -23,6 +27,18 @@ const onboardingActions = {
2327
PIN_EXTENSION_CLICK: makeOnboardingEvent('lace main view | pin the wallet extension | click')
2428
},
2529
create: {
30+
CHOOSE_RECOVERY_MODE_MNEMONIC_CLICK: makePaperWalletOnboardingCreateEvent('choose mode | recovery phrase | click'),
31+
CHOOSE_RECOVERY_MODE_PAPER_CLICK: makePaperWalletOnboardingCreateEvent('choose mode | paper wallet | click'),
32+
CHOOSE_RECOVERY_MODE_NEXT_CLICK: makePaperWalletOnboardingCreateEvent('choose mode | next | click'),
33+
PGP_PUBLIC_KEY_PAGE_VIEW: makePaperWalletOnboardingCreateEvent('step: pgp key | pageview'),
34+
PGP_PUBLIC_KEY_NEXT_CLICK: makePaperWalletOnboardingCreateEvent('step: pgp key | next | click'),
35+
WALLET_SETUP_GENERATE_PAPER_WALLET_CLICK: makePaperWalletOnboardingCreateEvent(
36+
'step: wallet info | Generate paper wallet | click'
37+
),
38+
PAPER_WALLET_DOWNLOAD_PAGEVIEW: makePaperWalletOnboardingCreateEvent('step: download pdf | pageview'),
39+
DOWNLOAD_PAPER_WALLET_CLICK: makePaperWalletOnboardingCreateEvent('download pdf | download pdf | click'),
40+
PRINT_PAPER_WALLET_CLICK: makePaperWalletOnboardingCreateEvent('print pdf | print pdf | click'),
41+
PAPER_WALLET_COMPLETE_CLICK: makePaperWalletOnboardingCreateEvent('open wallet | open wallet | click'),
2642
SETUP_OPTION_CLICK: makeOnboardingCreateEvent('create | click'),
2743
SAVE_RECOVERY_PHRASE_NEXT_CLICK: makeOnboardingCreateEvent('save your recovery phrase | next | click'),
2844
ENTER_RECOVERY_PHRASE_NEXT_CLICK: makeOnboardingCreateEvent('enter your recovery phrase | next | click'),
@@ -46,6 +62,18 @@ const onboardingActions = {
4662
WALLET_ADDED: makeOnboardingCreateEvent('added')
4763
},
4864
restore: {
65+
WALLET_SETUP_PAGEVIEW: makePaperWalletOnboardingCreateEvent('step: wallet info | pageview'),
66+
CHOOSE_RECOVERY_MODE_MNEMONIC_CLICK: makePaperWalletOnboardingRestoreEvent('choose mode | recovery phrase | click'),
67+
CHOOSE_RECOVERY_MODE_PAPER_CLICK: makePaperWalletOnboardingRestoreEvent('choose mode | paper wallet | click'),
68+
CHOOSE_RECOVERY_MODE_NEXT_CLICK: makePaperWalletOnboardingRestoreEvent('choose mode | next | click'),
69+
SCAN_QR_CODE_PAGEVIEW: makePaperWalletOnboardingRestoreEvent('step: scan qr code | pageview'),
70+
SCAN_QR_CODE_CAMERA_OK: makePaperWalletOnboardingRestoreEvent('step: scan qr code | camera ok'),
71+
SCAN_QR_CODE_CAMERA_ERROR: makePaperWalletOnboardingRestoreEvent('step: scan qr code | camera error'),
72+
SCAN_QR_CODE_READ_SUCCESS: makePaperWalletOnboardingRestoreEvent('step: scan qr code | read success'),
73+
SCAN_QR_CODE_READ_ERROR: makePaperWalletOnboardingRestoreEvent('step: scan qr code | read error'),
74+
WALLET_OVERVIEW_NEXT_CLICK: makePaperWalletOnboardingRestoreEvent('step: wallet overview | next | click'),
75+
ENTER_PGP_PRIVATE_KEY_PAGE_VIEW: makePaperWalletOnboardingRestoreEvent('step: pgp private key | pageview'),
76+
ENTER_PGP_PRIVATE_KEY_NEXT_CLICK: makePaperWalletOnboardingRestoreEvent('step: pgp private key | next | click'),
4977
SETUP_OPTION_CLICK: makeOnboardingRestoreEvent('restore | click'),
5078
ENTER_WALLET: makeOnboardingRestoreEvent("let's set up your new wallet | enter wallet | click"),
5179
ENTER_RECOVERY_PHRASE_NEXT_CLICK: makeOnboardingRestoreEvent(' enter your recovery phrase | next | click'),

apps/browser-extension-wallet/src/providers/AnalyticsProvider/analyticsTracker/events/types.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,32 @@ export type CreateFlowActions = Record<
99
| 'RECOVERY_PHRASE_PASTE_FROM_CLIPBOARD_CLICK'
1010
| 'RECOVERY_PHRASE_COPY_READ_MORE_CLICK'
1111
| 'RECOVERY_PHRASE_PASTE_READ_MORE_CLICK'
12-
| 'WALLET_ADDED',
12+
| 'WALLET_ADDED'
13+
| 'CHOOSE_RECOVERY_MODE_MNEMONIC_CLICK'
14+
| 'CHOOSE_RECOVERY_MODE_PAPER_CLICK'
15+
| 'CHOOSE_RECOVERY_MODE_NEXT_CLICK'
16+
| 'PGP_PUBLIC_KEY_PAGE_VIEW'
17+
| 'PGP_PUBLIC_KEY_NEXT_CLICK'
18+
| 'WALLET_SETUP_GENERATE_PAPER_WALLET_CLICK'
19+
| 'PAPER_WALLET_DOWNLOAD_PAGEVIEW'
20+
| 'DOWNLOAD_PAPER_WALLET_CLICK'
21+
| 'PRINT_PAPER_WALLET_CLICK'
22+
| 'PAPER_WALLET_COMPLETE_CLICK',
1323
string
1424
>;
1525
export type RestoreFlowActions = Record<
26+
| 'WALLET_SETUP_PAGEVIEW'
27+
| 'CHOOSE_RECOVERY_MODE_MNEMONIC_CLICK'
28+
| 'CHOOSE_RECOVERY_MODE_PAPER_CLICK'
29+
| 'CHOOSE_RECOVERY_MODE_NEXT_CLICK'
30+
| 'SCAN_QR_CODE_PAGEVIEW'
31+
| 'SCAN_QR_CODE_CAMERA_OK'
32+
| 'SCAN_QR_CODE_CAMERA_ERROR'
33+
| 'SCAN_QR_CODE_READ_SUCCESS'
34+
| 'SCAN_QR_CODE_READ_ERROR'
35+
| 'WALLET_OVERVIEW_NEXT_CLICK'
36+
| 'ENTER_PGP_PRIVATE_KEY_PAGE_VIEW'
37+
| 'ENTER_PGP_PRIVATE_KEY_NEXT_CLICK'
1638
| 'SETUP_OPTION_CLICK'
1739
| 'ENTER_RECOVERY_PHRASE_NEXT_CLICK'
1840
| 'ENTER_WALLET'
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
import { ExperimentName, ExperimentsConfig, FallbackConfiguration } from './types';
22

33
export const fallbackConfiguration: FallbackConfiguration = {
4-
[ExperimentName.COMBINED_NAME_PASSWORD_ONBOARDING_SCREEN]: 'control'
4+
[ExperimentName.COMBINED_NAME_PASSWORD_ONBOARDING_SCREEN]: 'control',
5+
[ExperimentName.CREATE_PAPER_WALLET]: false,
6+
[ExperimentName.RESTORE_PAPER_WALLET]: false
57
};
68

79
export const experiments: ExperimentsConfig = {
810
[ExperimentName.COMBINED_NAME_PASSWORD_ONBOARDING_SCREEN]: {
911
variants: ['control', 'test'],
10-
defaultVariant: 'control'
12+
default: 'control'
13+
},
14+
[ExperimentName.CREATE_PAPER_WALLET]: {
15+
value: false,
16+
default: false
17+
},
18+
[ExperimentName.RESTORE_PAPER_WALLET]: {
19+
value: false,
20+
default: false
1121
}
1222
};

apps/browser-extension-wallet/src/providers/ExperimentsProvider/context.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { createContext, useCallback, useEffect, useMemo, useState } from 'react';
1+
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
22
import { usePostHogClientContext } from '@providers/PostHogClientProvider';
33
import { ExperimentName, ExperimentsConfigStatus } from './types';
44

@@ -15,6 +15,12 @@ interface ExperimentsProviderProps {
1515
children: React.ReactNode;
1616
}
1717

18+
export const useExperimentsContext = (): ExperimentsContext => {
19+
const experiementsContext = useContext(ExperimentsContext);
20+
if (experiementsContext === null) throw new Error('ExperimentsContext not defined');
21+
return experiementsContext;
22+
};
23+
1824
export const ExperimentsProvider = ({ children }: ExperimentsProviderProps): React.ReactElement => {
1925
const postHogClient = usePostHogClientContext();
2026
const [experimentsConfigStatus, setExperimentsConfigStatus] = useState(ExperimentsConfigStatus.IDLE);

apps/browser-extension-wallet/src/providers/ExperimentsProvider/types.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,26 @@ export enum ExperimentsConfigStatus {
66
}
77

88
export enum ExperimentName {
9-
COMBINED_NAME_PASSWORD_ONBOARDING_SCREEN = 'combined-setup-name-password'
9+
COMBINED_NAME_PASSWORD_ONBOARDING_SCREEN = 'combined-setup-name-password',
10+
CREATE_PAPER_WALLET = 'create-paper-wallet',
11+
RESTORE_PAPER_WALLET = 'restore-paper-wallet'
12+
}
13+
14+
interface FeatureFlag {
15+
value: boolean;
16+
default: boolean;
17+
}
18+
19+
type Variant = ReadonlyArray<string>;
20+
21+
interface ExperiementVariant {
22+
variants: Variant;
23+
default: string;
1024
}
1125

1226
export type CombinedSetupNamePasswordVariants = readonly ['control', 'test'];
27+
1328
export type ExperimentsConfig = {
14-
[ExperimentName.COMBINED_NAME_PASSWORD_ONBOARDING_SCREEN]: {
15-
variants: CombinedSetupNamePasswordVariants;
16-
defaultVariant: string;
17-
};
29+
[key in ExperimentName]: FeatureFlag | ExperiementVariant;
1830
};
19-
export type FallbackConfiguration = Record<ExperimentName, 'control'>;
31+
export type FallbackConfiguration = Record<ExperimentName, 'control' | boolean>;

apps/browser-extension-wallet/src/providers/PostHogClientProvider/client/PostHogClient.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import { ExperimentName } from '@providers/ExperimentsProvider/types';
2323
import { Subscription, BehaviorSubject } from 'rxjs';
2424
import { PostHogAction, PostHogProperties } from '@lace/common';
2525

26+
type FeatureFlags = 'create-paper-wallet' | 'restore-paper-wallet';
27+
2628
/**
2729
* PostHog API reference:
2830
* https://posthog.com/docs/libraries/js
@@ -34,7 +36,9 @@ export class PostHogClient<Action extends string = string> {
3436
private hasPostHogInitialized$: BehaviorSubject<boolean>;
3537
private subscription: Subscription;
3638
private initSuccess: Promise<boolean>;
37-
39+
featureFlags: {
40+
[key in FeatureFlags]: string | boolean;
41+
};
3842
constructor(
3943
private chain: Wallet.Cardano.ChainId,
4044
private userIdService: UserIdService,
@@ -82,6 +86,7 @@ export class PostHogClient<Action extends string = string> {
8286
});
8387

8488
this.subscribeToDistinctIdUpdate();
89+
this.loadExperiments();
8590
}
8691

8792
static getInstance(
@@ -118,10 +123,6 @@ export class PostHogClient<Action extends string = string> {
118123
posthog.register({
119124
distinct_id: id
120125
});
121-
122-
if (type === UserTrackingType.Enhanced && !this.hasPostHogInitialized$.value) {
123-
this.loadExperiments();
124-
}
125126
}
126127
});
127128
}
@@ -194,27 +195,38 @@ export class PostHogClient<Action extends string = string> {
194195
posthog.featureFlags.override(flags);
195196
}
196197

197-
async getExperimentVariant(key: ExperimentName): Promise<string> {
198+
async getExperimentVariant(key: ExperimentName): Promise<string | boolean> {
198199
const variant = posthog?.getFeatureFlag(key, {
199200
send_event: false
200201
});
201202
// if we get a type of boolean means that the experiment is not running, so we return the fallback variant
202203
if (typeof variant === 'boolean') {
203-
return experiments[key].defaultVariant;
204+
return experiments[key].default;
204205
}
205206

206207
// if the variant does not exist, we need to check for out cache
207208
if (!variant) {
208209
const backgroundStorage = await this.backgroundServiceUtils.getBackgroundStorage();
209-
return (backgroundStorage?.experimentsConfiguration?.[key] as string) || experiments[key].defaultVariant;
210+
return (backgroundStorage?.experimentsConfiguration?.[key] as string) || experiments[key].default;
210211
}
211212

212213
return variant;
213214
}
214215

216+
isFeatureEnabled(key: ExperimentName | string): boolean {
217+
try {
218+
const isEnabled = posthog.isFeatureEnabled(key);
219+
return isEnabled || false;
220+
} catch {
221+
return false;
222+
}
223+
}
224+
215225
protected loadExperiments(): void {
216226
posthog.onFeatureFlags(async () => {
217-
const postHogExperimentConfiguration = posthog.featureFlags.getFlagVariants();
227+
const postHogExperimentConfiguration: Record<ExperimentName, string | boolean> =
228+
posthog.featureFlags.getFlagVariants();
229+
this.featureFlags = postHogExperimentConfiguration;
218230
const backgroundStorage = await this.backgroundServiceUtils.getBackgroundStorage();
219231
if (!backgroundStorage?.experimentsConfiguration && postHogExperimentConfiguration) {
220232
// save current posthog config in background storage

apps/browser-extension-wallet/src/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ export * from './activity-detail';
88
export * from './dappConnector';
99
export * from './ui';
1010
export * from './side-menu';
11+
export * from './pgp';
12+
export * from './paperWallet';

0 commit comments

Comments
 (0)