/** * Makes a post to a node to receive the timestamp info. If non-existant, returns -1 * @param snode Snode to send request to * @returns timestamp of the response from snode */ import { isNumber } from 'lodash'; import { Snode } from '../../../data/data'; import { doSnodeBatchRequest } from './batchRequest'; import { NetworkTimeSubRequest } from './SnodeRequestTypes'; function getNetworkTimeSubRequests(): Array { const request: NetworkTimeSubRequest = { method: 'info', params: {} }; return [request]; } const getNetworkTime = async (snode: Snode): Promise => { const subRequests = getNetworkTimeSubRequests(); const result = await doSnodeBatchRequest(subRequests, snode, 4000, null); if (!result || !result.length) { window?.log?.warn(`getNetworkTime on ${snode.ip}:${snode.port} returned falsish value`, result); throw new Error('getNetworkTime: Invalid result'); } const firstResult = result[0]; if (firstResult.code !== 200) { window?.log?.warn('Status is not 200 for getNetworkTime but: ', firstResult.code); throw new Error('getNetworkTime: Invalid status code'); } const timestamp = firstResult?.body?.timestamp; if (!timestamp) { throw new Error(`getNetworkTime returned invalid timestamp: ${timestamp}`); } GetNetworkTime.handleTimestampOffsetFromNetwork('getNetworkTime', timestamp); return timestamp; }; let latestTimestampOffset = Number.MAX_SAFE_INTEGER; function handleTimestampOffsetFromNetwork(_request: string, snodeTimestamp: number) { if (snodeTimestamp && isNumber(snodeTimestamp) && snodeTimestamp > 1609419600 * 1000) { // first january 2021. Arbitrary, just want to make sure the return timestamp is somehow valid and not some crazy low value const now = Date.now(); if (latestTimestampOffset === Number.MAX_SAFE_INTEGER) { window?.log?.info(`first timestamp offset received: ${now - snodeTimestamp}ms`); } latestTimestampOffset = now - snodeTimestamp; } } /** * This function has no use to be called except during tests. * @returns the current offset we have with the rest of the network. */ function getLatestTimestampOffset() { if (latestTimestampOffset === Number.MAX_SAFE_INTEGER) { window.log.debug('latestTimestampOffset is not set yet'); return 0; } // window.log.info('latestTimestampOffset is ', latestTimestampOffset); return latestTimestampOffset; } function getNowWithNetworkOffset() { // make sure to call exports here, as we stub the exported one for testing. return Date.now() - GetNetworkTime.getLatestTimestampOffset(); } export const GetNetworkTime = { getNetworkTime, handleTimestampOffsetFromNetwork, getLatestTimestampOffset, getNowWithNetworkOffset, };