diff --git a/rest/resources/rest.json b/rest/resources/rest.json
index 7be9fc85..4da42429 100644
--- a/rest/resources/rest.json
+++ b/rest/resources/rest.json
@@ -12,6 +12,10 @@
"allowedHosts": ["*"],
"allowedMethods": ["GET", "POST", "PUT", "OPTIONS"]
},
+ "uncirculatingAccountPublicKeys": [
+ "A4739036FD7EFED2750A51EE9D1D3113BA3F9849E0889213CED7F221B2AA1A20",
+ "2BF1E1F3072E3BE0CD851E4741E101E33DB19C163895F69AA890E7CF177C878C"
+ ],
"extensions": [
"accountLink",
"aggregate",
diff --git a/rest/src/index.js b/rest/src/index.js
index 63b426a5..6f695160 100644
--- a/rest/src/index.js
+++ b/rest/src/index.js
@@ -131,7 +131,9 @@ const registerRoutes = (server, db, services) => {
apiNode: services.config.apiNode,
websocket: services.config.websocket,
numBlocksTransactionFeeStats: services.config.numBlocksTransactionFeeStats,
- deployment: services.config.deployment
+ deployment: services.config.deployment,
+
+ uncirculatingAccountPublicKeys: services.config.uncirculatingAccountPublicKeys
},
connections: services.connectionService
};
diff --git a/rest/src/plugins/cmc/cmcRoutes.js b/rest/src/plugins/cmc/cmcRoutes.js
index 29f81810..762b5d55 100644
--- a/rest/src/plugins/cmc/cmcRoutes.js
+++ b/rest/src/plugins/cmc/cmcRoutes.js
@@ -20,66 +20,69 @@
*/
const cmcUtils = require('./cmcUtils');
-const uncirculatedAddresses = require('./unCirculatedAccounts');
+const { longToUint64 } = require('../../db/dbUtils');
const routeUtils = require('../../routes/routeUtils');
-const errors = require('../../server/errors');
const AccountType = require('../AccountType');
+const catapult = require('catapult-sdk');
const ini = require('ini');
const fs = require('fs');
const util = require('util');
+const { convert, uint64 } = catapult.utils;
+
module.exports = {
register: (server, db, services) => {
const sender = routeUtils.createSender('cmc');
+ const propertyValueToMosaicId = value => uint64.fromHex(value.replace(/'/g, '').replace('0x', ''));
+
const readAndParseNetworkPropertiesFile = () => {
const readFile = util.promisify(fs.readFile);
return readFile(services.config.apiNode.networkPropertyFilePath, 'utf8')
.then(fileData => ini.parse(fileData));
};
- server.get('/network/currency/supply/circulating', (req, res, next) => readAndParseNetworkPropertiesFile()
- .then(async propertiesObject => {
- /* eslint-disable global-require */
- const accountIds = routeUtils.parseArgumentAsArray({ addresses: uncirculatedAddresses }, 'addresses', 'address');
- const currencyId = propertiesObject.chain.currencyMosaicId.replace(/'/g, '').replace('0x', '');
- const mosaicId = routeUtils.parseArgument({ mosaicId: currencyId }, 'mosaicId', 'uint64hex');
+ const getUncirculatingAccountIds = propertiesObject => {
+ const publicKeys = [propertiesObject.network.nemesisSignerPublicKey].concat(services.config.uncirculatingAccountPublicKeys);
+ return publicKeys.map(publicKey => ({ [AccountType.publicKey]: convert.hexToUint8(publicKey) }));
+ };
- const mosaics = await db.mosaicsByIds([mosaicId]);
- const accounts = await db.catapultDb.accountsByIds(accountIds.map(accountId => ({ [AccountType.address]: accountId })));
+ const lookupMosaicAmount = (mosaics, currencyMosaicId) => {
+ const matchingMosaic = mosaics.find(mosaic => {
+ const mosaicId = longToUint64(mosaic.id); // convert Long to uint64
+ return 0 === uint64.compare(currencyMosaicId, mosaicId);
+ });
- const totalSupply = parseInt(mosaics[0].mosaic.supply.toString(), 10);
- const totalUncirculated = accounts.reduce((a, b) => a + parseInt(b.account.mosaics[0].amount.toString(), 10), 0);
+ return undefined === matchingMosaic ? 0 : matchingMosaic.amount.toNumber();
+ };
- const circulatingSupply = (totalSupply - totalUncirculated).toString();
+ server.get('/network/currency/supply/circulating', (req, res, next) => readAndParseNetworkPropertiesFile()
+ .then(async propertiesObject => {
+ const currencyMosaicId = propertyValueToMosaicId(propertiesObject.chain.currencyMosaicId);
+ const mosaics = await db.mosaicsByIds([currencyMosaicId]);
+ const accounts = await db.catapultDb.accountsByIds(getUncirculatingAccountIds(propertiesObject));
- sender.sendPlainText(res, next)(cmcUtils.convertToRelative(circulatingSupply));
- }).catch(() => {
- res.send(errors.createInvalidArgumentError('there was an error reading the network properties file'));
- next();
+ const totalSupply = mosaics[0].mosaic.supply.toNumber();
+ const burnedSupply = accounts.reduce(
+ (sum, account) => sum + lookupMosaicAmount(account.account.mosaics, currencyMosaicId),
+ 0
+ );
+ sender.sendPlainText(res, next)(cmcUtils.convertToRelative(totalSupply - burnedSupply));
}));
server.get('/network/currency/supply/total', (req, res, next) => readAndParseNetworkPropertiesFile()
.then(propertiesObject => {
- const currencyId = propertiesObject.chain.currencyMosaicId.replace(/'/g, '').replace('0x', '');
- const mosaicId = routeUtils.parseArgument({ mosaicId: currencyId }, 'mosaicId', 'uint64hex');
- return db.mosaicsByIds([mosaicId]).then(response => {
- const supply = response[0].mosaic.supply.toString();
-
+ const currencyMosaicId = propertyValueToMosaicId(propertiesObject.chain.currencyMosaicId);
+ return db.mosaicsByIds([currencyMosaicId]).then(response => {
+ const supply = response[0].mosaic.supply.toNumber();
sender.sendPlainText(res, next)(cmcUtils.convertToRelative(supply));
- }).catch(() => {
- res.send(errors.createInvalidArgumentError('there was an error reading the network properties file'));
- next();
});
}));
server.get('/network/currency/supply/max', (req, res, next) => readAndParseNetworkPropertiesFile()
.then(propertiesObject => {
- const supply = propertiesObject.chain.maxMosaicAtomicUnits.replace(/'/g, '').replace('0x', '');
+ const supply = parseInt(propertiesObject.chain.maxMosaicAtomicUnits.replace(/'/g, ''), 10);
sender.sendPlainText(res, next)(cmcUtils.convertToRelative(supply));
- }).catch(() => {
- res.send(errors.createInvalidArgumentError('there was an error reading the network properties file'));
- next();
}));
}
};
diff --git a/rest/src/plugins/cmc/unCirculatedAccounts.js b/rest/src/plugins/cmc/unCirculatedAccounts.js
deleted file mode 100644
index ba43e5ec..00000000
--- a/rest/src/plugins/cmc/unCirculatedAccounts.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2016-2019, Jaguar0625, gimre, BloodyRookie, Tech Bureau, Corp.
- * Copyright (c) 2020-present, Jaguar0625, gimre, BloodyRookie.
- * All rights reserved.
- *
- * This file is part of Catapult.
- *
- * Catapult is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Catapult is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Catapult. If not, see .
- */
-
-module.exports = [
- 'NCTOGU4INIO7DXLGWXBXBQHE3T6C6WBQNFUKY6A', // unclaimed cold
- 'NB6BURBVCY4LEUA6J6NETHQW6O2O2QVKLKFK5MY', // unclaimed hot
- 'NACXOOKIDID7S75S4FFSC7KBBIBHOBUXB5VSE7A', 'NALOQMBU45WOLZ4BCBYZX3N2Y2VSYQFOXGAO34A', 'NBNCW3DUUHGBCVJ53LYSYYNMKJ52TLR33C5U53A',
- 'NB5NIEQF7FM7LLSFASHOQF4X3F6IPDYSIGR3UVA', 'NCAXT7RH6SUPXEU75EIPAPF7DM4VWUBC5AW2L4Q', 'NCE3EP762222D5D2UAF6KIFL7XZ7U4TPFWBYVHA',
- 'NCKAC225JEFJTB3EO64MIVYF5D7YGZM2ZFXRJNI', 'NCQADXOA7ZHLUW2567H33HNNEKCOCN2OJ53PXIQ', 'NCTTMDTZUUQVN4OKTSF3FTEHJQL2QOGAV25MDCA',
- 'NCVQPB2LZ6UCYKGYJAMCC7V4JGXA35BBY44BMHY', 'NCXX3KEIEZ3NABMUU45GM7X7BLMPMQHFOZMMF4Q', 'NDC3U2UERNMRYFQA45XC74TEEETTZPRUVWKFPAY',
- 'NDF4ZCXFKIU5DSJEVBOOI2BDZMDKJTGJVBD6JRY', 'NDLFVQ3C25P5VO2VWP6AMHPIJT6FZYTXNJD4ZAY', 'NDLORKVADZSXTIVAA2FYLDMM7I32AIWE7HDWGUQ',
- 'NDNGH7WJHSMULMCKYE333V6WU4CQDWXZIJK2VCY', 'NDRLHNV4W7W2M527QOIP35OI3HOMAGTCJDPFDEQ', 'NDSQX6J2QALD2XTU5NQ4FWA2MMEFKBOBEB2BIOQ',
- 'NDX4GP6OL32EOSGXSB5FTGKXDJZP4D535ZZYDFI', 'ND6667LJBJJ6UMJSZKN2BLHQCS3WNZ3W4UGCFKI', 'NAQ3WTILPJUEKOOPNPOLJ7IG2TJSG4VKJ6SWBWA',
- 'NBSEOUUMRL4QFZN3OBVXCD5LHMUOWEFDUC4GVUA', 'NBX2AMNDYWKPD76MSIIRKWPSGOTNNFFJOWMN64I', 'NCFNZEG73E7GUHZYYUJ2LQEA46JFS3F2XIMAW3A',
- 'NCMYFGTYTPXVOEWRYKE56U3ZRUVBSP4ZZ7UAIIA', 'NCQ4WVGFRF34UYFGGJQ4UJLGAUQTP4T5NEQKGMQ', 'NC2545W433QN64625A26SA6VNFDD43YY5PGCDRA',
- 'NC4GM67MOMEQYUZMOLB2H4Y74ESYCD2LPK5IQXI', 'NC5LLAV5MPYSMX6HVJ7ISY2S7OIGY3FSEIYGJAY', 'NDNCVE4SF3I62M3WLS65CZ7NA2NMDXJYZQCTXGQ',
- 'NDRARXH6JHYTD5WJCZR3FMQW5ZLMQEGUR3JZSFA', 'NDYCPCRT2QXRFZYK4B2GRC4ISIXC4NXVWTZ5Z3A', 'NCPUTO6OUVSRSNDEOAJ5VNSMWDELRTND5VG2HDA',
- 'NAPOVZAZGMT6LVG7TKR5FE7IC4T7VCMQJUMDUAA', 'NBNTWN3JJSAREDXYWARBYBPOXOWUO6H3GXL4EPY', 'NBMDALVKGYK562LXSESZT6FFNI65FDXFY5VOXSQ',
- 'NABH3A5VDLYAVA73OV246JTVMAIPD2WEMAQL27I', 'NAL4XHZU6MANNNFQI4Z2WNMU3KRI2YW2MRRMHLI', 'NBBBCIKJV45U7PNYTNXETH2UFZLJ3C6TJKLJDQQ',
- 'NBGEJ36QK43DR4MYB6XFUFLSVFLULX3HBVNRCVY', 'NBNRFJSGE53UNHBGZIHYZXPG7SHLQISJN5REGIY', 'NBRENIWJUCSUU7RJ5S2DEJVXAOJOTZZDKEFOC3I',
- 'NBUW4OTD42VHELNPCLPQCUHNBHR47PQKLP2EKXA', 'NB5ORUTTH2QYHEVTDBB5WPQI4US22FNMODFRK5Y', 'NCASTBFHXMHGQB2UJVUDSW7ZI4N2FDW54OTSHKQ',
- 'NCBLL63WUAL7FBNPZQISGJR4WZNB7RVWCWG25MI', 'NCC3VKV3V2HCAP2KTXJUWSXCJ3B6U32EKR6VU5I', 'NCFH35TMUJ5QJL6LTBYRBO7ERMM4NIBH7TL6TFY',
- 'NCGCVCURBA2GCKPEGEA2Q6HKFEHYITKUNWRLMEA', 'NCNRS6KDPHV4MNMXOEGYD6LNRBMWUR7NT4SZI7I', 'NC2GXL6FQXZY3FXZAYJLBDQHBKSANZLGP4PL7VA',
- 'NC5CFRDWEZVCMGQ4Y77OEFSQLMQ3V4EL7JERY2A', 'NC54KVIISZCMMB3ABAMV6NQ6DAUIYYVKQ23S73Q', 'NC7QENF6OO2FRYV7Q4B5Q74LRSC54Y3YNYN5O3Y',
- 'NDE57ICE4UOAPUV3E4CYU3PBA2X4ABUGRGKDFBA', 'NDG6ORUW4PVWVQJRQ5AXADQBUQVL3KBX7AW7MUY', 'NDMR4GMUWGMODWY4FF2VZ3CEC2F56HTD3T6EJYY',
- 'NDTNPG2NUA3MPVDXHLC6D5PSKM4JLLTMQJ5HEDY', 'ND2MRMODKMLCFJWPFJ4MDFI76R7FLZVKIIVKD3A', 'ND4MLYCECHPACYSDDQUFMPXONSIQLPAWNVBWSIA',
- 'ND726EB3B2VG77J3EEQSGNGUX3SS6L2IEBS7PIY', 'NAAZKYH4V6SARDIJRGFXYEZIHVRWY7R2T62QFYA', 'NAGCLXJZHZSBM5ILN4LQBDKU4NYVHB6ZLGRTKJI',
- 'NAIPUZBSDXZIHQKKILAFT3F43IQPS4LOZCH2H4Q', 'NA2KVKEQDZZMM3NGXYVBHZ46JHM46UWIX3KJ4AY', 'NA5ZUGHBUUHO63E5OQQND7CYK7UZ3HVQONR2O6Y',
- 'NA7YZPY222RVYQMUM65ZSVFSPAHL55UWO3S35FY', 'NBGGUKW3GEUFHKTO4DYSGDTHIVPKAME3T2XSCGY', 'NBI2NEBVAD45WWV44H3A53AQ5675Z4G3ZDGDYLI',
- 'NBQS3VKGOJ3YNIABN4Y4SFUDBDQHARUIVS6IMGQ', 'NB3WMVRI4RM3O3NUSWBZM7U4EZMKADSOFDPPJRQ', 'NCFFJV3VTAK6BJZNV6ZRUZKUJPOWST6MYFAAK5A',
- 'NCRLDB2O2QDPU57PEG3D3AIFSGPGCZU7VVTKBUY', 'NCVG74MGUGR3PLVBWVNNACD6R37JA4RCQMXY3DY', 'NCVR72OUOHVGTVLYBKI7PLUDTIAYPRUWPMJJP3Q',
- 'NDBKLXZWYBMUUTNRRZ5ESRAJYMQIMHGLGAYLTGY', 'NDQLBLKXVOK2YS5G7J3AYYKTNW3S3RRK6RQONAQ', 'ND6ZNSQG3I7VWLWSJ3DTYVPEZSJRGSEERW2F7DI',
- 'NAE2BC5IQ6HAVL3SOJ3ENWMLNZVWJSSN4C4GMJQ', 'NAUXIAVKDQ7MYGY7EDNXYKMRFV6QUM5RJQVRTWI', 'NBQ2XKSB7HBT5SM5O36RYM57RLITSOLRC62HAOY',
- 'NCFO4UXV5TWFO6UOIBUYZCB4ZB2KEVXJZMCIAHA', 'NCF7G3YVN5SHQQ7PUO5VUZLKHFBRQPOSJNNBUAQ', 'NCN26TKNQQXZIJ6JPQVHPWE4RR6IJTQCRJZKFIY',
- 'NCOLND36Q2QY3VY2JBY5V565ROHFOWGWORRH2EA', 'NCXYYHL4TVBA3FAXHGUFX7GTFTROA4W5IFVC3NI', 'NDLEMSNJK524QEXKY4ZQLM5G2ON2557SSR775XA',
- 'NAD3FRYYDCOQX66WE22L7IU2WJV4CP4EWSTP2GQ', 'NAGF2Z6SNW5LVTFZ4SYZFZACNOVS3E7YIAISMNA', 'NASUT5TVKVP2RM7W76CDS3QJZZN524LFOCII36I',
- 'NBFU2WPO3GSR65NUINGYMPLH2246MWP2HCMY2GI', 'NBMBRKE3SWCDX42DAHQ4HEP3LXCHNYYMR6AXAGI', 'NBPRSZ6JI7WPBDYKX6OU6OJD5JLOMPQIQAXTPMQ',
- 'NB3CEDY5PU534FQLL7VIQI5MQXLHUIWMZFIJEMY', 'NB4GHQQDRETKMTRXR6P2Y4CSHDULAQMPS6CGRFY', 'NB7NGG255EODTQVGYIN7VTWN5E6NCJX6M7KJAWI',
- 'NCF63BYUDLEU22AVEQAAG4CNDCOQD6UFJZJMGFY', 'NCK4EQHDH5JOPLZ4IEOOGAN56M3MHMTAAHBVC2A', 'NCNHTLZ2445VPT3KOLK4APE7PIW73I7RPBPI6XQ',
- 'NCPSXIPESZYYLOMDB3JKP4KQSE2BKGSYBOCBU3Q', 'NCQIDQQGK4IYXST6TSIFUIBRPNJVDDGQUHGR3TI', 'NCXYZW7YPCIHTQSBCJAEMH4KKP7X74JN56EOKNQ',
- 'NCX6PYUTNYXK5R3HUVOO2UEFTDLCK7CE4YVB4XQ', 'NDCLSXHO4RSNUKK4EDLBWYZX5WBQOQBPTVLMSMQ', 'NDKSU3CKWVWNL4WDL5PMQ46MY5ND7RMK5GB4LKI',
- 'NDVVKJBP2DISI5WGPN4HBSZ5B5GXOL3ERODFHPA', 'ND5YALPCYLD3I6JV4KMHTU4ORSDQ3CPGGOPSWJI', 'NA2DF2PKUACZTB5KTTZABMAIR43LNQYOE7FOVLY',
- 'NAKFJTGMIAHMZXNB6M6WVRHFKAQWYEXYWTSTGBI', 'NBCNY4PULYTLMWVYYJWRDFTFODPHE3TBOUO2GNY', 'NDBJX22SLOP5DRAXZHZFCTZ3JAOMJQ6737FG75Y',
- 'NDZRWMC74JGW23OB4W7SHVAAQ77UEE3JZ37QGYI', 'ND4E7JUQX73TGCXZGWMG6WDR27AVJ74QDW3EOUI', 'NAYF7RRNNL6652SSVGPMCCMPL7FMPJ2EO6FAH5Y',
- 'NBFOERC6P2YY74O5HYQPZHNWBIL7YTHPZSGETSA', 'NCARLDVBLDKOMBVC22IPRTVZX72IYZCARRWR4FQ', 'NCNVQAWCEJL3TPOCVAVXF3RGMVMTI2HTUD47RTY',
- 'ND2LYJD467WB7YSK6NFQTL2SFIPWFNTRW7K46EA'
-];
diff --git a/rest/test/plugins/cmc/cmcRoutes_spec.js b/rest/test/plugins/cmc/cmcRoutes_spec.js
index 89105f1e..dddd30f9 100644
--- a/rest/test/plugins/cmc/cmcRoutes_spec.js
+++ b/rest/test/plugins/cmc/cmcRoutes_spec.js
@@ -19,6 +19,7 @@
* along with Catapult. If not, see .
*/
+const { convertToLong } = require('../../../src/db/dbUtils');
const cmcRoutes = require('../../../src/plugins/cmc/cmcRoutes');
const cmcUtils = require('../../../src/plugins/cmc/cmcUtils');
const { MockServer } = require('../../routes/utils/routeTestUtils');
@@ -27,18 +28,22 @@ const { expect } = require('chai');
const sinon = require('sinon');
const fs = require('fs');
-const { uint64 } = catapult.utils;
-
describe('cmc routes', () => {
describe('network currency supply', () => {
const maxSupply = 9000000000000000;
- const XYMSupply = 8998999998000000;
+ const xymSupply = 8998999998000000;
+
+ const currencyMosaicId = '0x1234\'5678\'ABCD\'EF01';
+ const nemesisSignerPublicKey = 'AF1B9DCF4FAD2CDC2C04B4F9CBDF3C9C884A9F05B40A59E233681E282DC824D9';
+ const uncirculatingAccountPublicKey1 = 'D4912C4CA33F608E95B9C3ABAE59263B99E2DF6E87252D61F8DEFADF7DFFC455';
+ const uncirculatingAccountPublicKey2 = '3BF1E1F3072E3BE0CD851E4741E101E33DB19C163895F69AA890E7CF177C878C';
+ const circulatingAccountPublicKey1 = '346AA758B2ED98923204D7361A5A47C7B569C594C7904461C67459703D7B5874';
const mosaicsSample = [{
id: '',
mosaic: {
- id: '1234567890ABCDEF',
- supply: XYMSupply,
+ id: convertToLong([0xABCDEF01, 0x12345678]),
+ supply: convertToLong(xymSupply),
startHeight: '',
ownerAddress: '',
revision: 1,
@@ -48,25 +53,34 @@ describe('cmc routes', () => {
}
}];
- const accountsSample = [{
- id: 'random1',
- account: {
- address: '',
- addressHeight: '',
- publicKey: '',
- publicKeyHeight: '',
- supplementalPublicKeys: {},
- importance: '',
- importanceHeight: '',
- activityBuckets: [],
- mosaics: [
- { id: 0, amount: uint64.fromUint((1000000)) }
- ]
- }
- }];
+ const createAccountSample = (publicKey, currencyAmount, otherAmount) => ({
+ address: '',
+ addressHeight: '',
+ publicKey: catapult.utils.convert.hexToUint8(publicKey),
+ publicKeyHeight: '',
+ supplementalPublicKeys: {},
+ importance: '',
+ importanceHeight: '',
+ activityBuckets: [],
+ mosaics: [
+ { id: convertToLong([0xABCDEF01, 0x22222222]), amount: convertToLong(otherAmount) },
+ { id: convertToLong([0xABCDEF01, 0x12345678]), amount: convertToLong(currencyAmount) }
+ ]
+ });
+
+ const accountsSample = [
+ { id: 'random1', account: createAccountSample(nemesisSignerPublicKey, 1000000, 9000000) },
+ { id: 'random2', account: createAccountSample(uncirculatingAccountPublicKey1, 2000000, 9000000) },
+ { id: 'random3', account: createAccountSample(circulatingAccountPublicKey1, 4000000, 9000000) },
+ { id: 'random4', account: createAccountSample(uncirculatingAccountPublicKey2, 8000000, 9000000) }
+ ];
const dbMosaicsFake = sinon.fake(() => Promise.resolve(mosaicsSample));
- const dbAccountsFake = sinon.fake(() => Promise.resolve(accountsSample));
+ const dbAccountsFake = sinon.fake(accountIds => {
+ const filteredAccountsSample = accountsSample.filter(accountSample =>
+ accountIds.some(accountId => catapult.utils.array.deepEqual(accountId.publicKey, accountSample.account.publicKey)));
+ return Promise.resolve(filteredAccountsSample);
+ });
const mockServer = new MockServer();
@@ -77,69 +91,90 @@ describe('cmc routes', () => {
}
};
- const services = { config: { apiNode: {} } };
+ const services = {
+ config: {
+ apiNode: {},
+ uncirculatingAccountPublicKeys: [uncirculatingAccountPublicKey1, uncirculatingAccountPublicKey2]
+ }
+ };
cmcRoutes.register(mockServer.server, db, services);
const req = { params: {} };
- beforeEach(() => {
+ afterEach(() => {
mockServer.resetStats();
dbMosaicsFake.resetHistory();
+ fs.readFile.restore();
});
describe('GET', () => {
- it('network currency supply circulating', () => {
- const readFileStub = sinon.stub(fs, 'readFile').callsFake((path, data, callback) =>
- callback(null, `[chain]\nmaxMosaicAtomicUnits = ${maxSupply}\ncurrencyMosaicId = "0x1234567890ABCDEF"`));
-
+ it('network currency supply circulating (without burns)', () => {
+ sinon.stub(fs, 'readFile').callsFake((path, data, callback) =>
+ callback(null, [
+ '[network]',
+ `nemesisSignerPublicKey=${nemesisSignerPublicKey}`,
+ '',
+ '[chain]',
+ 'currencyMosaicId = 0x1234\'5678\'ABCD\'EF02'
+ ].join('\n')));
const route = mockServer.getRoute('/network/currency/supply/circulating').get();
- // Arrange:
- const totalUncirculated = accountsSample.reduce((a, b) => a + parseInt(b.account.mosaics[0].amount.toString(), 10), 0);
- const circulatingSupply = XYMSupply - totalUncirculated;
+ // Act:
+ return mockServer.callRoute(route, req).then(() => {
+ // Assert:
+ expect(mockServer.next.calledOnce).to.equal(true);
+
+ const expectedSupply = mosaicsSample[0].mosaic.supply - 0;
+ expect(mockServer.send.firstCall.args[0]).to.equal(cmcUtils.convertToRelative(expectedSupply));
+ });
+ });
+
+ it('network currency supply circulating (with burns)', () => {
+ sinon.stub(fs, 'readFile').callsFake((path, data, callback) =>
+ callback(null, [
+ '[network]',
+ `nemesisSignerPublicKey=${nemesisSignerPublicKey}`,
+ '',
+ '[chain]',
+ `currencyMosaicId = ${currencyMosaicId}`
+ ].join('\n')));
+ const route = mockServer.getRoute('/network/currency/supply/circulating').get();
// Act:
return mockServer.callRoute(route, req).then(() => {
- // Assert
+ // Assert:
expect(mockServer.next.calledOnce).to.equal(true);
- expect(mockServer.send.firstCall.args[0]).to.equal(cmcUtils.convertToRelative(circulatingSupply));
- readFileStub.restore();
+
+ const expectedSupply = mosaicsSample[0].mosaic.supply - 11000000;
+ expect(mockServer.send.firstCall.args[0]).to.equal(cmcUtils.convertToRelative(expectedSupply));
});
});
it('network currency supply total', () => {
- const readFileStub = sinon.stub(fs, 'readFile').callsFake((path, data, callback) =>
- callback(null, '[chain]\ncurrencyMosaicId = 0x1234567890ABCDEF'));
+ sinon.stub(fs, 'readFile').callsFake((path, data, callback) =>
+ callback(null, `[chain]\ncurrencyMosaicId = ${currencyMosaicId}`));
const route = mockServer.getRoute('/network/currency/supply/total').get();
- // Arrange:
- const xymSupply = cmcUtils.convertToRelative(mosaicsSample[0].mosaic.supply);
-
// Act:
return mockServer.callRoute(route, req).then(() => {
- // Assert
+ // Assert:
expect(mockServer.next.calledOnce).to.equal(true);
- expect(mockServer.send.firstCall.args[0]).to.equal(xymSupply);
- readFileStub.restore();
+ expect(mockServer.send.firstCall.args[0]).to.equal(cmcUtils.convertToRelative(mosaicsSample[0].mosaic.supply));
});
});
it('network currency supply max', () => {
- const readFileStub = sinon.stub(fs, 'readFile').callsFake((path, data, callback) =>
+ sinon.stub(fs, 'readFile').callsFake((path, data, callback) =>
callback(null, `[chain]\nmaxMosaicAtomicUnits = ${maxSupply}`));
const route = mockServer.getRoute('/network/currency/supply/max').get();
- // Arrange:
- const mosaicMaxSupply = cmcUtils.convertToRelative(maxSupply);
-
// Act:
return mockServer.callRoute(route, req).then(() => {
- // Assert
+ // Assert:
expect(mockServer.next.calledOnce).to.equal(true);
- expect(mockServer.send.firstCall.args[0]).to.equal(mosaicMaxSupply);
- readFileStub.restore();
+ expect(mockServer.send.firstCall.args[0]).to.equal(cmcUtils.convertToRelative(maxSupply));
});
});
});