Skip to content

Commit

Permalink
Resolve merge
Browse files Browse the repository at this point in the history
  • Loading branch information
nikoulai committed Apr 11, 2022
2 parents b32fc4d + 8e57d5a commit af25dc9
Show file tree
Hide file tree
Showing 24 changed files with 999 additions and 681 deletions.
Empty file.
Binary file added .github/geth/data/geth/triecache/data.0.bin
Binary file not shown.
Binary file added .github/geth/data/geth/triecache/metadata.bin
Binary file not shown.
35 changes: 27 additions & 8 deletions packages/web3-common/src/web3_base_wallet.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
import { HexString } from 'web3-utils';

export type Web3EncryptedWallet = string;

export interface Web3BaseWalletAccount {
[key: string]: unknown;
readonly address: string;
readonly privateKey: string;
readonly signTransaction: (tx: Record<string, unknown>) => string;
readonly sign: (data: Record<string, unknown> | string) => string;
readonly encrypt: (password: string, options?: Record<string, unknown>) => Web3EncryptedWallet;
readonly signTransaction: (tx: Record<string, unknown>) => {
readonly messageHash: HexString;
readonly r: HexString;
readonly s: HexString;
readonly v: HexString;
readonly rawTransaction: HexString;
readonly transactionHash: HexString;
};
readonly sign: (data: Record<string, unknown> | string) => {
readonly messageHash: HexString;
readonly r: HexString;
readonly s: HexString;
readonly v: HexString;
readonly message?: string;
readonly signature: HexString;
};
readonly encrypt: (
password: string,
options?: Record<string, unknown>,
) => Promise<Web3EncryptedWallet>;
}

export interface Web3AccountProvider<T> {
privateKeyToAccount: (privateKey: string) => T;
create: () => T;
decrypt: (keystore: string, password: string, options?: Record<string, unknown>) => T;
decrypt: (keystore: string, password: string, options?: Record<string, unknown>) => Promise<T>;
}

export abstract class Web3BaseWallet<T extends Web3BaseWalletAccount> {
Expand All @@ -30,12 +49,12 @@ export abstract class Web3BaseWallet<T extends Web3BaseWalletAccount> {
public abstract encrypt(
password: string,
options?: Record<string, unknown>,
): Web3EncryptedWallet[];
): Promise<Web3EncryptedWallet[]>;
public abstract decrypt(
encryptedWallet: Web3EncryptedWallet[],
password: string,
options?: Record<string, unknown>,
): this;
public abstract save(password: string, keyName?: string): boolean | never;
public abstract load(password: string, keyName?: string): this | never;
): Promise<this>;
public abstract save(password: string, keyName?: string): Promise<boolean | never>;
public abstract load(password: string, keyName?: string): Promise<this | never>;
}
44 changes: 41 additions & 3 deletions packages/web3-core/src/web3_context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Web3APISpec } from 'web3-common';
import {
Web3APISpec,
Web3BaseWallet,
Web3BaseWalletAccount,
Web3AccountProvider,
} from 'web3-common';
import { HexString } from 'web3-utils';
import { SupportedProviders } from './types';
import { isSupportedProvider } from './utils';
Expand All @@ -23,6 +28,8 @@ export type Web3ContextObject<
subscriptionManager?: Web3SubscriptionManager<API, RegisteredSubs> | undefined;
registeredSubscriptions?: RegisteredSubs;
providers: typeof Web3RequestManager.providers;
accountProvider?: Web3AccountProvider<Web3BaseWalletAccount>;
wallet?: Web3BaseWallet<Web3BaseWalletAccount>;
};

export type Web3ContextInitOptions<
Expand All @@ -38,6 +45,8 @@ export type Web3ContextInitOptions<
requestManager?: Web3RequestManager<API>;
subscriptionManager?: Web3SubscriptionManager<API, RegisteredSubs> | undefined;
registeredSubscriptions?: RegisteredSubs;
accountProvider?: Web3AccountProvider<Web3BaseWalletAccount>;
wallet?: Web3BaseWallet<Web3BaseWalletAccount>;
};

export type Web3ContextConstructor<
Expand Down Expand Up @@ -67,6 +76,8 @@ export class Web3Context<
public readonly providers = Web3RequestManager.providers;
private _requestManager: Web3RequestManager<API>;
private _subscriptionManager?: Web3SubscriptionManager<API, RegisteredSubs>;
private _accountProvider?: Web3AccountProvider<Web3BaseWalletAccount>;
private _wallet?: Web3BaseWallet<Web3BaseWalletAccount>;

public constructor(
providerOrContext: SupportedProviders<API> | Web3ContextInitOptions<API, RegisteredSubs>,
Expand All @@ -84,8 +95,15 @@ export class Web3Context<
return;
}

const { config, provider, requestManager, subscriptionManager, registeredSubscriptions } =
providerOrContext as Partial<Web3ContextObject<API, RegisteredSubs>>;
const {
config,
provider,
requestManager,
subscriptionManager,
registeredSubscriptions,
accountProvider,
wallet,
} = providerOrContext as Partial<Web3ContextObject<API, RegisteredSubs>>;

this.setConfig(config ?? {});

Expand All @@ -99,6 +117,14 @@ export class Web3Context<
registeredSubscriptions,
);
}

if (accountProvider) {
this._accountProvider = accountProvider;
}

if (wallet) {
this._wallet = wallet;
}
}

public get requestManager() {
Expand All @@ -109,6 +135,14 @@ export class Web3Context<
return this._subscriptionManager;
}

public get wallet() {
return this._wallet;
}

public get accountProvider() {
return this._accountProvider;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public static fromContextObject<T extends Web3Context<any>, T3 extends unknown[]>(
this: Web3ContextConstructor<T, T3>,
Expand All @@ -126,6 +160,8 @@ export class Web3Context<
registeredSubscriptions: this.subscriptionManager
?.registeredSubscriptions as RegisteredSubs,
providers: this.providers,
wallet: this.wallet,
accountProvider: this.accountProvider,
};
}

Expand Down Expand Up @@ -159,6 +195,8 @@ export class Web3Context<
this._requestManager = parentContext.requestManager;
this.provider = parentContext.provider;
this._subscriptionManager = parentContext.subscriptionManager;
this._wallet = parentContext.wallet;
this._accountProvider = parentContext._accountProvider;

parentContext.on(Web3ConfigEvent.CONFIG_CHANGE, event => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

exports[`Web3Context getContextObject should return correct context object 1`] = `
Object {
"accountProvider": undefined,
"config": Object {
"blockHeaderTimeout": 10,
"defaultAccount": null,
Expand Down Expand Up @@ -46,5 +47,6 @@ Object {
},
},
"subscriptionManager": undefined,
"wallet": undefined,
}
`;
50 changes: 19 additions & 31 deletions packages/web3-eth-accounts/src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,14 @@ import {
} from 'web3-common';
import {
signatureObject,
signFunction,
signResult,
signTransactionFunction,
signTransactionResult,
KeyStore,
ScryptParams,
PBKDF2SHA256Params,
CipherOptions,
keyStoreSchema,
Web3Account,
} from './types';

/**
Expand Down Expand Up @@ -358,32 +357,27 @@ export const encrypt = async (
/**
* Get account from private key
*/
export const privateKeyToAccount = (
privateKey: string | Buffer,
): {
address: string;
privateKey: string;
signTransaction: signTransactionFunction; // From 1.x
sign: signFunction;
encrypt: (privateKey: string, password: string) => Promise<KeyStore>;
} => ({
address: privateKeyToAddress(privateKey),
privateKey: Buffer.isBuffer(privateKey) ? Buffer.from(privateKey).toString('hex') : privateKey,
signTransaction,
sign,
encrypt,
});
export const privateKeyToAccount = (privateKey: string | Buffer): Web3Account => {
const pKey = Buffer.isBuffer(privateKey) ? Buffer.from(privateKey).toString('hex') : privateKey;

return {
address: privateKeyToAddress(pKey),
privateKey: pKey,
signTransaction: (tx: Record<string, unknown>) => signTransaction(tx, pKey),
sign: (data: Record<string, unknown> | string) =>
sign(typeof data === 'string' ? data : JSON.stringify(data), pKey),
encrypt: async (password: string, options?: Record<string, unknown>) => {
const data = await encrypt(pKey, password, options);

return JSON.stringify(data);
},
};
};

/**
* Returns an acoount
*/
export const create = (): {
address: HexString;
privateKey: HexString;
signTransaction: signTransactionFunction; // From 1.x
sign: signFunction;
encrypt: (a: string, b: string) => Promise<KeyStore>;
} => {
export const create = (): Web3Account => {
const privateKey = utils.randomPrivateKey();

return privateKeyToAccount(`0x${Buffer.from(privateKey).toString('hex')}`);
Expand All @@ -397,13 +391,7 @@ export const decrypt = async (
keystore: KeyStore | string,
password: string | Buffer,
nonStrict?: boolean,
): Promise<{
address: string;
privateKey: HexString;
signTransaction: signTransactionFunction; // From 1.x
sign: signFunction;
encrypt: (privateKey: HexString, password: string) => Promise<KeyStore>;
}> => {
): Promise<Web3Account> => {
const json =
typeof keystore === 'object'
? keystore
Expand Down
13 changes: 11 additions & 2 deletions packages/web3-eth-accounts/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FeeMarketEIP1559TxData, AccessListEIP2930TxData, TxData } from '@ethereumjs/tx';
import { Web3BaseWalletAccount } from 'web3-common';
import { HexString } from 'web3-utils';

export type signatureObject = {
Expand Down Expand Up @@ -37,8 +38,11 @@ export type signTransactionResult = signatureObject & {
};

export type signTransactionFunction = (
transaction: TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData,
privateKey: string,
transaction:
| TxData
| AccessListEIP2930TxData
| FeeMarketEIP1559TxData
| Record<string, unknown>,
) => signTransactionResult;

export type signResult = signatureObject & {
Expand Down Expand Up @@ -92,3 +96,8 @@ export type KeyStore = {
version: 3;
address: string;
};

export interface Web3Account extends Web3BaseWalletAccount {
address: HexString;
privateKey: HexString;
}
29 changes: 20 additions & 9 deletions packages/web3-eth-accounts/src/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,35 +99,46 @@ export class Wallet<
return this;
}

public encrypt(password: string, options?: Record<string, unknown> | undefined) {
return Object.values(this._accounts).map(account => account.encrypt(password, options));
public async encrypt(password: string, options?: Record<string, unknown> | undefined) {
return Promise.all(
Object.values(this._accounts).map(async account => account.encrypt(password, options)),
);
}

public decrypt(
public async decrypt(
encryptedWallets: string[],
password: string,
options?: Record<string, unknown> | undefined,
) {
for (const wallet of encryptedWallets) {
this.add(this._accountProvider.decrypt(wallet, password, options));
const results = await Promise.all(
encryptedWallets.map(async wallet =>
this._accountProvider.decrypt(wallet, password, options),
),
);

for (const res of results) {
this.add(res);
}

return this;
}

public save(password: string, keyName?: string) {
public async save(password: string, keyName?: string) {
const storage = Wallet.getStorage();

if (!storage) {
throw new Error('Local storage not available.');
}

storage.setItem(keyName ?? this._defaultKeyName, JSON.stringify(this.encrypt(password)));
storage.setItem(
keyName ?? this._defaultKeyName,
JSON.stringify(await this.encrypt(password)),
);

return true;
}

public load(password: string, keyName?: string) {
public async load(password: string, keyName?: string) {
const storage = Wallet.getStorage();

if (!storage) {
Expand All @@ -137,7 +148,7 @@ export class Wallet<
const keystore = storage.getItem(keyName ?? this._defaultKeyName);

if (keystore) {
this.decrypt((JSON.parse(keystore) as Web3EncryptedWallet[]) || [], password);
await this.decrypt((JSON.parse(keystore) as Web3EncryptedWallet[]) || [], password);
}

return this;
Expand Down
20 changes: 11 additions & 9 deletions packages/web3-eth-accounts/test/unit/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('accounts', () => {
describe('privateKeyToAccount', () => {
describe('valid cases', () => {
it.each(validPrivateKeytoAccountData)('%s', (input, output) => {
expect(privateKeyToAccount(input)).toEqual(output);
expect(JSON.stringify(privateKeyToAccount(input))).toEqual(JSON.stringify(output));
});
});

Expand Down Expand Up @@ -138,17 +138,19 @@ describe('accounts', () => {
});

// make sure decrypt does not throw invalid password error
const result = await decrypt(keystore, input[1]).catch(err => {
throw err;
});
expect(result).toEqual(privateKeyToAccount(input[3].slice(2)));
const result = await decrypt(keystore, input[1]);

expect(JSON.stringify(result)).toEqual(
JSON.stringify(privateKeyToAccount(input[3].slice(2))),
);

const keystoreString = JSON.stringify(keystore);

const stringResult = await decrypt(keystoreString, input[1], true).catch(err => {
throw err;
});
expect(stringResult).toEqual(privateKeyToAccount(input[3].slice(2)));
const stringResult = await decrypt(keystoreString, input[1], true);

expect(JSON.stringify(stringResult)).toEqual(
JSON.stringify(privateKeyToAccount(input[3].slice(2))),
);
});
});

Expand Down
Loading

0 comments on commit af25dc9

Please sign in to comment.