Skip to content

Commit

Permalink
Merge pull request #3290 from superhero-com/feature/do-not-rely-on-sd…
Browse files Browse the repository at this point in the history
…k-to-confirm-transactions

feat: do not rely on sdk being valid in sign process
  • Loading branch information
CedrikNikita authored Dec 18, 2024
2 parents b4b49ea + 58ac17a commit 09ff51a
Show file tree
Hide file tree
Showing 25 changed files with 282 additions and 84 deletions.
28 changes: 17 additions & 11 deletions src/background/bgPopupHandler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { v4 as uuid } from 'uuid';
import type {
Dictionary,
IAppData,
IPopupProps,
PopupType,
} from '@/types';
Expand Down Expand Up @@ -32,30 +33,35 @@ const storageSession = (browser.storage as any)?.session;

export const openPopup = async (
popupType: PopupType,
aepp: string | Record<string, any>, // TODO establish correct type for the object
aepp: string | Record<string, any> | undefined, // TODO establish correct type for the object
popupProps: Partial<IPopupProps> = {},
) => {
const id = uuid();
const url = (typeof aepp === 'object') ? aepp.connection.port.sender.url : aepp;
const { href, protocol, host } = new URL(url);

// TODO fix the name resolving issue happening in `onSubscription` of aeSdk
const name = (typeof aepp === 'object') ? aepp.name : undefined;
let app: IAppData;

if (typeof aepp === 'object') {
app = new URL(aepp.connection.port.sender.url);
} else if (aepp === undefined) {
app = {} as IAppData;
} else {
app = new URL(aepp);
}

const tabs = await browser.tabs.query({ active: true });

tabs.forEach(({ url: tabURL, id: tabId }) => {
const tabUrl = new URL(tabURL as string);
if (
tabUrl.searchParams.get('type') === POPUP_TYPE_CONNECT
&& decodeURIComponent(tabUrl.searchParams.get('url') || '') === href
&& decodeURIComponent(tabUrl.searchParams.get('url') || '') === app.href
) {
browser.tabs.remove(tabId as number);
}
});

const extUrl = browser.runtime.getURL('./index.html');
const popupUrl = `${extUrl}?id=${id}&type=${popupType}&url=${encodeURIComponent(href)}`;
const popupUrl = `${extUrl}?id=${id}&type=${popupType}&url=${encodeURIComponent(app.href!)}`;
const isMacOsExtension = IS_EXTENSION && browser.runtime.getPlatformInfo().then(({ os }) => os === 'mac');

const popupWindow = await browser.windows.create({
Expand All @@ -74,10 +80,10 @@ export const openPopup = async (
props: {
...popupProps,
app: {
url: href,
name,
protocol,
host,
href: app.href,
name: app.name || app.host,
protocol: app.protocol,
host: app.host,
},
},
};
Expand Down
5 changes: 4 additions & 1 deletion src/composables/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { generateMnemonic, mnemonicToSeed, validateMnemonic } from '@aeternity/b

import { tg as t } from '@/popup/plugins/i18n';
import {
AUTHENTICATION_TIMEOUT_DEFAULT,
AUTHENTICATION_TIMEOUTS,
IS_EXTENSION,
IS_IOS,
IS_MOBILE_APP,
Expand Down Expand Up @@ -44,6 +44,9 @@ import { useModals } from './modals';
import { useStorageRef } from './storageRef';

const CHECK_FOR_SESSION_KEY_INTERVAL = 5000;
const AUTHENTICATION_TIMEOUT_DEFAULT = (IS_MOBILE_APP)
? AUTHENTICATION_TIMEOUTS[0]
: AUTHENTICATION_TIMEOUTS[2];

/**
* Top level composable that controls if user is allowed to interact with the wallet.
Expand Down
21 changes: 16 additions & 5 deletions src/composables/deepLinkApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ import {
} from '@/constants';
import { useModals } from '@/composables/modals';

export function useDeepLinkApi() {
const router = useIonRouter();
let isDeepLinkUsed = false;

export function useDeepLinkApi(
{ doNotInitializeRouter }: { doNotInitializeRouter?: boolean } = {},
) {
// `useIonRouter` breaks if it is not run in `IonPage` context
const router = doNotInitializeRouter ? null : useIonRouter();
const route = useRoute();

const callbackOrigin = ref<URL | null>(
route.query['x-success']
route?.query['x-success']
? (new URL(decodeURIComponent(route.query['x-success'] as string)))
: null,
);
Expand All @@ -42,14 +47,14 @@ export function useDeepLinkApi() {
) {
const callbackUrlTemplate = route.query[isSuccess ? 'x-success' : 'x-cancel'];
if (!callbackUrlTemplate) {
router.replace({ name: ROUTE_ACCOUNT });
router?.replace({ name: ROUTE_ACCOUNT });
return;
}
const callbackUrl = Object.entries(templateParams).reduce(
(url, [key, value]) => url.replace(new RegExp(`{${key}}`, 'g'), encodeURIComponent(value)),
decodeURIComponent(String(route.query[isSuccess ? 'x-success' : 'x-cancel'])),
) as string;
router.replace({ name: ROUTE_ACCOUNT });
router?.replace({ name: ROUTE_ACCOUNT });
/**
* When auto-sign is enabled (daily spend limit),
* there are cases (mostly on iOS) where it's not redirecting back to the callback URL.
Expand All @@ -66,9 +71,15 @@ export function useDeepLinkApi() {
}, IS_WEB ? 0 : 300);
}

function setIsDeepLinkUsed(value: boolean) {
isDeepLinkUsed = value;
}

return {
checkIfOpenTransferSendModal,
callbackOrigin,
openCallbackOrGoHome,
setIsDeepLinkUsed,
isDeepLinkUsed,
};
}
6 changes: 3 additions & 3 deletions src/composables/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export function usePermissions() {
host: url.host,
name: url.hostname,
protocol: url.protocol,
url: url.href,
href: url.href,
};
props = { ...props, app };
}
Expand All @@ -197,8 +197,8 @@ export function usePermissions() {
popup = POPUP_TYPE_RAW_SIGN;
}
await (
(IS_OFFSCREEN_TAB && app?.url)
? openPopup(popup, app.url, props)
(IS_OFFSCREEN_TAB)
? openPopup(popup, app?.href, props)
: openModal(modal, props)
);
return true;
Expand Down
7 changes: 5 additions & 2 deletions src/composables/popupProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ export function usePopupProps() {
const sender = computed((): IAccountOverview => ({
name: popupProps.value?.app?.name,
address: popupProps.value?.app?.host,
url: popupProps.value?.app?.url,
url: popupProps.value?.app?.href,
}));

const isUnknownDapp = computed(() => !popupProps.value?.app?.href);

return {
sender,
isUnknownDapp,
popupProps,
sender,
setPopupProps,
};
}
5 changes: 0 additions & 5 deletions src/constants/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { ICurrency, IPermission, ObjectValues } from '@/types';
import { IS_MOBILE_APP } from './environment';

export const APP_NAME = 'Superhero Wallet';
export const APP_URL = 'wallet.superhero.com';
Expand Down Expand Up @@ -549,10 +548,6 @@ export const AUTHENTICATION_TIMEOUTS = [
1800000,
] as const;

export const AUTHENTICATION_TIMEOUT_DEFAULT = (IS_MOBILE_APP)
? AUTHENTICATION_TIMEOUTS[0]
: AUTHENTICATION_TIMEOUTS[2];

export const PASSWORD_STRENGTH = {
weak: 'weak',
medium: 'medium',
Expand Down
2 changes: 1 addition & 1 deletion src/constants/stubs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const STUB_CURRENCY: CoinGeckoMarketResponse = {
};

export const STUB_APP_DATA: IAppData = {
url: 'http://localhost:5000/aepp/aepp',
href: 'http://localhost:5000/aepp/aepp',
name: 'AEPP',
protocol: 'http:',
host: 'localhost',
Expand Down
4 changes: 4 additions & 0 deletions src/icons/warning-outline.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/offscreen/popupHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const popups: Dictionary<IPopupConfig> = {};

export const openPopup = async (
popupType: PopupType,
aepp: string | object,
aepp: string | object | undefined,
popupProps: Partial<IPopupProps> = {},
) => executeOrSendMessageToBackground(
POPUP_METHODS.openPopup,
Expand Down
12 changes: 12 additions & 0 deletions src/popup/components/DetailsItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
:class="{
expandable,
expanded,
warning,
}"
>
<Component
Expand Down Expand Up @@ -63,6 +64,7 @@ export default defineComponent({
expandable: Boolean,
small: Boolean,
highlight: Boolean,
warning: Boolean,
},
setup(props) {
const expanded = ref(!props.expandable);
Expand Down Expand Up @@ -156,5 +158,15 @@ export default defineComponent({
}
}
}
&.warning {
.label {
color: $color-warning;
}
.value {
color: rgba($color-warning, 0.85);
}
}
}
</style>
20 changes: 18 additions & 2 deletions src/popup/components/Modals/ConfirmRawSign.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,19 @@
data-cy="popup-aex2"
>
<TransactionInfo
:custom-labels="[$t('modals.confirm-raw-sign.title')]"
:custom-labels="[
...(isUnknownDapp ? [$t('common.unknown')] : []),
$t('modals.confirm-raw-sign.title'),
]"
:sender="sender"
:recipient="activeAccount!"
:first-label-warning="isUnknownDapp"
/>

<NoOriginWarning
v-if="isUnknownDapp"
:action="$t('unknownDapp.signDataAction')"
:warning="$t('unknownDapp.signDataWarning')"
/>

<div
Expand Down Expand Up @@ -86,7 +96,12 @@ export default defineComponent({
CopyText,
},
setup() {
const { popupProps, sender, setPopupProps } = usePopupProps();
const {
isUnknownDapp,
popupProps,
sender,
setPopupProps,
} = usePopupProps();
const { getLastActiveProtocolAccount } = useAccounts();
const { openModal } = useModals();
Expand Down Expand Up @@ -124,6 +139,7 @@ export default defineComponent({
cancel,
activeAccount,
dataAsString,
isUnknownDapp,
sender,
};
},
Expand Down
13 changes: 11 additions & 2 deletions src/popup/components/Modals/ConfirmTransactionSign.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@
<template v-else>
<TransactionOverview
:transaction="transaction"
:additional-tag="appName"
:additional-tag="isUnknownDapp ? $t('common.unknown') : appName"
:first-label-warning="isUnknownDapp"
/>
<NoOriginWarning
v-if="isUnknownDapp"
:action="$t('unknownDapp.confirmTransactionAction')"
:warning="$t('unknownDapp.confirmTransactionWarning')"
/>
<div
v-if="appName || error"
Expand Down Expand Up @@ -268,6 +274,7 @@ import DetailsItem from '../DetailsItem.vue';
import TokenAmount from '../TokenAmount.vue';
import TransactionDetailsPoolTokenRow from '../TransactionDetailsPoolTokenRow.vue';
import TransactionCallDataDetails from '../TransactionCallDataDetails.vue';
import NoOriginWarning from '../NoOriginWarning.vue';
import AnimatedSpinner from '../../../icons/animated-spinner.svg?vue-component';
Expand Down Expand Up @@ -299,6 +306,7 @@ export default defineComponent({
TokenAmount,
TransactionDetailsPoolTokenRow,
TransactionCallDataDetails,
NoOriginWarning,
AnimatedSpinner,
},
setup() {
Expand All @@ -307,7 +315,7 @@ export default defineComponent({
const { aeActiveNetworkSettings } = useAeNetworkSettings();
const { getAeSdk } = useAeSdk();
const { getLastActiveProtocolAccount } = useAccounts();
const { popupProps, setPopupProps } = usePopupProps();
const { isUnknownDapp, popupProps, setPopupProps } = usePopupProps();
const { getProtocolAvailableTokens, getTxAssetSymbol } = useFungibleTokens();
const { openModal } = useModals();
const { areTokenSalesReady, tokenSaleAddressToTokenContractAddress } = useAeTokenSales();
Expand Down Expand Up @@ -658,6 +666,7 @@ export default defineComponent({
isDexSwap,
isTokenSale,
isHash,
isUnknownDapp,
loading,
nameAeFee,
popupProps,
Expand Down
Loading

0 comments on commit 09ff51a

Please sign in to comment.