UNPKG

@dashevo/wallet-lib

Version:
179 lines (167 loc) 10.7 kB
const Dashcore = require('@dashevo/dashcore-lib'); const { expect } = require('chai'); const DerivableKeyChain = require('./DerivableKeyChain'); const { mnemonicToHDPrivateKey } = require('../../utils/mnemonic'); let derivableKeyChain; let derivableKeyChain2; const mnemonic = 'during develop before curtain hazard rare job language become verb message travel'; const mnemonic2 = 'birth kingdom trash renew flavor utility donkey gasp regular alert pave layer'; const pk = '4226d5e2fe8cbfe6f5beb7adf5a5b08b310f6c4a67fc27826779073be6f5699e'; const hdPublicKey = 'xpub661MyMwAqRbcFGB6XSWBsD725rJDUbFUpy4zWe2u22nJ2BxpoHFxtVDfKnTnvVQHohnY7AsVpRTHDv6PyPQTYu1KxFPKw29MAVXPEpz1G7V'; const expectedRootDIP15AccountKey_0 = 'tprv8hRzmheQujhJN5XP2dj955nAFCKeEoSifJRWuutdbwWRtusdDQ426jbp75EqErUSuTxmPyxYmP1TpcF5qdxGhXLNXRLMGsRLG6NFCv1WnaQ'; const expectedRootDIP15AccountKey_1 = 'tprv8hRzmheQujhJQyCtFTuUFHxB3Ag5VLB994zhH4CfxbA41cq73HT2mpYq5M33V54oJyn6g514saxxVJB886G55eYX56J6D6x87UNNT6iQHkR'; const expectedKeyForChild_0 = 'tprv8d4podc2Tg459CH2bwLHXj3vdJFBT2rdsk5Nr1djH7hzHdt5LRdvN6QyFwMiDy7ffRdik7fEVRKKgsHB4F18sh8xF6jFXpKq4sUgGBoSbKw'; describe('DerivableKeyChain', function suite() { this.timeout(1000); it('should create a DerivableKeyChain', () => { const expectedException1 = 'Expect one of [mnemonic, HDPrivateKey, HDPublicKey, privateKey, publicKey, address] to be provided.'; expect(() => new DerivableKeyChain()).to.throw(expectedException1); derivableKeyChain = new DerivableKeyChain({ mnemonic: mnemonic, network: 'testnet' }); expect(derivableKeyChain.rootKeyType).to.equal('HDPrivateKey'); expect(derivableKeyChain.network.toString()).to.equal('testnet'); expect(derivableKeyChain.rootKey.network.toString()).to.equal('testnet'); derivableKeyChain2 = new DerivableKeyChain({ mnemonic: mnemonic2, network: 'livenet' }); }); it('should generate key for full path', () => { const path = 'm/44\'/1\'/0\'/0/0'; const pk2 = derivableKeyChain.getForPath(path).key; const address = new Dashcore.Address(pk2.publicKey.toAddress()).toString(); expect(address).to.equal('yNfUebksUc5HoSfg8gv98ruC3jUNJUM8pT'); }); it('should get hardened feature path', () => { const hardenedPk = derivableKeyChain.getHardenedBIP44HDKey(); const pk2 = derivableKeyChain.getForPath('m/44\'/1\'').key; expect(pk2.toString()).to.equal(hardenedPk.toString()); }); it('should get DIP15 account key', function () { const rootDIP15AccountKey_0 = derivableKeyChain.getHardenedDIP15AccountKey(0); expect(rootDIP15AccountKey_0.toString()).to.deep.equal(expectedRootDIP15AccountKey_0); const rootDIP15AccountKey_1 = derivableKeyChain.getHardenedDIP15AccountKey(1); expect(rootDIP15AccountKey_1.toString()).to.deep.equal(expectedRootDIP15AccountKey_1); }); it('should get DIP15 extended key', function () { const userUniqueId = '0x555d3854c910b7dee436869c4724bed2fe0784e198b8a39f02bbb49d8ebcfc3a'; const contactUniqueId = '0xa137439f36d04a15474ff7423e4b904a14373fafb37a41db74c84f1dbb5c89b5'; // m/9'/5'/15'/0'/0x555d3854c910b7dee436869c4724bed2fe0784e198b8a39f02bbb49d8ebcfc3a'/0xa137439f36d04a15474ff7423e4b904a14373fafb37a41db74c84f1dbb5c89b5'/0 const DIP15ExtPubKey_0 = derivableKeyChain2.getDIP15ExtendedKey(userUniqueId, contactUniqueId, 0, 0, type='HDPublicKey'); expect(DIP15ExtPubKey_0.toString()).to.equal('xpub6LTkTQFSb8KMgMSz4B6sMZLpkQAY6wSTDprDkHDmLwWLpnjxazuxZn13FrSLKUafitsxuaaffM5a49P6aswhpppWUuYW6eFnwBXshR2W2eY'); expect(DIP15ExtPubKey_0.publicKey.toString()).to.equal('038030c88ab0106e1f4af3b939db2bafc56f892554106f08da1ce1f9ef10f807bd') const DIP15ExtPrivKey_0 = derivableKeyChain2.getDIP15ExtendedKey(userUniqueId, contactUniqueId, 0, 0); expect(DIP15ExtPrivKey_0.toString()).to.equal('xprvA7UQ3tiYkkm4TsNWx9ZrzRQ6CNL3hUibrbvcwtp9nbyMwzQp3Tbi1ygZQaPoigDhCf8XUjMmGK2NbnB2kLXPYg99Lp6e3iki318sdWcFN3q'); expect(DIP15ExtPrivKey_0.privateKey.toString()).to.equal('fac40790776d171ee1db90899b5eb2df2f7d2aaf35ad56f07ffb8ed2c57f8e60') expect(DIP15ExtPrivKey_0.publicKey.toString()).to.equal('038030c88ab0106e1f4af3b939db2bafc56f892554106f08da1ce1f9ef10f807bd') const userAhash = "0xa11ce14f698b32e9bb306dba7bbbee831263dcf658abeebb39930460ead117e5"; const userBhash = "0xb0b052ff075c5ca3c16c3e20e9ac8223834475cc1324ab07889cb24ce6a62793"; const DIP15ExtKey_1 = derivableKeyChain.getDIP15ExtendedKey(userAhash, userBhash, 0, 0); expect(DIP15ExtKey_1.privateKey.toString()).to.equal('60581b6dca8244d3fb3cfe619b5a22277e5423b01e5285f356981f247e0f4a60') expect(DIP15ExtKey_1.publicKey.toString()).to.equal('03deaac00f721151307fbc7bf80d7b8afab98c1f026d67e5f56b21e2013f551ce6') }); it('should derive from hardened feature path', () => { const hardenedHDKey = derivableKeyChain.getHardenedBIP44HDKey(); const pk2 = derivableKeyChain.getForPath(`m/44'/1'`).key; expect(pk2.toString()).to.equal(hardenedHDKey.toString()); expect(hardenedHDKey.toString()).to.deep.equal('tprv8dtrJNytYHRiZY585hmHGbguS6VjGpK49puSB7oXZjLHcQfrAzQkF4ZCxM2DkEbyY85J4EYcZ8EjT5ZCU8ozB727TDdodbfXet5GkGau2RQ'); const derivedPk = hardenedHDKey.deriveChild(0, true).deriveChild(0).deriveChild(0); const address = new Dashcore.Address(derivedPk.publicKey.toAddress()).toString(); expect(address).to.equal('yNfUebksUc5HoSfg8gv98ruC3jUNJUM8pT'); }); it('should get hardened DIP9FeatureHDKey', function () { const hardenedHDKey = derivableKeyChain.getHardenedDIP9FeatureHDKey(); const pk2 = derivableKeyChain.getForPath(`m/9'/1'`).key; expect(pk2.toString()).to.equal(hardenedHDKey.toString()); expect(hardenedHDKey.toString()).to.deep.equal('tprv8fBJjWoGgCpGRCbyzE9RUA59rmoN1RUijhLnXGL4VHnLxvSe523yVg4GrGzbR6TyXtdynAEh5z8UX55EXt2Cb3xjvrsx2PgTY9BHxzFVkWn'); }); it('should get key for path', () => { const derivableKeyChain2 = new DerivableKeyChain({ HDPrivateKey: mnemonicToHDPrivateKey(mnemonic, 'testnet') }); const keyForChild = derivableKeyChain2.getForPath('m/0').key; expect(keyForChild.toString()).to.equal(expectedKeyForChild_0); }); it('should mark address watched and get watched addresses', function () { const key0 = derivableKeyChain.getForPath('m/0'); derivableKeyChain.getForPath('m/0').isWatched = true key0.isWatched = true; const key1 = derivableKeyChain.getForPath('m/1', { isWatched: true }); const key2 = derivableKeyChain.getForPath('m/2', { isWatched: true }); const watchedAddresses = derivableKeyChain.getWatchedAddresses(); let expectedWatchedAddresses = [ derivableKeyChain.getForPath('m/0').address.toString(), derivableKeyChain.getForPath('m/1').address.toString(), derivableKeyChain.getForPath('m/2').address.toString() ]; expect(watchedAddresses).to.deep.equal(expectedWatchedAddresses); }); it('should get watched addresses', function () { const watchedAddresses = derivableKeyChain.getWatchedAddresses(); const expectedWatchedAddresses = [ 'ybQDfNwiDjk8ZH5UUmHQzAMEmjbrbK5dAj', 'yhFX5rseJPitV45HUCaa9haeGHtLuooBaq', 'yhqxsmYk6jfoGWf1hJKq7d4U2cGHCgzpFU' ] expect(watchedAddresses).to.deep.equal(expectedWatchedAddresses); }); // it('should get watched public keys', function () { // const watchedPubKeys = derivableKeyChain.getWatchedPublicKeys(); // const expectedWatchedPubKeys = [ // '03e6ab8177a7ca2699da4f83ca3c27768fb88b70ae9d6bde1cba8de88355ccf199', // '0246a870b65153b98e453ff08f7198d06bce2a790286f44d90929aceafafa0673f', // '025ad16f78f67801e52abe5b512d66e3896d4c2fa3ca3150349437a5dd13519967' // ] // expect(watchedPubKeys).to.deep.equal(expectedWatchedPubKeys) // }); it('should remove an address from watched addresses', function () { const data0 = derivableKeyChain.getForPath('m/0', { isWatched: false }); const data1 = derivableKeyChain.getForPath('m/1'); const data2 = derivableKeyChain.getForPath('m/2'); data2.isWatched = false; expect(derivableKeyChain.getWatchedAddresses().length).to.equal(1); }); it('should get address for path', function (){ const address0_1 = derivableKeyChain.getForPath('m/1').address; expect(address0_1.toString()).to.equal('yhFX5rseJPitV45HUCaa9haeGHtLuooBaq') }) it('should mark address as used', function () { const address0_0 = derivableKeyChain.getForPath('m/0').address; derivableKeyChain.markAddressAsUsed(address0_0); expect(derivableKeyChain.issuedPaths.get('m/0').isUsed).to.equal(true) }); }); describe('DerivableKeyChain - HDPublicKey', function suite(){ let hdpubDerivableKeyChain; it('should initiate from a HDPublicKey', function () { hdpubDerivableKeyChain = new DerivableKeyChain({ HDPublicKey: new Dashcore.HDPublicKey(hdPublicKey), network: 'testnet' }); // As the HDPublicKey starts with xpub, it's livenet and should take priority over our network being set. expect(hdpubDerivableKeyChain.network.toString()).to.equal('livenet'); expect(hdpubDerivableKeyChain.keyChainId).to.equal('kc5059442d66'); expect(hdpubDerivableKeyChain.getRootKey().toString()).to.equal(hdPublicKey); }); it('should derivate', function () { const key0_1 = hdpubDerivableKeyChain.getForPath('m/1').key; expect(key0_1.publicKey.toAddress(hdpubDerivableKeyChain.network).toString()).to.equal('XoL5LcBiDWcj6L7fFwytsFoX5Vz7BVXw9w') }); it('should get address for path', function (){ const address0_1 = hdpubDerivableKeyChain.getForPath('m/2').address; expect(address0_1.toString()).to.equal('XwAzpxQKbgebaLiadq1c6rDeFJ4FKPUufy') }) }) describe('DerivableKeyChain - single privateKey', function suite() { this.timeout(10000); it('should correctly errors out when not a HDPublicKey (privateKey)', () => { const privateKey = Dashcore.PrivateKey().toString(); const network = 'livenet'; const pkDerivableKeyChain = new DerivableKeyChain({ privateKey, network }); expect(pkDerivableKeyChain.network).to.equal(network); expect(pkDerivableKeyChain.rootKeyType).to.equal('privateKey'); expect(pkDerivableKeyChain.rootKey.toString()).to.equal(privateKey); const expectedException1 = 'Wallet is not loaded from a mnemonic or a HDPrivateKey, impossible to derivate keys for path m/0'; expect(() => pkDerivableKeyChain.getForPath('m/0')).to.throw(expectedException1); }); it('should get private key', () => { const privateKey = Dashcore.PrivateKey().toString(); const pkDerivableKeyChain = new DerivableKeyChain({ privateKey, network: 'livenet' }); expect(pkDerivableKeyChain.getRootKey().toString()).to.equal(privateKey); expect(pkDerivableKeyChain.rootKey.toString()).to.equal(privateKey); }); });