diff --git a/package.json b/package.json index 2ba9fb742b4..5a6fbcaff8f 100644 --- a/package.json +++ b/package.json @@ -97,12 +97,12 @@ "@sentry/tracing": "6.16.1", "@stacks/blockchain-api-client": "0.65.0", "@stacks/common": "3.0.0", - "@stacks/storage": "3.2.0", "@stacks/connect": "6.4.0", "@stacks/connect-ui": "5.2.0", "@stacks/encryption": "3.0.0", "@stacks/network": "3.0.0", "@stacks/rpc-client": "1.0.3", + "@stacks/storage": "3.2.0", "@stacks/transactions": "3.0.0", "@stacks/ui": "7.10.0", "@stacks/ui-core": "7.3.0", @@ -253,6 +253,7 @@ "ts-node": "10.4", "ts-unused-exports": "7.0.3", "tsconfig-paths-webpack-plugin": "3.5.2", + "type-fest": "2.12.2", "typescript": "4.5.4", "vm-browserify": "1.1.2", "web-ext": "6.2.0", diff --git a/src/app/common/actions/send-request-account-response.ts b/src/app/common/actions/send-request-account-response.ts new file mode 100644 index 00000000000..ab882c3d193 --- /dev/null +++ b/src/app/common/actions/send-request-account-response.ts @@ -0,0 +1,18 @@ +import { SoftwareWalletAccountWithAddress } from '@app/store/accounts/account.models'; +import { sendMessageToTab } from '@shared/messages'; + +interface SendRequestAccountResponseToTabArgs { + tabId: string; + id: string; + account: SoftwareWalletAccountWithAddress; +} +export function sendRequestAccountResponseToTab(args: SendRequestAccountResponseToTabArgs) { + const { tabId, id, account } = args; + + const safeAccountKeys = { + stxPublicKey: account.stxPublicKey, + dataPublicKey: account.dataPublicKey, + }; + + return sendMessageToTab(parseInt(tabId), id, safeAccountKeys); +} diff --git a/src/app/common/hooks/auth/use-save-auth-request-callback.ts b/src/app/common/hooks/auth/use-save-auth-request-callback.ts index c0749077022..8d628efb26a 100644 --- a/src/app/common/hooks/auth/use-save-auth-request-callback.ts +++ b/src/app/common/hooks/auth/use-save-auth-request-callback.ts @@ -31,7 +31,7 @@ export function useSaveAuthRequest() { appURL: new URL(origin), }); - navigate(RouteUrls.ChooseAccount); + navigate(RouteUrls.AccountAuthentication); }, [saveAuthRequest, navigate] ); diff --git a/src/app/common/hooks/use-key-actions.ts b/src/app/common/hooks/use-key-actions.ts index cbaf6b69622..b8fee586ed3 100644 --- a/src/app/common/hooks/use-key-actions.ts +++ b/src/app/common/hooks/use-key-actions.ts @@ -7,7 +7,7 @@ import { clearSessionLocalData } from '@app/common/store-utils'; import { createNewAccount, stxChainActions } from '@app/store/chains/stx-chain.actions'; import { keyActions } from '@app/store/keys/key.actions'; import { useAnalytics } from './analytics/use-analytics'; -import { sendMessage } from '@shared/messages'; +import { sendMessageToBackground } from '@shared/messages'; import { InternalMethods } from '@shared/message-types'; import { inMemoryKeyActions } from '@app/store/in-memory-key/in-memory-key.actions'; @@ -23,7 +23,7 @@ export function useKeyActions() { generateWalletKey() { const secretKey = generateSecretKey(256); - sendMessage({ + sendMessageToBackground({ method: InternalMethods.ShareInMemoryKeyToBackground, payload: { secretKey, keyId: 'default' }, }); @@ -45,12 +45,12 @@ export function useKeyActions() { async signOut() { void analytics.track('sign_out'); dispatch(keyActions.signOut()); - sendMessage({ method: InternalMethods.RemoveInMemoryKeys, payload: undefined }); + sendMessageToBackground({ method: InternalMethods.RemoveInMemoryKeys, payload: undefined }); clearSessionLocalData(); }, lockWallet() { - sendMessage({ method: InternalMethods.RemoveInMemoryKeys, payload: undefined }); + sendMessageToBackground({ method: InternalMethods.RemoveInMemoryKeys, payload: undefined }); return dispatch(inMemoryKeyActions.lockWallet()); }, }), diff --git a/src/app/features/account-picker/accounts.tsx b/src/app/features/account-picker/accounts.tsx index 53b4cceb8e4..d6e06744518 100644 --- a/src/app/features/account-picker/accounts.tsx +++ b/src/app/features/account-picker/accounts.tsx @@ -65,11 +65,7 @@ const AccountItem = memo((props: AccountItemProps) => { /> } > - + diff --git a/src/app/pages/choose-account-request/account-request.tsx b/src/app/pages/choose-account-request/account-request.tsx index a9c13d53f90..d733c4261ee 100644 --- a/src/app/pages/choose-account-request/account-request.tsx +++ b/src/app/pages/choose-account-request/account-request.tsx @@ -2,37 +2,39 @@ import { useRouteHeader } from '@app/common/hooks/use-route-header'; import { useAppDetails } from '@app/common/hooks/auth/use-app-details'; import { Header } from '@app/components/header'; import { AccountPicker } from '@app/features/account-picker/accounts'; -import { useOnboardingState } from '@app/common/hooks/auth/use-onboarding-state'; import { useAccounts } from '@app/store/accounts/account.hooks'; import { AccountPickerLayout } from '@app/features/account-picker/account-picker.layout'; +import { logger } from '@shared/logger'; +import { sendRequestAccountResponseToTab } from '@app/common/actions/send-request-account-response'; + +import { useAccountRequestSearchParams } from './use-account-request-search-params'; export function AccountRequest() { const accounts = useAccounts(); const { name: appName } = useAppDetails(); - const { decodedAuthRequest } = useOnboardingState(); - // const [selectedAccountIndex, setSelectedAccountIndex] = useState(null); + + const { tabId, id } = useAccountRequestSearchParams(); useRouteHeader(
); const returnAccountDetailsToApp = async (index: number) => { - // setSelectedAccountIndex(index); - // await finishSignIn(index); - }; + if (!tabId || !id) { + logger.error('Missing either tabId or uuid. Both necessary to respond to app'); + return; + } - // const handleUnmount = useCallback(async () => { - // cancelAuthentication(); - // }, [cancelAuthentication]); + if (!accounts) return; - // useEffect(() => { - // window.addEventListener('beforeunload', handleUnmount); - // return () => window.removeEventListener('beforeunload', handleUnmount); - // }, [handleUnmount]); + console.log('xxxxxx', accounts[index]); + sendRequestAccountResponseToTab({ tabId, id, account: accounts[index] }); + // window.close(); + }; return ( returnAccountDetailsToApp(index)} - selectedAccountIndex={0} + selectedAccountIndex={null} /> ); diff --git a/src/app/pages/choose-account-request/use-account-request-search-params.ts b/src/app/pages/choose-account-request/use-account-request-search-params.ts new file mode 100644 index 00000000000..82ae533d80c --- /dev/null +++ b/src/app/pages/choose-account-request/use-account-request-search-params.ts @@ -0,0 +1,14 @@ +import { useMemo } from 'react'; +import { useSearchParams } from 'react-router-dom'; + +export function useAccountRequestSearchParams() { + const [searchParams] = useSearchParams(); + + return useMemo( + () => ({ + tabId: searchParams.get('tabId'), + id: searchParams.get('id'), + }), + [searchParams] + ); +} diff --git a/src/app/pages/home/home.tsx b/src/app/pages/home/home.tsx index df9f345cff9..551767d94b8 100644 --- a/src/app/pages/home/home.tsx +++ b/src/app/pages/home/home.tsx @@ -36,7 +36,7 @@ export function Home() { ); useEffect(() => { - if (decodedAuthRequest) navigate(RouteUrls.ChooseAccount); + if (decodedAuthRequest) navigate(RouteUrls.AccountAuthentication); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); diff --git a/src/app/pages/onboarding/set-password/set-password.tsx b/src/app/pages/onboarding/set-password/set-password.tsx index 89f37000ad5..794375835c0 100644 --- a/src/app/pages/onboarding/set-password/set-password.tsx +++ b/src/app/pages/onboarding/set-password/set-password.tsx @@ -62,7 +62,7 @@ export const SetPasswordPage = () => { if (!wallet) return; const { accounts } = wallet; if (accounts && accounts.length > 1) { - navigate(RouteUrls.ChooseAccount); + navigate(RouteUrls.AccountAuthentication); } else { await finishSignIn(0); } diff --git a/src/app/pages/unlock.tsx b/src/app/pages/unlock.tsx index 159b0412650..8fdb0a248b5 100644 --- a/src/app/pages/unlock.tsx +++ b/src/app/pages/unlock.tsx @@ -52,7 +52,7 @@ export function Unlock(): JSX.Element { await unlockWallet(password); if (decodedAuthRequest) { - navigate(RouteUrls.ChooseAccount); + navigate(RouteUrls.AccountAuthentication); } else { navigate(RouteUrls.Home); } diff --git a/src/app/routes/app-routes.tsx b/src/app/routes/app-routes.tsx index 1e33e4061b9..25b1f319775 100644 --- a/src/app/routes/app-routes.tsx +++ b/src/app/routes/app-routes.tsx @@ -28,6 +28,7 @@ import { RouteUrls } from '@shared/route-urls'; import { useOnWalletLock } from './hooks/use-on-wallet-lock'; import { useOnSignOut } from './hooks/use-on-sign-out'; import { OnboardingGate } from './onboarding-gate'; +import { AccountRequest } from '@app/pages/choose-account-request/account-request'; export function AppRoutes(): JSX.Element | null { const { pathname } = useLocation(); @@ -108,7 +109,7 @@ export function AppRoutes(): JSX.Element | null { } /> }> @@ -117,6 +118,16 @@ export function AppRoutes(): JSX.Element | null { } /> + + }> + + + + } + /> { const { encryptedSecretKey, salt } = await encryptMnemonic({ secretKey, password }); const highestAccountIndex = await restoredWalletHighestGeneratedAccountIndex(secretKey); - sendMessage({ + sendMessageToBackground({ method: InternalMethods.ShareInMemoryKeyToBackground, payload: { secretKey, keyId: defaultKeyId }, }); @@ -63,7 +63,7 @@ const unlockWalletAction = (password: string): AppThunk => { const { secretKey } = await decryptMnemonic({ password, ...currentKey }); - sendMessage({ + sendMessageToBackground({ method: InternalMethods.ShareInMemoryKeyToBackground, payload: { secretKey: secretKey, keyId: defaultKeyId }, }); diff --git a/src/background/background.ts b/src/background/background.ts index f02934ff6ef..631b5044c8d 100755 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -21,6 +21,7 @@ import { handleLegacyExternalMethodFormat, inferLegacyMessage, } from './legacy-external-message-handler'; +import { popupCenter } from './popup-center'; initSentry(); initContextMenuActions(); @@ -55,11 +56,19 @@ chrome.runtime.onConnect.addListener(port => switch (message.method) { case RpcMethods[RpcMethods.stx_requestAccounts]: { - chrome.tabs.sendMessage(port.sender.tab.id, { - source: MESSAGE_SOURCE, - id: message.id, - results: { publicKey: 'sldkfjs' }, + const params = new URLSearchParams(); + params.set('tabId', port.sender.tab.id.toString()); + params.set('id', message.id); + console.log(params.toString()); + popupCenter({ + url: `/popup-center.html#${RouteUrls.AccountRequest}?${params.toString()}`, }); + + // chrome.tabs.sendMessage(port.sender.tab.id, { + // source: MESSAGE_SOURCE, + // id: message.id, + // results: { publicKey: 'sldkfjs' }, + // }); break; } } diff --git a/src/inpage/inpage.ts b/src/inpage/inpage.ts index f9e1937249d..0cd0d25a5eb 100644 --- a/src/inpage/inpage.ts +++ b/src/inpage/inpage.ts @@ -117,10 +117,11 @@ const provider: StacksProvider = { }); document.dispatchEvent(event); const handleMessage = (event: MessageEvent) => { + console.log(event); if (event.data.id !== id) return; window.removeEventListener('message', handleMessage); - resolve(event.data); + resolve(event.data.result); }; window.addEventListener('message', handleMessage); }); diff --git a/src/shared/messages.ts b/src/shared/messages.ts index 67ee5b8ed0b..d659855bdcd 100644 --- a/src/shared/messages.ts +++ b/src/shared/messages.ts @@ -1,4 +1,4 @@ -import { ExtensionMethods, InternalMethods, Message } from '@shared/message-types'; +import { ExtensionMethods, InternalMethods, Message, MESSAGE_SOURCE } from '@shared/message-types'; /** * Vault <-> Background Script @@ -28,6 +28,10 @@ export type BackgroundActions = | RequestInMemoryKeys | RemoveInMemoryKeys; -export function sendMessage(message: BackgroundActions) { +export function sendMessageToBackground(message: BackgroundActions) { return chrome.runtime.sendMessage(message); } + +export function sendMessageToTab(tabId: number, id: string, message: object) { + return chrome.tabs.sendMessage(tabId, { source: MESSAGE_SOURCE, id, result: message }); +} diff --git a/src/shared/route-urls.ts b/src/shared/route-urls.ts index 4bf00b4de5e..3b312163aaa 100644 --- a/src/shared/route-urls.ts +++ b/src/shared/route-urls.ts @@ -11,7 +11,8 @@ export enum RouteUrls { Home = '/', AddNetwork = '/add-network', Buy = '/buy', - ChooseAccount = '/choose-account', + AccountAuthentication = '/authenticate-account', + AccountRequest = '/request-account', Receive = '/receive', Send = '/send', SignOutConfirm = '/sign-out', diff --git a/test-app/src/components/home.tsx b/test-app/src/components/home.tsx index a9e47771163..278d65e5037 100644 --- a/test-app/src/components/home.tsx +++ b/test-app/src/components/home.tsx @@ -67,7 +67,7 @@ export const Home: React.FC = () => { getStacksProvider() .request('stx_requestAccounts') .then(resp => { - setAccount([resp]); + setAccount(resp); console.log('request acct resp', resp); }); }} diff --git a/yarn.lock b/yarn.lock index e791afc2cf3..aa56d17a9f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18839,6 +18839,11 @@ type-detect@4.0.8, type-detect@^4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@2.12.2: + version "2.12.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.2.tgz#80a53614e6b9b475eb9077472fb7498dc7aa51d0" + integrity sha512-qt6ylCGpLjZ7AaODxbpyBZSs9fCI9SkL3Z9q2oxMBQhs/uyY+VD8jHA8ULCGmWQJlBgqvO3EJeAngOHD8zQCrQ== + type-fest@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"