Skip to content
This repository has been archived by the owner on Jun 21, 2023. It is now read-only.

Move Account creation process to a browser tab #436

Merged
merged 4 commits into from
Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 10 additions & 0 deletions packages/test-project/tests/common/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ async function inputPassword() {
await extensionPage.waitForFunction(() => !document.querySelector('#authButton'));
}

async function getOpenedTab() {
await dappPage.waitForTimeout(1500);
const pages = await browser.pages();
const tab = pages[pages.length - 1];

tab.on('console', (msg) => console.log('OPENED TAB LOG:', msg.text()));
return tab;
}

// Dapp Helpers
async function getPopup() {
await dappPage.waitForTimeout(1500);
Expand Down Expand Up @@ -181,6 +190,7 @@ module.exports = {
goBack,
closeModal,
inputPassword,
getOpenedTab,
getPopup,
getLedgerSuggestedParams,
sendTransaction,
Expand Down
59 changes: 35 additions & 24 deletions packages/test-project/tests/ui-accounts-e2e.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

const { wallet } = require('./common/constants');
const { openExtension } = require('./common/helpers');
const { openExtension, getOpenedTab } = require('./common/helpers');
const { CreateWallet, VerifyAccount, DeleteAccount } = require('./common/tests');

describe('Wallet Setup', () => {
Expand All @@ -22,67 +22,78 @@ describe('Create Account', () => {
name: 'Created-Account',
};
let mnemonicArray = [];
let openedTab;

test('Create An Account, Step 1 - Enter Account Name', async () => {
test('Create An Account, Step 0 - Open Account creation tab', async () => {
await extensionPage.waitForSelector('#addAccount');
await extensionPage.click('#addAccount');
await extensionPage.waitForSelector('#createAccount');
await extensionPage.click('#createAccount');
await extensionPage.type('#setAccountName', createdAccount.name);
await extensionPage.click('#nextStep');
openedTab = await getOpenedTab();
});

test('Create An Account, Step 1 - Enter Account Name', async () => {
await openedTab.type('#setAccountName', createdAccount.name);
await openedTab.click('#nextStep');
});

test('Create An Account, Step 2 - Get Mnemonic', async () => {
await extensionPage.click('#accountAddress');
createdAccount.address = await extensionPage.$eval('#accountAddress', (e) => e.innerText); // setup for another test
await openedTab.click('#accountAddress');
createdAccount.address = await openedTab.$eval('#accountAddress', (e) => e.innerText); // setup for another test

for (let i = 1; i <= 25; i++) {
mnemonicArray[i - 1] = await extensionPage.$eval(
mnemonicArray[i - 1] = await openedTab.$eval(
`[data-key-index="${i}"]`,
(e) => e.dataset['word']
);
}
await extensionPage.waitForSelector('#recordCheckbox');
await extensionPage.click('#recordCheckbox');
await extensionPage.click('#nextStep');
await openedTab.waitForSelector('#recordCheckbox');
await openedTab.click('#recordCheckbox');
await openedTab.click('#nextStep');
});

test('Create An Account, Step 3 - Use Mnemonic', async () => {
// Wait for mnemonic word buttons to be available
await extensionPage.waitForSelector('[data-index]:not([disabled])');
await openedTab.waitForSelector('[data-index]:not([disabled])');

// We test the remove word functionality by first filling with random words
const randomWords = [];
for (let i = 0; i < 5; i++) {
randomWords.push(mnemonicArray[i * 5 + Math.round(Math.random() * 4)]);
await extensionPage.click(`#${randomWords[i]}:not([disabled]):not(.is-link)`);
await openedTab.click(`#${randomWords[i]}:not([disabled]):not(.is-link)`);
}
await expect(extensionPage.$eval('#enterMnemonic', (e) => e.value)).resolves.toBe(
await expect(openedTab.$eval('#enterMnemonic', (e) => e.value)).resolves.toBe(
randomWords.join(' ')
);
await extensionPage.waitForTimeout(200);
await openedTab.waitForTimeout(200);
for (let i = 0; i < 5; i++) {
await extensionPage.click(`button.is-small.is-link`);
await openedTab.click(`button.is-small.is-link`);
}
await expect(extensionPage.$eval('#enterMnemonic', (e) => e.value)).resolves.toBe('');
await extensionPage.waitForTimeout(200);
await expect(openedTab.$eval('#enterMnemonic', (e) => e.value)).resolves.toBe('');
await openedTab.waitForTimeout(200);

// We build the actual mnemonic
for (let i = 0; i < 25; i++) {
await extensionPage.click(`#${mnemonicArray[i]}:not([disabled]):not(.is-link)`);
await openedTab.click(`#${mnemonicArray[i]}:not([disabled]):not(.is-link)`);
}
await expect(extensionPage.$eval('#enterMnemonic', (e) => e.value)).resolves.toBe(
await expect(openedTab.$eval('#enterMnemonic', (e) => e.value)).resolves.toBe(
mnemonicArray.join(' ')
);

await extensionPage.click('#nextStep');
await openedTab.click('#nextStep');
});

test('Create an Account, Step 4 - Write Account into Storage', async () => {
await extensionPage.waitForSelector('#enterPassword');
await extensionPage.type('#enterPassword', wallet.password);
await extensionPage.waitForTimeout(200);
await extensionPage.click('#authButton');
await openedTab.waitForSelector('#enterPassword');
await openedTab.type('#enterPassword', wallet.password);
await openedTab.waitForTimeout(200);
await openedTab.click('#authButton');
await openedTab.waitForSelector('[data-account-name]');
await expect(
openedTab.$eval('[data-account-name]', (e) => e.dataset['accountName'])
).resolves.toBe(createdAccount.name);
await openedTab.close();
await extensionPage.reload();
});

VerifyAccount(createdAccount);
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/CreateAccount/AccountKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const AccountKeys: FunctionalComponent = (props: any) => {
return html`
<div class="main-view" style="flex-direction: column; justify-content: space-between;">
<${HeaderView} action=${prevStep} title="Save your keys!" />
<div class="px-3" style="flex: 1;">
<div class="px-4" style="flex: 1;">
<div class="mb-4 px-4 py-2" style="background: #EFF4F7; border-radius: 5px;">
<div>
<b>Public Account address</b>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const ConfirmMnemonic: FunctionalComponent = (props: any) => {
return html`
<div class="main-view" style="flex-direction: column; justify-content: space-between;">
<${HeaderView} action=${prevStep} title="Confirm your mnemonic" />
<div class="px-3" style="flex: 1;">
<div class="px-4" style="flex: 1;">
<p class="mb-4">Use the buttons below to confirm the mnemonic</p>
<textarea
id="enterMnemonic"
Expand Down
20 changes: 20 additions & 0 deletions packages/ui/src/components/CreateAccount/FinishAccountCreation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { FunctionalComponent } from 'preact';
import { html } from 'htm/preact';

const FinishAccountCreation: FunctionalComponent = (props: any) => {
const { name, ledger } = props;

return html`
<div class="main-view" style="flex-direction: column; justify-content: space-between;">
<div class="px-4 py-3 has-text-weight-bold is-size-5">
<p class="" style="overflow: hidden; text-overflow: ellipsis;">Created Account</p>
</div>
<div class="px-4" style="flex: 1;">
<p data-account-name="${name}">New account '${name}' added for ${ledger}.</p>
<p class="my-3">You may now close this site and reopen AlgoSigner.</p>
</div>
</div>
`;
};

export default FinishAccountCreation;
9 changes: 4 additions & 5 deletions packages/ui/src/components/CreateAccount/SetAccountName.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { FunctionalComponent } from 'preact';
import { html } from 'htm/preact';
import { route } from 'preact-router';

import HeaderView from 'components/HeaderView';

const SetAccountName: FunctionalComponent = (props: any) => {
const { name, setName, ledger, nextStep } = props;

return html`
<div class="main-view" style="flex-direction: column; justify-content: space-between;">
<${HeaderView} action="${() => route('/wallet')}" title="Create ${ledger} Account" />
<div class="px-3" style="flex: 1;">
<div class="px-4 py-3 has-text-weight-bold is-size-5">
<p style="overflow: hidden; text-overflow: ellipsis;">Create ${ledger} Account</p>
</div>
<div class="px-4" style="flex: 1;">
<input
id="setAccountName"
class="input mb-4"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { FunctionalComponent } from 'preact';
import { html } from 'htm/preact';
import { useContext, useState } from 'preact/hooks';
import { sendMessage } from 'services/Messaging';

import { JsonRpcMethod } from '@algosigner/common/messaging/types';
import Authenticate from 'components/Authenticate';
import { ledgerActions } from './structure/ledgerActions';
import ReducedHeader from 'components/ReducedHeader';

import { sendMessage } from 'services/Messaging';
import { StoreContext } from 'services/StoreContext';
import { ledgerActions } from './structure/ledgerActions';

const LedgerHardwareConnector: FunctionalComponent = (props: any) => {
const { ledger } = props;
Expand Down Expand Up @@ -105,22 +108,23 @@ const LedgerHardwareConnector: FunctionalComponent = (props: any) => {
};

return html`
<${ReducedHeader} />
<div class="main-view" style="flex-direction: column; justify-content: space-between;">
<div class="px-3 py-3 has-text-weight-bold is-size-5">
<div class="px-4 py-3 has-text-weight-bold is-size-5">
<p style="overflow: hidden; text-overflow: ellipsis;"
>Adding Hardware Account for ${ledger}</p
>
</div>
${isComplete &&
html`
<div class="px-3" style="flex: 1;">
<div class="px-4" style="flex: 1;">
<p> New account ${name} added for ${ledger}. </p>
<p class="my-3"> You may now close this site and relaunch AlgoSigner.</p>
</div>
`}
${!isComplete &&
html`
<div class="px-3" style="flex: 1;">
<div class="px-4" style="flex: 1;">
<p>
Insert and unlock the hardware device, verify the Algorand application is open during
this process.
Expand Down
12 changes: 8 additions & 4 deletions packages/ui/src/components/LedgerDevice/LedgerHardwareSign.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { FunctionalComponent } from 'preact';
import { html } from 'htm/preact';
import { useContext, useEffect, useState } from 'preact/hooks';
import { sendMessage } from 'services/Messaging';

import { JsonRpcMethod } from '@algosigner/common/messaging/types';
import { ledgerActions } from './structure/ledgerActions';
import { getBaseSupportedLedgers } from '@algosigner/common/types/ledgers';
import { logging } from '@algosigner/common/logging';
import TxAcfg from 'components/SignTransaction/TxAcfg';
import TxPay from 'components/SignTransaction/TxPay';
import TxKeyreg from 'components/SignTransaction/TxKeyreg';
import TxAxfer from 'components/SignTransaction/TxAxfer';
import TxAfrz from 'components/SignTransaction/TxAfrz';
import TxAppl from 'components/SignTransaction/TxAppl';
import { logging } from '@algosigner/common/logging';
import ReducedHeader from 'components/ReducedHeader';

import { sendMessage } from 'services/Messaging';
import { StoreContext } from 'services/StoreContext';
import { ledgerActions } from './structure/ledgerActions';

const LedgerHardwareSign: FunctionalComponent = () => {
const store: any = useContext(StoreContext);
Expand Down Expand Up @@ -101,11 +104,12 @@ const LedgerHardwareSign: FunctionalComponent = () => {
};

return html`
<${ReducedHeader} />
<div
class="main-view"
style="flex-direction: column; justify-content: space-between; overflow: hidden;"
>
<div class="px-3 py-3 has-text-weight-bold is-size-5">
<div class="px-4 py-3 has-text-weight-bold is-size-5">
<p style="overflow: hidden; text-overflow: ellipsis;">Sign Using Ledger Device</p>
</div>
<div class="top-view" style="flex: 1; overflow-y: auto; overflow-x: hidden;">
Expand Down
15 changes: 15 additions & 0 deletions packages/ui/src/components/ReducedHeader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { FunctionalComponent } from 'preact';
import { html } from 'htm/preact';

import HeaderComponent from './HeaderComponent';
import Logo from './Logo';

const ReducedHeader: FunctionalComponent = () => {
return html`
<${HeaderComponent}>
<${Logo} />
</${HeaderComponent}>
`;
};

export default ReducedHeader;
6 changes: 3 additions & 3 deletions packages/ui/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,20 @@ const App = () => {
<${Welcome} path="/" />
<${SetPassword} path="/set-password" />
<${Login} path="/login/:redirect?" />
<${CreateAccount} path="/:ledger/create-account" />
<${LedgerHardwareConnector} path="/:ledger/ledger-hardware-connector" />
<${LedgerHardwareSign} path="/:ledger/ledger-hardware-sign" />
<${Root} path="/:*?">
<${MainHeader} />
<div style="overflow: auto; flex: 1; display: flex; flex-direction: column;">
<${Router}>
<${Wallet} path="/wallet" />
<${ContactsPage} path="/contacts-page" />
<${CreateAccount} path="/:ledger/create-account" />
<${ImportAccount} path="/:ledger/import-account" />
<${Account} path="/:ledger/:address" />
<${AccountDetails} path="/:ledger/:address/details" />
<${AddAsset} path="/:ledger/:address/add-asset" />
<${SendAlgos} path="/:ledger/:address/send" />
<${LedgerHardwareConnector} path="/:ledger/ledger-hardware-connector" />
<${LedgerHardwareSign} path="/:ledger/ledger-hardware-sign" />
<${LinkHardwareAccount} path="/:ledger/link-hardware-account" />
</${Router}>
</div>
Expand Down
17 changes: 10 additions & 7 deletions packages/ui/src/pages/CreateAccount.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { FunctionalComponent } from 'preact';
import { html } from 'htm/preact';
import { useState, useEffect, useContext } from 'preact/hooks';
import { route } from 'preact-router';
import { JsonRpcMethod } from '@algosigner/common/messaging/types';

import { sendMessage } from 'services/Messaging';

import { StoreContext } from 'services/StoreContext';

import { JsonRpcMethod } from '@algosigner/common/messaging/types';
import SetAccountName from 'components/CreateAccount/SetAccountName';
import AccountKeys from 'components/CreateAccount/AccountKeys';
import ConfirmMnemonic from 'components/CreateAccount/ConfirmMnemonic';
import FinishAccountCreation from 'components/CreateAccount/FinishAccountCreation';

import { sendMessage } from 'services/Messaging';
import { StoreContext } from 'services/StoreContext';
import Authenticate from 'components/Authenticate';
import ReducedHeader from 'components/ReducedHeader';

interface Account {
address: string;
Expand Down Expand Up @@ -83,13 +83,15 @@ const CreateAccount: FunctionalComponent = (props: any) => {
}
} else {
store.updateWallet(response, () => {
route('/wallet');
setAskAuth(false);
nextStep();
});
}
});
};

return html`
<${ReducedHeader} />
${step === 0 &&
html`
<${SetAccountName}
Expand Down Expand Up @@ -125,6 +127,7 @@ const CreateAccount: FunctionalComponent = (props: any) => {
/>
</div>
`}
${step === 3 && html`<${FinishAccountCreation} name=${name} ledger=${ledger} /> `}
`;
};

Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/pages/LinkHardwareAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const LinkHardwareAccount: FunctionalComponent = (props: any) => {
return html`
<div class="main-view" style="flex-direction: column; justify-content: space-between;">
<${HeaderView} action="${() => route('/wallet')}" title="Link ${ledger} account" />
<div class="px-3" style="flex: 1;">
<div class="px-4" style="flex: 1;">
<p class="my-3">
The extension will close and a new tab will be created to connect the Ledger device.
</p>
Expand Down
Loading