Blockchain syncing.

- Implement tracker for new accounts in the accounts index contract.
- Implement tracker for new blocks on Bloxberg network.
This commit is contained in:
Spencer Ofwiti 2021-02-24 18:09:50 +03:00
parent 2e4ee03ec6
commit 857994fe8b
13 changed files with 332 additions and 301 deletions

14
package-lock.json generated
View File

@ -4234,9 +4234,9 @@
} }
}, },
"webpack": { "webpack": {
"version": "5.22.0", "version": "5.24.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.22.0.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.24.1.tgz",
"integrity": "sha512-xqlb6r9RUXda/d9iA6P7YRTP1ChWeP50TEESKMMNIg0u8/Rb66zN9YJJO7oYgJTRyFyYi43NVC5feG45FSO1vQ==", "integrity": "sha512-eg+6OIt6npUSwbhRQY6XffAixEUSARBf+WAWOxrZwOB4jRbbpMXlridFy/Yt7N0U20Ry1vp/nnDbtN7l1rUdIA==",
"requires": { "requires": {
"@types/eslint-scope": "^3.7.0", "@types/eslint-scope": "^3.7.0",
"@types/estree": "^0.0.46", "@types/estree": "^0.0.46",
@ -4247,7 +4247,7 @@
"browserslist": "^4.14.5", "browserslist": "^4.14.5",
"chrome-trace-event": "^1.0.2", "chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.7.0", "enhanced-resolve": "^5.7.0",
"es-module-lexer": "^0.3.26", "es-module-lexer": "^0.4.0",
"eslint-scope": "^5.1.1", "eslint-scope": "^5.1.1",
"events": "^3.2.0", "events": "^3.2.0",
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
@ -6004,9 +6004,9 @@
} }
}, },
"es-module-lexer": { "es-module-lexer": {
"version": "0.3.26", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.3.26.tgz", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.0.tgz",
"integrity": "sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA==" "integrity": "sha512-iuEGihqqhKWFgh72Q/Jtch7V2t/ft8w8IPP2aEN8ArYKO+IWyo6hsi96hCdgyeEDQIV3InhYQ9BlwUFPGXrbEQ=="
}, },
"es-to-primitive": { "es-to-primitive": {
"version": "1.2.1", "version": "1.2.1",

View File

@ -26,7 +26,7 @@
"block-syncer": "^0.2.4", "block-syncer": "^0.2.4",
"bootstrap": "^4.5.3", "bootstrap": "^4.5.3",
"chart.js": "^2.9.4", "chart.js": "^2.9.4",
"cic-client": "^0.0.3", "cic-client": "0.0.3",
"cic-client-meta": "0.0.5", "cic-client-meta": "0.0.5",
"datatables.net": "^1.10.22", "datatables.net": "^1.10.22",
"datatables.net-dt": "^1.10.22", "datatables.net-dt": "^1.10.22",

View File

@ -1,4 +1,3 @@
import { AccountRegistry } from '@src/assets/js/eth_account_index';
// @ts-ignore // @ts-ignore
import * as accountIndex from '@src/assets/json/accountIndex.abi.json'; import * as accountIndex from '@src/assets/json/accountIndex.abi.json';
import {environment} from '@src/environments/environment'; import {environment} from '@src/environments/environment';
@ -15,34 +14,41 @@ export class AccountIndex {
constructor(contractAddress: string, signerAddress?: string) { constructor(contractAddress: string, signerAddress?: string) {
this.contractAddress = contractAddress; this.contractAddress = contractAddress;
this.contract = new web3.eth.Contract(abi, this.contractAddress);
if (signerAddress) { if (signerAddress) {
this.signerAddress = signerAddress; this.signerAddress = signerAddress;
}
this.contract = new AccountRegistry(web3, abi, this.contractAddress, this.signerAddress);
}
async totalAccounts(): Promise<number> {
return await this.contract.count();
}
async haveAccount(address: string): Promise<boolean> {
return await this.contract.have(address);
}
async addAccount(address: string): Promise<boolean> {
return await this.contract.add(address);
}
async last(numberOfAccounts: number): Promise<Array<string>> {
return await this.contract.last(numberOfAccounts);
}
async addToAccountRegistry(address: string): Promise<boolean> {
if (!await this.contract.have(address)) {
await this.contract.add(address);
return await this.contract.have(address);
} else { } else {
return await this.contract.have(address); this.signerAddress = web3.eth.accounts[0];
}
}
public async totalAccounts(): Promise<number> {
return this.contract.methods.count().call();
}
public async haveAccount(address: string): Promise<boolean> {
return await this.contract.methods.accountIndex(address).call() !== 0;
}
public async last(numberOfAccounts: number): Promise<Array<string>> {
const count = await this.totalAccounts();
let lowest = count - numberOfAccounts - 1;
if (lowest < 0) {
lowest = 0;
}
let accounts = [];
for (let i = count - 1; i > lowest; i--) {
const account = await this.contract.methods.accounts(i).call();
accounts.push(account);
}
return accounts;
}
public async addToAccountRegistry(address: string): Promise<boolean> {
if (!await this.haveAccount(address)) {
return await this.contract.methods.add(address).send({from: this.signerAddress});
} else {
return await this.haveAccount(address);
} }
} }
} }

View File

@ -11,8 +11,6 @@ const cic = require('@src/assets/js/block-sync/cic-client.web');
providedIn: 'root' providedIn: 'root'
}) })
export class BlockSyncService { export class BlockSyncService {
// registryAddress: string = '0xb708175e3f6Cd850643aAF7B32212AFad50e2549';
// registryAddress: string = '0x4f8af296202Bff3B8589DA4Af87A8cfe74ad4d3A';
trustedDeclaratorAddress: string = '0x5567139c7a1C2977A391f51D8cA45B1D6700f5F6'; trustedDeclaratorAddress: string = '0x5567139c7a1C2977A391f51D8cA45B1D6700f5F6';
readyStateTarget: number = 2; readyStateTarget: number = 2;
readyState: number = 0; readyState: number = 0;
@ -21,19 +19,14 @@ export class BlockSyncService {
blockSync(): any { blockSync(): any {
const settings = new Settings(this.scan); const settings = new Settings(this.scan);
// const provider = 'ws://localhost:8545';
const provider = environment.web3Provider; const provider = environment.web3Provider;
const readyStateElements = { const readyStateElements = {
token: 1, token: 1,
network: 2, network: 2,
}; };
// @ts-ignore
// const fileGetter = new httpGetter();
settings.w3.provider = provider; settings.w3.provider = provider;
settings.w3.engine = new Web3(provider); settings.w3.engine = new Web3(provider);
settings.registry = new Registry(settings.w3.engine, environment.registryAddress, abi); settings.registry = new Registry(settings.w3.engine, environment.registryAddress, abi);
// settings.registry = new cic.Registry(settings.w3.engine, environment.registryAddress, fileGetter, ['../../assets/js/block-sync/data']);
// settings.registry.addTrust(this.trustedDeclaratorAddress);
settings.txHelper = new TransactionHelper(settings.registry); settings.txHelper = new TransactionHelper(settings.registry);
settings.txHelper.ontransfer = async (transaction: any): Promise<void> => { settings.txHelper.ontransfer = async (transaction: any): Promise<void> => {
@ -121,4 +114,14 @@ export class BlockSyncService {
settings.scanFilter(settings, data.low, data.high, bOne, bTwo, data.filter_rounds); settings.scanFilter(settings, data.low, data.high, bOne, bTwo, data.filter_rounds);
}); });
} }
headWorker(): void {
const wHeadSync = new Worker('./../assets/js/block-sync/head.js', {type: 'module'});
wHeadSync.onmessage = (m) => {
console.log(m.data);
};
wHeadSync.postMessage({
w3_provider: environment.web3Provider,
});
}
} }

View File

@ -15,7 +15,7 @@ export class TransactionService {
private transactionList = new BehaviorSubject<any[]>(this.transactions); private transactionList = new BehaviorSubject<any[]>(this.transactions);
transactionsSubject = this.transactionList.asObservable(); transactionsSubject = this.transactionList.asObservable();
userInfo: any; userInfo: any;
request = new AccountIndex(environment.contractAddress, environment.signerAddress); request = new AccountIndex(environment.contractAddress);
constructor( constructor(
private http: HttpClient, private http: HttpClient,
@ -42,10 +42,8 @@ export class TransactionService {
transaction.type = 'transaction'; transaction.type = 'transaction';
this.getUser(transaction.from).then(async () => { this.getUser(transaction.from).then(async () => {
transaction.sender = this.userInfo; transaction.sender = this.userInfo;
console.log('Sender address ', transaction.from, ' status: ', await this.request.addToAccountRegistry(transaction.from));
this.getUser(transaction.to).then(async () => { this.getUser(transaction.to).then(async () => {
transaction.recipient = this.userInfo; transaction.recipient = this.userInfo;
console.log('Recipient address ', transaction.to, ' status: ', await this.request.addToAccountRegistry(transaction.to));
await this.addTransaction(transaction, cacheSize); await this.addTransaction(transaction, cacheSize);
}); });
}); });
@ -58,7 +56,6 @@ export class TransactionService {
this.getUser(conversion.trader).then(async () => { this.getUser(conversion.trader).then(async () => {
conversion.sender = this.userInfo; conversion.sender = this.userInfo;
conversion.recipient = this.userInfo; conversion.recipient = this.userInfo;
console.log('Trader address ', conversion.trader, ' status: ', await this.request.addToAccountRegistry(conversion.trader));
await this.addTransaction(conversion, cacheSize); await this.addTransaction(conversion, cacheSize);
}); });
} }

View File

@ -1,6 +1,8 @@
import {Component, HostListener, OnInit} from '@angular/core'; import {Component, HostListener, OnInit} from '@angular/core';
import {BlockSyncService, TransactionService} from '@app/_services'; import {BlockSyncService, TransactionService} from '@app/_services';
import {AuthService} from '@app/_services'; import {AuthService} from '@app/_services';
import {AccountIndex} from '@app/_helpers';
import {environment} from '@src/environments/environment';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -12,6 +14,7 @@ export class AppComponent implements OnInit {
readyStateTarget: number = 3; readyStateTarget: number = 3;
readyState: number = 0; readyState: number = 0;
mediaQuery = window.matchMedia('(max-width: 768px)'); mediaQuery = window.matchMedia('(max-width: 768px)');
accountIndexQuery = new AccountIndex(environment.contractAddress);
constructor( constructor(
private authService: AuthService, private authService: AuthService,
@ -23,8 +26,15 @@ export class AppComponent implements OnInit {
} }
ngOnInit(): void { ngOnInit(): void {
this.blockSyncService.headWorker();
this.mediaQuery.addListener(this.onResize); this.mediaQuery.addListener(this.onResize);
this.onResize(this.mediaQuery); this.onResize(this.mediaQuery);
this.queryAccountsIndex(20).then();
}
async queryAccountsIndex(numberOfAccounts: number): Promise<void> {
console.log(`Last ${numberOfAccounts} accounts are: `, await this.accountIndexQuery.last(numberOfAccounts));
console.log('Total number of accounts: ', await this.accountIndexQuery.totalAccounts());
} }
// Load resize // Load resize

File diff suppressed because one or more lines are too long

View File

@ -49,9 +49,10 @@ Driver.prototype.process = function(b, t) {
self.w3.eth.getTransactionFromBlock(b, t).then((t) => { self.w3.eth.getTransactionFromBlock(b, t).then((t) => {
self.w3.eth.getTransactionReceipt(t.hash).then((r) => { self.w3.eth.getTransactionReceipt(t.hash).then((r) => {
console.log('Receipt: ', r)
self.callback(r); self.callback(r);
}).catch((e) => { }).catch((e) => {
console.error('fail get recept', e); console.error('fail get receipt', e);
}); });
}).catch(function(e) { }).catch(function(e) {
//this.postMessage(['failed getTransactionFromBlock(' + b + ', ' + t + ')']); //this.postMessage(['failed getTransactionFromBlock(' + b + ', ' + t + ')']);

View File

@ -0,0 +1,45 @@
const window = self;
self.importScripts(
'driver.js',
'web3.min.js',
);
async function sync(driver) {
driver.hi = driver.lo;
let getBlockNumber = async function () {
while (true) {
const currentBlockNumber = await driver.w3.eth.getBlockNumber();
if (currentBlockNumber > driver.hi) {
for (let i = driver.hi + 1; i <= currentBlockNumber; i++) {
console.log(driver.hi, i, currentBlockNumber);
driver.w3.eth.getBlock(i).then(async block => {
console.log('current block', block);
const count = await driver.w3.eth.getBlockTransactionCount(block.number);
console.log('count', count);
for (let i = 0; i < count; i++) {
console.log('driver process ', block.number, i);
driver.process(block.number, i);
}
});
driver.hi++;
}
}
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
await getBlockNumber();
}
onmessage = function(o) {
const w3 = new Web3(o.data.w3_provider);
const callback = (o) => {
this.postMessage(o);
};
w3.eth.getBlockNumber().then(async function(blockNumber) {
const driver = new Driver(w3, blockNumber, undefined, undefined, callback);
await sync(driver);
});
};

View File

@ -1,29 +0,0 @@
const window = self;
self.importScripts(
'driver.js',
'web3.min.js',
);
async function sync(driver) {
driver.w3.eth.subscribe('newBlockHeaders', async function(e, r) {
const c = await driver.w3.eth.getBlockTransactionCount(r.number);
for (let i = 0; i < c; i++) {
console.log('driver process ', r.number, i);
driver.process(r.number, i);
}
});
}
onmessage = function(o) {
const w3 = new Web3(o.data.w3_provider);
const callback = (o) => {
this.postMessage(o);
};
w3.eth.getBlockNumber().then(function(n) {
const driver = new Driver(w3, n, undefined, undefined, callback);
sync(driver);
});
};

View File

@ -8,7 +8,6 @@ export const environment = {
web3Provider: 'ws://localhost:63546', web3Provider: 'ws://localhost:63546',
cicUssdUrl: 'http://localhost:63315', cicUssdUrl: 'http://localhost:63315',
cicEthUrl: 'http://localhost:63314', cicEthUrl: 'http://localhost:63314',
contractAddress: '0x35Ef60C4624Eaf6AeEBeBec9Ddd3CBA6b24C4b17', contractAddress: '0xd0097a901AF4ac2E63A5b6E86be8Ad91f10b05d7',
signerAddress: '0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C', registryAddress: '0xf374d7B507767101a4bf3bA2a6B99AC737A44f6d'
registryAddress: '0xb708175e3f6Cd850643aAF7B32212AFad50e2549'
}; };

View File

@ -12,9 +12,8 @@ export const environment = {
web3Provider: 'ws://localhost:63546', web3Provider: 'ws://localhost:63546',
cicUssdUrl: 'http://localhost:63315', cicUssdUrl: 'http://localhost:63315',
cicEthUrl: 'http://localhost:63314', cicEthUrl: 'http://localhost:63314',
contractAddress: '0x35Ef60C4624Eaf6AeEBeBec9Ddd3CBA6b24C4b17', contractAddress: '0xd0097a901AF4ac2E63A5b6E86be8Ad91f10b05d7',
signerAddress: '0xEb3907eCad74a0013c259D5874AE7f22DcBcC95C', registryAddress: '0xf374d7B507767101a4bf3bA2a6B99AC737A44f6d'
registryAddress: '0xb708175e3f6Cd850643aAF7B32212AFad50e2549'
}; };
/* /*