Skip to content
This repository has been archived by the owner on Jul 12, 2022. It is now read-only.

Commit

Permalink
feat: integrate with keychain and bloomfilter tx stream
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-Werner committed Dec 9, 2021
1 parent 392fc48 commit 16599c4
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 39 deletions.
20 changes: 13 additions & 7 deletions src/SDK/Client/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ export class Client extends EventEmitter {

this.dapiClient = new DAPIClient(dapiClientOptions);

let dashpayPlugin;
let dashpaySyncWorker;
// Initialize a wallet if `wallet` option is preset
if (this.options.wallet !== undefined) {
if (this.options.wallet.network !== undefined && this.options.wallet.network !== this.network) {
Expand All @@ -103,9 +105,12 @@ export class Client extends EventEmitter {
!this.options.wallet.privateKey &&
this.options.wallet.offlineMode !== true
){
dashpayPlugin = new DashPay();
dashpaySyncWorker = new DashPaySyncWorker();
//@ts-ignore
walletOptions.plugins = [new DashPay(), new DashPaySyncWorker()];
walletOptions.plugins = [dashpayPlugin, dashpaySyncWorker];
}
//@ts-ignore
this.wallet = new Wallet(walletOptions);

// @ts-ignore
Expand All @@ -132,6 +137,11 @@ export class Client extends EventEmitter {
driveProtocolVersion: this.options.driveProtocolVersion,
});

if(dashpaySyncWorker && dashpayPlugin){
dashpayPlugin.inject('platform', this.platform, true)
dashpaySyncWorker.inject('platform', this.platform, true)
}

}

/**
Expand All @@ -150,16 +160,12 @@ export class Client extends EventEmitter {
index: this.defaultAccountIndex,
...options,
}

const account = await wallet.getAccount(options);

try {
const dashpayPlugin = account.getPlugin('dashpay');
const dashpayworker = account.getWorker('DashPaySyncWorker');
// @ts-ignore
await dashpayPlugin.inject('platform', this.platform, true)
// @ts-ignore
await dashpayworker.inject('platform', this.platform, true)
//@ts-ignore
await dashpayworker.execute();
} catch {}

return account;
Expand Down
9 changes: 5 additions & 4 deletions src/SDK/Client/Platform/methods/identities/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ export default async function register(
await broadcastStateTransition(this, identityCreateTransition);

// If state transition was broadcast without any errors, import identity to the account
account.storage.insertIdentityIdAtIndex(
account.walletId,
identity.getId().toString(),
identityIndex,
account.storage
.getWalletStore(account.walletId)
.insertIdentityIdAtIndex(
identity.getId().toString(),
identityIndex,
);

return identity;
Expand Down
5 changes: 4 additions & 1 deletion src/SDK/Client/plugins/DashPay/DashPay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class DashPay extends plugins.StandardPlugin {
fetchReceivedContactRequests: any;
fetchSentContactRequests: any;
sendContactRequest: any;
private contacts: any[];
constructor() {
super({
name: 'DashPay',
Expand All @@ -35,17 +36,19 @@ export class DashPay extends plugins.StandardPlugin {
workerIntervalTime: 60 * 1000,
dependencies: [
'storage',
'keyChain',
'decrypt',
'encrypt',
'keyChainStore',
'walletId',
'network',
'identities',
'getUnusedIdentityIndex'
],
injectionOrder:{
after: ['IdentitySyncWorker']
}
});
this.contacts = []
}
}
DashPay.prototype.acceptContactRequest = acceptContactRequest;
Expand Down
34 changes: 32 additions & 2 deletions src/SDK/Client/plugins/DashPay/methods/fetchEstablishedContacts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Contact } from "../types/Contact";
import { HDPublicKey } from "@dashevo/dashcore-lib";
import {KeyChain} from "@dashevo/wallet-lib";

/**
* Fetch establish contact from a specific timestamp
Expand Down Expand Up @@ -50,7 +51,8 @@ export async function fetchEstablishedContacts(this: any, fromTimestamp = 0) {
}
});
await Promise.all(infoFetchingPromises);
const selfIdentitiesIds = this.storage.getIndexedIdentityIds(this.walletId);
const walletStore = this.storage.getWalletStore(this.walletId)
const selfIdentitiesIds = walletStore.getIndexedIdentityIds();
const selfIdentitiesPrimises = [];
const selfIdentities = [];
selfIdentitiesIds.forEach((selfIdentitiesId) => {
Expand Down Expand Up @@ -84,13 +86,41 @@ export async function fetchEstablishedContacts(this: any, fromTimestamp = 0) {
depth: Buffer.from('07', 'hex'),
childIndex: Buffer.alloc(4),
})

// @ts-ignore
const extendedPrivateKey = this.keyChain.getDIP15ExtendedKey('0x'+ `${selfIdentities[0].getId().toString()}`, '0x'+`${establishedContact.identity.getId().toString()}`);
const extendedPrivateKey = this.keyChainStore.getMasterKeyChain().getDIP15ExtendedKey('0x'+ `${selfIdentities[0].getId().toString()}`, '0x'+`${establishedContact.identity.getId().toString()}`);

establishedContact.setHDKeys({
sending: receivedContactPublicKey,
receiving: extendedPrivateKey
});

const lookAheadOpts = {
paths:{
'm/0': 10,
},
isWatched: true
}
//@ts-ignore
const sendingKeyChain = new KeyChain({HDPublicKey: receivedContactPublicKey, lookAheadOpts });
//@ts-ignore
const receivingKeyChain = new KeyChain({HDPublicKey: extendedPrivateKey, lookAheadOpts });
//@ts-ignore
const issuedSendingKeyChainPaths = sendingKeyChain.getIssuedPaths();
//@ts-ignore
const issuedReceivingKeyChainPaths = receivingKeyChain.getIssuedPaths();
establishedContact.setKeyChains({
sending: sendingKeyChain,
receiving: receivingKeyChain,
});
const chainStore = this.storage.getChainStore(this.network);

issuedReceivingKeyChainPaths.forEach((issuedPath) => {
chainStore.importAddress(issuedPath.address.toString());
});
issuedSendingKeyChainPaths.forEach((issuedPath) => {
chainStore.importAddress(issuedPath.address.toString());
});
})
return establishedContacts;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
*
*/
export async function fetchReceivedContactRequests(this: any, fromTimestamp = 0){
// @ts-ignore
const identities = this.storage.getIndexedIdentityIds(this.walletId);
const walletStore = this.storage.getWalletStore(this.walletId)
const identities = walletStore.getIndexedIdentityIds();
if(!identities.length){
throw new Error('Require an identity to fetch sent contact requests');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
*
*/
export async function fetchSentContactRequests(this: any, fromTimestamp = 0){
// @ts-ignore
const identities = this.storage.getIndexedIdentityIds(this.walletId);
const walletStore = this.storage.getWalletStore(this.walletId)
const identities = walletStore.getIndexedIdentityIds();
if(!identities.length){
throw new Error('Require an identity to fetch sent contact requests');
}
Expand Down
6 changes: 4 additions & 2 deletions src/SDK/Client/plugins/DashPay/methods/sendContactRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
*/
export async function sendContactRequest(this: any, contactName, accountLabel = 'Default account'){
// @ts-ignore
const identities = this.storage.getIndexedIdentityIds(this.walletId);
const walletStore = this.storage.getWalletStore(this.walletId);
// @ts-ignore
const identities = walletStore.getIndexedIdentityIds();
if(!identities.length){
throw new Error('Require an identity to send a contact request');
}
Expand All @@ -24,7 +26,7 @@ export async function sendContactRequest(this: any, contactName, accountLabel =
const receiverPublicKey = receiverIdentity.toJSON().publicKeys[0].data;
const receiverPublicKeyBuffer = Buffer.from(receiverPublicKey, 'base64');

const extendedPrivateKey = this.keyChain.getDIP15ExtendedKey('0x'+ senderDashUniqueIdentityId, '0x'+contactDashUniqueIdentityId);
const extendedPrivateKey = this.keyChainStore.getMasterKeyChain().getDIP15ExtendedKey('0x'+ senderDashUniqueIdentityId, '0x'+contactDashUniqueIdentityId);
const extendedPublicKey = extendedPrivateKey.hdPublicKey;

const extendedPublicKeyBuffers = Buffer.concat([extendedPublicKey._buffers.parentFingerPrint, extendedPublicKey._buffers.chainCode, extendedPublicKey._buffers.publicKey]);
Expand Down
12 changes: 12 additions & 0 deletions src/SDK/Client/plugins/DashPay/types/Contact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export class Contact {
public identity?: any;
public profile?: any;
public keys?: any;
public keychains?: any;

constructor(identityId, sentRequest, receivedRequest) {
this.username = null;
Expand All @@ -30,5 +31,16 @@ export class Contact {
sending
};
}
setKeyChains(keychainsSet){
const { receiving, sending } = keychainsSet;
this.keychains = {
receiving,
sending
};
}
getUnusedAddress(type = 'receiving'){
const keychain = this.keychains[type];
return keychain.getFirstUnusedAddress();
}
}

37 changes: 19 additions & 18 deletions src/SDK/Client/plugins/DashPaySyncWorker/DashPaySyncWorker.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { plugins } from "@dashevo/wallet-lib"
import {KeyChain, plugins} from "@dashevo/wallet-lib"

export class DashPaySyncWorker extends plugins.Worker {
private fromTimestamp: number;
Expand All @@ -8,6 +8,7 @@ export class DashPaySyncWorker extends plugins.Worker {
private getPlugin: any;
private storage: any;
private contacts: any[];
private keyChainStore: any;

constructor() {
super({
Expand All @@ -18,9 +19,9 @@ export class DashPaySyncWorker extends plugins.Worker {
workerIntervalTime: 60 * 1000,
dependencies: [
'storage',
'keyChainStore',
'getWorker',
'getPlugin',
'keyChain',
'walletId',
'identities',
'getUnusedIdentityIndex',
Expand All @@ -36,40 +37,40 @@ export class DashPaySyncWorker extends plugins.Worker {
this.fromTimestamp = 0;
}

async onStart(){

}

async execute() {
if (this.platform && this.platform.identities) {
const dashPay = await this.getPlugin('DashPay');
const identities = this.storage.getIndexedIdentityIds(this.walletId);
const walletStore = this.storage.getWalletStore(this.walletId)
const identities = walletStore.getIndexedIdentityIds(this.walletId);

// We require an identity to fetch contacts
if (identities.length) {
const contacts = await dashPay.fetchEstablishedContacts(this.fromTimestamp);
// set 10 minute before last query
// see: https://github.com/dashpay/dips/blob/master/dip-0015.md#fetching-contact-requests
this.fromTimestamp = +new Date() - 10 * 60 * 1000;
const addressesStore = this.storage.store.wallets[this.walletId].addresses;
// const walletStore = this.storage.getWalletStore(this.walletId);
// const addressesStore = this.storage.store.wallets[this.walletId].addresses;
//@ts-ignore
const txStreamSyncWorker = await this.getWorker('TransactionSyncStreamWorker');

contacts
.forEach((contact) => {
console.log(`DashPaySyncWorker - Fetched contact ${contact.username}`);
this.contacts.push(contact);
const { receiving } = contact.keys;
const receiverRootPath = `${contact.sentRequest.ownerId}/${contact.receivedRequest.ownerId}`
const sendingRootPath = `${contact.receivedRequest.ownerId}/${contact.sentRequest.ownerId}`
dashPay.contacts.push(contact);

addressesStore.misc[`${receiverRootPath}/0`] = {
path: `${sendingRootPath}/0`,
index: 0,
transactions: [],
address: receiving.deriveChild(0).privateKey.toAddress(),
balanceSat: 0,
unconfirmedBalanceSat: 0,
utxos: {},
fetchedLast: 0,
used: false
};
this.keyChainStore.addKeyChain(contact.keychains.receiving);
this.keyChainStore.addKeyChain(contact.keychains.sending);
//@ts-ignore
})

await txStreamSyncWorker.onStop()
await txStreamSyncWorker.onStart();
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"allowJs": true,
"sourceMap": true,
"declaration": true,
"declarationDir": "./dist"
"declarationDir": "./dist",
},
"include": ["src"],
"typeRoots": ["node_modules/@types"]
Expand Down

0 comments on commit 16599c4

Please sign in to comment.