Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
3d27f49
feat: add master password
Nick-1979 Oct 13, 2025
1168b0b
Merge branch 'main' into masterPass
Nick-1979 Oct 14, 2025
2ecaef0
chore: update emitted event type
Nick-1979 Oct 14, 2025
b2bf5a2
chore: guard against possible undefined
Nick-1979 Oct 14, 2025
e3c59b5
chore: remove logs
Nick-1979 Oct 14, 2025
fc12f4b
fix: no lock expiration for watchonlyies
Nick-1979 Oct 14, 2025
65fe4ab
refactor: update auto-lock
Nick-1979 Oct 14, 2025
a61c1c4
chore: remove is login enabled
Nick-1979 Oct 14, 2025
cafcf60
chore: pause assets balance fetch before login
Nick-1979 Oct 14, 2025
87c9649
refactor: adjust naming and reset on password change
Nick-1979 Oct 14, 2025
e95a181
chore: change enable to adjust auto lock
Nick-1979 Oct 14, 2025
18e5e49
chore: update translation
Nick-1979 Oct 14, 2025
4ef1be3
fix: use master password for account creation
Nick-1979 Oct 14, 2025
3e77c7d
chore: remove unused
Nick-1979 Oct 14, 2025
323b7c8
perf: remove unnecessary delays
Nick-1979 Oct 14, 2025
ad90a47
chore: remove console.log
Nick-1979 Oct 14, 2025
d706ff4
fix: resolve known issues
Nick-1979 Oct 15, 2025
9354618
chore: remove unused
Nick-1979 Oct 15, 2025
b138b3b
chore: move to home after successful pass change
Nick-1979 Oct 18, 2025
f1d69f9
refactor: make code simpler
Nick-1979 Oct 18, 2025
a63c401
fix: add migrate url to reset path list
Nick-1979 Oct 18, 2025
8fd03f7
chore: reorder items in the list alphabetically
Nick-1979 Oct 18, 2025
3f5cbd6
chore: fix invalid master password on import
Nick-1979 Oct 18, 2025
f6dd211
chore: refactor codes
Nick-1979 Oct 18, 2025
8240969
refactor: refactor to improve code readability
Nick-1979 Oct 18, 2025
8c56bae
fix: handle single-account JSON import correctly
Nick-1979 Oct 18, 2025
6e73ec9
chore: generalize the function type
Nick-1979 Oct 19, 2025
79295c8
chore: yield one frame to render busy state before async execution
Nick-1979 Oct 19, 2025
c70bd63
chore: fix lint issue
Nick-1979 Oct 19, 2025
f9da8ef
Merge branch 'main' into masterPass
Nick-1979 Oct 19, 2025
27f9a6c
Merge branch 'main' into masterPass
Nick-1979 Oct 19, 2025
e639743
refactor: use await in async function
Nick-1979 Oct 19, 2025
8d2d291
chore: adjust password input title
Nick-1979 Oct 19, 2025
f695435
Merge branch 'main' into masterPass
Nick-1979 Oct 20, 2025
7354cd9
Merge branch 'main' into masterPass
Nick-1979 Oct 20, 2025
5431264
refactor: refactor imports and create account (#1969)
Nick-1979 Oct 21, 2025
5ae276d
refactor: remove unnecessary UI keyring logic (#1970)
Nick-1979 Oct 21, 2025
ced7988
refactor: chore: use send for passwordless approval (#1973)
Nick-1979 Oct 21, 2025
5cc73b8
style: add animations to the password migration flow (#1977)
Nick-1979 Oct 21, 2025
729add3
refactor: apply rabbit suggestions
Nick-1979 Oct 21, 2025
3719408
refactor: update fee extraction logic and ensure subscription cleanup…
Nick-1979 Oct 21, 2025
08651a4
fix: add signer.assetId support to pay transaction fees with non-nati…
Nick-1979 Oct 21, 2025
fceee70
Merge branch 'main' into masterPass
Nick-1979 Oct 21, 2025
08a95cd
Merge branch 'main' into masterPass
Nick-1979 Oct 21, 2025
d99ac83
style: update wait screen loading gif
Nick-1979 Oct 22, 2025
fbf20cc
chore: add auto lock to storage keys
Nick-1979 Oct 22, 2025
f0086f4
fix: gracefully handle non-existent key pair during forgot password f…
Nick-1979 Oct 22, 2025
4dab080
feat: add proactive unlock cache expiry detection and redirect UI to …
Nick-1979 Oct 25, 2025
6307867
chore: update translations
Nick-1979 Oct 25, 2025
85616c2
chore: adjust logs text and remove extra space
Nick-1979 Oct 25, 2025
1fe2802
refactor: unify auto-lock logic for extension and fullscreen modes (#…
Nick-1979 Oct 25, 2025
5b312cf
fix: handle locking accounts issue
Nick-1979 Oct 25, 2025
a267907
fix: remove duplicate account creation
Nick-1979 Oct 25, 2025
40f4834
chore: check the result of reset on forget password
Nick-1979 Oct 25, 2025
9542e95
fix: correct alignment value
Nick-1979 Oct 25, 2025
a74bfe6
refactor: use getAndWatchStorage to manage and sync saved items in st…
Nick-1979 Oct 26, 2025
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
31 changes: 16 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"build": "NODE_ENV=production yarn apply-version && polkadot-dev-build-ts && yarn build:zip && yarn build:rollup",
"build:before": "yarn build:i18n",
"build:clean": "yarn build && find packages/extension/build -name '*.map' -type f -delete",
"build:dev": "NODE_ENV=development polkadot-dev-build-ts",
"build:i18n": "i18next-scanner --config i18next-scanner.config.cjs",
"build:release": "polkadot-ci-ghact-build",
"build:rollup": "polkadot-exec-rollup --config",
Expand Down Expand Up @@ -57,18 +58,18 @@
"@mui/lab": "^5.0.0-alpha.85",
"@mui/material": "^5.8.3",
"@paraspell/sdk-pjs": "^11.8.6",
"@polkadot/api": "^16.4.6",
"@polkadot/api-augment": "^16.4.6",
"@polkadot/api-base": "^16.4.6",
"@polkadot/api-contract": "^16.4.6",
"@polkadot/api-derive": "^16.4.6",
"@polkadot/rpc-augment": "^16.4.6",
"@polkadot/rpc-core": "^16.4.6",
"@polkadot/rpc-provider": "^16.4.6",
"@polkadot/types": "^16.4.6",
"@polkadot/types-codec": "^16.4.6",
"@polkadot/types-known": "^16.4.6",
"@polkadot/types-support": "^16.4.6",
"@polkadot/api": "^16.4.8",
"@polkadot/api-augment": "^16.4.8",
"@polkadot/api-base": "^16.4.8",
"@polkadot/api-contract": "^16.4.8",
"@polkadot/api-derive": "^16.4.8",
"@polkadot/rpc-augment": "^16.4.8",
"@polkadot/rpc-core": "^16.4.8",
"@polkadot/rpc-provider": "^16.4.8",
"@polkadot/types": "^16.4.8",
"@polkadot/types-codec": "^16.4.8",
"@polkadot/types-known": "^16.4.8",
"@polkadot/types-support": "^16.4.8",
"@polkadot/util": "^13.5.3",
"@polkadot/util-crypto": "^13.5.3",
"@polkagate/apps-config": "^1.1.1",
Expand Down Expand Up @@ -128,12 +129,12 @@
"webpack-bundle-analyzer": "^4.9.0"
},
"resolutions": {
"@polkadot/api": "^16.4.6",
"@polkadot/api": "^16.4.8",
"@polkadot/keyring": "^13.5.3",
"@polkadot/networks": "^13.5.3",
"@polkadot/react-identicon": "^3.15.2",
"@polkadot/types": "^16.4.6",
"@polkadot/types-augment": "^16.4.6",
"@polkadot/types": "^16.4.8",
"@polkadot/types-augment": "^16.4.8",
"@polkadot/ui-keyring": "^3.15.2",
"@polkadot/ui-settings": "^3.15.2",
"@polkadot/util": "^13.5.3",
Expand Down
6 changes: 3 additions & 3 deletions packages/extension-base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@
"version": "0.47.5",
"main": "index.js",
"dependencies": {
"@polkadot/api": "^16.4.6",
"@polkadot/api": "^16.4.8",
"@polkadot/extension-chains": "^0.47.5",
"@polkadot/extension-dapp": "^0.47.5",
"@polkadot/extension-inject": "^0.47.5",
"@polkadot/keyring": "12.3.2",
"@polkadot/networks": "^13.1.1",
"@polkadot/phishing": "^0.22.8",
"@polkadot/rpc-provider": "^16.4.6",
"@polkadot/types": "^16.4.6",
"@polkadot/rpc-provider": "^16.4.8",
"@polkadot/types": "^16.4.8",
"@polkadot/ui-keyring": "^3.6.6",
"@polkadot/ui-settings": "^3.6.6",
"@polkadot/util": "^13.1.1",
Expand Down
127 changes: 111 additions & 16 deletions packages/extension-base/src/background/handlers/Extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import type { MetadataDef } from '@polkadot/extension-inject/types';
import type { KeyringPair, KeyringPair$Json, KeyringPair$Meta } from '@polkadot/keyring/types';
import type { SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types';
import type { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
import type { HexString } from '@polkadot/util/types';
import type { KeypairType } from '@polkadot/util-crypto/types';
// added for plus to import RequestUpdateMeta
import type { AccountJson, AllowedPath, ApplyAddedTime, AuthorizeRequest, AuthUrls, MessageTypes, MetadataRequest, RequestAccountBatchExport, RequestAccountChangePassword, RequestAccountCreateExternal, RequestAccountCreateHardware, RequestAccountCreateSuri, RequestAccountEdit, RequestAccountExport, RequestAccountForget, RequestAccountShow, RequestAccountTie, RequestAccountValidate, RequestAuthorizeApprove, RequestBatchRestore, RequestDeriveCreate, RequestDeriveValidate, RequestJsonRestore, RequestMetadataApprove, RequestMetadataReject, RequestSeedCreate, RequestSeedValidate, RequestSigningApprovePassword, RequestSigningApproveSignature, RequestSigningCancel, RequestSigningIsLocked, RequestTypes, RequestUpdateAuthorizedAccounts, RequestUpdateMeta, ResponseAccountExport, ResponseAccountsExport, ResponseAuthorizeList, ResponseDeriveValidate, ResponseJsonGetAccountInfo, ResponseSeedCreate, ResponseSeedValidate, ResponseSigningIsLocked, ResponseType, SigningRequest } from '../types';
import type { AccountJson, AllowedPath, ApplyAddedTime, AuthorizeRequest, AuthUrls, MessageTypes, MetadataRequest, RequestAccountBatchExport, RequestAccountChangePassword, RequestAccountCreateExternal, RequestAccountCreateHardware, RequestAccountCreateSuri, RequestAccountEdit, RequestAccountExport, RequestAccountForget, RequestAccountShow, RequestAccountTie, RequestAccountValidate, RequestAuthorizeApprove, RequestBatchRestore, RequestDeriveCreate, RequestDeriveValidate, RequestJsonRestore, RequestMetadataApprove, RequestMetadataReject, RequestSeedCreate, RequestSeedValidate, RequestSigningApprovePassword, RequestSigningApproveSignature, RequestSigningCancel, RequestSigningIsLocked, RequestSigninSignature, RequestTypes, RequestUnlockAllAccounts, RequestUpdateAuthorizedAccounts, RequestUpdateMeta, ResponseAccountExport, ResponseAccountsExport, ResponseAuthorizeList, ResponseDeriveValidate, ResponseJsonGetAccountInfo, ResponseSeedCreate, ResponseSeedValidate, ResponseSigningIsLocked, ResponseType, SigningRequest } from '../types';
import type State from './State';

import { ALLOWED_PATH, PASSWORD_EXPIRY_MS, START_WITH_PATH } from '@polkadot/extension-base/defaults';
Expand Down Expand Up @@ -131,16 +132,35 @@ export default class Extension {
}

private lockExtension (): boolean {
// clear cache and lock all accounts
Object.entries(this.#cachedUnlocks).forEach(([address]) => {
const pair = keyring.getPair(address);

if (pair && !pair.isLocked) {
pair.lock();
}

this.#cachedUnlocks[address] = 0;
});

// apply to all open tabs
const currentDomain = chrome.runtime.getURL('/');

chrome.tabs.query({}, function (tabs) {
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (let i = 0; i < tabs.length; i++) {
const tabParsedUrl = new URL(tabs[i].url!);
const { id, url } = tabs[i];

if (!url || id === undefined) {
continue;
}

const tabParsedUrl = new URL(url);

const tabDomain = `${tabParsedUrl?.protocol}//${tabParsedUrl?.hostname}/`;

if (tabDomain === currentDomain) {
chrome.tabs.reload(tabs[i].id!).catch(console.error);
chrome.tabs.reload(id).catch(console.error);
}
}
});
Expand Down Expand Up @@ -197,7 +217,7 @@ export default class Extension {

console.warn('NO TIE ANYMORE IN NEW DESIGN, genesisHash:', genesisHash);

keyring.saveAccountMeta(pair, { ...pair.meta, genesisHash: null }); //NO TIE ANYMORE IN NEW DESIGN
keyring.saveAccountMeta(pair, { ...pair.meta, genesisHash: null }); // NO TIE ANYMORE IN NEW DESIGN

return true;
}
Expand Down Expand Up @@ -384,6 +404,58 @@ export default class Extension {
};
}

private accountsUnlockAll ({ cacheTime, password }: RequestUnlockAllAccounts): boolean {
console.log('get message to unlock accounts ...');

if (!password) {
throw new Error('Password needed to unlock the account');
}

const accounts = keyring.getAccounts();

const localAccounts = accounts.filter(({ meta }) => !meta.isExternal);

console.log('localAccounts:', localAccounts);

const res = localAccounts.map(({ address }) => {
const pair = keyring.getPair(address);

if (!pair) {
throw new Error('Unable to find pair');
}

if (pair.isLocked) {
pair.decodePkcs8(password);
}

this.#cachedUnlocks[address] = Date.now() + cacheTime;

return true;
});

return res.every((success) => success);
}

private areLocksExpired (): boolean {
return Object.entries(this.#cachedUnlocks).every(([, time]) => time < Date.now());
}

private handleRegistry (payload: SignerPayloadJSON): void {
// Get the metadata for the genesisHash
const currentMetadata = this.metadataGet(payload.genesisHash);

// set the registry before calling the sign function
const signedExtensions = currentMetadata?.signedExtensions?.length
? currentMetadata.signedExtensions
: registry.signedExtensions;

registry.setSignedExtensions(signedExtensions, currentMetadata?.userExtensions);

if (currentMetadata) {
registry.register(currentMetadata?.types);
}
}

private signingApprovePassword ({ id, password, remainingTime, savePass }: RequestSigningApprovePassword): boolean {
const queued = this.#state.getSignRequest(id);

Expand Down Expand Up @@ -417,16 +489,7 @@ export default class Extension {
const { payload } = request;

if (isJsonPayload(payload)) {
// Get the metadata for the genesisHash
const currentMetadata = this.#state.knownMetadata.find((meta: MetadataDef) =>
meta.genesisHash === payload.genesisHash);

// set the registry before calling the sign function
registry.setSignedExtensions(payload.signedExtensions, currentMetadata?.userExtensions);

if (currentMetadata) {
registry.register(currentMetadata?.types);
}
this.handleRegistry(payload);
}

const result = request.sign(registry, pair);
Expand All @@ -447,6 +510,27 @@ export default class Extension {
return true;
}

private getSignature ({ payload }: RequestSigninSignature): HexString | null {
const { address } = payload;

if (!payload?.address || !payload.genesisHash) {
throw new Error('Invalid payload: missing required fields.');
}

const pair = keyring.getPair(address);

this.refreshAccountPasswordCache(pair); // check if auto lock duration is expired

if (pair.isLocked) {
return null;
}

this.handleRegistry(payload);
const { signature } = registry.createType('ExtrinsicPayload', payload, { version: payload.version }).sign(pair);

return signature;
}

private signingApproveSignature ({ id, signature, signedTransaction }: RequestSigningApproveSignature): boolean {
const queued = this.#state.getSignRequest(id);

Expand Down Expand Up @@ -595,12 +679,23 @@ export default class Extension {
case 'pri(accounts.create.suri)':
return this.accountsCreateSuri(request as RequestAccountCreateSuri);

case 'pri(accounts.updateMeta)': // added for polkagate
// ----------------added for polkagate---------------------
case 'pri(accounts.updateMeta)':
return this.accountsUpdateMeta(request as RequestUpdateMeta);

case 'pri(extension.lock)': // added for polkagate
case 'pri(extension.lock)':
return this.lockExtension();

case 'pri(signing.getSignature)':
return this.getSignature(request as RequestSigninSignature);

case 'pri(accounts.unlockAll)':
return this.accountsUnlockAll(request as RequestUnlockAllAccounts);

case 'pri(accounts.locksExpired)':
return this.areLocksExpired();
// -------------------------------------

case 'pri(accounts.changePassword)':
return this.accountsChangePassword(request as RequestAccountChangePassword);

Expand Down
20 changes: 16 additions & 4 deletions packages/extension-base/src/background/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,13 @@ export interface RequestSignatures {
'pri(accounts.create.suri)': [RequestAccountCreateSuri, boolean];
'pri(accounts.edit)': [RequestAccountEdit, boolean];

'pri(accounts.updateMeta)': [RequestUpdateMeta, boolean]; // added for polkagate
'pri(extension.lock)': [null, boolean]; // added for polkagate
'pri(authorize.ignore)': [string, void]; // added for polkagate
'pri(metadata.update)': [MetadataDef, boolean]; // added for polkagate
// added for polkagate
'pri(accounts.updateMeta)': [RequestUpdateMeta, boolean];
'pri(extension.lock)': [null, boolean];
'pri(authorize.ignore)': [string, void];
'pri(metadata.update)': [MetadataDef, boolean];
'pri(accounts.unlockAll)': [RequestUnlockAllAccounts, boolean];
'pri(accounts.locksExpired)': [null, boolean];

'pri(accounts.export)': [RequestAccountExport, ResponseAccountExport];
'pri(accounts.batchExport)': [RequestAccountBatchExport, ResponseAccountsExport]
Expand All @@ -115,6 +118,7 @@ export interface RequestSignatures {
'pri(accounts.subscribe)': [RequestAccountSubscribe, boolean, AccountJson[]];
'pri(accounts.validate)': [RequestAccountValidate, boolean];
'pri(accounts.changePassword)': [RequestAccountChangePassword, boolean];
'pri(signing.getSignature)': [RequestSigninSignature, HexString | null];
'pri(authorize.approve)': [RequestAuthorizeApprove, boolean];
'pri(authorize.update)': [RequestUpdateAuthorizedAccounts, void];
'pri(authorize.list)': [null, ResponseAuthorizeList];
Expand Down Expand Up @@ -306,6 +310,10 @@ export interface RequestSigningApprovePassword {
remainingTime?: number;
}

export interface RequestSigninSignature {
payload: SignerPayloadJSON;
}

export interface RequestSigningApproveSignature {
id: string;
signature: HexString;
Expand Down Expand Up @@ -391,6 +399,10 @@ export interface ResponseSeedValidate {
address: string;
suri: string;
}
export interface RequestUnlockAllAccounts {
password: string;
cacheTime: number; // milisec
}

export interface ResponseAccountExport {
exportedJson: KeyringPair$Json;
Expand Down
3 changes: 2 additions & 1 deletion packages/extension-base/src/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const START_WITH_PATH = [
'/send/',
'/settingsfs/',
'/stake/',
'/socialRecovery/'
'/socialRecovery/',
'/migratePasswords'
] as const;

const ROOT_PATH = [
Expand Down
12 changes: 9 additions & 3 deletions packages/extension-chains/src/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,22 @@ const definitions = new Map<string, MetadataDef>(

const expanded = new Map<string, Chain>();

export function metadataExpand(definition: MetadataDef, isPartial = false): Chain {
export function metadataExpand (definition: MetadataDef, isPartial = false): Chain {
const cached = expanded.get(definition.genesisHash);

if (cached && cached.specVersion === definition.specVersion) {
return cached;
}

const { chain, genesisHash, icon, metaCalls, specVersion, ss58Format, tokenDecimals, tokenSymbol, types, userExtensions } = definition;
const { chain, genesisHash, icon, metaCalls, signedExtensions, specVersion, ss58Format, tokenDecimals, tokenSymbol, types, userExtensions } = definition;
const registry = new TypeRegistry();

if (!isPartial) {
registry.register(types);

if (definition.knownTypes) {
registry.setKnownTypes(definition.knownTypes);
}
}

registry.setChainProperties(registry.createType('ChainProperties', {
Expand All @@ -42,7 +46,9 @@ export function metadataExpand(definition: MetadataDef, isPartial = false): Chai
const hasMetadata = !!metaCalls && !isPartial;

if (hasMetadata) {
registry.setMetadata(new Metadata(registry, base64Decode(metaCalls)), undefined, userExtensions);
const metadata = new Metadata(registry, base64Decode(metaCalls));

registry.setMetadata(metadata, signedExtensions, userExtensions || {});
}

const isUnknown = genesisHash === '0x';
Expand Down
6 changes: 3 additions & 3 deletions packages/extension-inject/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
"version": "0.47.5",
"main": "index.js",
"dependencies": {
"@polkadot/api": "^16.4.6",
"@polkadot/rpc-provider": "^16.4.6",
"@polkadot/types": "^16.4.6",
"@polkadot/api": "^16.4.8",
"@polkadot/rpc-provider": "^16.4.8",
"@polkadot/types": "^16.4.8",
"@polkadot/util": "^13.1.1",
"@polkadot/util-crypto": "^13.1.1",
"@polkadot/x-global": "^13.1.1",
Expand Down
3 changes: 3 additions & 0 deletions packages/extension-inject/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { ProviderInterface } from '@polkadot/rpc-provider/types';
import type { ExtDef } from '@polkadot/types/extrinsic/signedExtensions/types';
import type { HexString } from '@polkadot/util/types';
import type { KeypairType } from '@polkadot/util-crypto/types';
import type { RegisteredTypes } from '@polkadot/types/types';

// eslint-disable-next-line no-undef
type This = typeof globalThis;
Expand Down Expand Up @@ -68,6 +69,8 @@ export interface MetadataDef extends MetadataDefBase {
tokenSymbol: string;
types: Record<string, Record<string, string> | string>;
metaCalls?: string;
knownTypes?: RegisteredTypes;
signedExtensions?: string[];
userExtensions?: ExtDef;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/extension-polkagate/src/class/endpointManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import type { EndpointType } from '../util/types';

import { NO_PASS_PERIOD as ENDPOINT_TIMEOUT } from '../util/constants';
import { ENDPOINT_TIMEOUT } from '../util/constants';

// Define types for saved endpoints and listener function
type SavedEndpoints = Record<string, Record<string, EndpointType>>;
Expand Down
Loading
Loading