Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature refactor vault recovery #307

Merged
merged 7 commits into from
May 2, 2024
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
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -635,4 +635,10 @@
##### [BREAKING Changes] Removed getAssets() method

* Removed function `getAssets()` to get the list of assets of all the accounts associated as it is moved to an api service.
* Updated avalanche, base and zkEVM controllers.
* Updated avalanche, base and zkEVM controllers.

### 2.5.1 (2024-02-20)

* Refactored recover vault logic and generalized it for evm and non evm chains
* updated labeling for evm and non evm wallet accounts
* Integrated restore account logs for vault recovery
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@getsafle/safle-vault",
"version": "2.5.0",
"version": "2.5.1",
"description": "Safle Vault is a non-custodial, flexible and highly available crypto wallet which can be used to access dapps, send/receive crypto and store identity. Vault SDK is used to manage the vault and provide methods to generate vault, add new accounts, update the state and also enable the user to perform several vault related operations.",
"main": "src/index.js",
"scripts": {
Expand Down
25 changes: 16 additions & 9 deletions src/lib/keyring.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ class Keyring {
const acc = await this.getAccounts();

if (Chains.evmChains.hasOwnProperty(this.chain) || this.chain === 'ethereum') {

let labelPrefix = 'EVM'
const accounts = await this.keyringInstance.getAccounts();

const keyring = await this.keyringInstance.getKeyringForAccount(accounts[0]);
Expand All @@ -229,7 +231,7 @@ class Keyring {

const newAccount = await this.keyringInstance.getAccounts();

this.decryptedVault.eth.public.push({ address: newAccount[newAccount.length - 1], isDeleted: false, isImported: false, label: `Wallet ${acc.response.length + 1}` })
this.decryptedVault.eth.public.push({ address: newAccount[newAccount.length - 1], isDeleted: false, isImported: false, label: `${labelPrefix} Wallet ${acc.response.length + 1}` })
this.decryptedVault.eth.numberOfAccounts++;

const encryptedVault = await helper.cryptography(JSON.stringify(this.decryptedVault), JSON.stringify(encryptionKey), 'encryption');
Expand All @@ -245,6 +247,8 @@ class Keyring {

let newAddress;

let labelPrefix = Chains.nonEvmChains[this.chain]

if (this[this.chain] === undefined) {
const keyringInstance = await helper.getCoinInstance(this.chain, mnemonic);

Expand All @@ -254,14 +258,14 @@ class Keyring {

newAddress = address;

const publicData = [ { address, isDeleted: false, isImported: false, label: `${this.chain[0].toUpperCase() + this.chain.slice(1)} Wallet ${acc.response ? acc.response.length + 1 : 1}` } ];
const publicData = [ { address, isDeleted: false, isImported: false, label: `${labelPrefix} Wallet ${acc.response ? acc.response.length + 1 : 1}` } ];
this.decryptedVault[this.chain] = { public: publicData, numberOfAccounts: 1 };
} else {
const { address } = await this[this.chain].addAccount();

newAddress = address;

(this.decryptedVault[this.chain] === undefined) ? this.decryptedVault[this.chain] = { public: [ { address: newAddress, isDeleted: false, isImported: false, label: `${this.chain[0].toUpperCase() + this.chain.slice(1)} Wallet ${acc.response.length + 1}` } ], numberOfAccounts: 1 } : this.decryptedVault[this.chain].public.push({ address: newAddress, isDeleted: false, isImported: false, label: `${this.chain[0].toUpperCase() + this.chain.slice(1)} Wallet ${acc.response.length + 1}` });
(this.decryptedVault[this.chain] === undefined) ? this.decryptedVault[this.chain] = { public: [ { address: newAddress, isDeleted: false, isImported: false, label: `${labelPrefix} Wallet ${acc.response.length + 1}` } ], numberOfAccounts: 1 } : this.decryptedVault[this.chain].public.push({ address: newAddress, isDeleted: false, isImported: false, label: `${labelPrefix} Wallet ${acc.response.length + 1}` });
this.decryptedVault[this.chain].numberOfAccounts++;
}

Expand Down Expand Up @@ -643,6 +647,8 @@ class Keyring {
}

if (Chains.evmChains.hasOwnProperty(this.chain) || this.chain === 'ethereum') {

let labelPrefix = 'EVM'

const keyringInstance = await helper.getCoinInstance(this.chain);

Expand All @@ -663,13 +669,14 @@ class Keyring {
}

if (this.decryptedVault.importedWallets === undefined) {
this.decryptedVault.importedWallets = { evmChains: { data: [{ address, privateKey: encryptedPrivKey, isDeleted: false, isImported: true, label: `Wallet ${numOfAcc + 1}` }] } };
this.decryptedVault.importedWallets = { evmChains: { data: [{ address, privateKey: encryptedPrivKey, isDeleted: false, isImported: true, label: `${labelPrefix} Wallet ${numOfAcc + 1}` }] } };
} else if (this.decryptedVault.importedWallets.evmChains === undefined) {
this.decryptedVault.importedWallets.evmChains = { data: [{ address, privateKey: encryptedPrivKey, isDeleted: false, isImported: true, label: `Wallet ${numOfAcc + 1}` }] };
this.decryptedVault.importedWallets.evmChains = { data: [{ address, privateKey: encryptedPrivKey, isDeleted: false, isImported: true, label: `${labelPrefix} Wallet ${numOfAcc + 1}` }] };
} else {
this.decryptedVault.importedWallets.evmChains.data.push({ address, privateKey: encryptedPrivKey, isDeleted: false, isImported: true, label: `Wallet ${numOfAcc + 1}` });
this.decryptedVault.importedWallets.evmChains.data.push({ address, privateKey: encryptedPrivKey, isDeleted: false, isImported: true, label: `${labelPrefix} Wallet ${numOfAcc + 1}` });
}
} else {
let labelPrefix = Chains.nonEvmChains[this.chain]
const { response: mnemonic } = await this.exportMnemonic(pin);

if (this[this.chain] === undefined) {
Expand Down Expand Up @@ -699,16 +706,16 @@ class Keyring {
if (this.decryptedVault.importedWallets === undefined) {
let object = {};

const data = [ { address, isDeleted: false, isImported: true, privateKey: encryptedPrivKey, label: `${this.chain[0].toUpperCase() + this.chain.slice(1)} Wallet ${numOfAcc + 1}` } ];
const data = [ { address, isDeleted: false, isImported: true, privateKey: encryptedPrivKey, label: `${labelPrefix} Wallet ${numOfAcc + 1}` } ];

object[this.chain] = { data };
this.decryptedVault.importedWallets = object;
} else if (this.decryptedVault.importedWallets[this.chain] === undefined) {
const data = [ { address, isDeleted: false, isImported: true, privateKey: encryptedPrivKey, label: `${this.chain[0].toUpperCase() + this.chain.slice(1)} Wallet ${numOfAcc + 1}` } ];
const data = [ { address, isDeleted: false, isImported: true, privateKey: encryptedPrivKey, label: `${labelPrefix} Wallet ${numOfAcc + 1}` } ];

this.decryptedVault.importedWallets[this.chain] = { data };
} else {
this.decryptedVault.importedWallets[this.chain].data.push({ address, isDeleted: false, isImported: true, privateKey: encryptedPrivKey, label: `${this.chain[0].toUpperCase() + this.chain.slice(1)} Wallet ${numOfAcc + 1}` });
this.decryptedVault.importedWallets[this.chain].data.push({ address, isDeleted: false, isImported: true, privateKey: encryptedPrivKey, label: `${labelPrefix} Wallet ${numOfAcc + 1}` });
}
}

Expand Down
24 changes: 15 additions & 9 deletions src/lib/vault.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ class Vault extends Keyring {

const privData = await helper.generatePrivData(mnemonic, pin);

const rawVault = { eth: { public: [ { address: accounts[0], isDeleted: false, isImported: false, label: 'Wallet 1' } ], private: privData, numberOfAccounts: 1 }}
const rawVault = { eth: { public: [ { address: accounts[0], isDeleted: false, isImported: false, label: 'EVM Wallet 1' } ], private: privData, numberOfAccounts: 1 }}

this.initializeSupportedChainKeyringController(mnemonic);

for (const chain of Object.keys(Chains.nonEvmChains)) {
const {address: addedAcc } = await this[chain].addAccount();
let label = `${chain.charAt(0).toUpperCase() + chain.substr(1).toLowerCase()} Wallet 1`
let label = `${Chains.nonEvmChains[chain]} Wallet 1`
rawVault[chain] = { public: [ { address: addedAcc, isDeleted: false, isImported: false, label: label } ], numberOfAccounts: 1 }
}

Expand Down Expand Up @@ -129,8 +129,14 @@ class Vault extends Keyring {

const vaultState = await this.keyringInstance.createNewVaultAndRestore(JSON.stringify(encryptionKey), mnemonic);

const accountsArray = await helper.removeEmptyAccounts(vaultState.keyrings[0].accounts[0], this.keyringInstance, vaultState, unmarshalApiKey, recoverMechanism, logs);

let accountsArray = [];
if(recoverMechanism === 'transactions') {
accountsArray = await helper.getAccountsFromTransactions(vaultState.keyrings[0].accounts[0], this.keyringInstance, vaultState, unmarshalApiKey)
}
else if (recoverMechanism === 'logs') {
accountsArray = await helper.getAccountsFromLogs('ethereum', this.keyringInstance, vaultState, logs, vaultState.keyrings[0].accounts[0])
}

const privData = await helper.generatePrivData(mnemonic, pin);

const numberOfAccounts = accountsArray.length;
Expand All @@ -141,14 +147,14 @@ class Vault extends Keyring {

//generate other chain's keyring instance and get accounts from logs
let obj = {}
for ( let chainData of nonEvmChainList) {

const keyringInstance = await helper.getCoinInstance(chainData.toLowerCase(), mnemonic);
for ( let chain of nonEvmChainList) {
const keyringInstance = await helper.getCoinInstance(chain.toLowerCase(), mnemonic);

const accArray = await helper.getAccountsFromLogs(keyringInstance, vaultState, recoverMechanism, logs);
let {address} = await keyringInstance.addAccount();
const accArray = await helper.getAccountsFromLogs(chain, keyringInstance, vaultState, logs, address);
const numberOfAcc = accArray.length;

rawVault[chainData.toLowerCase()] = { public: accArray, numberOfAccounts: numberOfAcc }
rawVault[chain.toLowerCase()] = { public: accArray, numberOfAccounts: numberOfAcc }

}

Expand Down
Loading
Loading