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

[DDW-359] V1 API endpoints integration 5/5 #1045

Merged
Show file tree
Hide file tree
Changes from 8 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
19 changes: 0 additions & 19 deletions source/renderer/app/api/ada/getAdaLocalTimeDifference.js

This file was deleted.

19 changes: 0 additions & 19 deletions source/renderer/app/api/ada/getAdaSyncProgress.js

This file was deleted.

19 changes: 19 additions & 0 deletions source/renderer/app/api/ada/getNodeInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// @flow
import type { NodeInfo } from './types';
import { request } from './lib/v1/request';

export type GetNodeInfoParams = {
ca: string,
};

export const getNodeInfo = (
{ ca }: GetNodeInfoParams
): Promise<NodeInfo> => (
request({
hostname: 'localhost',
method: 'GET',
path: '/api/v1/node-info',
port: 8090,
ca,
})
);
28 changes: 14 additions & 14 deletions source/renderer/app/api/ada/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import WalletAddress from '../../domains/WalletAddress';
import { isValidMnemonic } from '../../../../common/decrypt';
import { isValidRedemptionKey, isValidPaperVendRedemptionKey } from '../../../../common/redemption-key-validation';
import { LOVELACES_PER_ADA } from '../../config/numbersConfig';
import { getAdaSyncProgress } from './getAdaSyncProgress';
import environment from '../../../../common/environment';
import patchAdaApi from './mocks/patchAdaApi';

Expand Down Expand Up @@ -40,12 +39,10 @@ import { getAdaAccountRecoveryPhrase } from './getAdaAccountRecoveryPhrase';
import { getAdaWalletCertificateAdditionalMnemonics } from './getAdaWalletCertificateAdditionalMnemonics';
import { getAdaWalletCertificateRecoveryPhrase } from './getAdaWalletCertificateRecoveryPhrase';
import { getAdaWalletRecoveryPhraseFromCertificate } from './getAdaWalletRecoveryPhraseFromCertificate';
import { getAdaLocalTimeDifference } from './getAdaLocalTimeDifference';
import { getNodeInfo } from './getNodeInfo';
import { sendAdaBugReport } from './sendAdaBugReport';

import type {
AdaLocalTimeDifference,
AdaSyncProgressResponse,
AdaAddress,
AdaAccounts,
AdaTransaction,
Expand All @@ -60,6 +57,7 @@ import type {
GetWalletCertificateAdditionalMnemonicsResponse,
GetWalletCertificateRecoveryPhraseResponse,
GetWalletRecoveryPhraseFromCertificateResponse,
NodeInfo,
} from './types';

import type {
Expand Down Expand Up @@ -694,15 +692,14 @@ export default class AdaApi {
getSyncProgress = async (): Promise<GetSyncProgressResponse> => {
Logger.debug('AdaApi::syncProgress called');
try {
const response: AdaSyncProgressResponse = await getAdaSyncProgress({ ca });
const response: NodeInfo = await getNodeInfo({ ca });
Logger.debug('AdaApi::syncProgress success: ' + stringifyData(response));
const localDifficulty = response._spLocalCD.getChainDifficulty.getBlockCount;
// In some cases we dont get network difficulty & we need to wait for it from the notify API
let networkDifficulty = null;
if (response._spNetworkCD) {
networkDifficulty = response._spNetworkCD.getChainDifficulty.getBlockCount;
}
return { localDifficulty, networkDifficulty };
const { localBlockchainHeight, blockchainHeight, syncProgress } = response;
return {
localBlockchainHeight: localBlockchainHeight.quantity,
blockchainHeight: blockchainHeight.quantity,
syncProgress: syncProgress.quantity
};
} catch (error) {
Logger.debug('AdaApi::syncProgress error: ' + stringifyError(error));
throw new GenericApiError();
Expand Down Expand Up @@ -778,9 +775,12 @@ export default class AdaApi {
async getLocalTimeDifference(): Promise<GetLocalTimeDifferenceResponse> {
Logger.debug('AdaApi::getLocalTimeDifference called');
try {
const response: AdaLocalTimeDifference = await getAdaLocalTimeDifference({ ca });
const response: NodeInfo = await getNodeInfo({ ca });
Logger.debug('AdaApi::getLocalTimeDifference success: ' + stringifyData(response));
return Math.abs(response); // time offset direction is irrelevant to the UI

const { localTimeInformation: { differenceFromNtpServer } } = response;
const timeDifference = differenceFromNtpServer.quantity;
return timeDifference;
} catch (error) {
Logger.error('AdaApi::getLocalTimeDifference error: ' + stringifyError(error));
throw new GenericApiError();
Expand Down
53 changes: 41 additions & 12 deletions source/renderer/app/api/ada/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,34 @@ export type GetWalletCertificateAdditionalMnemonicsResponse = Array<string>;
export type GetWalletCertificateRecoveryPhraseResponse = Array<string>;
export type GetWalletRecoveryPhraseFromCertificateResponse = Array<string>;

export type AdaSyncProgressResponse = {
_spLocalCD: {
getChainDifficulty: {
getBlockCount: number,
}
// Regarding GetNodeInfoResponse below:
// getNodeInfo.js currently does not return "meta" and "status" properties
// though the docs indicate it should, and they are present in Postman
export type GetNodeInfoResponse = {
data: NodeInfo,
...ResponseBaseV1
};

export type NodeInfo = {
syncProgress: {
quantity: number,
unit: 'percent'
},
blockchainHeight: {
quantity: number,
unit: 'blocks'
},
_spNetworkCD: {
getChainDifficulty: {
getBlockCount: number,
localBlockchainHeight: {
quantity: number,
unit: 'blocks'
},
localTimeInformation: {
differenceFromNtpServer: {
quantity: number,
unit: 'microseconds'
}
},
_spPeers: number,
subscriptionStatus: any
};

export type AdaWalletInitData = {
Expand Down Expand Up @@ -101,9 +117,6 @@ export type AdaWallet = {

export type AdaWallets = Array<AdaWallet>;

export type AdaLocalTimeDifference = number;


// ========== V1 API =========

export type AdaV1Assurance = 'normal' | 'strict';
Expand Down Expand Up @@ -145,3 +158,19 @@ export const AdaV1AssuranceOptions: {
} = {
NORMAL: 'normal', STRICT: 'strict',
};

export type Pagination = {
pagination: {
totalPages: number,
page: number,
perPage: number,
totalEntries: number
}
};

export type ResponseStatus = 'success' | 'fail' | 'error';

export type ResponseBaseV1 = {
status: ResponseStatus,
meta: Pagination
};
5 changes: 3 additions & 2 deletions source/renderer/app/api/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ export type RestoreWalletRequest = {
};

export type GetSyncProgressResponse = {
localDifficulty: ?number,
networkDifficulty: ?number,
syncProgress: number,
blockchainHeight: ?number,
localBlockchainHeight: number,
};

export type GetTransactionsRequest = {
Expand Down
54 changes: 24 additions & 30 deletions source/renderer/app/stores/NetworkStatusStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default class NetworkStatusStore extends Store {
@observable hasBeenConnected = false;
@observable localDifficulty = 0;
@observable networkDifficulty = 0;
@observable syncProgress = 0;
@observable localTimeDifference = 0;
@observable syncProgressRequest: Request<GetSyncProgressResponse> = new Request(
// Use the sync progress for target API
Expand Down Expand Up @@ -92,24 +93,7 @@ export default class NetworkStatusStore extends Store {
}

@computed get hasBlockSyncingStarted(): boolean {
return this.networkDifficulty >= 1;
}

@computed get relativeSyncPercentage(): number {
if (this.networkDifficulty > 0 && this._localDifficultyStartedWith !== null) {
const relativeLocal = this.localDifficulty - this._localDifficultyStartedWith;
const relativeNetwork = this.networkDifficulty - this._localDifficultyStartedWith;
// In case node is in sync after first local difficulty messages
// local and network difficulty will be the same (0)
Logger.debug('Network difficulty: ' + this.networkDifficulty);
Logger.debug('Local difficulty: ' + this.localDifficulty);
Logger.debug('Relative local difficulty: ' + relativeLocal);
Logger.debug('Relative network difficulty: ' + relativeNetwork);

if (relativeLocal >= relativeNetwork) return 100;
return relativeLocal / relativeNetwork * 100;
}
return 0;
return this.syncProgress >= 1;
}

@computed get relativeSyncBlocksDifference(): number {
Expand All @@ -130,11 +114,7 @@ export default class NetworkStatusStore extends Store {
}

@computed get syncPercentage(): number {
if (this.networkDifficulty > 0) {
if (this.localDifficulty >= this.networkDifficulty) return 100;
return this.localDifficulty / this.networkDifficulty * 100;
}
return 0;
return this.syncProgress;
}

@computed get isSystemTimeCorrect(): boolean {
Expand All @@ -153,13 +133,23 @@ export default class NetworkStatusStore extends Store {
return (
!this.isConnecting &&
this.hasBlockSyncingStarted &&
this.relativeSyncBlocksDifference <= OUT_OF_SYNC_BLOCKS_LIMIT
this.relativeSyncBlocksDifference <= OUT_OF_SYNC_BLOCKS_LIMIT &&
this.syncProgress === 100
);
}

@action _updateSyncProgress = async () => {
try {
const difficulty = await this.syncProgressRequest.execute().promise;
const {
localBlockchainHeight,
blockchainHeight,
syncProgress
} = await this.syncProgressRequest.execute().promise;

runInAction('update syncProgress', () => {
this.syncProgress = syncProgress;
});

runInAction('update difficulties', () => {
// We are connected, move on to syncing stage
if (this._startupStage === STARTUP_STAGES.CONNECTING) {
Expand All @@ -168,18 +158,21 @@ export default class NetworkStatusStore extends Store {
);
this._startupStage = STARTUP_STAGES.SYNCING;
}

// If we haven't set local difficulty before, mark the first
// result as 'start' difficulty for the sync progress
if (this._localDifficultyStartedWith === null) {
this._localDifficultyStartedWith = difficulty.localDifficulty;
Logger.debug('Initial difficulty: ' + JSON.stringify(difficulty));
this._localDifficultyStartedWith = localBlockchainHeight;
Logger.debug('Initial difficulty: ' + JSON.stringify({ localBlockchainHeight, blockchainHeight }));
}

// Update the local difficulty on each request
this.localDifficulty = difficulty.localDifficulty;
this.localDifficulty = localBlockchainHeight;
Logger.debug('Local difficulty changed: ' + this.localDifficulty);

// Check if network difficulty is stalled (e.g. unchanged for more than 2 minutes)
// e.g. in case there is no Internet connection Api will send the last known value
if (this.networkDifficulty !== difficulty.networkDifficulty) {
if (this.networkDifficulty !== blockchainHeight) {
if (!this.isConnected) this.isConnected = true;
this._lastNetworkDifficultyChange = Date.now();
} else if (this.isConnected) {
Expand All @@ -191,8 +184,9 @@ export default class NetworkStatusStore extends Store {
if (!this.hasBeenConnected) this.hasBeenConnected = true;
}
}

// Update the network difficulty on each request
this.networkDifficulty = difficulty.networkDifficulty;
this.networkDifficulty = blockchainHeight;
});
Logger.debug('Network difficulty changed: ' + this.networkDifficulty);

Expand Down