Merge pull request #2333 from mempool/fix/difficulty-api
Fix: Difficulty API (REST) with frontend fixes
This commit is contained in:
		
						commit
						69d4ba18d5
					
				@ -7,11 +7,14 @@ const config: Config.InitialOptions = {
 | 
				
			|||||||
  automock: false,
 | 
					  automock: false,
 | 
				
			||||||
  collectCoverage: true,
 | 
					  collectCoverage: true,
 | 
				
			||||||
  collectCoverageFrom: ["./src/**/**.ts"],
 | 
					  collectCoverageFrom: ["./src/**/**.ts"],
 | 
				
			||||||
  coverageProvider: "v8",
 | 
					  coverageProvider: "babel",
 | 
				
			||||||
  coverageThreshold: {
 | 
					  coverageThreshold: {
 | 
				
			||||||
    global: {
 | 
					    global: {
 | 
				
			||||||
      lines: 1
 | 
					      lines: 1
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  },
 | 
				
			||||||
 | 
					  setupFiles: [
 | 
				
			||||||
 | 
					    "./testSetup.ts",
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
export default config;
 | 
					export default config;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										62
									
								
								backend/src/__tests__/api/difficulty-adjustment.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								backend/src/__tests__/api/difficulty-adjustment.test.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					import { calcDifficultyAdjustment, DifficultyAdjustment } from '../../api/difficulty-adjustment';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Mempool Difficulty Adjustment', () => {
 | 
				
			||||||
 | 
					  test('should calculate Difficulty Adjustments properly', () => {
 | 
				
			||||||
 | 
					    const dt = (dtString) => {
 | 
				
			||||||
 | 
					      return Math.floor(new Date(dtString).getTime() / 1000);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const vectors = [
 | 
				
			||||||
 | 
					      [ // Vector 1
 | 
				
			||||||
 | 
					        [ // Inputs
 | 
				
			||||||
 | 
					          dt('2022-08-18T11:07:00.000Z'), // Last DA time (in seconds)
 | 
				
			||||||
 | 
					          dt('2022-08-19T14:03:53.000Z'), // Current time (now) (in seconds)
 | 
				
			||||||
 | 
					          750134,                         // Current block height
 | 
				
			||||||
 | 
					          0.6280047707459726,             // Previous retarget % (Passed through)
 | 
				
			||||||
 | 
					          'mainnet',                      // Network (if testnet, next value is non-zero)
 | 
				
			||||||
 | 
					          0,                              // If not testnet, not used
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        { // Expected Result
 | 
				
			||||||
 | 
					          progressPercent: 9.027777777777777,
 | 
				
			||||||
 | 
					          difficultyChange: 12.562233927411782,
 | 
				
			||||||
 | 
					          estimatedRetargetDate: 1661895424692,
 | 
				
			||||||
 | 
					          remainingBlocks: 1834,
 | 
				
			||||||
 | 
					          remainingTime: 977591692,
 | 
				
			||||||
 | 
					          previousRetarget: 0.6280047707459726,
 | 
				
			||||||
 | 
					          nextRetargetHeight: 751968,
 | 
				
			||||||
 | 
					          timeAvg: 533038,
 | 
				
			||||||
 | 
					          timeOffset: 0,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      [ // Vector 2 (testnet)
 | 
				
			||||||
 | 
					        [ // Inputs
 | 
				
			||||||
 | 
					          dt('2022-08-18T11:07:00.000Z'), // Last DA time (in seconds)
 | 
				
			||||||
 | 
					          dt('2022-08-19T14:03:53.000Z'), // Current time (now) (in seconds)
 | 
				
			||||||
 | 
					          750134,                         // Current block height
 | 
				
			||||||
 | 
					          0.6280047707459726,             // Previous retarget % (Passed through)
 | 
				
			||||||
 | 
					          'testnet',                      // Network
 | 
				
			||||||
 | 
					          dt('2022-08-19T13:52:46.000Z'), // Latest block timestamp in seconds
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        { // Expected Result is same other than timeOffset
 | 
				
			||||||
 | 
					          progressPercent: 9.027777777777777,
 | 
				
			||||||
 | 
					          difficultyChange: 12.562233927411782,
 | 
				
			||||||
 | 
					          estimatedRetargetDate: 1661895424692,
 | 
				
			||||||
 | 
					          remainingBlocks: 1834,
 | 
				
			||||||
 | 
					          remainingTime: 977591692,
 | 
				
			||||||
 | 
					          previousRetarget: 0.6280047707459726,
 | 
				
			||||||
 | 
					          nextRetargetHeight: 751968,
 | 
				
			||||||
 | 
					          timeAvg: 533038,
 | 
				
			||||||
 | 
					          timeOffset: -667000, // 11 min 7 seconds since last block (testnet only)
 | 
				
			||||||
 | 
					          // If we add time avg to abs(timeOffset) it makes exactly 1200000 ms, or 20 minutes
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    ] as [[number, number, number, number, string, number], DifficultyAdjustment][];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const vector of vectors) {
 | 
				
			||||||
 | 
					      const result = calcDifficultyAdjustment(...vector[0]);
 | 
				
			||||||
 | 
					      // previousRetarget is passed through untouched
 | 
				
			||||||
 | 
					      expect(result.previousRetarget).toStrictEqual(vector[0][3]);
 | 
				
			||||||
 | 
					      expect(result).toStrictEqual(vector[1]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -136,5 +136,4 @@ describe('Mempool Backend Config', () => {
 | 
				
			|||||||
      expect(config.EXTERNAL_DATA_SERVER).toStrictEqual(fixture.EXTERNAL_DATA_SERVER);
 | 
					      expect(config.EXTERNAL_DATA_SERVER).toStrictEqual(fixture.EXTERNAL_DATA_SERVER);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,84 @@ import config from '../config';
 | 
				
			|||||||
import { IDifficultyAdjustment } from '../mempool.interfaces';
 | 
					import { IDifficultyAdjustment } from '../mempool.interfaces';
 | 
				
			||||||
import blocks from './blocks';
 | 
					import blocks from './blocks';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface DifficultyAdjustment {
 | 
				
			||||||
 | 
					  progressPercent: number;       // Percent: 0 to 100
 | 
				
			||||||
 | 
					  difficultyChange: number;      // Percent: -75 to 300
 | 
				
			||||||
 | 
					  estimatedRetargetDate: number; // Unix time in ms
 | 
				
			||||||
 | 
					  remainingBlocks: number;       // Block count
 | 
				
			||||||
 | 
					  remainingTime: number;         // Duration of time in ms
 | 
				
			||||||
 | 
					  previousRetarget: number;      // Percent: -75 to 300
 | 
				
			||||||
 | 
					  nextRetargetHeight: number;    // Block Height
 | 
				
			||||||
 | 
					  timeAvg: number;               // Duration of time in ms
 | 
				
			||||||
 | 
					  timeOffset: number;            // (Testnet) Time since last block (cap @ 20min) in ms
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function calcDifficultyAdjustment(
 | 
				
			||||||
 | 
					  DATime: number,
 | 
				
			||||||
 | 
					  nowSeconds: number,
 | 
				
			||||||
 | 
					  blockHeight: number,
 | 
				
			||||||
 | 
					  previousRetarget: number,
 | 
				
			||||||
 | 
					  network: string,
 | 
				
			||||||
 | 
					  latestBlockTimestamp: number,
 | 
				
			||||||
 | 
					): DifficultyAdjustment {
 | 
				
			||||||
 | 
					  const ESTIMATE_LAG_BLOCKS = 146; // For first 7.2% of epoch, don't estimate.
 | 
				
			||||||
 | 
					  const EPOCH_BLOCK_LENGTH = 2016; // Bitcoin mainnet
 | 
				
			||||||
 | 
					  const BLOCK_SECONDS_TARGET = 600; // Bitcoin mainnet
 | 
				
			||||||
 | 
					  const TESTNET_MAX_BLOCK_SECONDS = 1200; // Bitcoin testnet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const diffSeconds = nowSeconds - DATime;
 | 
				
			||||||
 | 
					  const blocksInEpoch = (blockHeight >= 0) ? blockHeight % EPOCH_BLOCK_LENGTH : 0;
 | 
				
			||||||
 | 
					  const progressPercent = (blockHeight >= 0) ? blocksInEpoch / EPOCH_BLOCK_LENGTH * 100 : 100;
 | 
				
			||||||
 | 
					  const remainingBlocks = EPOCH_BLOCK_LENGTH - blocksInEpoch;
 | 
				
			||||||
 | 
					  const nextRetargetHeight = (blockHeight >= 0) ? blockHeight + remainingBlocks : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let difficultyChange = 0;
 | 
				
			||||||
 | 
					  let timeAvgSecs = BLOCK_SECONDS_TARGET;
 | 
				
			||||||
 | 
					  // Only calculate the estimate once we have 7.2% of blocks in current epoch
 | 
				
			||||||
 | 
					  if (blocksInEpoch >= ESTIMATE_LAG_BLOCKS) {
 | 
				
			||||||
 | 
					    timeAvgSecs = diffSeconds / blocksInEpoch;
 | 
				
			||||||
 | 
					    difficultyChange = (BLOCK_SECONDS_TARGET / timeAvgSecs - 1) * 100;
 | 
				
			||||||
 | 
					    // Max increase is x4 (+300%)
 | 
				
			||||||
 | 
					    if (difficultyChange > 300) {
 | 
				
			||||||
 | 
					      difficultyChange = 300;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // Max decrease is /4 (-75%)
 | 
				
			||||||
 | 
					    if (difficultyChange < -75) {
 | 
				
			||||||
 | 
					      difficultyChange = -75;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Testnet difficulty is set to 1 after 20 minutes of no blocks,
 | 
				
			||||||
 | 
					  // therefore the time between blocks will always be below 20 minutes (1200s).
 | 
				
			||||||
 | 
					  let timeOffset = 0;
 | 
				
			||||||
 | 
					  if (network === 'testnet') {
 | 
				
			||||||
 | 
					    if (timeAvgSecs > TESTNET_MAX_BLOCK_SECONDS) {
 | 
				
			||||||
 | 
					      timeAvgSecs = TESTNET_MAX_BLOCK_SECONDS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const secondsSinceLastBlock = nowSeconds - latestBlockTimestamp;
 | 
				
			||||||
 | 
					    if (secondsSinceLastBlock + timeAvgSecs > TESTNET_MAX_BLOCK_SECONDS) {
 | 
				
			||||||
 | 
					      timeOffset = -Math.min(secondsSinceLastBlock, TESTNET_MAX_BLOCK_SECONDS) * 1000;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const timeAvg = Math.floor(timeAvgSecs * 1000);
 | 
				
			||||||
 | 
					  const remainingTime = remainingBlocks * timeAvg;
 | 
				
			||||||
 | 
					  const estimatedRetargetDate = remainingTime + nowSeconds * 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    progressPercent,
 | 
				
			||||||
 | 
					    difficultyChange,
 | 
				
			||||||
 | 
					    estimatedRetargetDate,
 | 
				
			||||||
 | 
					    remainingBlocks,
 | 
				
			||||||
 | 
					    remainingTime,
 | 
				
			||||||
 | 
					    previousRetarget,
 | 
				
			||||||
 | 
					    nextRetargetHeight,
 | 
				
			||||||
 | 
					    timeAvg,
 | 
				
			||||||
 | 
					    timeOffset,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DifficultyAdjustmentApi {
 | 
					class DifficultyAdjustmentApi {
 | 
				
			||||||
  constructor() { }
 | 
					  constructor() { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -11,56 +89,12 @@ class DifficultyAdjustmentApi {
 | 
				
			|||||||
    const blockHeight = blocks.getCurrentBlockHeight();
 | 
					    const blockHeight = blocks.getCurrentBlockHeight();
 | 
				
			||||||
    const blocksCache = blocks.getBlocks();
 | 
					    const blocksCache = blocks.getBlocks();
 | 
				
			||||||
    const latestBlock = blocksCache[blocksCache.length - 1];
 | 
					    const latestBlock = blocksCache[blocksCache.length - 1];
 | 
				
			||||||
 | 
					    const nowSeconds = Math.floor(new Date().getTime() / 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const now = new Date().getTime() / 1000;
 | 
					    return calcDifficultyAdjustment(
 | 
				
			||||||
    const diff = now - DATime;
 | 
					      DATime, nowSeconds, blockHeight, previousRetarget,
 | 
				
			||||||
    const blocksInEpoch = blockHeight % 2016;
 | 
					      config.MEMPOOL.NETWORK, latestBlock.timestamp
 | 
				
			||||||
    const progressPercent = (blocksInEpoch >= 0) ? blocksInEpoch / 2016 * 100 : 100;
 | 
					    );
 | 
				
			||||||
    const remainingBlocks = 2016 - blocksInEpoch;
 | 
					 | 
				
			||||||
    const nextRetargetHeight = blockHeight + remainingBlocks;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let difficultyChange = 0;
 | 
					 | 
				
			||||||
    if (remainingBlocks < 1870) {
 | 
					 | 
				
			||||||
      if (blocksInEpoch > 0) {
 | 
					 | 
				
			||||||
        difficultyChange = (600 / (diff / blocksInEpoch) - 1) * 100;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (difficultyChange > 300) {
 | 
					 | 
				
			||||||
        difficultyChange = 300;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (difficultyChange < -75) {
 | 
					 | 
				
			||||||
        difficultyChange = -75;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let timeAvgMins = blocksInEpoch && blocksInEpoch > 146 ? diff / blocksInEpoch / 60 : 10;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Testnet difficulty is set to 1 after 20 minutes of no blocks,
 | 
					 | 
				
			||||||
    // therefore the time between blocks will always be below 20 minutes (1200s).
 | 
					 | 
				
			||||||
    let timeOffset = 0;
 | 
					 | 
				
			||||||
    if (config.MEMPOOL.NETWORK === 'testnet') {
 | 
					 | 
				
			||||||
      if (timeAvgMins > 20) {
 | 
					 | 
				
			||||||
        timeAvgMins = 20;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (now - latestBlock.timestamp + timeAvgMins * 60 > 1200) {
 | 
					 | 
				
			||||||
        timeOffset = -Math.min(now - latestBlock.timestamp, 1200) * 1000;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const timeAvg = timeAvgMins * 60 * 1000 ;
 | 
					 | 
				
			||||||
    const remainingTime = (remainingBlocks * timeAvg) + (now * 1000);
 | 
					 | 
				
			||||||
    const estimatedRetargetDate = remainingTime + now;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
      progressPercent,
 | 
					 | 
				
			||||||
      difficultyChange,
 | 
					 | 
				
			||||||
      estimatedRetargetDate,
 | 
					 | 
				
			||||||
      remainingBlocks,
 | 
					 | 
				
			||||||
      remainingTime,
 | 
					 | 
				
			||||||
      previousRetarget,
 | 
					 | 
				
			||||||
      nextRetargetHeight,
 | 
					 | 
				
			||||||
      timeAvg,
 | 
					 | 
				
			||||||
      timeOffset,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								backend/testSetup.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								backend/testSetup.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					jest.mock('./mempool-config.json', () => ({}), { virtual: true });
 | 
				
			||||||
 | 
					jest.mock('./src/logger.ts', () => ({}), { virtual: true });
 | 
				
			||||||
 | 
					jest.mock('./src/api/rbf-cache.ts', () => ({}), { virtual: true });
 | 
				
			||||||
 | 
					jest.mock('./src/api/mempool.ts', () => ({}), { virtual: true });
 | 
				
			||||||
 | 
					jest.mock('./src/api/memory-cache.ts', () => ({}), { virtual: true });
 | 
				
			||||||
@ -10,7 +10,7 @@
 | 
				
			|||||||
            <ng-template #blocksPlural let-i i18n="shared.blocks">{{ i }} <span class="shared-block">blocks</span></ng-template>
 | 
					            <ng-template #blocksPlural let-i i18n="shared.blocks">{{ i }} <span class="shared-block">blocks</span></ng-template>
 | 
				
			||||||
            <ng-template #blocksSingular let-i i18n="shared.block">{{ i }} <span class="shared-block">block</span></ng-template>
 | 
					            <ng-template #blocksSingular let-i i18n="shared.block">{{ i }} <span class="shared-block">block</span></ng-template>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div class="symbol"><app-time-until [time]="epochData.remainingTime" [fastRender]="true"></app-time-until></div>
 | 
					          <div class="symbol"><app-time-until [time]="epochData.estimatedRetargetDate" [fastRender]="true"></app-time-until></div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="item">
 | 
					        <div class="item">
 | 
				
			||||||
          <h5 class="card-title" i18n="difficulty-box.estimate">Estimate</h5>
 | 
					          <h5 class="card-title" i18n="difficulty-box.estimate">Estimate</h5>
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ interface EpochProgress {
 | 
				
			|||||||
  newDifficultyHeight: number;
 | 
					  newDifficultyHeight: number;
 | 
				
			||||||
  colorAdjustments: string;
 | 
					  colorAdjustments: string;
 | 
				
			||||||
  colorPreviousAdjustments: string;
 | 
					  colorPreviousAdjustments: string;
 | 
				
			||||||
  remainingTime: number;
 | 
					  estimatedRetargetDate: number;
 | 
				
			||||||
  previousRetarget: number;
 | 
					  previousRetarget: number;
 | 
				
			||||||
  blocksUntilHalving: number;
 | 
					  blocksUntilHalving: number;
 | 
				
			||||||
  timeUntilHalving: number;
 | 
					  timeUntilHalving: number;
 | 
				
			||||||
@ -74,7 +74,7 @@ export class DifficultyComponent implements OnInit {
 | 
				
			|||||||
          colorAdjustments,
 | 
					          colorAdjustments,
 | 
				
			||||||
          colorPreviousAdjustments,
 | 
					          colorPreviousAdjustments,
 | 
				
			||||||
          newDifficultyHeight: da.nextRetargetHeight,
 | 
					          newDifficultyHeight: da.nextRetargetHeight,
 | 
				
			||||||
          remainingTime: da.remainingTime,
 | 
					          estimatedRetargetDate: da.estimatedRetargetDate,
 | 
				
			||||||
          previousRetarget: da.previousRetarget,
 | 
					          previousRetarget: da.previousRetarget,
 | 
				
			||||||
          blocksUntilHalving,
 | 
					          blocksUntilHalving,
 | 
				
			||||||
          timeUntilHalving,
 | 
					          timeUntilHalving,
 | 
				
			||||||
 | 
				
			|||||||
@ -114,11 +114,14 @@ export const restApiDocsData = [
 | 
				
			|||||||
          curl: [],
 | 
					          curl: [],
 | 
				
			||||||
          response: `{
 | 
					          response: `{
 | 
				
			||||||
  progressPercent: 44.397234501112074,
 | 
					  progressPercent: 44.397234501112074,
 | 
				
			||||||
  difficultyChange: 0.9845932018381687,
 | 
					  difficultyChange: 98.45932018381687,
 | 
				
			||||||
  estimatedRetargetDate: 1627762478.9111245,
 | 
					  estimatedRetargetDate: 1627762478,
 | 
				
			||||||
  remainingBlocks: 1121,
 | 
					  remainingBlocks: 1121,
 | 
				
			||||||
  remainingTime: 665977.6261244365,
 | 
					  remainingTime: 665977,
 | 
				
			||||||
  previousRetarget: -4.807005268478962
 | 
					  previousRetarget: -4.807005268478962,
 | 
				
			||||||
 | 
					  nextRetargetHeight: 741888,
 | 
				
			||||||
 | 
					  timeAvg: 302328,
 | 
				
			||||||
 | 
					  timeOffset: 0
 | 
				
			||||||
}`
 | 
					}`
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        codeSampleTestnet: {
 | 
					        codeSampleTestnet: {
 | 
				
			||||||
@ -127,11 +130,14 @@ export const restApiDocsData = [
 | 
				
			|||||||
          curl: [],
 | 
					          curl: [],
 | 
				
			||||||
          response: `{
 | 
					          response: `{
 | 
				
			||||||
  progressPercent: 44.397234501112074,
 | 
					  progressPercent: 44.397234501112074,
 | 
				
			||||||
  difficultyChange: 0.9845932018381687,
 | 
					  difficultyChange: 98.45932018381687,
 | 
				
			||||||
  estimatedRetargetDate: 1627762478.9111245,
 | 
					  estimatedRetargetDate: 1627762478,
 | 
				
			||||||
  remainingBlocks: 1121,
 | 
					  remainingBlocks: 1121,
 | 
				
			||||||
  remainingTime: 665977.6261244365,
 | 
					  remainingTime: 665977,
 | 
				
			||||||
  previousRetarget: -4.807005268478962
 | 
					  previousRetarget: -4.807005268478962,
 | 
				
			||||||
 | 
					  nextRetargetHeight: 741888,
 | 
				
			||||||
 | 
					  timeAvg: 302328,
 | 
				
			||||||
 | 
					  timeOffset: 0
 | 
				
			||||||
}`
 | 
					}`
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        codeSampleSignet: {
 | 
					        codeSampleSignet: {
 | 
				
			||||||
@ -140,11 +146,14 @@ export const restApiDocsData = [
 | 
				
			|||||||
          curl: [],
 | 
					          curl: [],
 | 
				
			||||||
          response: `{
 | 
					          response: `{
 | 
				
			||||||
  progressPercent: 44.397234501112074,
 | 
					  progressPercent: 44.397234501112074,
 | 
				
			||||||
  difficultyChange: 0.9845932018381687,
 | 
					  difficultyChange: 98.45932018381687,
 | 
				
			||||||
  estimatedRetargetDate: 1627762478.9111245,
 | 
					  estimatedRetargetDate: 1627762478,
 | 
				
			||||||
  remainingBlocks: 1121,
 | 
					  remainingBlocks: 1121,
 | 
				
			||||||
  remainingTime: 665977.6261244365,
 | 
					  remainingTime: 665977,
 | 
				
			||||||
  previousRetarget: -4.807005268478962
 | 
					  previousRetarget: -4.807005268478962,
 | 
				
			||||||
 | 
					  nextRetargetHeight: 741888,
 | 
				
			||||||
 | 
					  timeAvg: 302328,
 | 
				
			||||||
 | 
					  timeOffset: 0
 | 
				
			||||||
}`
 | 
					}`
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        codeSampleLiquid: {
 | 
					        codeSampleLiquid: {
 | 
				
			||||||
@ -153,11 +162,14 @@ export const restApiDocsData = [
 | 
				
			|||||||
          curl: [],
 | 
					          curl: [],
 | 
				
			||||||
          response: `{
 | 
					          response: `{
 | 
				
			||||||
  progressPercent: 44.397234501112074,
 | 
					  progressPercent: 44.397234501112074,
 | 
				
			||||||
  difficultyChange: 0.9845932018381687,
 | 
					  difficultyChange: 98.45932018381687,
 | 
				
			||||||
  estimatedRetargetDate: 1627762478.9111245,
 | 
					  estimatedRetargetDate: 1627762478,
 | 
				
			||||||
  remainingBlocks: 1121,
 | 
					  remainingBlocks: 1121,
 | 
				
			||||||
  remainingTime: 665977.6261244365,
 | 
					  remainingTime: 665977,
 | 
				
			||||||
  previousRetarget: -4.807005268478962
 | 
					  previousRetarget: -4.807005268478962,
 | 
				
			||||||
 | 
					  nextRetargetHeight: 741888,
 | 
				
			||||||
 | 
					  timeAvg: 302328,
 | 
				
			||||||
 | 
					  timeOffset: 0
 | 
				
			||||||
}`
 | 
					}`
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user