diff --git a/.changeset/chilled-pumas-play.md b/.changeset/chilled-pumas-play.md new file mode 100644 index 000000000..141d329b1 --- /dev/null +++ b/.changeset/chilled-pumas-play.md @@ -0,0 +1,9 @@ +--- +'@blockchain-lab-um/masca-connector': patch +'@blockchain-lab-um/masca-types': patch +'@blockchain-lab-um/dapp': patch +'@blockchain-lab-um/masca-docs': patch +'@blockchain-lab-um/masca': patch +--- + +Changed and updated trusted dapps diff --git a/packages/connector/src/snap.ts b/packages/connector/src/snap.ts index 3f1de034e..ee7e52299 100644 --- a/packages/connector/src/snap.ts +++ b/packages/connector/src/snap.ts @@ -220,26 +220,33 @@ async function togglePopups(this: Masca): Promise> { } /** - * Adds origin of the current dapp to the list of friendly dapps. This will disable popups from appearing while using the dapp. + * Adds origin of the current dapp to the list of trusted dapps. This will disable popups from appearing while using the dapp. * * @return Result - true if the addition was successful */ -async function addFriendlyDapp(this: Masca): Promise> { - return sendSnapMethod(this, { method: 'addFriendlyDapp' }, this.snapId); +async function addTrustedDapp( + this: Masca, + origin: string +): Promise> { + return sendSnapMethod( + this, + { method: 'addTrustedDapp', params: { origin } }, + this.snapId + ); } /** - * Removes origin of the current dapp from the list of friendly dapps. This will enable popups while using the dapp. + * Removes origin of the current dapp from the list of trusted dapps. This will enable popups while using the dapp. * * @return Result - true if the removal was successful */ -async function removeFriendlyDapp( +async function removeTrustedDapp( this: Masca, - id: string + origin: string ): Promise> { return sendSnapMethod( this, - { method: 'removeFriendlyDapp', params: { id } }, + { method: 'removeTrustedDapp', params: { origin } }, this.snapId ); } @@ -577,8 +584,8 @@ export class Masca { queryCredentials: wrapper(queryCredentials.bind(this)), createPresentation: wrapper(createPresentation.bind(this)), togglePopups: wrapper(togglePopups.bind(this)), - addFriendlyDapp: wrapper(addFriendlyDapp.bind(this)), - removeFriendlyDapp: wrapper(removeFriendlyDapp.bind(this)), + addTrustedDapp: wrapper(addTrustedDapp.bind(this)), + removeTrustedDapp: wrapper(removeTrustedDapp.bind(this)), getDID: wrapper(getDID.bind(this)), getSelectedMethod: wrapper(getSelectedMethod.bind(this)), getAvailableMethods: wrapper(getAvailableMethods.bind(this)), diff --git a/packages/dapp/src/app/[locale]/app/(protected)/shared-presentations/sharedPresentations.tsx b/packages/dapp/src/app/[locale]/app/(protected)/shared-presentations/sharedPresentations.tsx index 6a9796bae..6e46a40c5 100644 --- a/packages/dapp/src/app/[locale]/app/(protected)/shared-presentations/sharedPresentations.tsx +++ b/packages/dapp/src/app/[locale]/app/(protected)/shared-presentations/sharedPresentations.tsx @@ -244,8 +244,8 @@ export const SharedPresentations = () => { column.key === 'actions' ? 'text-end' : column.key === 'title' - ? 'text-start' - : 'text-center' + ? 'text-start' + : 'text-center' )} > {column.label} @@ -265,8 +265,8 @@ export const SharedPresentations = () => { columnKey === 'actions' ? 'text-end' : columnKey === 'title' - ? 'text-start' - : 'text-center' + ? 'text-start' + : 'text-center' )} > {renderCell(item, columnKey)} diff --git a/packages/dapp/src/app/[locale]/app/(public)/share-presentation/[id]/page.tsx b/packages/dapp/src/app/[locale]/app/(public)/share-presentation/[id]/page.tsx index 7f9554258..d69edd67f 100644 --- a/packages/dapp/src/app/[locale]/app/(public)/share-presentation/[id]/page.tsx +++ b/packages/dapp/src/app/[locale]/app/(public)/share-presentation/[id]/page.tsx @@ -1,4 +1,3 @@ -import { headers } from 'next/headers'; import { notFound } from 'next/navigation'; import { createClient } from '@supabase/supabase-js'; import { VerifiablePresentation } from '@veramo/core'; diff --git a/packages/dapp/src/components/SettingsCard/AddFriendlydAppModal.tsx b/packages/dapp/src/components/SettingsCard/AddFriendlydAppModal.tsx deleted file mode 100644 index 15ec7a44f..000000000 --- a/packages/dapp/src/components/SettingsCard/AddFriendlydAppModal.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { useState } from 'react'; -import { Modal, ModalBody, ModalContent, ModalHeader } from '@nextui-org/react'; - -import Button from '@/components//Button'; -import InputField from '../InputField'; - -interface AddFriendlydAppModalProps { - isOpen: boolean; - setOpen: (open: boolean) => void; - addDapp: (dapp: string) => void; -} - -function AddFriendlydAppModal({ - isOpen, - setOpen, - addDapp, -}: AddFriendlydAppModalProps) { - const [dapp, setDapp] = useState(''); - return ( - <> - setOpen(false)} - hideCloseButton={true} - placement="center" - className="main-bg mx-4 py-2" - > - - {() => ( - <> - -
- Add Friendly dapp -
-
- -
-

- Input the URL of the dapp you want to add. -

-
- -
-
- -
-
- -
-
-
- - )} -
-
- - ); -} - -export default AddFriendlydAppModal; diff --git a/packages/dapp/src/components/SettingsCard/FriendlydAppTable.tsx b/packages/dapp/src/components/SettingsCard/TrustedDappTable.tsx similarity index 76% rename from packages/dapp/src/components/SettingsCard/FriendlydAppTable.tsx rename to packages/dapp/src/components/SettingsCard/TrustedDappTable.tsx index 5318b9eec..76ffa892e 100644 --- a/packages/dapp/src/components/SettingsCard/FriendlydAppTable.tsx +++ b/packages/dapp/src/components/SettingsCard/TrustedDappTable.tsx @@ -4,23 +4,17 @@ import { TrashIcon } from '@heroicons/react/24/outline'; import { useTranslations } from 'next-intl'; import { useMascaStore, useToastStore } from '@/stores'; +import Button from '../Button'; +import InputField from '../InputField'; -export const FriendlydAppTable = () => { - const t = useTranslations('FriendlydAppTable'); +export const TrustedDappTable = () => { + const t = useTranslations('TrustedDappTable'); const [settings, setSettings] = useState(); + const [origin, setOrigin] = useState(window.location.origin); const { api } = useMascaStore((state) => ({ api: state.mascaApi, })); - const isMascaFriendlyDapp = ( - friendlyDapps: string[] | undefined - ): boolean => { - if (friendlyDapps && friendlyDapps.includes('https://masca.io')) { - return true; - } - return false; - }; - const snapGetSettings = async () => { if (!api) return; const snapSettings = await api.getSnapSettings(); @@ -34,8 +28,8 @@ export const FriendlydAppTable = () => { snapGetSettings().catch((e) => console.log(e)); }, []); - const addFriendlydApp = async () => { - if (!api) return; + const addTrustedDapp = async () => { + if (!api || !origin) return; setTimeout(() => { useToastStore.setState({ @@ -46,8 +40,7 @@ export const FriendlydAppTable = () => { link: null, }); }, 200); - - const res = await api.addFriendlyDapp(); + const res = await api.addTrustedDapp(origin); if (res) { await snapGetSettings(); @@ -73,7 +66,7 @@ export const FriendlydAppTable = () => { }, 200); }; - const removeFriendlydApp = async (dapp: string) => { + const removeTrustedDapp = async (dapp: string) => { if (!api) return; setTimeout(() => { @@ -85,7 +78,7 @@ export const FriendlydAppTable = () => { link: null, }); }, 200); - const res = await api.removeFriendlyDapp(dapp); + const res = await api.removeTrustedDapp(dapp); if (res) { await snapGetSettings(); setTimeout(() => { @@ -115,6 +108,13 @@ export const FriendlydAppTable = () => {

{t('popups-desc')}

+
+ + +
+ @@ -123,7 +123,7 @@ export const FriendlydAppTable = () => { - {settings?.dApp.friendlyDapps.map((app, i) => ( + {settings?.dApp.trustedDapps?.map((app, i) => ( {
- {!isMascaFriendlyDapp(settings?.dApp.friendlyDapps) && ( -
- -
- )} ); }; diff --git a/packages/dapp/src/components/SettingsCard/index.tsx b/packages/dapp/src/components/SettingsCard/index.tsx index 9440a6326..1006b6495 100644 --- a/packages/dapp/src/components/SettingsCard/index.tsx +++ b/packages/dapp/src/components/SettingsCard/index.tsx @@ -11,8 +11,8 @@ import { useMascaStore, useToastStore } from '@/stores'; import Button from '../Button'; import InfoIcon from '../InfoIcon'; import UploadButton from '../UploadButton'; -import { FriendlydAppTable } from './FriendlydAppTable'; import GoogleBackupForm from './GoogleBackupForm'; +import { TrustedDappTable } from './TrustedDappTable'; const SettingsCard = () => { const t = useTranslations('SettingsCard'); @@ -229,7 +229,7 @@ const SettingsCard = () => { {t('popups')}
- +
{t('disable-popups')} diff --git a/packages/dapp/src/messages/en.json b/packages/dapp/src/messages/en.json index aaf79f0fd..83aa0f2e7 100644 --- a/packages/dapp/src/messages/en.json +++ b/packages/dapp/src/messages/en.json @@ -350,16 +350,17 @@ "expired-on": "Expired on", "polygon-unsupported": "Polygon ID VCs aren't supported yet. Please remove this credential to continue!" }, - "FriendlydAppTable": { - "add-failed": "Failed to add Friendly dapp", - "add-masca": "Add Masca.io to Friendly dapps", - "added": "Friendly dapp added", - "adding": "Adding Friendly dapp", + "TrustedDappTable": { + "add-failed": "Failed to add trusted dapp", + "add-masca": "Add masca.io to trusted dapps", + "added": "Trusted dapp added", + "adding": "Adding trusted dapp", "app-url": "Application URL", - "popups-desc": "Disabling pop-ups is very dangerous. We recommend setting friendly dapps instead!", - "remove-failed": "Failed to remove Friendly dapp", - "removed": "Friendly dapp removed", - "removing": "Removing Friendly dapp" + "popups-desc": "Disabling pop-ups is very dangerous. We recommend setting trusted dapps instead!", + "remove-failed": "Failed to remove trusted dapp", + "removed": "Trusted dapp removed", + "removing": "Removing trusted dapp", + "add": "Add" }, "GetCredential": { "handling": "Handling credential offer", @@ -520,7 +521,7 @@ "import-success": "Successfully imported backup", "not-implemented": "Not implemented yet", "popups": "Pop-ups", - "popups-desc": "Disabling pop-ups is very dangerous. We recommend setting friendly dapps instead!", + "popups-desc": "Disabling pop-ups is very dangerous. We recommend setting trusted dapps instead!", "title": "Settings", "unknown-error": "Unknown error", "wallet-error": "Failed to get wallet ID" diff --git a/packages/dapp/src/utils/supabase/database.types.ts b/packages/dapp/src/utils/supabase/database.types.ts index 46eea7e3f..1b3525d8e 100644 --- a/packages/dapp/src/utils/supabase/database.types.ts +++ b/packages/dapp/src/utils/supabase/database.types.ts @@ -144,14 +144,14 @@ export type Tables< ? R : never : PublicTableNameOrOptions extends keyof (Database['public']['Tables'] & - Database['public']['Views']) - ? (Database['public']['Tables'] & - Database['public']['Views'])[PublicTableNameOrOptions] extends { - Row: infer R; - } - ? R - : never - : never; + Database['public']['Views']) + ? (Database['public']['Tables'] & + Database['public']['Views'])[PublicTableNameOrOptions] extends { + Row: infer R; + } + ? R + : never + : never; export type TablesInsert< PublicTableNameOrOptions extends @@ -167,12 +167,12 @@ export type TablesInsert< ? I : never : PublicTableNameOrOptions extends keyof Database['public']['Tables'] - ? Database['public']['Tables'][PublicTableNameOrOptions] extends { - Insert: infer I; - } - ? I - : never - : never; + ? Database['public']['Tables'][PublicTableNameOrOptions] extends { + Insert: infer I; + } + ? I + : never + : never; export type TablesUpdate< PublicTableNameOrOptions extends @@ -188,12 +188,12 @@ export type TablesUpdate< ? U : never : PublicTableNameOrOptions extends keyof Database['public']['Tables'] - ? Database['public']['Tables'][PublicTableNameOrOptions] extends { - Update: infer U; - } - ? U - : never - : never; + ? Database['public']['Tables'][PublicTableNameOrOptions] extends { + Update: infer U; + } + ? U + : never + : never; export type Enums< PublicEnumNameOrOptions extends @@ -205,5 +205,5 @@ export type Enums< > = PublicEnumNameOrOptions extends { schema: keyof Database } ? Database[PublicEnumNameOrOptions['schema']]['Enums'][EnumName] : PublicEnumNameOrOptions extends keyof Database['public']['Enums'] - ? Database['public']['Enums'][PublicEnumNameOrOptions] - : never; + ? Database['public']['Enums'][PublicEnumNameOrOptions] + : never; diff --git a/packages/docs/docs/integrate-masca/masca-connector.md b/packages/docs/docs/integrate-masca/masca-connector.md index 068587650..300bb2162 100644 --- a/packages/docs/docs/integrate-masca/masca-connector.md +++ b/packages/docs/docs/integrate-masca/masca-connector.md @@ -234,18 +234,18 @@ const vpRes = await api.verifyData({ presentation: VP, verbose: true }); `togglePopups` is used to enable/disable the `"Are you sure?"` alerts on any dapp. Pop-ups are enabled by default for user to approve every action. -`addFriendlyDapp` is used to add a current dapp (origin of the dapp) to the list of friendly dapps. Pop-ups do not appear on friendly dapps. +`addTrustedDapp` is used to add a dapp to the list of trusted dapps. Pop-ups do not appear on trusted dapps. This method can be called to add ANY dapp ONLY ON `https://masca.io`. On any other dapp origin is set automatically (You can only add dapp X on dapp X). -`removeFriendlyDapp` is used to remove a dapp from the list of friendly dapps. +`removeTrustedDapp` is used to remove a dapp from the list of trusted dapps. This method can only remove dapps with the same origin (dApp X can only remove dapp X). `getSnapSettings` and `getAccountSettings` are used to retrieve global settings and settings for currently selected account. ```typescript const res = await api.togglePopups(); -const res = await api.addFriendlyDapp(); +const res = await api.addTrustedDapp('https://masca.io'); -const res = await api.removeFriendlyDapp("https://www.masca.io"); +const res = await api.removeTrustedDapp("https://www.masca.io"); ``` ```typescript diff --git a/packages/docs/docs/integrate-masca/rpc-methods.md b/packages/docs/docs/integrate-masca/rpc-methods.md index 48ff3ece6..599aa521b 100644 --- a/packages/docs/docs/integrate-masca/rpc-methods.md +++ b/packages/docs/docs/integrate-masca/rpc-methods.md @@ -521,7 +521,7 @@ We recommend calling this method in `window.ethereum.on('accountsChanged', handl #### Description -`togglePopups` toggles pop-ups that show up whenever the user tries to save a VC, generate a VP, etc. Pop-ups are enabled by default to keep user in total control of their actions. With pop-ups disabled, a dapp can query user's credentials, etc. without them knowing. We recommend using `addFriendlyDapp` instead to only trust specific dapps. +`togglePopups` toggles pop-ups that show up whenever the user tries to save a VC, generate a VP, etc. Pop-ups are enabled by default to keep user in total control of their actions. With pop-ups disabled, a dapp can query user's credentials, etc. without them knowing. We recommend using `addTrustedDapp` instead to only trust specific dapps. ```typescript const response = await ethereum.request({ @@ -535,11 +535,11 @@ const response = await ethereum.request({ }); ``` -### addFriendlyDapp +### addTrustedDapp #### Description -`addFriendlyDapp` adds the current dapp (origin of the current dapp) to the list of friendly dapps. Friendly dapps do not show pop-ups. +`addTrustedDapp` adds a dapp to the list of trusted dapps. Trusted dapps do not show pop-ups. Dapps (other than `masca.io`) can only add themselves to the list of trusted dapps. ```typescript const response = await ethereum.request({ @@ -547,17 +547,20 @@ const response = await ethereum.request({ params: { snapId: snapId, request: { - method: 'addFriendlyDapp', + method: 'addTrustedDapp', + params: { + origin: 'https://www.masca.io', + }, }, }, }); ``` -### removeFriendlyDapp +### removeTrustedDapp #### Description -`removeFriendlyDapp` removes a dapp from friendly dapps. +`removeTrustedDapp` removes a dapp from trusted dapps. Dapps (other than `masca.io`) can only remove themselves from the list of trusted dapps. ```typescript const response = await ethereum.request({ @@ -565,9 +568,9 @@ const response = await ethereum.request({ params: { snapId: snapId, request: { - method: 'removeFriendlyDapp', + method: 'removeTrustedDapp', params: { - id: 'https://www.masca.io', + origin: 'https://www.masca.io', }, }, }, @@ -635,7 +638,7 @@ export type MascaConfig = { }; dApp: { disablePopups: boolean; - friendlyDapps: string[]; + trustedDapps: string[]; }; }; ``` diff --git a/packages/snap/snap.manifest.json b/packages/snap/snap.manifest.json index 9ad3f29f1..e3fa56013 100644 --- a/packages/snap/snap.manifest.json +++ b/packages/snap/snap.manifest.json @@ -26,7 +26,7 @@ "./files/circuits/credentialAtomicQuerySigV2/circuit_final.zkey", "./files/circuits/credentialAtomicQuerySigV2/verification_key.json" ], - "shasum": "WcGYh+wxUGmNhtRywe2CtCMeSCk2kSi4GMm+tLoE4No=" + "shasum": "47l9MPTWaA9XbNEHnA1U5k6cuOpm5qc3+QsPd+zgOYU=" }, "initialPermissions": { "endowment:ethereum-provider": {}, diff --git a/packages/snap/src/General.service.ts b/packages/snap/src/General.service.ts index e01e49b22..d43b81e2c 100644 --- a/packages/snap/src/General.service.ts +++ b/packages/snap/src/General.service.ts @@ -58,47 +58,51 @@ class GeneralService { } /** - * Function that lets you add a friendly dapp - * @param dapp - dapp to add to the friendly dapps list. + * Function that lets you add a trusted dapp + * @param dapp - dapp to add to the trusted dapps list. * @returns void */ - static async addFriendlyDapp(params: { id: string }): Promise { + static async addTrustedDapp(params: { origin: string }): Promise { const state = StorageService.get(); + if (params.origin === '' || !params.origin) + throw new Error('No origin provided.'); if ( - state[CURRENT_STATE_VERSION].config.dApp.friendlyDapps.includes(params.id) + state[CURRENT_STATE_VERSION].config.dApp.trustedDapps.includes( + params.origin + ) ) return; - if (!(await UIService.addFriendlyDappDialog(params.id))) { - throw new Error('User rejected friendly dapp addition.'); + if (!(await UIService.addTrustedDappDialog(params.origin))) { + throw new Error('User rejected trusted dapp addition.'); } - state[CURRENT_STATE_VERSION].config.dApp.friendlyDapps.push(params.id); + state[CURRENT_STATE_VERSION].config.dApp.trustedDapps.push(params.origin); } /** - * Function that lets you remove a friendly dapp - * @param dapp - dapp to remove from the friendly dapps list. + * Function that lets you remove a trusted dapp + * @param dapp - dapp to remove from the trusted dapps list. * @returns void */ - static async removeFriendlyDapp(params: { id: string }): Promise { - if (!(await UIService.removeFriendlyDappDialog(params.id))) { - throw new Error('User rejected friendly dapp removal.'); + static async removeTrustedDapp(params: { origin: string }): Promise { + if (!(await UIService.removeTrustedDappDialog(params.origin))) { + throw new Error('User rejected trusted dapp removal.'); } const state = StorageService.get(); - state[CURRENT_STATE_VERSION].config.dApp.friendlyDapps = state[ + state[CURRENT_STATE_VERSION].config.dApp.trustedDapps = state[ CURRENT_STATE_VERSION - ].config.dApp.friendlyDapps.filter((d) => d !== params.id); + ].config.dApp.trustedDapps.filter((d) => d !== params.origin); } /** - * Function that checks if a dApp is friendly + * Function that checks if a dApp is trusted * @param params.id - dApp to check. - * @returns boolean - whether the dapp is friendly. + * @returns boolean - whether the dapp is trusted. */ - static async isFriendlyDapp(params: { id: string }): Promise { + static async isTrustedDapp(params: { id: string }): Promise { const { id } = params; const state = StorageService.get(); - return state[CURRENT_STATE_VERSION].config.dApp.friendlyDapps.includes(id); + return state[CURRENT_STATE_VERSION].config.dApp.trustedDapps.includes(id); } /** diff --git a/packages/snap/src/Snap.service.ts b/packages/snap/src/Snap.service.ts index 10047a539..e129322f8 100644 --- a/packages/snap/src/Snap.service.ts +++ b/packages/snap/src/Snap.service.ts @@ -471,6 +471,8 @@ class SnapService { let res; + let trustedOrigin = origin; + const state = StorageService.get(); switch (method) { @@ -545,11 +547,15 @@ class SnapService { case 'togglePopups': res = await GeneralService.togglePopups(); return ResultObject.success(res); - case 'addFriendlyDapp': - await GeneralService.addFriendlyDapp({ id: this.origin }); + case 'addTrustedDapp': + if (origin === 'masca.io') + trustedOrigin = new URL(params.origin).hostname; + await GeneralService.addTrustedDapp({ origin: trustedOrigin }); return ResultObject.success(true); - case 'removeFriendlyDapp': - await GeneralService.removeFriendlyDapp(params); + case 'removeTrustedDapp': + if (origin !== 'masca.io' && origin !== new URL(params.origin).hostname) + throw new Error('Unauthorized to remove other dApps'); + await GeneralService.removeTrustedDapp({ origin: trustedOrigin }); return ResultObject.success(true); case 'switchDIDMethod': isValidSwitchMethodRequest(params); diff --git a/packages/snap/src/UI.service.ts b/packages/snap/src/UI.service.ts index d96d2b73b..dca1fcb17 100644 --- a/packages/snap/src/UI.service.ts +++ b/packages/snap/src/UI.service.ts @@ -16,6 +16,7 @@ import { import { W3CVerifiableCredential } from '@veramo/core'; import StorageService from './storage/Storage.service'; +import { isTrustedDapp } from './utils/permissions'; class UIService { static origin: string; @@ -34,11 +35,11 @@ class UIService { const { content, force = false } = params; const state = StorageService.get(); - const { disablePopups, friendlyDapps } = + const { disablePopups, trustedDapps } = state[CURRENT_STATE_VERSION].config.dApp; - // Show popups if force is true or if popups are not disabled AND the dapp is not friendly - if (force || !(disablePopups || friendlyDapps.includes(this.origin))) { + // Show popups if force is true or if popups are not disabled AND the dapp is not trusted + if (force || !(disablePopups || isTrustedDapp(this.origin, trustedDapps))) { const res = await snap.request({ method: 'snap_dialog', params: { @@ -58,11 +59,11 @@ class UIService { const { content, force = false } = params; const state = StorageService.get(); - const { disablePopups, friendlyDapps } = + const { disablePopups, trustedDapps } = state[CURRENT_STATE_VERSION].config.dApp; - // Show popups if force is true or if popups are not disabled AND the dapp is not friendly - if (force || !(disablePopups || friendlyDapps.includes(this.origin))) { + // Show popups if force is true or if popups are not disabled AND the dapp is not trusted + if (force || !(disablePopups || trustedDapps.includes(this.origin))) { await snap.request({ method: 'snap_dialog', params: { @@ -225,25 +226,25 @@ class UIService { return res; } - static async addFriendlyDappDialog(origin: string) { + static async addTrustedDappDialog(origin: string) { const uiPanel = panel([ - heading('Add Friendly DApp'), + heading('Add Trusted DApp'), ...this.originWrapper, - text(`Would you like to add ${origin} as a friendly dapp?`), + text(`Would you like to add ${origin} as a trusted dapp?`), divider(), - text('Pop-ups do not appear on friendly dapps.'), + text('Pop-ups do not appear on trusted dapps.'), ]); const res = await UIService.snapConfirm({ content: uiPanel, force: true }); return res; } - static async removeFriendlyDappDialog(origin: string) { + static async removeTrustedDappDialog(origin: string) { const uiPanel = panel([ - heading('Remove Friendly DApp'), + heading('Remove Trusted DApp'), ...this.originWrapper, text( - `Would you like to remove ${origin} from the list of friendly dapps?` + `Would you like to remove ${origin} from the list of trusted dapps?` ), ]); diff --git a/packages/snap/src/index.ts b/packages/snap/src/index.ts index 4ea21f95e..55901b384 100644 --- a/packages/snap/src/index.ts +++ b/packages/snap/src/index.ts @@ -16,6 +16,7 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ request, origin, }): Promise> => { + const referrer = new URL(origin); try { await StorageService.init(); @@ -40,7 +41,11 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ const { method, params } = request; - const response = await SnapService.handleRpcRequest(method, params, origin); + const response = await SnapService.handleRpcRequest( + method, + params, + referrer.hostname + ); await StorageService.save(); diff --git a/packages/snap/src/utils/config.ts b/packages/snap/src/utils/config.ts index 15eb6f0cc..4e6d74a74 100644 --- a/packages/snap/src/utils/config.ts +++ b/packages/snap/src/utils/config.ts @@ -69,7 +69,7 @@ const initialSnapState: MascaState = { config: { dApp: { disablePopups: false, - friendlyDapps: [], + trustedDapps: [], }, snap: { acceptedTerms: true, diff --git a/packages/snap/src/utils/permissions.ts b/packages/snap/src/utils/permissions.ts new file mode 100644 index 000000000..38a498b3f --- /dev/null +++ b/packages/snap/src/utils/permissions.ts @@ -0,0 +1,3 @@ +export function isTrustedDapp(origin: string, trustedDapps: string[]) { + return trustedDapps.includes(new URL(origin).hostname); +} diff --git a/packages/snap/tests/cron/handleAuthorizationFlow.spec.ts b/packages/snap/tests/cron/handleAuthorizationFlow.spec.ts index 0c0be64c4..a8010e445 100644 --- a/packages/snap/tests/cron/handleAuthorizationFlow.spec.ts +++ b/packages/snap/tests/cron/handleAuthorizationFlow.spec.ts @@ -27,7 +27,7 @@ describe('handlePolygonFlow', () => { it('should succeed authorization and credential offer for Polygon ID', async () => { const resSwitchMethod = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -54,7 +54,7 @@ describe('handlePolygonFlow', () => { ); const resHandleAuthRequest = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -71,7 +71,7 @@ describe('handlePolygonFlow', () => { `https://issuer-v2.polygonid.me/api/status?id=${sessionId}` ); const did = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -123,7 +123,7 @@ describe('handlePolygonFlow', () => { await responseCredentialOffer.json() ); const resCredentialOffer = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/data/defaultSnapState.ts b/packages/snap/tests/data/defaultSnapState.ts index 036ddc339..c748f9b99 100644 --- a/packages/snap/tests/data/defaultSnapState.ts +++ b/packages/snap/tests/data/defaultSnapState.ts @@ -17,7 +17,7 @@ const defaultSnapState = (address: string): MascaState => { config: { dApp: { disablePopups: false, - friendlyDapps: [], + trustedDapps: [], }, snap: { acceptedTerms: true, diff --git a/packages/snap/tests/e2e/addFriendlyDapp.spec.ts b/packages/snap/tests/e2e/addFriendlyDapp.spec.ts deleted file mode 100644 index 03ab066bf..000000000 --- a/packages/snap/tests/e2e/addFriendlyDapp.spec.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { CURRENT_STATE_VERSION } from '@blockchain-lab-um/masca-types'; -import { isError, Result } from '@blockchain-lab-um/utils'; -import { MetaMaskInpageProvider } from '@metamask/providers'; -import { SnapsProvider } from '@metamask/snaps-sdk'; -import { beforeAll, describe, expect, it, vi } from 'vitest'; - -import { onRpcRequest } from '../../src'; -import UIService from '../../src/UI.service'; -import { account } from '../data/constants'; -import { getDefaultSnapState } from '../data/defaultSnapState'; -import { createMockSnap, SnapMock } from '../helpers/snapMock'; - -describe('addFriendlyDapp', () => { - let snapMock: SnapsProvider & SnapMock; - - beforeAll(async () => { - snapMock = createMockSnap(); - global.snap = snapMock; - global.ethereum = snapMock as unknown as MetaMaskInpageProvider; - }); - - it('should add a friendlyDapp to the list', async () => { - const defaultState = getDefaultSnapState(account); - await snapMock.rpcMocks.snap_manageState({ - operation: 'update', - newState: defaultState, - }); - - const res = (await onRpcRequest({ - origin: 'localhost', - request: { - id: 'test-id', - jsonrpc: '2.0', - method: 'addFriendlyDapp', - params: {}, - }, - })) as Result; - - if (isError(res)) { - throw new Error(res.error); - } - - expect(res.data).toBe(true); - - const state = await snapMock.rpcMocks.snap_manageState({ - operation: 'get', - }); - - expect( - state[CURRENT_STATE_VERSION].config.dApp.friendlyDapps - ).toStrictEqual(['localhost']); - - expect.assertions(2); - }); - - it('Should not show pop-up if the dapp is already in the list', async () => { - const spy = vi.spyOn(UIService, 'addFriendlyDappDialog'); - - const defaultState = getDefaultSnapState(account); - defaultState[CURRENT_STATE_VERSION].config.dApp.friendlyDapps = [ - 'localhost2', - ]; - await snapMock.rpcMocks.snap_manageState({ - operation: 'update', - newState: defaultState, - }); - - await onRpcRequest({ - origin: 'localhost2', - request: { - id: 'test-id', - jsonrpc: '2.0', - method: 'queryVCs', - params: {}, - }, - }); - - expect(spy).toHaveBeenCalledTimes(0); - expect.assertions(1); - }); -}); diff --git a/packages/snap/tests/e2e/addTrustedDapp.spec.ts b/packages/snap/tests/e2e/addTrustedDapp.spec.ts new file mode 100644 index 000000000..9f0662598 --- /dev/null +++ b/packages/snap/tests/e2e/addTrustedDapp.spec.ts @@ -0,0 +1,152 @@ +import { CURRENT_STATE_VERSION } from '@blockchain-lab-um/masca-types'; +import { isError, Result } from '@blockchain-lab-um/utils'; +import { MetaMaskInpageProvider } from '@metamask/providers'; +import { SnapsProvider } from '@metamask/snaps-sdk'; +import { beforeAll, describe, expect, it, vi } from 'vitest'; + +import { onRpcRequest } from '../../src'; +import UIService from '../../src/UI.service'; +import { account } from '../data/constants'; +import { getDefaultSnapState } from '../data/defaultSnapState'; +import { createMockSnap, SnapMock } from '../helpers/snapMock'; + +describe('addTrustedDapp', () => { + let snapMock: SnapsProvider & SnapMock; + + beforeAll(async () => { + snapMock = createMockSnap(); + global.snap = snapMock; + global.ethereum = snapMock as unknown as MetaMaskInpageProvider; + }); + + it('should add any trustedDapp to the list', async () => { + const defaultState = getDefaultSnapState(account); + await snapMock.rpcMocks.snap_manageState({ + operation: 'update', + newState: defaultState, + }); + + const res = (await onRpcRequest({ + origin: 'https://masca.io', + request: { + id: 'test-id', + jsonrpc: '2.0', + method: 'addTrustedDapp', + params: { origin: 'http://localhost:8081' }, + }, + })) as Result; + + if (isError(res)) { + throw new Error(res.error); + } + + expect(res.data).toBe(true); + + const state = await snapMock.rpcMocks.snap_manageState({ + operation: 'get', + }); + + expect(state[CURRENT_STATE_VERSION].config.dApp.trustedDapps).toStrictEqual( + ['localhost'] + ); + + expect.assertions(2); + }); + + it('should add origin trustedDapp to the list on a random dApp', async () => { + const defaultState = getDefaultSnapState(account); + await snapMock.rpcMocks.snap_manageState({ + operation: 'update', + newState: defaultState, + }); + + const res = (await onRpcRequest({ + origin: 'http://random-different.com', + request: { + id: 'test-id', + jsonrpc: '2.0', + method: 'addTrustedDapp', + params: { origin: 'http://random.com' }, + }, + })) as Result; + + if (isError(res)) { + throw new Error(res.error); + } + + expect(res.data).toBe(true); + + const state = await snapMock.rpcMocks.snap_manageState({ + operation: 'get', + }); + + expect(state[CURRENT_STATE_VERSION].config.dApp.trustedDapps).toStrictEqual( + ['random-different.com'] + ); + + expect.assertions(2); + }); + + it('should not add empty trustedDapp to the list', async () => { + const defaultState = getDefaultSnapState(account); + defaultState[CURRENT_STATE_VERSION].config.dApp.trustedDapps = [ + 'localhost', + ]; + await snapMock.rpcMocks.snap_manageState({ + operation: 'update', + newState: defaultState, + }); + + const res = (await onRpcRequest({ + origin: 'http://localhost:8081', + request: { + id: 'test-id', + jsonrpc: '2.0', + method: 'addTrustedDapp', + params: {}, + }, + })) as Result; + + if (isError(res)) { + throw new Error(res.error); + } + + expect(res.data).toBe(true); + + const state = await snapMock.rpcMocks.snap_manageState({ + operation: 'get', + }); + + expect(state[CURRENT_STATE_VERSION].config.dApp.trustedDapps).toStrictEqual( + ['localhost'] + ); + + expect.assertions(2); + }); + + it('Should not show pop-up if the dapp is already in the list', async () => { + const spy = vi.spyOn(UIService, 'addTrustedDappDialog'); + + const defaultState = getDefaultSnapState(account); + defaultState[CURRENT_STATE_VERSION].config.dApp.trustedDapps = [ + 'localhost2', + ]; + await snapMock.rpcMocks.snap_manageState({ + operation: 'update', + newState: defaultState, + }); + + await onRpcRequest({ + origin: 'http://localhost2:8081', + request: { + id: 'test-id', + jsonrpc: '2.0', + method: 'queryVCs', + params: {}, + }, + }); + + expect(spy).toHaveBeenCalledTimes(0); + expect.assertions(1); + }); +}); diff --git a/packages/snap/tests/e2e/createVerifiableCredential.spec.ts b/packages/snap/tests/e2e/createVerifiableCredential.spec.ts index 3ecfc30ed..401d029ff 100644 --- a/packages/snap/tests/e2e/createVerifiableCredential.spec.ts +++ b/packages/snap/tests/e2e/createVerifiableCredential.spec.ts @@ -55,7 +55,7 @@ describe('createVerifiableCredential', () => { agent = VeramoService.getAgent(); const switchMethod = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -78,7 +78,7 @@ describe('createVerifiableCredential', () => { describe.each(proofFormats)('Using Proof Format: %s', (proofFormat) => { it('Should create a VerifiableCredential', async () => { const vc = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -112,7 +112,7 @@ describe('createVerifiableCredential', () => { 'Should create and save a VerifiableCredential in %s', async (store) => { const vc = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -133,7 +133,7 @@ describe('createVerifiableCredential', () => { } const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -158,7 +158,7 @@ describe('createVerifiableCredential', () => { it('Should create a VC without proofFormat option set', async () => { const vc = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -186,7 +186,7 @@ describe('createVerifiableCredential', () => { it.skip('Should fail creating a VC without minimalUnsignedCredential', async () => { const vc = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -206,7 +206,7 @@ describe('createVerifiableCredential', () => { it('Should fail creating a VC with invalid minimalUnsignedCredential', async () => { const vc = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/createVerifiablePresentation.spec.ts b/packages/snap/tests/e2e/createVerifiablePresentation.spec.ts index 2741dbaa7..e90476e54 100644 --- a/packages/snap/tests/e2e/createVerifiablePresentation.spec.ts +++ b/packages/snap/tests/e2e/createVerifiablePresentation.spec.ts @@ -65,7 +65,7 @@ describe('createVerifiablePresentation', () => { agent = VeramoService.getAgent(); const switchMethod = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -92,7 +92,7 @@ describe('createVerifiablePresentation', () => { 'Should create a Verifiable Presentation with domain: `$domain` and challenge: `$challenge`', async (option) => { const vp = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -130,7 +130,7 @@ describe('createVerifiablePresentation', () => { } else { it('Should create a Verifiable Presentation without domain or challenge', async () => { const vp = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -167,7 +167,7 @@ describe('createVerifiablePresentation', () => { it('Should create a VP without proofFormat option set', async () => { const vp = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -200,7 +200,7 @@ describe('createVerifiablePresentation', () => { it('Should fail creating a VP without any VC', async () => { const vp = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -221,7 +221,7 @@ describe('createVerifiablePresentation', () => { it('Should fail creating a VP with invalid VC', async () => { const vp = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/deleteVerifiableCredentials.spec.ts b/packages/snap/tests/e2e/deleteVerifiableCredentials.spec.ts index 01af9dde3..6c3aa9172 100644 --- a/packages/snap/tests/e2e/deleteVerifiableCredentials.spec.ts +++ b/packages/snap/tests/e2e/deleteVerifiableCredentials.spec.ts @@ -91,7 +91,7 @@ describe('deleteCredential', () => { it('should succeed saving and deleting 1 VC', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -115,7 +115,7 @@ describe('deleteCredential', () => { ]); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -132,7 +132,7 @@ describe('deleteCredential', () => { expect(res.data).toEqual([true, false]); const result = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -152,7 +152,7 @@ describe('deleteCredential', () => { it('should succeed saving and deleting 1 VC with store', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -176,7 +176,7 @@ describe('deleteCredential', () => { ]); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -195,7 +195,7 @@ describe('deleteCredential', () => { expect(res.data).toEqual([true]); const result = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -215,7 +215,7 @@ describe('deleteCredential', () => { it('should fail deleting 1 VC with wrong id', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -239,7 +239,7 @@ describe('deleteCredential', () => { ]); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -258,7 +258,7 @@ describe('deleteCredential', () => { expect(res.error).toBe('Error: No VC found with the given id'); const result = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/exportStateBackup.spec.ts b/packages/snap/tests/e2e/exportStateBackup.spec.ts index 9639d5e35..683812769 100644 --- a/packages/snap/tests/e2e/exportStateBackup.spec.ts +++ b/packages/snap/tests/e2e/exportStateBackup.spec.ts @@ -61,7 +61,7 @@ describe('exportStateBackup', () => { it('Should suceed with default empty state', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -81,7 +81,7 @@ describe('exportStateBackup', () => { it('Should suceed with non-empty state (1 credential)', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -105,7 +105,7 @@ describe('exportStateBackup', () => { ]); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/getAccountSettings.spec.ts b/packages/snap/tests/e2e/getAccountSettings.spec.ts index bc553e887..06e7cf41e 100644 --- a/packages/snap/tests/e2e/getAccountSettings.spec.ts +++ b/packages/snap/tests/e2e/getAccountSettings.spec.ts @@ -26,7 +26,7 @@ describe('getAccountSettings', () => { const state = getDefaultSnapState(account); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/getAvailableMethods.spec.ts b/packages/snap/tests/e2e/getAvailableMethods.spec.ts index cdb32db53..5563ecd8a 100644 --- a/packages/snap/tests/e2e/getAvailableMethods.spec.ts +++ b/packages/snap/tests/e2e/getAvailableMethods.spec.ts @@ -24,7 +24,7 @@ describe('getAvailableMethods', () => { it('should succeed and return available methods', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/getAvailableVCStores.spec.ts b/packages/snap/tests/e2e/getAvailableVCStores.spec.ts index 715393616..69f8b0b8e 100644 --- a/packages/snap/tests/e2e/getAvailableVCStores.spec.ts +++ b/packages/snap/tests/e2e/getAvailableVCStores.spec.ts @@ -24,7 +24,7 @@ describe('getAvailableCredentialStores', () => { it('should succeed and return available VC stores', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/getDID.spec.ts b/packages/snap/tests/e2e/getDID.spec.ts index 5146c9a6d..c6c4820e4 100644 --- a/packages/snap/tests/e2e/getDID.spec.ts +++ b/packages/snap/tests/e2e/getDID.spec.ts @@ -51,7 +51,7 @@ describe('getDID', () => { 'should return correct identifier for $method', async (methodObj) => { const switchMethod = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -77,7 +77,7 @@ describe('getDID', () => { } const did = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/getSelectedMethod.spec.ts b/packages/snap/tests/e2e/getSelectedMethod.spec.ts index f94633408..e20667c84 100644 --- a/packages/snap/tests/e2e/getSelectedMethod.spec.ts +++ b/packages/snap/tests/e2e/getSelectedMethod.spec.ts @@ -24,7 +24,7 @@ describe('getSelectedMethod', () => { it('should succeed and return did:ethr', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -44,7 +44,7 @@ describe('getSelectedMethod', () => { it('should succeed and return did:key', async () => { await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -56,7 +56,7 @@ describe('getSelectedMethod', () => { }); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/getSnapSettings.spec.ts b/packages/snap/tests/e2e/getSnapSettings.spec.ts index 65da71984..cfa37824f 100644 --- a/packages/snap/tests/e2e/getSnapSettings.spec.ts +++ b/packages/snap/tests/e2e/getSnapSettings.spec.ts @@ -26,7 +26,7 @@ describe('getSnapSettings', () => { const state = getDefaultSnapState(account); it('should succeed and return snap settings', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/getVCStore.spec.ts b/packages/snap/tests/e2e/getVCStore.spec.ts index 0a91f7e2a..3c960ac90 100644 --- a/packages/snap/tests/e2e/getVCStore.spec.ts +++ b/packages/snap/tests/e2e/getVCStore.spec.ts @@ -23,7 +23,7 @@ describe('getVCStore', () => { it('should succeed and return snap', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/importStateBackup.spec.ts b/packages/snap/tests/e2e/importStateBackup.spec.ts index d2821dec2..674887171 100644 --- a/packages/snap/tests/e2e/importStateBackup.spec.ts +++ b/packages/snap/tests/e2e/importStateBackup.spec.ts @@ -63,7 +63,7 @@ describe('importStateBackup', () => { it('Should suceed with default empty state', async () => { const startState: MascaState = cloneDeep(StorageService.get()); const resExport = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -77,7 +77,7 @@ describe('importStateBackup', () => { } const resImport = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -96,7 +96,7 @@ describe('importStateBackup', () => { it('Should suceed with non-empty state (1 credential)', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -121,7 +121,7 @@ describe('importStateBackup', () => { const startState: MascaState = cloneDeep(StorageService.get()); const resExport = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -135,7 +135,7 @@ describe('importStateBackup', () => { } const resImport = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/queryVerifiableCredentials.spec.ts b/packages/snap/tests/e2e/queryVerifiableCredentials.spec.ts index 5b4967c83..e94ebbd6e 100644 --- a/packages/snap/tests/e2e/queryVerifiableCredentials.spec.ts +++ b/packages/snap/tests/e2e/queryVerifiableCredentials.spec.ts @@ -91,7 +91,7 @@ describe('queryVerifiableCredentials', () => { it('should succeed with empty array', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -111,7 +111,7 @@ describe('queryVerifiableCredentials', () => { it('should succeed with 1 VC matching query - filter by ID', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -138,7 +138,7 @@ describe('queryVerifiableCredentials', () => { ]; const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -163,7 +163,7 @@ describe('queryVerifiableCredentials', () => { it('should succeed with 1 VC matching query - no filter or store', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -190,7 +190,7 @@ describe('queryVerifiableCredentials', () => { ]; const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -210,7 +210,7 @@ describe('queryVerifiableCredentials', () => { it('should succeed with 1 VC matching query - store defined', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -237,7 +237,7 @@ describe('queryVerifiableCredentials', () => { ]; const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -259,7 +259,7 @@ describe('queryVerifiableCredentials', () => { it('should succeed with 1 VC matching query - without store', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -285,7 +285,7 @@ describe('queryVerifiableCredentials', () => { ]; const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -307,7 +307,7 @@ describe('queryVerifiableCredentials', () => { it('should succeed with 1 VC matching query - filter by JSONPath', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -334,7 +334,7 @@ describe('queryVerifiableCredentials', () => { ]; const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/removeFriendlyDapp.spec.ts b/packages/snap/tests/e2e/removeTrustedDapp.spec.ts similarity index 71% rename from packages/snap/tests/e2e/removeFriendlyDapp.spec.ts rename to packages/snap/tests/e2e/removeTrustedDapp.spec.ts index d2b85e718..bc4001023 100644 --- a/packages/snap/tests/e2e/removeFriendlyDapp.spec.ts +++ b/packages/snap/tests/e2e/removeTrustedDapp.spec.ts @@ -16,7 +16,7 @@ import { getDefaultSnapState } from '../data/defaultSnapState'; import { createTestVCs } from '../helpers/generateTestVCs'; import { createMockSnap, SnapMock } from '../helpers/snapMock'; -describe('removeFriendlyDapp', () => { +describe('removeTrustedDapp', () => { let snapMock: SnapsProvider & SnapMock; let generatedVC: VerifiableCredential; @@ -60,14 +60,52 @@ describe('removeFriendlyDapp', () => { } }); - it('should remove a friendlyDapp from the list', async () => { + it('should fail removing another trustedDapp from the list', async () => { const resultAdd = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost:8081', request: { id: 'test-id', jsonrpc: '2.0', - method: 'addFriendlyDapp', - params: {}, + method: 'addTrustedDapp', + params: { origin: 'http://localhost:8081' }, + }, + })) as Result; + + if (isError(resultAdd)) { + throw new Error(resultAdd.error); + } + + expect(resultAdd.data).toBe(true); + + const resultRemove = (await onRpcRequest({ + origin: 'http://localhost2:8081', + request: { + id: 'test-id', + jsonrpc: '2.0', + method: 'removeTrustedDapp', + params: { origin: 'http://localhost:8081' }, + }, + })) as Result; + + if (!isError(resultRemove)) { + throw new Error("Should've thrown an error"); + } + + expect(resultRemove.error).toBe( + 'Error: Unauthorized to remove other dApps' + ); + + expect.assertions(2); + }); + + it('should remove a trustedDapp from the list', async () => { + const resultAdd = (await onRpcRequest({ + origin: 'https://masca.io', + request: { + id: 'test-id', + jsonrpc: '2.0', + method: 'addTrustedDapp', + params: { origin: 'http://localhost:8081' }, }, })) as Result; @@ -78,12 +116,12 @@ describe('removeFriendlyDapp', () => { expect(resultAdd.data).toBe(true); const resultRemove = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost:8081', request: { id: 'test-id', jsonrpc: '2.0', - method: 'removeFriendlyDapp', - params: { id: 'localhost' }, + method: 'removeTrustedDapp', + params: { origin: 'http://localhost:8081' }, }, })) as Result; @@ -97,9 +135,9 @@ describe('removeFriendlyDapp', () => { operation: 'get', }); - expect( - state[CURRENT_STATE_VERSION].config.dApp.friendlyDapps - ).toStrictEqual([]); + expect(state[CURRENT_STATE_VERSION].config.dApp.trustedDapps).toStrictEqual( + [] + ); expect.assertions(3); }); @@ -115,7 +153,7 @@ describe('removeFriendlyDapp', () => { }); const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost:8081', request: { id: 'test-id', jsonrpc: '2.0', @@ -132,7 +170,7 @@ describe('removeFriendlyDapp', () => { } (await onRpcRequest({ - origin: 'localhost2', + origin: 'http://localhost2:8081', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/resolveDID.spec.ts b/packages/snap/tests/e2e/resolveDID.spec.ts index 0a9aa4484..681f7e437 100644 --- a/packages/snap/tests/e2e/resolveDID.spec.ts +++ b/packages/snap/tests/e2e/resolveDID.spec.ts @@ -37,7 +37,7 @@ describe('resolveDID', () => { 'should resolve a $didResolutionMetadata.did.method method', async (method) => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -68,7 +68,7 @@ describe('resolveDID', () => { it('should return an error if the did is not found', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/saveVerifiableCredential.spec.ts b/packages/snap/tests/e2e/saveVerifiableCredential.spec.ts index f143e6ffd..4e64bc37d 100644 --- a/packages/snap/tests/e2e/saveVerifiableCredential.spec.ts +++ b/packages/snap/tests/e2e/saveVerifiableCredential.spec.ts @@ -128,7 +128,7 @@ describe('saveVerifiableCredential', () => { 'Should save VC in correct store - $title', async (store) => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -158,7 +158,7 @@ describe('saveVerifiableCredential', () => { 'Should save & query VC in correct store - $title', async (store) => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -181,7 +181,7 @@ describe('saveVerifiableCredential', () => { ]); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -213,7 +213,7 @@ describe('saveVerifiableCredential', () => { 'Should succeed saving a JWT string and retrieving whole VC - %s', async (store) => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -236,7 +236,7 @@ describe('saveVerifiableCredential', () => { ]); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -266,7 +266,7 @@ describe('saveVerifiableCredential', () => { it('Should fail because store does not exist', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -291,7 +291,7 @@ describe('saveVerifiableCredential', () => { snapMock.rpcMocks.snap_dialog.mockReturnValue(false); let res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -312,7 +312,7 @@ describe('saveVerifiableCredential', () => { snapMock.rpcMocks.snap_dialog.mockReturnValue(true); res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -332,7 +332,7 @@ describe('saveVerifiableCredential', () => { it('should throw error because request is not valid', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -356,7 +356,7 @@ describe('saveVerifiableCredential', () => { it('should throw error because request is not valid: store format', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -379,7 +379,7 @@ describe('saveVerifiableCredential', () => { it('should throw error because request is not valid: store not supported in array', async () => { const saveRes = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/setCeramicSession.spec.ts b/packages/snap/tests/e2e/setCeramicSession.spec.ts index db60d8a9b..072856ea5 100644 --- a/packages/snap/tests/e2e/setCeramicSession.spec.ts +++ b/packages/snap/tests/e2e/setCeramicSession.spec.ts @@ -28,7 +28,7 @@ describe('setCeramicSession', () => { newState: defaultState, }); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/setCurrentAccount.spec.ts b/packages/snap/tests/e2e/setCurrentAccount.spec.ts index e5bbf74c6..416099054 100644 --- a/packages/snap/tests/e2e/setCurrentAccount.spec.ts +++ b/packages/snap/tests/e2e/setCurrentAccount.spec.ts @@ -26,7 +26,7 @@ describe('setCurrentAccount', () => { it('should succeed setting the current account', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -47,7 +47,7 @@ describe('setCurrentAccount', () => { it('should fail setting the current account - missing current account parameter', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -73,7 +73,7 @@ describe('setCurrentAccount', () => { }); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/setVCStore.spec.ts b/packages/snap/tests/e2e/setVCStore.spec.ts index 6b56cfd90..7de60200f 100644 --- a/packages/snap/tests/e2e/setVCStore.spec.ts +++ b/packages/snap/tests/e2e/setVCStore.spec.ts @@ -26,7 +26,7 @@ describe('setVCStore', () => { // FIXME: Enable after we put back params checks it.skip('should throw and error when using wrong vcStore', async () => { let res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -42,7 +42,7 @@ describe('setVCStore', () => { expect(res.error).toBe('Error: invalid_argument: $input.store'); res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -62,7 +62,7 @@ describe('setVCStore', () => { it('should succeed toggling ceramic store to true', async () => { let res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -78,7 +78,7 @@ describe('setVCStore', () => { expect(res.data).toBe(true); res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/signData.spec.ts b/packages/snap/tests/e2e/signData.spec.ts index b642bbadd..0d5f7043e 100644 --- a/packages/snap/tests/e2e/signData.spec.ts +++ b/packages/snap/tests/e2e/signData.spec.ts @@ -233,7 +233,7 @@ describe('signData', () => { currentMethod = testCase.method; const switchMethod = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -250,7 +250,7 @@ describe('signData', () => { } const signedData = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -335,7 +335,7 @@ describe('signData', () => { currentMethod = testCase.method; const switchMethod = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -351,7 +351,7 @@ describe('signData', () => { } const signedData = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -375,7 +375,7 @@ describe('signData', () => { */ it('should return an error if the DID method is not supported', async () => { const switchMethod = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -391,7 +391,7 @@ describe('signData', () => { } let signedData = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -417,7 +417,7 @@ describe('signData', () => { expect(signedData.error).toBe('Error: Unsupported DID method'); signedData = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/switchDIDMethod.spec.ts b/packages/snap/tests/e2e/switchDIDMethod.spec.ts index c96c0c029..c3096e52c 100644 --- a/packages/snap/tests/e2e/switchDIDMethod.spec.ts +++ b/packages/snap/tests/e2e/switchDIDMethod.spec.ts @@ -55,7 +55,7 @@ describe('switchDIDMethod', () => { 'should return correct identifier for $method', async (methodObj) => { const switchMethod = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/togglePopups.spec.ts b/packages/snap/tests/e2e/togglePopups.spec.ts index cdae60d88..3b469347a 100644 --- a/packages/snap/tests/e2e/togglePopups.spec.ts +++ b/packages/snap/tests/e2e/togglePopups.spec.ts @@ -26,7 +26,7 @@ describe('togglePopups', () => { it('should enable pop-ups and then disable them', async () => { const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -42,7 +42,7 @@ describe('togglePopups', () => { expect(res.data).toBe(true); const res2 = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/validateStoredCeramicSession.spec.ts b/packages/snap/tests/e2e/validateStoredCeramicSession.spec.ts index 6ef37bcb7..0dce2c188 100644 --- a/packages/snap/tests/e2e/validateStoredCeramicSession.spec.ts +++ b/packages/snap/tests/e2e/validateStoredCeramicSession.spec.ts @@ -29,7 +29,7 @@ describe('validateStoredCeramicSession', () => { newState: defaultState, }); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -57,7 +57,7 @@ describe('validateStoredCeramicSession', () => { newState: defaultState, }); const res = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/snap/tests/e2e/verifyData.spec.ts b/packages/snap/tests/e2e/verifyData.spec.ts index 09705a378..84d2bbd78 100644 --- a/packages/snap/tests/e2e/verifyData.spec.ts +++ b/packages/snap/tests/e2e/verifyData.spec.ts @@ -64,7 +64,7 @@ describe('verifyData', () => { it('should succeed verifiying a VC', async () => { const verifyDataResult = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -85,7 +85,7 @@ describe('verifyData', () => { it('should succeed verifying a VP', async () => { const switchMethodResult = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -101,7 +101,7 @@ describe('verifyData', () => { } const createPresentationResult = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', @@ -117,7 +117,7 @@ describe('verifyData', () => { } const verified = (await onRpcRequest({ - origin: 'localhost', + origin: 'http://localhost', request: { id: 'test-id', jsonrpc: '2.0', diff --git a/packages/types/src/api.ts b/packages/types/src/api.ts index 761f4038b..e3fa55ccf 100644 --- a/packages/types/src/api.ts +++ b/packages/types/src/api.ts @@ -78,8 +78,8 @@ export interface MascaApi { ): Promise>; setCeramicSession(serializedSession: string): Promise>; validateStoredCeramicSession(): Promise>; - addFriendlyDapp(): Promise>; - removeFriendlyDapp(id: string): Promise>; + addTrustedDapp(origin: string): Promise>; + removeTrustedDapp(origin: string): Promise>; importStateBackup( params: ImportStateBackupRequestParams ): Promise>; diff --git a/packages/types/src/methods.ts b/packages/types/src/methods.ts index 0b6297d75..45199567c 100644 --- a/packages/types/src/methods.ts +++ b/packages/types/src/methods.ts @@ -1,4 +1,5 @@ import type { + AddTrustedDappRequestParams, CreateCredentialRequestParams, CreatePresentationRequestParams, DeleteCredentialsRequestParams, @@ -6,7 +7,7 @@ import type { HandleCredentialOfferRequestParams, ImportStateBackupRequestParams, QueryCredentialsRequestParams, - RemoveFriendlyDappRequestParams, + RemoveTrustedDappRequestParams, ResolveDIDRequestParams, SaveCredentialRequestParams, SetCeramicSessionRequestParams, @@ -127,13 +128,14 @@ export interface ImportStateBackup { params: ImportStateBackupRequestParams; } -export interface AddFriendlyDapp { - method: 'addFriendlyDapp'; +export interface AddTrustedDapp { + method: 'addTrustedDapp'; + params: AddTrustedDappRequestParams; } -export interface RemoveFriendlyDapp { - method: 'removeFriendlyDapp'; - params: RemoveFriendlyDappRequestParams; +export interface RemoveTrustedDapp { + method: 'removeTrustedDapp'; + params: RemoveTrustedDappRequestParams; } export interface GetWalletId { diff --git a/packages/types/src/params.ts b/packages/types/src/params.ts index 771d196dd..9796516d6 100644 --- a/packages/types/src/params.ts +++ b/packages/types/src/params.ts @@ -156,8 +156,12 @@ export interface ImportStateBackupRequestParams { serializedState: string; } -export interface RemoveFriendlyDappRequestParams { - id: string; +export interface AddTrustedDappRequestParams { + origin: string; +} + +export interface RemoveTrustedDappRequestParams { + origin: string; } export type SignDataRequestParams = { diff --git a/packages/types/src/requests.ts b/packages/types/src/requests.ts index 443f21f4e..c7ff39261 100644 --- a/packages/types/src/requests.ts +++ b/packages/types/src/requests.ts @@ -1,5 +1,5 @@ import type { - AddFriendlyDapp, + AddTrustedDapp, CreateCredential, CreatePresentation, DeleteCredential, @@ -16,7 +16,7 @@ import type { HandleCredentialOffer, ImportStateBackup, QueryCredentials, - RemoveFriendlyDapp, + RemoveTrustedDapp, ResolveDID, SaveCredential, SetCeramicSession, @@ -35,8 +35,8 @@ export type MascaRPCRequest = | CreatePresentation | DeleteCredential | TogglePopups - | AddFriendlyDapp - | RemoveFriendlyDapp + | AddTrustedDapp + | RemoveTrustedDapp | GetDID | GetMethod | GetAvailableMethods diff --git a/packages/types/src/state.ts b/packages/types/src/state.ts index deabb5d02..d5130d97a 100644 --- a/packages/types/src/state.ts +++ b/packages/types/src/state.ts @@ -13,7 +13,7 @@ export interface MascaConfig { }; dApp: { disablePopups: boolean; - friendlyDapps: string[]; + trustedDapps: string[]; }; }