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

NodeJs: sweet improvements 🍓 #2161

Merged
merged 12 commits into from
Mar 19, 2024
6 changes: 3 additions & 3 deletions bindings/nodejs/lib/types/wallet/bridge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
__PrepareConsolidateOutputsMethod__,
__PrepareCreateAccountOutputMethod__,
__DeregisterParticipationEventMethod__,
__GetAddressMethod__,
__GetBalanceMethod__,
__GetOutputMethod__,
__GetFoundryOutputMethod__,
Expand Down Expand Up @@ -69,7 +70,6 @@ import type {
__StopBackgroundSyncMethod__,
__StoreMnemonicMethod__,
__UpdateNodeAuthMethod__,
__AddressMethod__,
} from './wallet';

export type __WalletMethod__ =
Expand All @@ -79,6 +79,7 @@ export type __WalletMethod__ =
| __PrepareConsolidateOutputsMethod__
| __PrepareCreateAccountOutputMethod__
| __DeregisterParticipationEventMethod__
| __GetAddressMethod__
| __GetBalanceMethod__
| __GetOutputMethod__
| __GetIncomingTransactionMethod__
Expand Down Expand Up @@ -142,5 +143,4 @@ export type __WalletMethod__ =
| __StartBackgroundSyncMethod__
| __StopBackgroundSyncMethod__
| __StoreMnemonicMethod__
| __UpdateNodeAuthMethod__
| __AddressMethod__;
| __UpdateNodeAuthMethod__;
2 changes: 1 addition & 1 deletion bindings/nodejs/lib/types/wallet/bridge/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export type __GetTransactionMethod__ = {
};
};

export type __AddressMethod__ = {
export type __GetAddressMethod__ = {
name: 'getAddress';
};

Expand Down
210 changes: 96 additions & 114 deletions bindings/nodejs/tests/wallet/wallet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,151 +13,54 @@ import {
} from '../../lib/';

describe('Wallet', () => {

it('create wallet', async () => {
let storagePath = 'test-create-wallet';
removeDir(storagePath);

const strongholdSecretManager = {
stronghold: {
snapshotPath: `./${storagePath}/wallet.stronghold`,
password: `A12345678*`,
},
};

const secretManager = SecretManager.create(strongholdSecretManager);

await secretManager.storeMnemonic(
'vital give early extra blind skin eight discover scissors there globe deal goat fat load robot return rate fragile recycle select live ordinary claim',
);

const wallet_address = await secretManager.generateEd25519Addresses({
coinType: CoinType.IOTA,
accountIndex: 0,
range: {
start: 0,
end: 1,
},
bech32Hrp: 'tst',
});

const walletOptions: WalletOptions = {
address: wallet_address[0],
storagePath: './test-create-wallet',
clientOptions: {
nodes: ['https://api.testnet.shimmer.network'],
protocolParameters: Utils.iotaMainnetProtocolParameters(),
},
bipPath: {
coinType: CoinType.IOTA,
},
secretManager: strongholdSecretManager,
};

const walletOptions = await createDefaultWalletOptions(storagePath);
const wallet = await Wallet.create(walletOptions);

await wallet.destroy();

removeDir(storagePath);
}, 20000);

it('recreate wallet', async () => {
let storagePath = 'test-recreate-wallet';
it('restore wallet', async () => {
let storagePath = 'test-restore-wallet';
removeDir(storagePath);

const strongholdSecretManager = {
stronghold: {
snapshotPath: `./${storagePath}/wallet.stronghold`,
password: `A12345678*`,
},
};

const secretManager = SecretManager.create(strongholdSecretManager);

await secretManager.storeMnemonic(
'vital give early extra blind skin eight discover scissors there globe deal goat fat load robot return rate fragile recycle select live ordinary claim',
);

const wallet_address = await secretManager.generateEd25519Addresses({
coinType: CoinType.IOTA,
accountIndex: 0,
range: {
start: 0,
end: 1,
},
bech32Hrp: 'tst',
});

const walletOptions: WalletOptions = {
address: wallet_address[0],
storagePath,
clientOptions: {
nodes: ['https://api.testnet.shimmer.network'],
protocolParameters: Utils.iotaMainnetProtocolParameters(),
},
bipPath: {
coinType: CoinType.IOTA,
},
secretManager: strongholdSecretManager,
};

const walletOptions = await createDefaultWalletOptions(storagePath);
const wallet = await Wallet.create(walletOptions);

const client = await wallet.getClient();
const hrp = await client.getBech32Hrp();
expect(hrp).toEqual('smr');

const originalAddress = await wallet.address();
expect(originalAddress).toEqual(walletOptions.address);

await wallet.destroy();

const recreatedWallet = await Wallet.create({ storagePath });
const restoredWallet = await Wallet.create({ storagePath });
expect(originalAddress).toEqual(await restoredWallet.address());

const restoredClient = await restoredWallet.getClient();
const restoredHrp = await restoredClient.getBech32Hrp();
expect(restoredHrp).toEqual(hrp);

// TODO: make add test to verify wallet equality
// expect(accounts.length).toStrictEqual(0);
await restoredWallet.destroy();

await recreatedWallet.destroy();
removeDir(storagePath);
}, 20000);

it('error after destroy', async () => {
let storagePath = 'test-error-after-destroy';
removeDir(storagePath);

const strongholdSecretManager = {
stronghold: {
snapshotPath: `./${storagePath}/wallet.stronghold`,
password: `A12345678*`,
},
};
const secretManager = await SecretManager.create(
strongholdSecretManager,
);
await secretManager.storeMnemonic(
'vital give early extra blind skin eight discover scissors there globe deal goat fat load robot return rate fragile recycle select live ordinary claim',
);

const wallet_address = await secretManager.generateEd25519Addresses({
coinType: CoinType.IOTA,
accountIndex: 0,
range: {
start: 0,
end: 1,
},
bech32Hrp: 'tst',
});

const walletOptions = {
address: wallet_address[0],
storagePath,
clientOptions: {
nodes: ['https://api.testnet.shimmer.network'],
protocolParameters: Utils.iotaMainnetProtocolParameters(),
},
bipPath: {
coinType: CoinType.IOTA,
},
secretManager: strongholdSecretManager,
};

const walletOptions = await createDefaultWalletOptions(storagePath);
const wallet = await Wallet.create(walletOptions);

await wallet.destroy();

try {
Expand All @@ -175,8 +78,87 @@ describe('Wallet', () => {
}
removeDir(storagePath);
}, 35000);

it('error on address conflict', async () => {
let storagePath = 'test-error-on-address-conflict';
removeDir(storagePath);

const walletOptions = await createDefaultWalletOptions(storagePath);
const wallet = await Wallet.create(walletOptions);
await wallet.destroy();

walletOptions.address = "tst1qpqzgvcehafmlxh87zrf9w8ck8q2kw5070ztf68ylhzk89en9a4fyg6k2w3";

try {
const _restoredWallet = await Wallet.create(walletOptions);
throw 'Should return an error because the provided address conflicts with the stored one';
} catch (err: any) {
expect(err.message).toEqual(
'wallet address mismatch: tst1qpqzgvcehafmlxh87zrf9w8ck8q2kw5070ztf68ylhzk89en9a4fyg6k2w3, existing address is: smr1qpqzgvcehafmlxh87zrf9w8ck8q2kw5070ztf68ylhzk89en9a4fyq4ten7');
}

removeDir(storagePath);
}, 20000);

it('error on bip path conflict', async () => {
let storagePath = 'test-error-on-bip-path-conflict';
removeDir(storagePath);

const walletOptions = await createDefaultWalletOptions(storagePath);
const wallet = await Wallet.create(walletOptions);
await wallet.destroy();

walletOptions.bipPath = { coinType: CoinType.IOTA };

try {
const _restoredWallet = await Wallet.create(walletOptions);
throw 'Should return an error because the provided bip path conflicts with the stored one';
} catch (err: any) {
expect(err.message).toEqual('bip path mismatch: Some(Bip44 { coin_type: 4218, account: 0, change: 0, address_index: 0 }), existing bip path is: Some(Bip44 { coin_type: 4219, account: 0, change: 0, address_index: 0 })');
}

removeDir(storagePath);
}, 20000);
});

async function createDefaultWalletOptions(storagePath: string): Promise<WalletOptions> {
const strongholdSecretManager = {
stronghold: {
snapshotPath: `./${storagePath}/wallet.stronghold`,
password: `A12345678*`,
},
};
const secretManager = SecretManager.create(strongholdSecretManager);
await secretManager.storeMnemonic(
'vital give early extra blind skin eight discover scissors there globe deal goat fat load robot return rate fragile recycle select live ordinary claim',
);

const coinType = CoinType.Shimmer;
const address = (await secretManager.generateEd25519Addresses({
coinType,
accountIndex: 0,
range: {
start: 0,
end: 1,
},
bech32Hrp: 'smr',
}))[0];

return {
address,
alias: "Alice",
bipPath: {
coinType,
},
storagePath,
clientOptions: {
nodes: ['https://api.testnet.shimmer.network'],
protocolParameters: Utils.shimmerMainnetProtocolParameters(),
},
secretManager: strongholdSecretManager,
};
}

function removeDir(storagePath: string) {
const fs = require('fs');
fs.rmSync(storagePath, { recursive: true, force: true });
Expand Down
3 changes: 2 additions & 1 deletion sdk/src/wallet/core/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ where
}
};

// May use a previously stored wallet alias if it wasn't provided
// May use a previously stored wallet alias if it wasn't provided.
// An already stored alias will be silently replaced.
if self.alias.is_none() {
self.alias = loaded_wallet_builder.as_ref().and_then(|builder| builder.alias.clone());
}
Expand Down
Loading