Export account (#166)
* setup tests * export account WIP * Fix linter errors. * Frontend test for Export component. * Test for account export by background handler. * Add password to export. * Add simple account export functionality. * Add dedicated selectors. * Improve export view layout * make export textarea bigger * Fix linter error. * Update wrapper in test to make it pass. * test refactoring * add copying exported JSON to clipboard * lint fix * add UI tests * fix dependencies * refactoring * copyright headers; minor refactorings * make input field blink after entering wrong password * download exported JSON * simplify exported JSON download * removed redundant tests * disable export functionality for external accounts * add export restrictions tests * tests refactoring * after successful export go back to main screen
This commit is contained in:
parent
a9b405ca73
commit
29122d1f8f
31
__mocks__/extensionizer.ts
Normal file
31
__mocks__/extensionizer.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2019 @polkadot/extension-ui authors & contributors
|
||||||
|
// This software may be modified and distributed under the terms
|
||||||
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import chrome from 'sinon-chrome';
|
||||||
|
|
||||||
|
class MessagingFake {
|
||||||
|
private listeners: any = [];
|
||||||
|
|
||||||
|
get onMessage (): any {
|
||||||
|
return {
|
||||||
|
addListener: (cb: any): any => this.listeners.push(cb)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get onDisconnect (): any {
|
||||||
|
return {
|
||||||
|
addListener: (): any => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
postMessage (data: any): void {
|
||||||
|
this.listeners.forEach((cb: any) => cb.call(this, data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const messagingFake = new MessagingFake();
|
||||||
|
chrome.runtime.connect.returns(messagingFake);
|
||||||
|
|
||||||
|
export default chrome;
|
||||||
@ -1,3 +1,3 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: '@polkadot/dev/config/babel'
|
extends: '@polkadot/dev-react/config/babel'
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,11 +4,15 @@ const config = require('@polkadot/dev/config/jest');
|
|||||||
module.exports = Object.assign({}, config, {
|
module.exports = Object.assign({}, config, {
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'@polkadot/extension-(chains|dapp|inject|ui)(.*)$': '<rootDir>/packages/extension-$1/src/$2',
|
'@polkadot/extension-(chains|dapp|inject|ui)(.*)$': '<rootDir>/packages/extension-$1/src/$2',
|
||||||
|
'@polkadot/extension(.*)$': '<rootDir>/packages/extension/src/$1',
|
||||||
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'empty/object',
|
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'empty/object',
|
||||||
'\\.(css|less)$': 'empty/object'
|
'\\.(css|less)$': 'empty/object'
|
||||||
},
|
},
|
||||||
modulePathIgnorePatterns: [
|
modulePathIgnorePatterns: [
|
||||||
'<rootDir>/packages/extension/build',
|
'<rootDir>/packages/extension/build',
|
||||||
'<rootDir>/packages/extension-ui/build'
|
'<rootDir>/packages/extension-ui/build',
|
||||||
|
'<rootDir>/packages/extension-chains/build',
|
||||||
|
'<rootDir>/packages/extension-inject/build',
|
||||||
|
'<rootDir>/packages/extension-dapp/build'
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
"clean": "polkadot-dev-clean-build",
|
"clean": "polkadot-dev-clean-build",
|
||||||
"postinstall": "polkadot-dev-yarn-only",
|
"postinstall": "polkadot-dev-yarn-only",
|
||||||
"start": "yarn watch",
|
"start": "yarn watch",
|
||||||
"test": "echo \"no tests... yet\"",
|
"test": "jest",
|
||||||
"watch": "cd packages/extension && webpack --config webpack.config.js --watch"
|
"watch": "cd packages/extension && webpack --config webpack.config.js --watch"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -12,5 +12,11 @@
|
|||||||
"@types/react-router-dom": "^5.1.0",
|
"@types/react-router-dom": "^5.1.0",
|
||||||
"react-router": "^5.1.0",
|
"react-router": "^5.1.0",
|
||||||
"react-router-dom": "^5.1.0"
|
"react-router-dom": "^5.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/enzyme": "^3.10.3",
|
||||||
|
"@types/enzyme-adapter-react-16": "^1.0.5",
|
||||||
|
"@types/sinon-chrome": "^2.2.6",
|
||||||
|
"sinon-chrome": "^3.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
42
packages/extension-ui/src/Popup/Accounts/Account.test.tsx
Normal file
42
packages/extension-ui/src/Popup/Accounts/Account.test.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2019 @polkadot/extension-ui authors & contributors
|
||||||
|
// This software may be modified and distributed under the terms
|
||||||
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
|
import Adapter from 'enzyme-adapter-react-16';
|
||||||
|
import { configure, mount, ReactWrapper } from 'enzyme';
|
||||||
|
import { Link } from '@polkadot/extension-ui/components';
|
||||||
|
import { MemoryRouter } from 'react-router';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Account from './Account';
|
||||||
|
|
||||||
|
configure({ adapter: new Adapter() });
|
||||||
|
|
||||||
|
describe('Account component', () => {
|
||||||
|
let wrapper: ReactWrapper;
|
||||||
|
const VALID_ADDRESS = 'HjoBp62cvsWDA3vtNMWxz6c9q13ReEHi9UGHK7JbZweH5g5';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const mountAccountComponent = (additionalAccountProperties: any): ReactWrapper => mount(
|
||||||
|
<MemoryRouter>
|
||||||
|
<Account
|
||||||
|
{...{ address: VALID_ADDRESS, ...additionalAccountProperties }}>
|
||||||
|
</Account>
|
||||||
|
</MemoryRouter>);
|
||||||
|
|
||||||
|
it('shows Export option if account is not external', () => {
|
||||||
|
wrapper = mountAccountComponent({ isExternal: false });
|
||||||
|
|
||||||
|
expect(wrapper.find(Link).length).toBe(3);
|
||||||
|
expect(wrapper.find(Link).at(0).text()).toContain('Edit');
|
||||||
|
expect(wrapper.find(Link).at(1).text()).toContain('Export');
|
||||||
|
expect(wrapper.find(Link).at(2).text()).toContain('Forget');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not show Export option if account is external', () => {
|
||||||
|
wrapper = mountAccountComponent({ isExternal: true });
|
||||||
|
|
||||||
|
expect(wrapper.find(Link).length).toBe(2);
|
||||||
|
expect(wrapper.find(Link).at(0).text()).toContain('Edit');
|
||||||
|
expect(wrapper.find(Link).at(1).text()).toContain('Forget');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -16,7 +16,7 @@ interface Props extends AccountJson {
|
|||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Account ({ address, className }: Props): React.ReactElement<Props> {
|
function Account ({ address, className, isExternal }: Props): React.ReactElement<Props> {
|
||||||
const onAction = useContext(ActionContext);
|
const onAction = useContext(ActionContext);
|
||||||
const [isEditing, setEditing] = useState(false);
|
const [isEditing, setEditing] = useState(false);
|
||||||
const [editedName, setName] = useState<string | null>(null);
|
const [editedName, setName] = useState<string | null>(null);
|
||||||
@ -50,6 +50,7 @@ function Account ({ address, className }: Props): React.ReactElement<Props> {
|
|||||||
)}
|
)}
|
||||||
<ActionBar>
|
<ActionBar>
|
||||||
<Link onClick={_toggleEdit}>Edit</Link>
|
<Link onClick={_toggleEdit}>Edit</Link>
|
||||||
|
{!isExternal && <Link to={`/account/export/${address}`}>Export</Link>}
|
||||||
<Link to={`/account/forget/${address}`}>Forget</Link>
|
<Link to={`/account/forget/${address}`}>Forget</Link>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
</Address>
|
</Address>
|
||||||
|
|||||||
55
packages/extension-ui/src/Popup/Export.test.tsx
Normal file
55
packages/extension-ui/src/Popup/Export.test.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// Copyright 2019 @polkadot/extension-ui authors & contributors
|
||||||
|
// This software may be modified and distributed under the terms
|
||||||
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
|
import Adapter from 'enzyme-adapter-react-16';
|
||||||
|
import { configure, mount, ReactWrapper } from 'enzyme';
|
||||||
|
import { MemoryRouter, Route } from 'react-router';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { Button } from '../components';
|
||||||
|
import Export from './Export';
|
||||||
|
import { exportAccount } from '../messaging';
|
||||||
|
|
||||||
|
configure({ adapter: new Adapter() });
|
||||||
|
jest.mock('../messaging');
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||||
|
const flushAllPromises = (): Promise<void> => new Promise(resolve => setImmediate(resolve));
|
||||||
|
|
||||||
|
describe('Export component', () => {
|
||||||
|
let wrapper: ReactWrapper;
|
||||||
|
const VALID_ADDRESS = 'HjoBp62cvsWDA3vtNMWxz6c9q13ReEHi9UGHK7JbZweH5g5';
|
||||||
|
|
||||||
|
const enterPassword = (password = 'any password'): void => {
|
||||||
|
wrapper.find('[data-export-password] input').simulate('change', { target: { value: password } });
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
(exportAccount as jest.Mock).mockResolvedValue({ exportedJson: '{ "meta": { "name": "account_name" } }' });
|
||||||
|
|
||||||
|
wrapper = mount(<MemoryRouter
|
||||||
|
initialEntries={ [`/account/export/${VALID_ADDRESS}`] }>
|
||||||
|
<Route path='/account/export/:address' component={ Export }/>
|
||||||
|
</MemoryRouter>);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates export message on button press', async () => {
|
||||||
|
enterPassword('passw0rd');
|
||||||
|
wrapper.find('[data-export-button] button').simulate('click');
|
||||||
|
await act(flushAllPromises);
|
||||||
|
|
||||||
|
expect(exportAccount).toHaveBeenCalledWith(VALID_ADDRESS, 'passw0rd');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('button is disabled before any password is typed', () => {
|
||||||
|
expect(wrapper.find(Button).prop('isDisabled')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('button is enabled after password is typed', async () => {
|
||||||
|
enterPassword();
|
||||||
|
await act(flushAllPromises);
|
||||||
|
|
||||||
|
expect(wrapper.find(Button).prop('isDisabled')).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
63
packages/extension-ui/src/Popup/Export.tsx
Normal file
63
packages/extension-ui/src/Popup/Export.tsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright 2019 @polkadot/extension-ui authors & contributors
|
||||||
|
// This software may be modified and distributed under the terms
|
||||||
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
|
import React, { useContext, useState } from 'react';
|
||||||
|
import { RouteComponentProps, withRouter } from 'react-router';
|
||||||
|
|
||||||
|
import { ActionContext, Address, Button, Header, Input, Tip } from '../components';
|
||||||
|
import { exportAccount } from '../messaging';
|
||||||
|
import { Back } from '../partials';
|
||||||
|
|
||||||
|
const MIN_LENGTH = 6;
|
||||||
|
|
||||||
|
type Props = RouteComponentProps<{ address: string }>;
|
||||||
|
|
||||||
|
function Export ({ match: { params: { address } } }: Props): React.ReactElement<Props> {
|
||||||
|
const onAction = useContext(ActionContext);
|
||||||
|
|
||||||
|
const [pass, setPass] = useState('');
|
||||||
|
const [wrongPasswordHighlight, setWrongPasswordHighlight] = useState(false);
|
||||||
|
|
||||||
|
const _onExportButtonClick = (): Promise<void> =>
|
||||||
|
exportAccount(address, pass)
|
||||||
|
.then(({ exportedJson }) => {
|
||||||
|
const element = document.createElement('a');
|
||||||
|
element.href = `data:text/plain;charset=utf-8,${exportedJson}`;
|
||||||
|
element.download = `${JSON.parse(exportedJson).meta.name}_exported_account_${Date.now()}.json`;
|
||||||
|
element.click();
|
||||||
|
onAction('/');
|
||||||
|
})
|
||||||
|
.catch((error: Error) => {
|
||||||
|
console.error(error);
|
||||||
|
setWrongPasswordHighlight(true);
|
||||||
|
setTimeout(() => setWrongPasswordHighlight(false), 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Header label='export account' />
|
||||||
|
<Back />
|
||||||
|
<Address address={address}>
|
||||||
|
<Tip header='danger' type='error'>You are exporting your account. Keep it safe and don't share it with anyone.</Tip>
|
||||||
|
<Input
|
||||||
|
isError={pass.length < MIN_LENGTH || wrongPasswordHighlight}
|
||||||
|
label='password for this account'
|
||||||
|
onChange={setPass}
|
||||||
|
type='password'
|
||||||
|
data-export-password
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
isDisabled={pass.length === 0}
|
||||||
|
isDanger
|
||||||
|
label='I want to export this account'
|
||||||
|
onClick={_onExportButtonClick}
|
||||||
|
className='export-button'
|
||||||
|
data-export-button
|
||||||
|
/>
|
||||||
|
</Address>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(Export);
|
||||||
@ -15,6 +15,7 @@ import { subscribeAccounts, subscribeAuthorize, subscribeSigning } from '../mess
|
|||||||
import Accounts from './Accounts';
|
import Accounts from './Accounts';
|
||||||
import Authorize from './Authorize';
|
import Authorize from './Authorize';
|
||||||
import Create from './Create';
|
import Create from './Create';
|
||||||
|
import Export from './Export';
|
||||||
import Forget from './Forget';
|
import Forget from './Forget';
|
||||||
import ImportQr from './ImportQr';
|
import ImportQr from './ImportQr';
|
||||||
import ImportSeed from './ImportSeed';
|
import ImportSeed from './ImportSeed';
|
||||||
@ -85,6 +86,7 @@ export default function Popup (): React.ReactElement<{}> {
|
|||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/account/create' component={Create} />
|
<Route path='/account/create' component={Create} />
|
||||||
<Route path='/account/forget/:address' component={Forget} />
|
<Route path='/account/forget/:address' component={Forget} />
|
||||||
|
<Route path='/account/export/:address' component={Export} />
|
||||||
<Route path='/account/import-qr' component={ImportQr} />
|
<Route path='/account/import-qr' component={ImportQr} />
|
||||||
<Route path='/account/import-seed' component={ImportSeed} />
|
<Route path='/account/import-seed' component={ImportSeed} />
|
||||||
<Route path='/settings' component={Settings} />
|
<Route path='/settings' component={Settings} />
|
||||||
|
|||||||
@ -13,12 +13,13 @@ interface Props {
|
|||||||
isError?: boolean;
|
isError?: boolean;
|
||||||
isFocussed?: boolean;
|
isFocussed?: boolean;
|
||||||
isReadOnly?: boolean;
|
isReadOnly?: boolean;
|
||||||
|
rowsCount?: number;
|
||||||
label: string;
|
label: string;
|
||||||
onChange?: (value: string) => void;
|
onChange?: (value: string) => void;
|
||||||
value?: string;
|
value?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function TextArea ({ className, isFocussed, isReadOnly, label, onChange, value }: Props): React.ReactElement<Props> {
|
function TextArea ({ className, isFocussed, isReadOnly, label, onChange, value, rowsCount }: Props): React.ReactElement<Props> {
|
||||||
const _onChange = ({ target: { value } }: React.ChangeEvent<HTMLTextAreaElement>): void => {
|
const _onChange = ({ target: { value } }: React.ChangeEvent<HTMLTextAreaElement>): void => {
|
||||||
onChange && onChange(value.trim());
|
onChange && onChange(value.trim());
|
||||||
};
|
};
|
||||||
@ -33,6 +34,7 @@ function TextArea ({ className, isFocussed, isReadOnly, label, onChange, value }
|
|||||||
onChange={_onChange}
|
onChange={_onChange}
|
||||||
readOnly={isReadOnly}
|
readOnly={isReadOnly}
|
||||||
value={value}
|
value={value}
|
||||||
|
rows={rowsCount || 2}
|
||||||
/>
|
/>
|
||||||
</Label>
|
</Label>
|
||||||
);
|
);
|
||||||
|
|||||||
24
packages/extension-ui/src/messaging.test.ts
Normal file
24
packages/extension-ui/src/messaging.test.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright 2019 @polkadot/extension-ui authors & contributors
|
||||||
|
// This software may be modified and distributed under the terms
|
||||||
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
|
import Adapter from 'enzyme-adapter-react-16';
|
||||||
|
import { configure } from 'enzyme';
|
||||||
|
import extensionizer from 'extensionizer';
|
||||||
|
import { exportAccount } from './messaging';
|
||||||
|
|
||||||
|
configure({ adapter: new Adapter() });
|
||||||
|
|
||||||
|
describe('messaging sends message to background via extension port for', () => {
|
||||||
|
test('exportAccount', () => {
|
||||||
|
const callback = jest.fn();
|
||||||
|
extensionizer.runtime.connect().onMessage.addListener(callback);
|
||||||
|
|
||||||
|
exportAccount('HjoBp62cvsWDA3vtNMWxz6c9q13ReEHi9UGHK7JbZweH5g5', 'passw0rd');
|
||||||
|
|
||||||
|
expect(callback).toHaveBeenCalledWith(expect.objectContaining({
|
||||||
|
message: 'pri(accounts.export)',
|
||||||
|
request: { address: 'HjoBp62cvsWDA3vtNMWxz6c9q13ReEHi9UGHK7JbZweH5g5', password: 'passw0rd' }
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -66,6 +66,10 @@ export async function forgetAccount (address: string): Promise<boolean> {
|
|||||||
return sendMessage('pri(accounts.forget)', { address });
|
return sendMessage('pri(accounts.forget)', { address });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function exportAccount (address: string, password: string): Promise<{ exportedJson: string }> {
|
||||||
|
return sendMessage('pri(accounts.export)', { address, password });
|
||||||
|
}
|
||||||
|
|
||||||
export async function rejectAuthRequest (id: string): Promise<boolean> {
|
export async function rejectAuthRequest (id: string): Promise<boolean> {
|
||||||
return sendMessage('pri(authorize.reject)', { id });
|
return sendMessage('pri(authorize.reject)', { id });
|
||||||
}
|
}
|
||||||
|
|||||||
28
packages/extension/src/background/handlers/Extension.test.ts
Normal file
28
packages/extension/src/background/handlers/Extension.test.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import Extension from '@polkadot/extension/background/handlers/Extension';
|
||||||
|
import keyring from '@polkadot/ui-keyring';
|
||||||
|
import { cryptoWaitReady } from '@polkadot/util-crypto';
|
||||||
|
import State from '@polkadot/extension/background/handlers/State';
|
||||||
|
import { ResponseAccountExport } from '@polkadot/extension/background/types';
|
||||||
|
import ExtensionStore from '@polkadot/ui-keyring/stores/Extension';
|
||||||
|
|
||||||
|
describe('Extension', () => {
|
||||||
|
async function createExtension (): Promise<Extension> {
|
||||||
|
await cryptoWaitReady();
|
||||||
|
keyring.loadAll({ store: new ExtensionStore() });
|
||||||
|
return new Extension(new State());
|
||||||
|
}
|
||||||
|
|
||||||
|
test('exports account from keyring', async () => {
|
||||||
|
const extension = await createExtension();
|
||||||
|
const { pair: { address } } = keyring.addUri(
|
||||||
|
'seed sock milk update focus rotate barely fade car face mechanic mercy', 'passw0rd'
|
||||||
|
);
|
||||||
|
const result = await extension.handle('id', 'pri(accounts.export)', {
|
||||||
|
address,
|
||||||
|
password: 'passw0rd'
|
||||||
|
}, {} as chrome.runtime.Port) as ResponseAccountExport;
|
||||||
|
|
||||||
|
expect(result.exportedJson).toContain(address);
|
||||||
|
expect(result.exportedJson).toContain('"encoded"');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -3,7 +3,28 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
||||||
import { AccountJson, AuthorizeRequest, RequestAccountCreateExternal, RequestAccountCreateSuri, RequestAccountEdit, RequestAuthorizeApprove, RequestAuthorizeReject, RequestSigningApprovePassword, RequestSigningApproveSignature, RequestSigningCancel, RequestSeedCreate, ResponseSeedCreate, RequestSeedValidate, ResponseSeedValidate, RequestAccountForget, SigningRequest, RequestTypes, ResponseTypes, MessageTypes } from '../types';
|
import {
|
||||||
|
AccountJson,
|
||||||
|
AuthorizeRequest,
|
||||||
|
RequestAccountCreateExternal,
|
||||||
|
RequestAccountCreateSuri,
|
||||||
|
RequestAccountEdit,
|
||||||
|
RequestAuthorizeApprove,
|
||||||
|
RequestAuthorizeReject,
|
||||||
|
RequestSigningApprovePassword,
|
||||||
|
RequestSigningApproveSignature,
|
||||||
|
RequestSigningCancel,
|
||||||
|
RequestSeedCreate,
|
||||||
|
ResponseSeedCreate,
|
||||||
|
RequestSeedValidate,
|
||||||
|
ResponseSeedValidate,
|
||||||
|
RequestAccountForget,
|
||||||
|
SigningRequest,
|
||||||
|
RequestTypes,
|
||||||
|
ResponseTypes,
|
||||||
|
MessageTypes,
|
||||||
|
RequestAccountExport, ResponseAccountExport
|
||||||
|
} from '../types';
|
||||||
|
|
||||||
import extension from 'extensionizer';
|
import extension from 'extensionizer';
|
||||||
import keyring from '@polkadot/ui-keyring';
|
import keyring from '@polkadot/ui-keyring';
|
||||||
@ -60,6 +81,10 @@ export default class Extension {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private accountsExport ({ address, password }: RequestAccountExport): ResponseAccountExport {
|
||||||
|
return { exportedJson: JSON.stringify(keyring.backupAccount(keyring.getPair(address), password), null, 2) };
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME This looks very much like what we have in Tabs
|
// FIXME This looks very much like what we have in Tabs
|
||||||
private accountsSubscribe (id: string, port: chrome.runtime.Port): boolean {
|
private accountsSubscribe (id: string, port: chrome.runtime.Port): boolean {
|
||||||
const cb = createSubscription<'pri(accounts.subscribe)'>(id, port);
|
const cb = createSubscription<'pri(accounts.subscribe)'>(id, port);
|
||||||
@ -233,6 +258,9 @@ export default class Extension {
|
|||||||
case 'pri(accounts.forget)':
|
case 'pri(accounts.forget)':
|
||||||
return this.accountsForget(request as RequestAccountForget);
|
return this.accountsForget(request as RequestAccountForget);
|
||||||
|
|
||||||
|
case 'pri(accounts.export)':
|
||||||
|
return this.accountsExport(request as RequestAccountExport);
|
||||||
|
|
||||||
case 'pri(accounts.edit)':
|
case 'pri(accounts.edit)':
|
||||||
return this.accountsEdit(request as RequestAccountEdit);
|
return this.accountsEdit(request as RequestAccountEdit);
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,7 @@ export interface RequestSignatures {
|
|||||||
'pri(accounts.create.suri)': [RequestAccountCreateSuri, boolean];
|
'pri(accounts.create.suri)': [RequestAccountCreateSuri, boolean];
|
||||||
'pri(accounts.edit)': [RequestAccountEdit, boolean];
|
'pri(accounts.edit)': [RequestAccountEdit, boolean];
|
||||||
'pri(accounts.forget)': [RequestAccountForget, boolean];
|
'pri(accounts.forget)': [RequestAccountForget, boolean];
|
||||||
|
'pri(accounts.export)': [RequestAccountExport, ResponseAccountExport];
|
||||||
'pri(accounts.subscribe)': [RequestAccountSubscribe, boolean, AccountJson[]];
|
'pri(accounts.subscribe)': [RequestAccountSubscribe, boolean, AccountJson[]];
|
||||||
'pri(authorize.approve)': [RequestAuthorizeApprove, boolean];
|
'pri(authorize.approve)': [RequestAuthorizeApprove, boolean];
|
||||||
'pri(authorize.reject)': [RequestAuthorizeReject, boolean];
|
'pri(authorize.reject)': [RequestAuthorizeReject, boolean];
|
||||||
@ -120,6 +121,11 @@ export interface RequestAccountForget {
|
|||||||
address: string;
|
address: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RequestAccountExport {
|
||||||
|
address: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type RequestAccountList = null;
|
export type RequestAccountList = null;
|
||||||
|
|
||||||
export type RequestAccountSubscribe = null;
|
export type RequestAccountSubscribe = null;
|
||||||
@ -193,6 +199,10 @@ export interface ResponseSeedValidate {
|
|||||||
suri: string;
|
suri: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ResponseAccountExport {
|
||||||
|
exportedJson: string;
|
||||||
|
}
|
||||||
|
|
||||||
// Subscriptions
|
// Subscriptions
|
||||||
|
|
||||||
export type SubscriptionMessageTypes = NoUndefinedValues<{
|
export type SubscriptionMessageTypes = NoUndefinedValues<{
|
||||||
|
|||||||
128
yarn.lock
128
yarn.lock
@ -2264,6 +2264,35 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-0.14.1.tgz#f4923bba22d7c68a4be3575ba27790947b212633"
|
resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-0.14.1.tgz#f4923bba22d7c68a4be3575ba27790947b212633"
|
||||||
integrity sha512-Xng7L2Z8TNZa/5g6pot4O06Jf0ohQRZdvfl8eQL+E/L2mcqJYC1IjkMxJBSBuQEV7hisWzh9mHOy5WCcgPk29Q==
|
integrity sha512-Xng7L2Z8TNZa/5g6pot4O06Jf0ohQRZdvfl8eQL+E/L2mcqJYC1IjkMxJBSBuQEV7hisWzh9mHOy5WCcgPk29Q==
|
||||||
|
|
||||||
|
"@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0", "@sinonjs/commons@^1.4.0":
|
||||||
|
version "1.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.6.0.tgz#ec7670432ae9c8eb710400d112c201a362d83393"
|
||||||
|
integrity sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==
|
||||||
|
dependencies:
|
||||||
|
type-detect "4.0.8"
|
||||||
|
|
||||||
|
"@sinonjs/formatio@^3.2.1":
|
||||||
|
version "3.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.1.tgz#52310f2f9bcbc67bdac18c94ad4901b95fde267e"
|
||||||
|
integrity sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==
|
||||||
|
dependencies:
|
||||||
|
"@sinonjs/commons" "^1"
|
||||||
|
"@sinonjs/samsam" "^3.1.0"
|
||||||
|
|
||||||
|
"@sinonjs/samsam@^3.1.0", "@sinonjs/samsam@^3.3.3":
|
||||||
|
version "3.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.3.tgz#46682efd9967b259b81136b9f120fd54585feb4a"
|
||||||
|
integrity sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==
|
||||||
|
dependencies:
|
||||||
|
"@sinonjs/commons" "^1.3.0"
|
||||||
|
array-from "^2.1.1"
|
||||||
|
lodash "^4.17.15"
|
||||||
|
|
||||||
|
"@sinonjs/text-encoding@^0.7.1":
|
||||||
|
version "0.7.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
|
||||||
|
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
|
||||||
|
|
||||||
"@types/babel__core@^7.1.0":
|
"@types/babel__core@^7.1.0":
|
||||||
version "7.1.3"
|
version "7.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30"
|
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30"
|
||||||
@ -2325,7 +2354,14 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/base-x" "*"
|
"@types/base-x" "*"
|
||||||
|
|
||||||
"@types/chrome@^0.0.89":
|
"@types/cheerio@*":
|
||||||
|
version "0.22.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.13.tgz#5eecda091a24514185dcba99eda77e62bf6523e6"
|
||||||
|
integrity sha512-OZd7dCUOUkiTorf97vJKwZnSja/DmHfuBAroe1kREZZTCf/tlFecwHhsOos3uVHxeKGZDwzolIrCUApClkdLuA==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/chrome@*", "@types/chrome@^0.0.89":
|
||||||
version "0.0.89"
|
version "0.0.89"
|
||||||
resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.89.tgz#0d5baef543aaa0715b345b57b86cba6ca708b524"
|
resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.89.tgz#0d5baef543aaa0715b345b57b86cba6ca708b524"
|
||||||
integrity sha512-nWgL4U38SnIuMpG2rKMCGDknfZb193KFY15imqHUVFF4IJAVXvdEJOOgtcX9v2XsAaZiz2UUOInvWk5x1DhENQ==
|
integrity sha512-nWgL4U38SnIuMpG2rKMCGDknfZb193KFY15imqHUVFF4IJAVXvdEJOOgtcX9v2XsAaZiz2UUOInvWk5x1DhENQ==
|
||||||
@ -2351,6 +2387,21 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/color-convert" "*"
|
"@types/color-convert" "*"
|
||||||
|
|
||||||
|
"@types/enzyme-adapter-react-16@^1.0.5":
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.5.tgz#1bf30a166f49be69eeda4b81e3f24113c8b4e9d5"
|
||||||
|
integrity sha512-K7HLFTkBDN5RyRmU90JuYt8OWEY2iKUn43SDWEoBOXd/PowUWjLZ3Q6qMBiQuZeFYK/TOstaZxsnI0fXoAfLpg==
|
||||||
|
dependencies:
|
||||||
|
"@types/enzyme" "*"
|
||||||
|
|
||||||
|
"@types/enzyme@*", "@types/enzyme@^3.10.3":
|
||||||
|
version "3.10.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.3.tgz#02b6c5ac7d0472005944a652e79045e2f6c66804"
|
||||||
|
integrity sha512-f/Kcb84sZOSZiBPCkr4He9/cpuSLcKRyQaEE20Q30Prx0Dn6wcyMAWI0yofL6yvd9Ht9G7EVkQeRqK0n5w8ILw==
|
||||||
|
dependencies:
|
||||||
|
"@types/cheerio" "*"
|
||||||
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/eslint-visitor-keys@^1.0.0":
|
"@types/eslint-visitor-keys@^1.0.0":
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
|
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
|
||||||
@ -2564,6 +2615,19 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/sinon-chrome@^2.2.6":
|
||||||
|
version "2.2.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/sinon-chrome/-/sinon-chrome-2.2.6.tgz#0ce2b8caea8d6ec0a2f9e20ca72c820b590bef81"
|
||||||
|
integrity sha512-R4FM7ywHxsqkHQlGdM42etVouSEUxZTUyXAheAyEe19DOGkEwNk7bIWi9aGc6WToIkQcFk/3O9aXCQh1YbgcMQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/chrome" "*"
|
||||||
|
"@types/sinon" "*"
|
||||||
|
|
||||||
|
"@types/sinon@*":
|
||||||
|
version "7.0.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-7.0.13.tgz#ca039c23a9e27ebea53e0901ef928ea2a1a6d313"
|
||||||
|
integrity sha512-d7c/C/+H/knZ3L8/cxhicHUiTDxdgap0b/aNJfsmLwFu/iOP17mdgbQsbHA3SJmrzsjD0l3UEE5SN4xxuz5ung==
|
||||||
|
|
||||||
"@types/stack-utils@^1.0.1":
|
"@types/stack-utils@^1.0.1":
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
|
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
|
||||||
@ -3326,6 +3390,11 @@ array-flatten@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
|
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
|
||||||
integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
|
integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
|
||||||
|
|
||||||
|
array-from@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/array-from/-/array-from-2.1.1.tgz#cfe9d8c26628b9dc5aecc62a9f5d8f1f352c1195"
|
||||||
|
integrity sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=
|
||||||
|
|
||||||
array-ify@^1.0.0:
|
array-ify@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
|
resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
|
||||||
@ -5350,6 +5419,11 @@ diff-sequences@^24.9.0:
|
|||||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
|
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
|
||||||
integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
|
integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
|
||||||
|
|
||||||
|
diff@^3.5.0:
|
||||||
|
version "3.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||||
|
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
|
||||||
|
|
||||||
diffie-hellman@^5.0.0:
|
diffie-hellman@^5.0.0:
|
||||||
version "5.0.3"
|
version "5.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
|
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
|
||||||
@ -8615,6 +8689,11 @@ jsx-ast-utils@^2.1.0:
|
|||||||
array-includes "^3.0.3"
|
array-includes "^3.0.3"
|
||||||
object.assign "^4.1.0"
|
object.assign "^4.1.0"
|
||||||
|
|
||||||
|
just-extend@^4.0.2:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.0.2.tgz#f3f47f7dfca0f989c55410a7ebc8854b07108afc"
|
||||||
|
integrity sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==
|
||||||
|
|
||||||
keygrip@~1.0.3:
|
keygrip@~1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.3.tgz#399d709f0aed2bab0a059e0cdd3a5023a053e1dc"
|
resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.3.tgz#399d709f0aed2bab0a059e0cdd3a5023a053e1dc"
|
||||||
@ -9011,7 +9090,7 @@ lodash.uniq@^4.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||||
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
||||||
|
|
||||||
lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.5, lodash@^4.2.1:
|
lodash@^4.15.0, lodash@^4.16.3, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.5, lodash@^4.2.1:
|
||||||
version "4.17.15"
|
version "4.17.15"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||||
@ -9031,6 +9110,11 @@ loglevelnext@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-3.0.1.tgz#e3e4659c4061c09264f6812c33586dc55a009a04"
|
resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-3.0.1.tgz#e3e4659c4061c09264f6812c33586dc55a009a04"
|
||||||
integrity sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==
|
integrity sha512-JpjaJhIN1reaSb26SIxDGtE0uc67gPl19OMVHrr+Ggt6b/Vy60jmCtKgQBrygAH0bhRA2nkxgDvM+8QvR8r0YA==
|
||||||
|
|
||||||
|
lolex@^4.1.0, lolex@^4.2.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lolex/-/lolex-4.2.0.tgz#ddbd7f6213ca1ea5826901ab1222b65d714b3cd7"
|
||||||
|
integrity sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==
|
||||||
|
|
||||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
|
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||||
@ -9730,6 +9814,17 @@ nice-try@^1.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||||
|
|
||||||
|
nise@^1.5.2:
|
||||||
|
version "1.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.2.tgz#b6d29af10e48b321b307e10e065199338eeb2652"
|
||||||
|
integrity sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==
|
||||||
|
dependencies:
|
||||||
|
"@sinonjs/formatio" "^3.2.1"
|
||||||
|
"@sinonjs/text-encoding" "^0.7.1"
|
||||||
|
just-extend "^4.0.2"
|
||||||
|
lolex "^4.1.0"
|
||||||
|
path-to-regexp "^1.7.0"
|
||||||
|
|
||||||
no-case@^2.2.0:
|
no-case@^2.2.0:
|
||||||
version "2.3.2"
|
version "2.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
|
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
|
||||||
@ -12427,6 +12522,28 @@ simple-swizzle@^0.2.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.3.1"
|
is-arrayish "^0.3.1"
|
||||||
|
|
||||||
|
sinon-chrome@^3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/sinon-chrome/-/sinon-chrome-3.0.1.tgz#9fb14c230fa0959cb280f9f589e9eda8ccfda1d9"
|
||||||
|
integrity sha512-NTEFhyuiWEMnRmIqldUiA2DhKn2EqnZxyEk5Ez5rBXj+Nl54aJ0MEmF4wjltrxecxd8zlNLxyE0HyLabev9JsQ==
|
||||||
|
dependencies:
|
||||||
|
lodash "^4.16.3"
|
||||||
|
sinon "^7.2.3"
|
||||||
|
urijs "^1.18.2"
|
||||||
|
|
||||||
|
sinon@^7.2.3:
|
||||||
|
version "7.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.4.2.tgz#ecd54158fef2fcfbdb231a3fa55140e8cb02ad6c"
|
||||||
|
integrity sha512-pY5RY99DKelU3pjNxcWo6XqeB1S118GBcVIIdDi6V+h6hevn1izcg2xv1hTHW/sViRXU7sUOxt4wTUJ3gsW2CQ==
|
||||||
|
dependencies:
|
||||||
|
"@sinonjs/commons" "^1.4.0"
|
||||||
|
"@sinonjs/formatio" "^3.2.1"
|
||||||
|
"@sinonjs/samsam" "^3.3.3"
|
||||||
|
diff "^3.5.0"
|
||||||
|
lolex "^4.2.0"
|
||||||
|
nise "^1.5.2"
|
||||||
|
supports-color "^5.5.0"
|
||||||
|
|
||||||
sisteransi@^1.0.3:
|
sisteransi@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.3.tgz#98168d62b79e3a5e758e27ae63c4a053d748f4eb"
|
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.3.tgz#98168d62b79e3a5e758e27ae63c4a053d748f4eb"
|
||||||
@ -13401,7 +13518,7 @@ type-check@~0.3.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prelude-ls "~1.1.2"
|
prelude-ls "~1.1.2"
|
||||||
|
|
||||||
type-detect@^4.0.0, type-detect@^4.0.5:
|
type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5:
|
||||||
version "4.0.8"
|
version "4.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
|
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
|
||||||
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
|
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
|
||||||
@ -13640,6 +13757,11 @@ uri-js@^4.2.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
|
urijs@^1.18.2:
|
||||||
|
version "1.19.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.1.tgz#5b0ff530c0cbde8386f6342235ba5ca6e995d25a"
|
||||||
|
integrity sha512-xVrGVi94ueCJNrBSTjWqjvtgvl3cyOTThp2zaMaFNGp3F542TR6sM3f2o8RqZl+AwteClSVmoCyt0ka4RjQOQg==
|
||||||
|
|
||||||
urix@^0.1.0:
|
urix@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user