Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to select xverse as default browser wallet in settings #774

Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/app/hooks/useChromeLocalStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { chromeLocalStorage } from '@utils/chromeStorage';
import { useEffect, useState } from 'react';

export const useChromeLocalStorage = <T extends unknown>(key: string, defaultValue?: T) => {
victorkirov marked this conversation as resolved.
Show resolved Hide resolved
const [value, setValueState] = useState<T | undefined>(undefined);

useEffect(() => {
setValueState(undefined);
chromeLocalStorage.getItem<T>(key).then((result) => {
const newValue = result === undefined ? defaultValue : result;
setValueState(newValue);
});
}, [key]);

const setValue = (newValue: T) => {
chromeLocalStorage.setItem(key, newValue);
setValueState(newValue);
};

return [value, setValue] as const;
};

export default useChromeLocalStorage;
4 changes: 2 additions & 2 deletions src/app/hooks/useSeedVault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ const cryptoUtilsAdapter: CryptoUtilsAdapter = {
};

const secureStorageAdapter: StorageAdapter = {
get: async (key: string) => chromeSessionStorage.getItem<string>(key),
get: async (key: string) => chromeSessionStorage.getItem<string, null>(key, null),
set: async (key: string, value: string) => chromeSessionStorage.setItem(key, value),
remove: async (key: string) => chromeSessionStorage.removeItem(key),
};

const commonStorageAdapter: StorageAdapter = {
get: async (key: string) => chromeLocalStorage.getItem<string>(key),
get: async (key: string) => chromeLocalStorage.getItem<string, null>(key, null),
set: async (key: string, value: string) => chromeLocalStorage.setItem(key, value),
remove: async (key: string) => chromeLocalStorage.removeItem(key),
};
Expand Down
22 changes: 20 additions & 2 deletions src/app/screens/settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import ArrowIcon from '@assets/img/settings/arrow.svg';
import XverseLogo from '@assets/img/settings/logo.svg';
import PasswordInput from '@components/passwordInput';
import BottomBar from '@components/tabBar';
import useChromeLocalStorage from '@hooks/useChromeLocalStorage';
import useSeedVault from '@hooks/useSeedVault';
import useWalletReducer from '@hooks/useWalletReducer';
import useWalletSelector from '@hooks/useWalletSelector';
Expand All @@ -11,6 +12,7 @@ import {
ChangeActivateRareSatsAction,
ChangeActivateRBFAction,
} from '@stores/wallet/actions/actionCreators';
import { chromeLocalStorageKeys } from '@utils/chromeLocalStorage';
import { PRIVACY_POLICY_LINK, SUPPORT_LINK, TERMS_LINK } from '@utils/constants';
import { isInOptions, isLedgerAccount } from '@utils/helper';
import { useState } from 'react';
Expand Down Expand Up @@ -67,6 +69,10 @@ function Setting() {
hasActivatedRBFKey,
selectedAccount,
} = useWalletSelector();
const [isPriorityWallet, setIsPriorityWallet] = useChromeLocalStorage<boolean>(
chromeLocalStorageKeys.isPriorityWallet,
true,
);
const navigate = useNavigate();
const dispatch = useDispatch();
const { resetWallet } = useWalletReducer();
Expand Down Expand Up @@ -100,6 +106,10 @@ function Setting() {
navigate('/backup-wallet');
};

const switchIsPriorityWallet = () => {
setIsPriorityWallet(!isPriorityWallet);
};

const switchActivateOrdinalState = () => {
dispatch(ChangeActivateOrdinalsAction(!hasActivatedOrdinalsKey));
// disable rare sats if ordinal is disabled
Expand Down Expand Up @@ -202,6 +212,7 @@ function Setting() {
onClick={openChangeNetworkScreen}
textDetail={network.type}
/>

<SettingComponent
title={t('SECURITY')}
text={t('UPDATE_PASSWORD')}
Expand All @@ -226,6 +237,7 @@ function Setting() {
onClick={openResetWalletPrompt}
showWarningTitle
/>

<SettingComponent
title={t('ADVANCED')}
text={t('ACTIVATE_ORDINAL_NFTS')}
Expand All @@ -241,7 +253,6 @@ function Setting() {
showDivider
disabled={!hasActivatedOrdinalsKey}
/>

<SettingComponent
text={t('ENABLE_RARE_SATS')}
description={t('ENABLE_RARE_SATS_DETAIL')}
Expand All @@ -251,7 +262,14 @@ function Setting() {
disabled={!hasActivatedOrdinalsKey}
showDivider
/>

<SettingComponent
text={t('XVERSE_DEFAULT')}
description={t('XVERSE_DEFAULT_DESCRIPTION')}
toggle
toggleFunction={switchIsPriorityWallet}
toggleValue={isPriorityWallet}
showDivider
/>
<SettingComponent
text={t('ENABLE_SPEED_UP_TRANSACTIONS')}
description={t('ENABLE_SPEED_UP_TRANSACTIONS_DETAIL')}
Expand Down
13 changes: 13 additions & 0 deletions src/app/utils/chromeLocalStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { chromeLocalStorage } from './chromeStorage';

export const chromeLocalStorageKeys = {
isPriorityWallet: 'isPriorityWallet',
};

export async function getIsPriorityWallet(): Promise<boolean> {
const isPriorityWallet = await chromeLocalStorage.getItem<boolean>(
chromeLocalStorageKeys.isPriorityWallet,
);

return isPriorityWallet ?? true;
}
12 changes: 6 additions & 6 deletions src/app/utils/chromeStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,35 @@ class ChromeStorage {
return runtimeMap.get(this).lastError;
}

setItem(key: string, item: any): Promise<any> {
setItem(key: string, item: any): Promise<void> {
return new Promise((resolve, reject) => {
this.getDriver().set({ [key]: item }, () => {
if (this.hasError()) {
return reject(this.getError());
}
return resolve(true);
return resolve();
});
});
}

getItem<T = any>(key: string): Promise<T> {
getItem<T = any, D = undefined>(key: string, defaultValue?: D): Promise<T | D> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default, the storage interface returns an empty object if the key is not present, resulting in a response of undefined. The Seed Vault expects null though, so I had to add this default value.

return new Promise((resolve, reject) => {
this.getDriver().get(key, (response: any) => {
if (this.hasError()) {
return reject(this.getError());
}
return resolve(response[key]);
return resolve(response[key] ?? defaultValue);
});
});
}

removeItem(key: string): Promise<any> {
removeItem(key: string): Promise<void> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried changing this and the setItem one to boolean, but the seedVault stuff started to complain. Checking the rest of the code, nothing was actually using the return value, so I removed it.

return new Promise((resolve, reject) => {
this.getDriver().remove(key, () => {
if (this.hasError()) {
return reject(this.getError());
}
return resolve(true);
return resolve();
});
});
}
Expand Down
22 changes: 17 additions & 5 deletions src/content-scripts/content-script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
} from '@common/types/message-types';
import getEventSourceWindow from '@common/utils/get-event-source-window';
import RequestsRoutes from '@common/utils/route-urls';
import { getIsPriorityWallet } from '@utils/chromeLocalStorage';

// Legacy messaging to work with older versions of Connect
window.addEventListener('message', (event) => {
Expand Down Expand Up @@ -203,8 +204,19 @@ document.addEventListener(DomEventName.createRepeatInscriptionsRequest, ((
});
}) as EventListener);

// Inject inpage script (Stacks Provider)
const inpage = document.createElement('script');
inpage.src = chrome.runtime.getURL('inpage.js');
inpage.id = 'xverse-wallet-provider';
document.body.appendChild(inpage);
// Inject in-page script (Stacks and Bitcoin Providers)
const injectInPageScript = (isPriority) => {
const inpage = document.createElement('script');
inpage.src = chrome.runtime.getURL('inpage.js');
inpage.id = 'xverse-wallet-provider';
inpage.setAttribute('data-is-priority', isPriority ? 'true' : '');
document.body.appendChild(inpage);
};

getIsPriorityWallet()
.then((isPriorityWallet) => {
injectInPageScript(isPriorityWallet);
})
.catch(() => {
injectInPageScript(false);
});
11 changes: 9 additions & 2 deletions src/inpage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,15 @@ declare global {
}
}
// we inject these in case implementors call the default providers
window.StacksProvider = StacksMethodsProvider as StacksProvider;
window.BitcoinProvider = SatsMethodsProvider as BitcoinProvider;
if (document.currentScript?.dataset.isPriority) {
Object.defineProperties(window, {
StacksProvider: { get: () => StacksMethodsProvider, set: () => {} },
BitcoinProvider: { get: () => SatsMethodsProvider, set: () => {} },
});
} else {
window.StacksProvider = StacksMethodsProvider as StacksProvider;
window.BitcoinProvider = SatsMethodsProvider;
}

// We also inject the providers in an Xverse object in order to have them exclusively available for Xverse wallet
// and not clash with providers from other wallets
Expand Down
4 changes: 3 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,9 @@
"ENABLE_RARE_SATS_DETAIL": "Automatically scan and display rare sats in your Ordinals wallet.",
"ENABLE_SPEED_UP_TRANSACTIONS": "Enable speed up transactions",
"ENABLE_SPEED_UP_TRANSACTIONS_DETAIL": "Allows you to speed up unconfirmed transactions by paying a higher fee.",
"ADVANCED": "Advanced"
"ADVANCED": "Advanced",
"XVERSE_DEFAULT": "Use Xverse as default wallet",
"XVERSE_DEFAULT_DESCRIPTION": "Allow apps to prioritize Xverse when looking for a wallet with which to connect."
},
"OPTIONS_DIALOG": {
"SWITCH_ACCOUNT": "Switch Account",
Expand Down
Loading