diff --git a/package-lock.json b/package-lock.json index d213b362..fa717561 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "bodhi-server", - "version": "6.1.2", + "version": "6.1.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1371,6 +1371,15 @@ "check-error": "^1.0.2" } }, + "chai-exclude": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/chai-exclude/-/chai-exclude-2.0.1.tgz", + "integrity": "sha512-9cZ0ZzlGRwZvNiKUPTbx4E1anQ4aTqtKOX96+cb4XrNa+8B5KNZg3d43clYNawgXgBcQAenXeX5fbeY7+TdkrA==", + "dev": true, + "requires": { + "fclone": "^1.0.11" + } + }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -1731,10 +1740,12 @@ } }, "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-3.0.1.tgz", + "integrity": "sha512-dUL0cJ4PBLanJGJQBHQUkvZ3C4q13MXzl54oRqAIiJGiNkOZ4JDwkg/SBo7daGghzlJv16yW1p/4lIQukmbedA==", + "requires": { + "type-fest": "^0.5.2" + } }, "cycle": { "version": "1.0.3", @@ -2959,6 +2970,12 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fclone": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", + "integrity": "sha1-EOhdo4v+p/xZk0HClu4ddyZu5kA=", + "dev": true + }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -7117,6 +7134,11 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, + "type-fest": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz", + "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==" + }, "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", @@ -7221,6 +7243,14 @@ "dev": true, "requires": { "crypto-random-string": "^1.0.0" + }, + "dependencies": { + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + } } }, "universalify": { diff --git a/package.json b/package.json index 851e4987..b72124ac 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "Server that parses, stores, sends, and receives Bodhi-related data from the blockchain.", "author": "bodhi.network", "license": "LGPL-3.0", - "version": "6.1.2", + "version": "6.1.3", "repository": "git@github.com:bodhiproject/bodhi-server.git", "keywords": [ "bodhi", @@ -26,6 +26,7 @@ "babel-polyfill": "^6.26.0", "chai": "^4.1.2", "chai-as-promised": "^7.1.1", + "crypto-random-string": "^3.0.1", "dotenv": "^6.0.0", "express": "^4.16.3", "express-winston": "^2.5.1", @@ -45,6 +46,7 @@ "winston-daily-rotate-file": "^3.2.1" }, "devDependencies": { + "chai-exclude": "^2.0.1", "easygraphql-tester": "^5.1.3", "eslint": "^4.16.0", "eslint-config-airbnb": "^16.1.0", diff --git a/src/api/config-manager.js b/src/api/config-manager.js index decb9a9d..5260c81e 100644 --- a/src/api/config-manager.js +++ b/src/api/config-manager.js @@ -12,9 +12,11 @@ const getContract = () => { }; module.exports = { + getContract, + async bodhiTokenAddress() { try { - return getContract().methods.bodhiTokenAddress().call(); + return this.getContract().methods.bodhiTokenAddress().call(); } catch (err) { logger.error(`Error ConfigManager.bodhiTokenAddress(): ${err.message}`); throw err; @@ -23,7 +25,7 @@ module.exports = { async eventFactoryAddress() { try { - return getContract().methods.eventFactoryAddress().call(); + return this.getContract().methods.eventFactoryAddress().call(); } catch (err) { logger.error(`Error ConfigManager.eventFactoryAddress(): ${err.message}`); throw err; @@ -32,7 +34,7 @@ module.exports = { async eventEscrowAmount() { try { - const res = await getContract().methods.eventEscrowAmount().call(); + const res = await this.getContract().methods.eventEscrowAmount().call(); return web3.utils.toBN(res).toString(10); } catch (err) { logger.error(`Error ConfigManager.eventEscrowAmount(): ${err.message}`); @@ -42,7 +44,7 @@ module.exports = { async arbitrationLength() { try { - const res = await getContract().methods.arbitrationLength().call(); + const res = await this.getContract().methods.arbitrationLength().call(); return map(res, len => web3.utils.toBN(len).toNumber()); } catch (err) { logger.error(`Error ConfigManager.arbitrationLength(): ${err.message}`); @@ -52,7 +54,7 @@ module.exports = { async startingConsensusThreshold() { try { - const res = await getContract().methods.startingConsensusThreshold().call(); + const res = await this.getContract().methods.startingConsensusThreshold().call(); return map(res, len => web3.utils.toBN(len).toString(10)); } catch (err) { logger.error(`Error ConfigManager.startingOracleThreshold(): ${err.message}`); @@ -62,7 +64,7 @@ module.exports = { async thresholdPercentIncrease() { try { - const res = await getContract().methods.thresholdPercentIncrease().call(); + const res = await this.getContract().methods.thresholdPercentIncrease().call(); return web3.utils.toBN(res).toString(10); } catch (err) { logger.error(`Error ConfigManager.thresholdPercentIncrease(): ${err.message}`); @@ -75,7 +77,7 @@ module.exports = { const { address } = args; if (isUndefined(address)) throw TypeError('address is not defined'); - return getContract().methods.isWhitelisted(address).call(); + return this.getContract().methods.isWhitelisted(address).call(); } catch (err) { logger.error(`Error ConfigManager.isWhitelisted(): ${err.message}`); throw err; diff --git a/src/api/multiple-results-event.js b/src/api/multiple-results-event.js index 7f6a8b1a..0afa7694 100644 --- a/src/api/multiple-results-event.js +++ b/src/api/multiple-results-event.js @@ -13,13 +13,15 @@ const getContract = async (eventAddress) => { }; module.exports = { + getContract, + async calculateWinnings(args) { try { const { eventAddress, address } = args; if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); if (isUndefined(address)) throw TypeError('address is not defined'); - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); const res = await contract.methods.calculateWinnings(address).call(); return web3.utils.toBN(res).toString(10); } catch (err) { @@ -33,7 +35,7 @@ module.exports = { const { eventAddress } = args; if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); const res = await contract.methods.version().call(); return web3.utils.toBN(res).toNumber(); } catch (err) { @@ -47,7 +49,7 @@ module.exports = { const { eventAddress } = args; if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); const res = await contract.methods.currentRound().call(); return web3.utils.toBN(res).toNumber(); } catch (err) { @@ -61,7 +63,7 @@ module.exports = { const { eventAddress } = args; if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); const res = await contract.methods.currentResultIndex().call(); return web3.utils.toBN(res).toNumber(); } catch (err) { @@ -75,7 +77,7 @@ module.exports = { const { eventAddress } = args; if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); const res = await contract.methods.currentConsensusThreshold().call(); return web3.utils.toBN(res).toString(10); } catch (err) { @@ -89,7 +91,7 @@ module.exports = { const { eventAddress } = args; if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); const res = await contract.methods.currentArbitrationEndTime().call(); return web3.utils.toBN(res).toString(10); } catch (err) { @@ -104,7 +106,7 @@ module.exports = { if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); const { utils: { toBN, hexToUtf8 } } = web3; - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); const res = await contract.methods.eventMetadata().call(); return [ toBN(res[0]).toNumber(), @@ -124,7 +126,7 @@ module.exports = { if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); const { utils: { toBN } } = web3; - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); const res = await contract.methods.centralizedMetadata().call(); return [ res[0], @@ -145,7 +147,7 @@ module.exports = { if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); const { utils: { toBN } } = web3; - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); const res = await contract.methods.configMetadata().call(); return [ toBN(res[0]).toString(10), @@ -164,7 +166,7 @@ module.exports = { const { eventAddress } = args; if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); const res = await contract.methods.totalBets().call(); return web3.utils.toBN(res).toString(10); } catch (err) { @@ -179,7 +181,7 @@ module.exports = { if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); if (isUndefined(address)) throw TypeError('address is not defined'); - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); return contract.methods.didWithdraw(address).call(); } catch (err) { logger.error(`Error MultipleResultsEvent.didWithdraw(): ${err.message}`); @@ -192,7 +194,7 @@ module.exports = { const { eventAddress } = args; if (isUndefined(eventAddress)) throw TypeError('eventAddress is not defined'); - const contract = await getContract(eventAddress); + const contract = await this.getContract(eventAddress); return contract.methods.didWithdrawEscrow().call(); } catch (err) { logger.error(`Error MultipleResultsEvent.didWithdrawEscrow(): ${err.message}`); diff --git a/src/db/index.js b/src/db/index.js index 0c8a938d..b9debdad 100644 --- a/src/db/index.js +++ b/src/db/index.js @@ -44,8 +44,11 @@ const initDB = async () => { await db.Bets.ensureIndex({ fieldName: 'txid', unique: true }); await db.ResultSets.ensureIndex({ fieldName: 'txid', unique: true }); await db.Withdraws.ensureIndex({ fieldName: 'txid', unique: true }); + await db.TransactionReceipts.ensureIndex({ fieldName: 'transactionHash' }); - await applyMigrations(); + if (process.env.TEST_ENV !== 'true') { + await applyMigrations(); + } } catch (err) { logger.error(`DB load Error: ${err.message}`); throw err; @@ -114,7 +117,6 @@ async function applyMigrations() { logger.error(`Migration scripts load error: ${err.message}`); throw err; } - /** * whilst source code: https://caolan.github.io/async/v3/whilst.js.html * check(err, truth) and next(err, res) are built-in funcs in the source code @@ -122,41 +124,39 @@ async function applyMigrations() { * 1. test: take check(err, truth), if truth is true, then call iter(next), otherwise, call callback to end the loop * 2. iter: take next(err, res), which triggers test if no err, otherwise trigger callback(err) * 3. callback: will only be triggered if test fails, or err encountered, reaching callback means end of the loop - */ - let i = 0; - async.whilst( - check => check(null, i < migrations.length), // trigger iter - (next) => { - const migration = migrations[i]; - i++; - try { - if (Number(migration.number) > lastMigration) { - // Run migration - logger.info(`Running migration ${migration.number}...`); - // pass next() to migrate(), await not allowed, only callback func - migration.migrate(() => { - // Track the last migration number - lastMigration = migration.number; - fs.outputFileSync(migrationTrackPath, `LAST_MIGRATION=${lastMigration}\n`); - next(null, i); // trigger the next test - }); - } else { - next(null, i); // if no migration here, trigger the next test + */ + try { + let i = 0; + await async.whilst( + check => check(null, i < migrations.length), // trigger iter + (next) => { + const migration = migrations[i]; + i++; + try { + if (Number(migration.number) > lastMigration) { + // Run migration + logger.info(`Running migration ${migration.number}...`); + // pass next() to migrate(), await not allowed, only callback func + migration.migrate(() => { + // Track the last migration number + lastMigration = migration.number; + fs.outputFileSync(migrationTrackPath, `LAST_MIGRATION=${lastMigration}\n`); + next(null, i); // trigger the next test + }); + } else { + next(null, i); // if no migration here, trigger the next test + } + } catch (err) { + next(err, i); // err met, trigger the callback to end this loop } - } catch (err) { - next(err, i); // err met, trigger the callback to end this loop - } - }, - (err, number) => { - // will only be called if should end this loop - if (err) { - logger.error(`Migration ${number} error: ${err.message}`); - return; - } - - logger.info('Migrations complete.'); - }, - ); + }, + ); + } catch (err) { + // will only be called if should end this loop + logger.error(err); + throw err; + } + logger.info('Migrations complete.'); } module.exports = { diff --git a/src/graphql/queries/events.js b/src/graphql/queries/events.js index cbda0ddb..02f466db 100644 --- a/src/graphql/queries/events.js +++ b/src/graphql/queries/events.js @@ -67,7 +67,7 @@ const buildFilter = (rawFilter, version) => { if (language) filter.language = language; return filter; -} +}; module.exports = async ( parent, diff --git a/src/sync/bet-placed.js b/src/sync/bet-placed.js index f6ed2fcb..d354c12d 100644 --- a/src/sync/bet-placed.js +++ b/src/sync/bet-placed.js @@ -21,10 +21,10 @@ const syncBetPlaced = async ({ startBlock, endBlock, syncPromises, limit }) => { // Add to syncPromises array to be executed in parallel logger.info(`Found ${logs.length} BetPlaced`); each(logs, (log) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (logObj) => { try { // Parse and insert bet - const bet = parseBet({ log }); + const bet = parseBet({ log: logObj }); await DBHelper.insertBet(bet); // Fetch and insert tx receipt @@ -34,7 +34,7 @@ const syncBetPlaced = async ({ startBlock, endBlock, syncPromises, limit }) => { logger.error('Error syncBetPlaced parse'); throw insertErr; } - })); + }, log)); }); } catch (err) { logger.error('Error syncBetPlaced'); @@ -52,9 +52,9 @@ const pendingBetPlaced = async ({ syncPromises, limit }) => { logger.info(`Checking ${pending.length} pending BetPlaced`); each(pending, (p) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (pendingBet) => { try { - const txReceipt = await getTransactionReceipt(p.txid); + const txReceipt = await getTransactionReceipt(pendingBet.txid); if (isNull(txReceipt)) return; await DBHelper.insertTransactionReceipt(txReceipt); @@ -83,7 +83,7 @@ const pendingBetPlaced = async ({ syncPromises, limit }) => { } catch (insertErr) { logger.error(`Error pendingBetPlaced: ${insertErr.message}`); } - })); + }, p)); }); } catch (err) { logger.error(`Error pendingBetPlaced findBet: ${err.message}`); diff --git a/src/sync/blocks.js b/src/sync/blocks.js index bb9cc7ac..83c6510f 100644 --- a/src/sync/blocks.js +++ b/src/sync/blocks.js @@ -17,16 +17,16 @@ const getBlockTime = async (blockNum) => { module.exports = ({ startBlock, endBlock, syncPromises, limit }) => { try { const addPromise = (blockNum) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (bNum) => { try { // Get block time and insert - const blockTime = await getBlockTime(blockNum); - await DBHelper.insertBlock(blockNum, blockTime); + const blockTime = await getBlockTime(bNum); + await DBHelper.insertBlock(bNum, blockTime); } catch (insertErr) { logger.error('Error insert Block'); throw insertErr; } - })); + }, blockNum)); }; for (let i = startBlock; i <= endBlock; i++) addPromise(i); } catch (err) { diff --git a/src/sync/multiple-results-event-created.js b/src/sync/multiple-results-event-created.js index cfe23c12..c828e7d2 100644 --- a/src/sync/multiple-results-event-created.js +++ b/src/sync/multiple-results-event-created.js @@ -23,10 +23,10 @@ const syncMultipleResultsEventCreated = async ( // Add to syncPromises array to be executed in parallel logger.info(`Found ${logs.length} MultipleResultsEventCreated`); each(logs, (log) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (logObj) => { try { // Parse and insert event - const event = await parseEvent({ log }); + const event = await parseEvent({ log: logObj }); await DBHelper.insertEvent(event); // Fetch and insert tx receipt @@ -36,7 +36,7 @@ const syncMultipleResultsEventCreated = async ( logger.error('Error syncMultipleResultsEventCreated parse'); throw insertErr; } - })); + }, log)); }); } catch (err) { logger.error('Error syncMultipleResultsEventCreated'); @@ -51,9 +51,9 @@ const pendingMultipleResultsEventCreated = async ({ syncPromises, limit }) => { logger.info(`Checking ${pending.length} pending MultipleResultsEventCreated`); each(pending, (p) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (pendingEvent) => { try { - const txReceipt = await getTransactionReceipt(p.txid); + const txReceipt = await getTransactionReceipt(pendingEvent.txid); if (isNull(txReceipt)) return; await DBHelper.insertTransactionReceipt(txReceipt); @@ -83,7 +83,7 @@ const pendingMultipleResultsEventCreated = async ({ syncPromises, limit }) => { logger.error('Error pendingMultipleResultsEventCreated'); throw insertErr; } - })); + }, p)); }); } catch (err) { logger.error(`Error pendingMultipleResultsEventCreated findEvent: ${err.message}`); diff --git a/src/sync/result-set.js b/src/sync/result-set.js index b03fd05c..de9b3649 100644 --- a/src/sync/result-set.js +++ b/src/sync/result-set.js @@ -22,10 +22,10 @@ const syncResultSet = async ({ startBlock, endBlock, syncPromises, limit }) => { // Add to syncPromises array to be executed in parallel logger.info(`Found ${logs.length} ResultSet`); each(logs, (log) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (logObj) => { try { // Parse and insert result set - const resultSet = parseResultSet({ log }); + const resultSet = parseResultSet({ log: logObj }); await DBHelper.insertResultSet(resultSet); // Fetch and insert tx receipt @@ -38,7 +38,7 @@ const syncResultSet = async ({ startBlock, endBlock, syncPromises, limit }) => { logger.error('Error syncResultSet parse'); throw insertErr; } - })); + }, log)); }); } catch (err) { logger.error('Error syncResultSet'); @@ -56,9 +56,9 @@ const pendingResultSet = async ({ syncPromises, limit }) => { logger.info(`Checking ${pending.length} pending ResultSet`); each(pending, (p) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (pendingSet) => { try { - const txReceipt = await getTransactionReceipt(p.txid); + const txReceipt = await getTransactionReceipt(pendingSet.txid); if (isNull(txReceipt)) return; await DBHelper.insertTransactionReceipt(txReceipt); @@ -90,7 +90,7 @@ const pendingResultSet = async ({ syncPromises, limit }) => { } catch (insertErr) { logger.error(`Error pendingResultSet: ${insertErr.message}`); } - })); + }, p)); }); } catch (err) { logger.error(`Error pendingResultSet findResultSet: ${err.message}`); diff --git a/src/sync/vote-placed.js b/src/sync/vote-placed.js index f8f38fa4..6ffa3d9b 100644 --- a/src/sync/vote-placed.js +++ b/src/sync/vote-placed.js @@ -21,10 +21,10 @@ const syncVotePlaced = async ({ startBlock, endBlock, syncPromises, limit }) => // Add to syncPromises array to be executed in parallel logger.info(`Found ${logs.length} VotePlaced`); each(logs, (log) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (logObj) => { try { // Parse and insert vote - const bet = parseBet({ log }); + const bet = parseBet({ log: logObj }); await DBHelper.insertBet(bet); // Fetch and insert tx receipt @@ -34,7 +34,7 @@ const syncVotePlaced = async ({ startBlock, endBlock, syncPromises, limit }) => logger.error('Error syncVotePlaced parse'); throw insertErr; } - })); + }, log)); }); } catch (err) { logger.error('Error syncVotePlaced'); @@ -52,9 +52,9 @@ const pendingVotePlaced = async ({ syncPromises, limit }) => { logger.info(`Checking ${pending.length} pending VotePlaced`); each(pending, (p) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (pendingVote) => { try { - const txReceipt = await getTransactionReceipt(p.txid); + const txReceipt = await getTransactionReceipt(pendingVote.txid); if (isNull(txReceipt)) return; await DBHelper.insertTransactionReceipt(txReceipt); @@ -83,7 +83,7 @@ const pendingVotePlaced = async ({ syncPromises, limit }) => { } catch (insertErr) { logger.error(`Error pendingVotePlaced: ${insertErr.message}`); } - })); + }, p)); }); } catch (err) { logger.error(`Error pendingVotePlaced findBet: ${err.message}`); diff --git a/src/sync/vote-result-set.js b/src/sync/vote-result-set.js index 8054c22c..545e362f 100644 --- a/src/sync/vote-result-set.js +++ b/src/sync/vote-result-set.js @@ -24,10 +24,10 @@ const syncVoteResultSet = async ( // Add to syncPromises array to be executed in parallel logger.info(`Found ${logs.length} VoteResultSet`); each(logs, (log) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (logObj) => { try { // Parse and insert vote result set - const resultSet = parseResultSet({ log }); + const resultSet = parseResultSet({ log: logObj }); await DBHelper.insertResultSet(resultSet); // Fetch and insert tx receipt @@ -40,7 +40,7 @@ const syncVoteResultSet = async ( logger.error('Error syncVoteResultSet parse'); throw insertErr; } - })); + }, log)); }); } catch (err) { logger.error('Error syncVoteResultSet'); @@ -58,9 +58,9 @@ const pendingVoteResultSet = async ({ syncPromises, limit }) => { logger.info(`Checking ${pending.length} pending VoteResultSet`); each(pending, (p) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (pendingSet) => { try { - const txReceipt = await getTransactionReceipt(p.txid); + const txReceipt = await getTransactionReceipt(pendingSet.txid); if (isNull(txReceipt)) return; await DBHelper.insertTransactionReceipt(txReceipt); @@ -92,7 +92,7 @@ const pendingVoteResultSet = async ({ syncPromises, limit }) => { } catch (insertErr) { logger.error(`Error pendingVoteResultSet: ${insertErr.message}`); } - })); + }, p)); }); } catch (err) { logger.error(`Error pendingVoteResultSet findResultSet: ${err.message}`); diff --git a/src/sync/winnings-withdrawn.js b/src/sync/winnings-withdrawn.js index 654918c8..46cee600 100644 --- a/src/sync/winnings-withdrawn.js +++ b/src/sync/winnings-withdrawn.js @@ -23,10 +23,10 @@ const syncWinningsWithdrawn = async ( // Add to syncPromises array to be executed in parallel logger.info(`Found ${logs.length} WinningsWithdrawn`); each(logs, (log) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (logObj) => { try { // Parse and insert withdraw - const withdraw = parseWithdraw({ log }); + const withdraw = parseWithdraw({ log: logObj }); await DBHelper.insertWithdraw(withdraw); // Add withdrawer into event withdrawnList @@ -39,7 +39,7 @@ const syncWinningsWithdrawn = async ( logger.error('Error syncWinningsWithdrawn parse'); throw insertErr; } - })); + }, log)); }); } catch (err) { logger.error('Error syncWinningsWithdrawn'); @@ -54,9 +54,9 @@ const pendingWinningsWithdrawn = async ({ syncPromises, limit }) => { logger.info(`Checking ${pending.length} pending WinningsWithdrawn`); each(pending, (p) => { - syncPromises.push(limit(async () => { + syncPromises.push(limit(async (pendingWithdraw) => { try { - const txReceipt = await getTransactionReceipt(p.txid); + const txReceipt = await getTransactionReceipt(pendingWithdraw.txid); if (isNull(txReceipt)) return; await DBHelper.insertTransactionReceipt(txReceipt); @@ -87,7 +87,7 @@ const pendingWinningsWithdrawn = async ({ syncPromises, limit }) => { } catch (insertErr) { logger.error(`Error pendingWinningsWithdrawn: ${insertErr.message}`); } - })); + }, p)); }); } catch (err) { logger.error(`Error pendingWinningsWithdrawn findWithdraw: ${err.message}`); diff --git a/test/api/config-manager.test.js b/test/api/config-manager.test.js new file mode 100644 index 00000000..a512c721 --- /dev/null +++ b/test/api/config-manager.test.js @@ -0,0 +1,103 @@ +const { isString, isNumber, isArray, isBoolean } = require('lodash'); +const Chai = require('chai'); +const sinon = require('sinon'); +const ChaiAsPromised = require('chai-as-promised'); + +const ConfigManager = require('../../src/api/config-manager'); +const { getContract } = require('./mock/contract'); + +Chai.use(ChaiAsPromised); +const assert = Chai.assert; +const expect = Chai.expect; + +const eventAddress = '0x8b2b1838efff78e5ed9e00d95d9ef071f2c27be6'; +const address = '0x939592864C0Bd3355B2D54e4fA2203E8343B6d6a'; + +describe('api/config-manager', () => { + let stubGetContract; + beforeEach(() => { + stubGetContract = sinon.stub(ConfigManager, 'getContract').callsFake(getContract); + }); + + afterEach(() => { + stubGetContract.restore(); + }); + + describe('bodhiTokenAddress()', () => { + it('It returns the bodhiTokenAddress', async () => { + const res = await ConfigManager.bodhiTokenAddress(); + assert.isDefined(res); + assert.isTrue(isString(res)); + }); + }); + + describe('eventFactoryAddress()', () => { + it('It returns the eventFactoryAddress', async () => { + const res = await ConfigManager.eventFactoryAddress(); + assert.isDefined(res); + assert.isTrue(isString(res)); + }); + }); + + describe('eventEscrowAmount()', () => { + it('It returns the eventEscrowAmount', async () => { + const res = await ConfigManager.eventEscrowAmount(); + assert.isDefined(res); + assert.isTrue(isString(res)); + assert.isFalse(isNaN(res)); + }); + }); + + describe('arbitrationLength()', () => { + it('It returns the arbitrationLength', async () => { + const res = await ConfigManager.arbitrationLength(); + assert.isDefined(res); + assert.isTrue(isArray(res)); + assert.isTrue(res.length === 4); + + assert.isTrue(isNumber(res[0])); + assert.isTrue(isNumber(res[1])); + assert.isTrue(isNumber(res[2])); + assert.isTrue(isNumber(res[3])); + }); + }); + + describe('startingConsensusThreshold()', () => { + it('It returns the startingConsensusThreshold', async () => { + const res = await ConfigManager.startingConsensusThreshold(); + assert.isDefined(res); + assert.isTrue(isArray(res)); + assert.isTrue(res.length === 4); + + assert.isTrue(isString(res[0])); + assert.isFalse(isNaN(res[0])); + assert.isTrue(isString(res[1])); + assert.isFalse(isNaN(res[1])); + assert.isTrue(isString(res[2])); + assert.isFalse(isNaN(res[2])); + assert.isTrue(isString(res[3])); + assert.isFalse(isNaN(res[3])); + }); + }); + + describe('thresholdPercentIncrease()', () => { + it('It returns the thresholdPercentIncrease', async () => { + const res = await ConfigManager.thresholdPercentIncrease(); + assert.isDefined(res); + assert.isTrue(isString(res)); + assert.isFalse(isNaN(res)); + }); + }); + + describe('isWhitelisted()', () => { + it('It returns the isWhitelisted', async () => { + const res = await ConfigManager.isWhitelisted({ address }); + assert.isDefined(res); + assert.isTrue(isBoolean(res)); + }); + + it('It throws if address is undefined', () => { + expect(ConfigManager.isWhitelisted()).to.be.rejectedWith(Error); + }); + }); +}); diff --git a/test/api/mock/contract.js b/test/api/mock/contract.js new file mode 100644 index 00000000..5e1c4a8d --- /dev/null +++ b/test/api/mock/contract.js @@ -0,0 +1,87 @@ +const sinon = require('sinon'); +const { map } = require('lodash'); +const web3 = require('../../../src/web3'); + +const results = ['Invalid', '1', 'y']; + +// stubs for multiple-results-event +const TOKEN_DECIMALS = 8; +const stubCalculateWinnings = sinon.stub().returns(() => '10200000000'); +const stubVersion = sinon.stub().returns(() => 6); +const stubCurrentRound = sinon.stub().returns(() => 0); +const stubCurrentResultIndex = sinon.stub().returns(() => 0); +const stubCurrentConsensusThreshold = sinon.stub().returns(() => 10); +const stubCurrentArbitrationEndTime = sinon.stub().returns(() => 17600); +const stubEventMetadata = sinon.stub().returns(() => [ + 6, + 'Test', + map(results, (item) => web3.utils.utf8ToHex(item)), + 3, +]); +const stubCentralizedMetadata = sinon.stub().returns(() => [ + '0xae017b8048d79a45867a15345d55912ee4ecaf7c', + 1560965704, + 1560965705, + 1560965705, + 1560965706, +]); +const stubConfigMetadata = sinon.stub().returns(() => [ + 10000000, + 17600, + 10, + 10, +]); +const stubTotalBets = sinon.stub().returns(() => '10200000000'); +const stubDidWithdraw = sinon.stub().returns(() => true); +const stubDidWithdrawEscrow = sinon.stub().returns(() => true); + +// stubs for config-manager +const stubBodhiTokenAddress = sinon.stub().returns(() => '0xae017b8048d79a45867a15345d55912ee4ecaf7c'); +const stubEventFactoryAddress = sinon.stub().returns(() => '0xae017b8048d79a45867a15345d55912ee4ecaf7c'); +const stubEventEscrowAmount = sinon.stub().returns(() => 10000000000); +const stubArbitrationLength = sinon.stub().returns(() => [ + 172800, // 48 hours + 86400, // 24 hours + 43200, // 12 hours + 21600 // 6 hours +]); +const stubStartingConsensusThreshold = sinon.stub().returns(() => [ + 100 * (10 ** TOKEN_DECIMALS), + 1000 * (10 ** TOKEN_DECIMALS), + 5000 * (10 ** TOKEN_DECIMALS), + 10000 * (10 ** TOKEN_DECIMALS) +]); +const stubThresholdPercentIncrease = sinon.stub().returns(() => 10); +const stubIsWhitelisted = sinon.stub().returns(() => true); + +const getContract = () => { + return { + methods: { + // multiple-results-event + calculateWinnings: stubCalculateWinnings, + version: stubVersion, + currentRound: stubCurrentRound, + currentResultIndex: stubCurrentResultIndex, + currentConsensusThreshold: stubCurrentConsensusThreshold, + currentArbitrationEndTime: stubCurrentArbitrationEndTime, + eventMetadata: stubEventMetadata, + centralizedMetadata: stubCentralizedMetadata, + configMetadata: stubConfigMetadata, + totalBets: stubTotalBets, + didWithdraw: stubDidWithdraw, + didWithdrawEscrow: stubDidWithdrawEscrow, + // config-manager + bodhiTokenAddress: stubBodhiTokenAddress, + eventFactoryAddress: stubEventFactoryAddress, + eventEscrowAmount: stubEventEscrowAmount, + arbitrationLength: stubArbitrationLength, + startingConsensusThreshold: stubStartingConsensusThreshold, + thresholdPercentIncrease: stubThresholdPercentIncrease, + isWhitelisted: stubIsWhitelisted, + } + } +}; + +module.exports = { + getContract, +}; diff --git a/test/api/multiple-results-event.test.js b/test/api/multiple-results-event.test.js new file mode 100644 index 00000000..cc6f3780 --- /dev/null +++ b/test/api/multiple-results-event.test.js @@ -0,0 +1,217 @@ +const { isString, isNumber, isArray, isBoolean } = require('lodash'); +const Chai = require('chai'); +const sinon = require('sinon'); +const ChaiAsPromised = require('chai-as-promised'); + +const Event = require('../../src/api/multiple-results-event'); +const { getContract } = require('./mock/contract'); + +Chai.use(ChaiAsPromised); +const assert = Chai.assert; +const expect = Chai.expect; + +const eventAddress = '0x8b2b1838efff78e5ed9e00d95d9ef071f2c27be6'; +const address = '0x939592864C0Bd3355B2D54e4fA2203E8343B6d6a'; + +describe('api/multiple-results-event', () => { + let stubGetContract; + beforeEach(() => { + stubGetContract = sinon.stub(Event, 'getContract').callsFake(getContract); + }); + + afterEach(() => { + stubGetContract.restore(); + }); + + describe('calculateWinnings()', () => { + it('It returns the calculateWinnings', async () => { + const res = await Event.calculateWinnings({ eventAddress, address }); + assert.isDefined(res); + assert.isTrue(isString(res)); + assert.isFalse(isNaN(res)); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.calculateWinnings({ + address, + })).to.be.rejectedWith(Error); + }); + + it('It throws if address is undefined', () => { + expect(Event.calculateWinnings({ + eventAddress, + })).to.be.rejectedWith(Error); + }); + }); + + describe('version()', () => { + it('It returns the version', async () => { + const res = await Event.version({ eventAddress }); + assert.isDefined(res); + assert.isTrue(isNumber(res)); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.version({})).to.be.rejectedWith(Error); + }); + }); + + describe('currentRound()', () => { + it('It returns the currentRound', async () => { + const res = await Event.currentRound({ eventAddress }); + assert.isDefined(res); + assert.isTrue(isNumber(res)); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.currentRound({})).to.be.rejectedWith(Error); + }); + }); + + describe('currentResultIndex()', () => { + it('It returns the currentResultIndex', async () => { + const res = await Event.currentResultIndex({ eventAddress }); + assert.isDefined(res); + assert.isTrue(isNumber(res)); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.currentResultIndex({})).to.be.rejectedWith(Error); + }); + }); + + describe('currentConsensusThreshold()', () => { + it('It returns the currentConsensusThreshold', async () => { + const res = await Event.currentConsensusThreshold({ eventAddress }); + assert.isDefined(res); + assert.isTrue(isString(res)); + assert.isFalse(isNaN(res)); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.currentConsensusThreshold({})).to.be.rejectedWith(Error); + }); + }); + + describe('currentArbitrationEndTime()', () => { + it('It returns the currentArbitrationEndTime', async () => { + const res = await Event.currentArbitrationEndTime({ eventAddress }); + assert.isDefined(res); + assert.isTrue(isString(res)); + assert.isFalse(isNaN(res)); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.currentArbitrationEndTime({})).to.be.rejectedWith(Error); + }); + }); + + describe('eventMetadata()', () => { + it('It returns the eventMetadata', async () => { + const res = await Event.eventMetadata({ eventAddress }); + assert.isDefined(res); + assert.isTrue(isArray(res)); + assert.isTrue(res.length === 4); + + assert.isTrue(isNumber(res[0])); + assert.isTrue(isString(res[1])); + assert.isTrue(isArray(res[2])); + assert.isTrue(isNumber(res[3])); + assert.isTrue(res[2].length === res[3]); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.eventMetadata({})).to.be.rejectedWith(Error); + }); + }); + + describe('centralizedMetadata()', () => { + it('It returns the centralizedMetadata', async () => { + const res = await Event.centralizedMetadata({ eventAddress }); + assert.isDefined(res); + assert.isTrue(isArray(res)); + assert.isTrue(res.length === 5); + + assert.isTrue(isString(res[0])); + assert.isTrue(isString(res[1])); + assert.isFalse(isNaN(res[1])); + assert.isTrue(isString(res[2])); + assert.isFalse(isNaN(res[2])); + assert.isTrue(isString(res[3])); + assert.isFalse(isNaN(res[3])); + assert.isTrue(isString(res[4])); + assert.isFalse(isNaN(res[4])); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.centralizedMetadata({})).to.be.rejectedWith(Error); + }); + }); + + describe('configMetadata()', () => { + it('It returns the configMetadata', async () => { + const res = await Event.configMetadata({ eventAddress }); + assert.isDefined(res); + assert.isTrue(isArray(res)); + assert.isTrue(res.length === 4); + + assert.isTrue(isString(res[0])); + assert.isFalse(isNaN(res[0])); + assert.isTrue(isString(res[1])); + assert.isFalse(isNaN(res[1])); + assert.isTrue(isString(res[2])); + assert.isFalse(isNaN(res[2])); + assert.isTrue(isString(res[3])); + assert.isFalse(isNaN(res[3])); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.configMetadata({})).to.be.rejectedWith(Error); + }); + }); + + describe('totalBets()', () => { + it('It returns the totalBets', async () => { + const res = await Event.totalBets({ eventAddress, address }); + assert.isDefined(res); + assert.isTrue(isString(res)); + assert.isFalse(isNaN(res)); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.totalBets({})).to.be.rejectedWith(Error); + }); + }); + + describe('didWithdraw()', () => { + it('It returns the didWithdraw', async () => { + const res = await Event.didWithdraw({ eventAddress, address }); + assert.isDefined(res); + assert.isTrue(isBoolean(res)); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.didWithdraw({ + address, + })).to.be.rejectedWith(Error); + }); + + it('It throws if address is undefined', () => { + expect(Event.didWithdraw({ + eventAddress, + })).to.be.rejectedWith(Error); + }); + }); + + describe('didWithdrawEscrow()', () => { + it('It returns the didWithdrawEscrow', async () => { + const res = await Event.didWithdrawEscrow({ eventAddress, address }); + assert.isDefined(res); + assert.isTrue(isBoolean(res)); + }); + + it('It throws if eventAddress is undefined', () => { + expect(Event.didWithdrawEscrow({})).to.be.rejectedWith(Error); + }); + }); +}); diff --git a/test/db/index.js b/test/db/index.js new file mode 100644 index 00000000..494e7203 --- /dev/null +++ b/test/db/index.js @@ -0,0 +1,1777 @@ +const chai = require('chai'); +const chaiExclude = require('chai-exclude'); +const cryptoRandomString = require('crypto-random-string'); + +chai.use(chaiExclude); +const should = chai.should(); +const { expect } = chai; +const fs = require('fs-extra'); +const { initDB, db } = require('../../src/db'); +const { getDbDir } = require('../../src/config'); +const DBHelper = require('../../src/db/db-helper'); +const { EVENT_STATUS, TX_STATUS } = require('../../src/constants'); + +function padHex(length) { + let hexString = cryptoRandomString({ length }); + hexString = `0x${hexString}`; + return hexString; +} + +describe('db', () => { + before(async () => { + await initDB(); + }); + + /* Blocks */ + describe('test block db', () => { + describe('find latest block', () => { + let blockCount; + it('should return empty with an empty db', async () => { + blockCount = await db.Blocks.count({}); + blockCount.should.equal(0); + const latestBlock = await DBHelper.findLatestBlock(); + latestBlock.length.should.equal(0); + }); + + it('should return the latest block with a non-empty db', async () => { + const latestBlockNum = 10000; + const latestBlockTime = Date.now(); + await DBHelper.insertBlock(latestBlockNum, latestBlockTime); + let latestBlock = await DBHelper.findLatestBlock(); + latestBlock[0].blockNum.should.equal(latestBlockNum); + latestBlock[0].blockTime.should.equal(latestBlockTime); + await DBHelper.insertBlock(latestBlockNum - 1000, latestBlockTime - 10000); + latestBlock = await DBHelper.findLatestBlock(); + latestBlock[0].blockNum.should.equal(latestBlockNum); + latestBlock[0].blockTime.should.equal(latestBlockTime); + }); + }); + + describe('insert', () => { + let blockCount; + let blocks; + const toBeInsertedBlockNum = 11111; + const toBeInsertedBlockTime = Date.now(); + + it('should insert with new block num', async () => { + blockCount = await db.Blocks.count({}); + blockCount.should.equal(2); + await DBHelper.insertBlock(toBeInsertedBlockNum, toBeInsertedBlockTime); + blockCount = await db.Blocks.count({}); + blockCount.should.equal(3); + blocks = await db.Blocks.find({ blockNum: toBeInsertedBlockNum }); + blocks[0].blockNum.should.equal(toBeInsertedBlockNum); + blocks[0].blockTime.should.equal(toBeInsertedBlockTime); + }); + + it('should not insert with existed block num', async () => { + const toBeInsertedFailBlockTime = Date.now(); + await DBHelper.insertBlock(toBeInsertedBlockNum, toBeInsertedFailBlockTime); + blockCount = await db.Blocks.count({}); + blockCount.should.equal(3); + blocks = await db.Blocks.find({ blockNum: toBeInsertedBlockNum }); + blocks[0].blockNum.should.equal(toBeInsertedBlockNum); + blocks[0].blockTime.should.equal(toBeInsertedBlockTime); + }); + }); + + describe('find block', () => { + const toBeInsertedBlockNum = 10001; + const toBeInsertedBlockTime = Date.now(); + it('finds the existing block by blockNum', async () => { + await DBHelper.insertBlock(toBeInsertedBlockNum, toBeInsertedBlockTime); + const block = await DBHelper.findOneBlock({ blockNum: toBeInsertedBlockNum }); + should.exist(block); + block.blockNum.should.equal(toBeInsertedBlockNum); + block.blockTime.should.equal(toBeInsertedBlockTime); + }); + + it('does not find the non-existing block by blockNum', async () => { + let block = await DBHelper.findOneBlock({ blockNum: -1 }); + should.not.exist(block); + block = await DBHelper.findOneBlock({ blockNum: 123456789 }); + should.not.exist(block); + }); + }); + }); + + + /* TransactionReceipts */ + describe('test transactionReceipts db', () => { + let txReceiptsCount; + let txReceipt; + const UnconfirmedTxReceipt = { + blockHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + blockNum: null, + transactionHash: '0x81fcd2aec9f2f45a96eea6deb858a76fecce619df091f62ec92ec3bce6181d18', + from: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + to: '0x809388c8770c578cb87df1d1e84e3436d8156fda', + cumulativeGasUsed: 500000, + gasUsed: 500000, + gasPrice: '47619047620', + }; + const confirmedTxReceipt = { + status: true, + blockHash: '0x67be035531840561747a4c1bf9aa32a31641367ae1270db74cc321c9eb78e82f', + blockNum: 4400858, + transactionHash: '0x81fcd2aec9f2f45a96eea6deb858a76fecce619df091f62ec92ec3bce6181d18', + from: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + to: '0x809388c8770c578cb87df1d1e84e3436d8156fda', + contractAddress: null, + cumulativeGasUsed: 207559, + gasUsed: 207559, + gasPrice: '30000000', + }; + + describe('insert', () => { + it('should start with empty transactionReceipts db', async () => { + txReceiptsCount = await db.TransactionReceipts.count({}); + txReceiptsCount.should.equal(0); + }); + + it('should insert with new transaction receipt', async () => { + await DBHelper.insertTransactionReceipt(UnconfirmedTxReceipt); + txReceipt = await db.TransactionReceipts.find({}); + txReceipt.length.should.equal(1); + expect(txReceipt[0]).excluding('_id').to.deep.equal(UnconfirmedTxReceipt); + }); + + it('should insert with existed transaction Hash', async () => { + await DBHelper.insertTransactionReceipt(confirmedTxReceipt); + txReceipt = await db.TransactionReceipts.find({}); + txReceipt.length.should.equal(1); + expect(txReceipt[0]).excluding(['_id', 'gasPrice']).to.deep.equal(confirmedTxReceipt); + txReceipt[0].gasPrice.should.equal(UnconfirmedTxReceipt.gasPrice); + }); + }); + + describe('find one transaction receipt', () => { + it('should find existing tx receipt by transactionHash', async () => { + txReceipt = await DBHelper.findOneTransactionReceipt({ transactionHash: confirmedTxReceipt.transactionHash }); + should.exist(txReceipt); + expect(txReceipt).excluding(['_id', 'gasPrice']).to.deep.equal(confirmedTxReceipt); + txReceipt.gasPrice.should.equal(UnconfirmedTxReceipt.gasPrice); + }); + + it('should not find non-existing tx receipt by transactionHash', async () => { + txReceipt = await DBHelper.findOneTransactionReceipt({ transactionHash: 123321 }); + should.not.exist(txReceipt); + }); + }); + + describe('update transaction receipt', () => { + it('should update existing tx receipt', async () => { + const toBeUpdatedExistedTxReceipt = { + status: true, + blockHash: '0x67b323ds35531840561747a4c1bf9aa32a31641367ae1270db74cc321c9eb78e82f', + blockNum: 143234534, + transactionHash: '0x81fcd2aec9f2f45a96eea6deb858a76fecce619df091f62ec92ec3bce6181d18', + from: '0x47ba776b3ed5230ffa7e', + to: '0x809388c8770c578cb873o2399436d8156fda', + contractAddress: '0x47ba776b3ed5230ffa7e', + cumulativeGasUsed: 234359, + gasUsed: 324432, + gasPrice: '60000000', + }; + await DBHelper.updateTransactionReceipt(toBeUpdatedExistedTxReceipt); + txReceipt = await DBHelper.findOneTransactionReceipt({ transactionHash: toBeUpdatedExistedTxReceipt.transactionHash }); + expect(txReceipt).excluding('_id').to.deep.equal(toBeUpdatedExistedTxReceipt); + }); + }); + + it('should fail update non-existed transaction Hash transaction receipt', async () => { + const toBeUpdatedExistedTxReceipt = { + status: true, + blockHash: '0x67b323ds35531840561747a4c1bf9aa32a31641367ae1270db74cc321c9eb78e82f', + blockNum: 143234534, + transactionHash: '0xe619df091f62ec92ec3bce6181d18', + from: '0x47ba776b3ed5230ffa7e', + to: '0x809388c8770c578cb873o2399436d8156fda', + contractAddress: '0x47ba776b3ed5230ffa7e', + cumulativeGasUsed: 234359, + gasUsed: 324432, + gasPrice: '60000000', + }; + await DBHelper.updateTransactionReceipt(toBeUpdatedExistedTxReceipt); + txReceipt = await DBHelper.findOneTransactionReceipt({ transactionHash: toBeUpdatedExistedTxReceipt.transactionHash }); + should.not.exist(txReceipt); + }); + }); + + /* Events */ + describe('test event db', () => { + const mockEvent = [ + { + txType: 'CREATE_EVENT', + txid: '0xa47a223155ee3f9e1d313735547e7ad3e299d20992c0524f6b9694984100f7b0', + txStatus: 'SUCCESS', + blockNum: 4242848, + address: '0x60f243ed4a99e3309ef67d9486b9db14334bc6d4', + ownerAddress: '0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428', + version: 6, + name: 'Test v6', + results: [ + 'Invalid', + '1', + '2', + ], + numOfResults: 3, + centralizedOracle: '0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428', + betStartTime: 1561082467, + betEndTime: 1561168846, + resultSetStartTime: 1561168846, + resultSetEndTime: 1561341646, + escrowAmount: '100000000', + arbitrationLength: 300, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 0, + currentResultIndex: 255, + consensusThreshold: '1000000000', + arbitrationEndTime: 0, + status: 'OPEN_RESULT_SETTING', + language: 'zh-Hans-CN', + }, + { + txType: 'CREATE_EVENT', + txid: '0xf0e68c3cfa4e77f0a5b46afd9f8c5efccd5d90f419053c6d452b021bc203c44f', + txStatus: 'SUCCESS', + blockNum: 3979339, + address: '0xfef4a675dba91b91608dc75c40deaca0333af514', + ownerAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + version: 5, + name: 'QQQ', + results: [ + 'Invalid', + '2', + '1', + ], + numOfResults: 3, + centralizedOracle: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + betStartTime: 1560292822, + betEndTime: 1560379222, + resultSetStartTime: 1560379222, + resultSetEndTime: 1560465622, + escrowAmount: '100000000', + arbitrationLength: 300, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 0, + currentResultIndex: 255, + consensusThreshold: '1000000000', + arbitrationEndTime: 0, + status: 'OPEN_RESULT_SETTING', + language: 'en-US', + }, + { + txType: 'CREATE_EVENT', + txid: '0x050497d3ed87c02246ba45ccd965f28e4194aace1167a25e46a2f6e29407d01c', + txStatus: 'SUCCESS', + blockNum: 3778535, + address: '0x80b35153213219ac3a3a3f28fe3cd3996518804a', + ownerAddress: '0x939592864c0bd3355b2d54e4fa2203e8343b6d6a', + version: 4, + name: 'test', + results: [ + 'Invalid', + '1', + '2', + ], + numOfResults: 3, + centralizedOracle: '0x939592864c0bd3355b2d54e4fa2203e8343b6d6a', + betStartTime: 1559689800, + betEndTime: 1559691600, + resultSetStartTime: 1559691600, + resultSetEndTime: 1559863179, + escrowAmount: '100000000', + arbitrationLength: 86400, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 0, + currentResultIndex: 255, + consensusThreshold: '10000000000', + arbitrationEndTime: 0, + status: 'OPEN_RESULT_SETTING', + language: 'zh-Hans-CN', + }, + ]; + let eventCount; + + describe('find event', () => { + it('should return existing events if passing sort', async () => { + await DBHelper.insertEvent(mockEvent[0]); + await DBHelper.insertEvent(mockEvent[1]); + eventCount = await db.Events.count({}); + eventCount.should.equal(2); + const foundEvents = await DBHelper.findEvent({}, { blockNum: -1 }); + foundEvents.length.should.equal(2); + expect(foundEvents[0]).excluding('_id').to.deep.equal(mockEvent[0]); + expect(foundEvents[1]).excluding('_id').to.deep.equal(mockEvent[1]); + }); + + it('should return empty find non-existing event if passing sort', async () => { + const foundEvents = await DBHelper.findEvent({ txid: '0x12344' }, { blockNum: -1 }); + foundEvents.length.should.equal(0); + }); + + it('should return existing events if not passing sort', async () => { + const foundEvents = await DBHelper.findEvent({ txid: mockEvent[0].txid }); + foundEvents.length.should.equal(1); + expect(foundEvents[0]).excluding('_id').to.deep.equal(mockEvent[0]); + }); + + it('should return empty find non-existing event if not passing sort', async () => { + const foundEvents = await DBHelper.findEvent({ txid: '0x12344' }); + foundEvents.length.should.equal(0); + }); + }); + + describe('find one event', () => { + it('find one existed event', async () => { + const foundEvent = await DBHelper.findOneEvent({ txid: mockEvent[0].txid }); + should.exist(foundEvent); + expect(foundEvent).excluding('_id').to.deep.equal(mockEvent[0]); + }); + + it('find one non-existed event', async () => { + const foundEvent = await DBHelper.findOneEvent({ txid: '0x12344' }); + should.not.exist(foundEvent); + }); + }); + + describe('insert Event', () => { + it('should insert new event', async () => { + eventCount = await db.Events.count({}); + eventCount.should.equal(2); + await DBHelper.insertEvent(mockEvent[2]); + eventCount = await db.Events.count({}); + eventCount.should.equal(3); + const event = await DBHelper.findOneEvent({ txid: mockEvent[2].txid }); + should.exist(event); + expect(event).excluding('_id').to.deep.equal(mockEvent[2]); + }); + + it('insert existed txid event', async () => { + const newEventWithExistedTxid = { + txType: 'CREATE_EVENT', + txid: '0x050497d3ed87c02246ba45ccd965f28e4194aace1167a25e46a2f6e29407d01c', + txStatus: 'FAIL', + blockNum: 3728535, + address: '0x939592432410bd335521454e4fa2203e8343b6d6a', + ownerAddress: '0x939592432410bd3355b2d54e4fa2203e8343b6d6a', + version: 5, + name: 'N', + results: [ + 'Invalid', + '12', + '2', + ], + numOfResults: 3, + centralizedOracle: '0x939592864c0b32d3355b2d15a2203e8343b6d6a', + betStartTime: 1559689700, + betEndTime: 1559692600, + resultSetStartTime: 1559692600, + resultSetEndTime: 1559864179, + escrowAmount: '110000000', + arbitrationLength: 86400, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 0, + currentResultIndex: 255, + consensusThreshold: '10000000000', + arbitrationEndTime: 0, + status: 'OPEN_RESULT_SETTING', + language: 'en-US', + }; + await DBHelper.insertEvent(newEventWithExistedTxid); + eventCount = await db.Events.count({}); + eventCount.should.equal(3); + const event = await DBHelper.findOneEvent({ txid: newEventWithExistedTxid.txid }); + should.exist(event); + expect(event).excluding(['_id', 'language']).to.deep.equal(newEventWithExistedTxid); + event.language.should.equal(mockEvent[2].language); + }); + }); + + describe('update event', () => { + it('update event by txid', async () => { + const updateNewEvent = { + txType: 'CREATE_EVENT', + txid: '0x050497d3ed87c02246ba45ccd965f28e4194aace1167a25e46a2f6e29407d01c', + txStatus: 'SUCCESS', + blockNum: 123442, + address: '0x0c97ba43149c1232920ef1e9d410316905c1ce8a', + ownerAddress: '0xea5854445251393b0e6f0a870799da15c003fc03', + version: 6, + name: 'N', + results: [ + 'Invalid', + '12', + '2', + ], + numOfResults: 3, + centralizedOracle: '0x939592864c0b32d3355b2d15a2203e8343b6d6a', + betStartTime: 1559689700, + betEndTime: 1559692600, + resultSetStartTime: 1559692600, + resultSetEndTime: 1559864179, + escrowAmount: '110000000', + arbitrationLength: 86400, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 0, + currentResultIndex: 255, + consensusThreshold: '10000000000', + arbitrationEndTime: 0, + status: 'OPEN_RESULT_SETTING', + language: 'en-US', + }; + let event = await DBHelper.findOneEvent({ txid: mockEvent[2].txid }); + expect(event).excluding(['_id']).to.deep.not.equal(updateNewEvent); + await DBHelper.updateEvent(mockEvent[2].txid, updateNewEvent); + eventCount = await db.Events.count({}); + eventCount.should.equal(3); + event = await DBHelper.findOneEvent({ txid: updateNewEvent.txid }); + should.exist(event); + expect(event).excluding(['_id']).to.deep.equal(updateNewEvent); + }); + + it('update event by address', async () => { + let event = await DBHelper.findOneEvent({ address: '0x0c97ba43149c1232920ef1e9d410316905c1ce8a' }); + expect(event).excluding(['_id']).to.deep.not.equal(mockEvent[2]); + await DBHelper.updateEventByAddress('0x0c97ba43149c1232920ef1e9d410316905c1ce8a', mockEvent[2]); + eventCount = await db.Events.count({}); + eventCount.should.equal(3); + event = await DBHelper.findOneEvent({ txid: mockEvent[2].txid }); + should.exist(event); + expect(event).excluding(['_id']).to.deep.equal(mockEvent[2]); + }); + }); + + describe('event status update', () => { + let event; + + describe('update event status to PRE_BETTING', () => { + const mockCreatedStatusEvent = { + txType: 'CREATE_EVENT', + txid: '0x1628812210d8e7d071ee343ece4d79c248191fdf76938cecd572158c475cb7f5', + txStatus: 'SUCCESS', + blockNum: 4404133, + address: '0x1c97ba43149c6eee920ef1e9d410316905c1ce8a', + ownerAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + version: 6, + name: 'TEST EVENT STATUS', + results: [ + 'Invalid', + '1', + '2', + ], + numOfResults: 3, + centralizedOracle: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + betStartTime: 1561585230, + betEndTime: 1561671614, + resultSetStartTime: 1561671714, + resultSetEndTime: 1561844414, + escrowAmount: '100000000', + arbitrationLength: 86400, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 0, + currentResultIndex: 255, + consensusThreshold: '10000000000', + arbitrationEndTime: 0, + status: 'CREATED', + language: 'en-US', + withdrawnList: [ + ], + }; + + it('should not update event status to PRE_BETTING if txStatus is FAIL', async () => { + const createdEvent = {}; + Object.assign(createdEvent, mockCreatedStatusEvent, { txStatus: TX_STATUS.FAIL, txid: padHex(64) }); + // FAIL tx doesn't have address + delete createdEvent.address; + + await DBHelper.insertEvent(createdEvent); + await DBHelper.updateEventStatusPreBetting(createdEvent.betStartTime - 1); + event = await DBHelper.findEvent({ txid: createdEvent.txid }); + event.length.should.equal(1); + event[0].txid.should.equal(createdEvent.txid); + event[0].status.should.equal(createdEvent.status); + }); + + it('should not update event status to PRE_BETTING if txStatus is PENDING', async () => { + const createdEvent = {}; + Object.assign(createdEvent, mockCreatedStatusEvent, { txStatus: TX_STATUS.PENDING, txid: padHex(64) }); + // PENDING tx doesn't have address + delete createdEvent.address; + await DBHelper.insertEvent(createdEvent); + await DBHelper.updateEventStatusPreBetting(createdEvent.betStartTime - 1); + event = await DBHelper.findEvent({ txid: createdEvent.txid }); + event.length.should.equal(1); + event[0].txid.should.equal(createdEvent.txid); + event[0].status.should.equal(createdEvent.status); + }); + + it('should not update event already in PRE_BETTING to PRE_BETTING', async () => { + const createdEvent = {}; + Object.assign(createdEvent, mockCreatedStatusEvent, { status: EVENT_STATUS.PRE_BETTING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(createdEvent); + await DBHelper.updateEventStatusPreBetting(createdEvent.betStartTime - 1); + event = await DBHelper.findEvent({ address: createdEvent.address }); + event.length.should.equal(1); + event[0].txid.should.equal(createdEvent.txid); + event[0].status.should.equal(createdEvent.status); + }); + + it('should update event status to PRE_BETTING if currBlockTime < betStartTime', async () => { + const createdEvent = {}; + Object.assign(createdEvent, mockCreatedStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(createdEvent); + await DBHelper.updateEventStatusPreBetting(createdEvent.betStartTime - 1); + event = await DBHelper.findEvent({ address: createdEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(createdEvent.address); + event[0].status.should.equal(EVENT_STATUS.PRE_BETTING); + }); + + it('should not update event status to PRE_BETTING if currBlockTime = betStartTime', async () => { + const createdEvent = {}; + Object.assign(createdEvent, mockCreatedStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(createdEvent); + await DBHelper.updateEventStatusPreBetting(createdEvent.betStartTime); + event = await DBHelper.findEvent({ address: createdEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(createdEvent.address); + event[0].status.should.equal(createdEvent.status); + }); + + it('should not update event status to PRE_BETTING if currentRound > 0', async () => { + const createdEvent = {}; + Object.assign(createdEvent, mockCreatedStatusEvent, { currentRound: 1, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(createdEvent); + await DBHelper.updateEventStatusPreBetting(createdEvent.betStartTime - 1); + event = await DBHelper.findEvent({ address: createdEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(createdEvent.address); + event[0].status.should.equal(createdEvent.status); + }); + }); + + // BETTING + describe('update event status to BETTING', () => { + const mockPreBettingStatusEvent = { + txType: 'CREATE_EVENT', + txid: '0x1628812210d8e7d071ee343ece4d79c248191fdf76938cecd572158c475cb7f5', + txStatus: 'SUCCESS', + blockNum: 4404133, + address: '0x1c97ba43149c6eee920ef1e9d410316905c1ce8a', + ownerAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + version: 6, + name: 'TEST EVENT STATUS', + results: [ + 'Invalid', + '1', + '2', + ], + numOfResults: 3, + centralizedOracle: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + betStartTime: 1561585230, + betEndTime: 1561671614, + resultSetStartTime: 1561671714, + resultSetEndTime: 1561844414, + escrowAmount: '100000000', + arbitrationLength: 86400, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 0, + currentResultIndex: 255, + consensusThreshold: '10000000000', + arbitrationEndTime: 0, + status: 'PRE_BETTING', + language: 'en-US', + withdrawnList: [ + ], + }; + + it('should not update event status to BETTING if txStatus is FAIL', async () => { + const preBetEvent = {}; + Object.assign(preBetEvent, mockPreBettingStatusEvent, { txStatus: TX_STATUS.FAIL, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preBetEvent); + await DBHelper.updateEventStatusBetting(preBetEvent.betStartTime); + event = await DBHelper.findEvent({ address: preBetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preBetEvent.address); + event[0].status.should.equal(preBetEvent.status); + }); + + it('should not update event status to BETTING if txStatus is PENDING', async () => { + const preBetEvent = {}; + Object.assign(preBetEvent, mockPreBettingStatusEvent, { txStatus: TX_STATUS.PENDING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preBetEvent); + await DBHelper.updateEventStatusBetting(preBetEvent.betStartTime); + event = await DBHelper.findEvent({ address: preBetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preBetEvent.address); + event[0].status.should.equal(preBetEvent.status); + }); + + it('should not update event status to BETTING if status is already BETTING', async () => { + const preBetEvent = {}; + Object.assign(preBetEvent, mockPreBettingStatusEvent, { status: EVENT_STATUS.BETTING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preBetEvent); + await DBHelper.updateEventStatusBetting(preBetEvent.betStartTime); + event = await DBHelper.findEvent({ address: preBetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preBetEvent.address); + event[0].status.should.equal(preBetEvent.status); + }); + + it('should not update event status to BETTING if currBlockTime < betStartTime', async () => { + const preBetEvent = {}; + Object.assign(preBetEvent, mockPreBettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preBetEvent); + await DBHelper.updateEventStatusBetting(preBetEvent.betStartTime - 1); + event = await DBHelper.findEvent({ address: preBetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preBetEvent.address); + event[0].status.should.equal(preBetEvent.status); + }); + + it('should update event status to BETTING if currBlockTime = betStartTime', async () => { + const preBetEvent = {}; + Object.assign(preBetEvent, mockPreBettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preBetEvent); + await DBHelper.updateEventStatusBetting(preBetEvent.betStartTime); + event = await DBHelper.findEvent({ address: preBetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preBetEvent.address); + event[0].status.should.equal(EVENT_STATUS.BETTING); + }); + + it('should update event status to BETTING if currBlockTime = betEndTime - 1', async () => { + const preBetEvent = {}; + Object.assign(preBetEvent, mockPreBettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preBetEvent); + await DBHelper.updateEventStatusBetting(preBetEvent.betEndTime - 1); + event = await DBHelper.findEvent({ address: preBetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preBetEvent.address); + event[0].status.should.equal(EVENT_STATUS.BETTING); + }); + + it('should not update event status to BETTING if currBlockTime = betEndTime', async () => { + const preBetEvent = {}; + Object.assign(preBetEvent, mockPreBettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preBetEvent); + await DBHelper.updateEventStatusBetting(preBetEvent.betEndTime); + event = await DBHelper.findEvent({ address: preBetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preBetEvent.address); + event[0].status.should.equal(preBetEvent.status); + }); + }); + + // PRE_RESULT_SETTING + describe('update event status to PRE_RESULT_SETTING', () => { + const mockBettingStatusEvent = { + txType: 'CREATE_EVENT', + txid: '0x1628812210d8e7d071ee343ece4d79c248191fdf76938cecd572158c475cb7f5', + txStatus: 'SUCCESS', + blockNum: 4404133, + address: '0x1c97ba43149c6eee920ef1e9d410316905c1ce8a', + ownerAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + version: 6, + name: 'TEST EVENT STATUS', + results: [ + 'Invalid', + '1', + '2', + ], + numOfResults: 3, + centralizedOracle: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + betStartTime: 1561585230, + betEndTime: 1561671614, + resultSetStartTime: 1561671714, + resultSetEndTime: 1561844414, + escrowAmount: '100000000', + arbitrationLength: 86400, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 0, + currentResultIndex: 255, + consensusThreshold: '10000000000', + arbitrationEndTime: 0, + status: 'BETTING', + language: 'en-US', + withdrawnList: [ + ], + }; + + it('should not update event status to PRE_RESULT_SETTING if txStatus is FAIL', async () => { + const betEvent = {}; + Object.assign(betEvent, mockBettingStatusEvent, { txStatus: TX_STATUS.FAIL, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(betEvent); + await DBHelper.updateEventStatusPreResultSetting(betEvent.betEndTime); + event = await DBHelper.findEvent({ address: betEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(betEvent.address); + event[0].status.should.equal(betEvent.status); + }); + + it('should not update event status to PRE_RESULT_SETTING if txStatus is PENDING', async () => { + const betEvent = {}; + Object.assign(betEvent, mockBettingStatusEvent, { txStatus: TX_STATUS.PENDING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(betEvent); + await DBHelper.updateEventStatusPreResultSetting(betEvent.betEndTime); + event = await DBHelper.findEvent({ address: betEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(betEvent.address); + event[0].status.should.equal(betEvent.status); + }); + + it('should not update event status to PRE_RESULT_SETTING if status is already PRE_RESULT_SETTING', async () => { + const betEvent = {}; + Object.assign(betEvent, mockBettingStatusEvent, { status: EVENT_STATUS.PRE_RESULT_SETTING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(betEvent); + await DBHelper.updateEventStatusPreResultSetting(betEvent.betEndTime); + event = await DBHelper.findEvent({ address: betEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(betEvent.address); + event[0].status.should.equal(betEvent.status); + }); + + it('should not update event status to PRE_RESULT_SETTING if currBlockTime < betEndTime', async () => { + const betEvent = {}; + Object.assign(betEvent, mockBettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(betEvent); + await DBHelper.updateEventStatusPreResultSetting(betEvent.betEndTime - 1); + event = await DBHelper.findEvent({ address: betEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(betEvent.address); + event[0].status.should.equal(betEvent.status); + }); + + it('should update event status to PRE_RESULT_SETTING if currBlockTime = betEndTime', async () => { + const betEvent = {}; + Object.assign(betEvent, mockBettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(betEvent); + await DBHelper.updateEventStatusPreResultSetting(betEvent.betEndTime); + event = await DBHelper.findEvent({ address: betEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(betEvent.address); + event[0].status.should.equal(EVENT_STATUS.PRE_RESULT_SETTING); + }); + + it('should update event status to PRE_RESULT_SETTING if currBlockTime = resultSetStartTime - 1', async () => { + const betEvent = {}; + Object.assign(betEvent, mockBettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(betEvent); + await DBHelper.updateEventStatusPreResultSetting(betEvent.resultSetStartTime - 1); + event = await DBHelper.findEvent({ address: betEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(betEvent.address); + event[0].status.should.equal(EVENT_STATUS.PRE_RESULT_SETTING); + }); + + it('should not update event status to PRE_RESULT_SETTING if currBlockTime = resultSetStartTime', async () => { + const betEvent = {}; + Object.assign(betEvent, mockBettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(betEvent); + await DBHelper.updateEventStatusPreResultSetting(betEvent.resultSetStartTime); + event = await DBHelper.findEvent({ address: betEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(betEvent.address); + event[0].status.should.equal(betEvent.status); + }); + + it('should not update event status to PRE_RESULT_SETTING if currentRound > 0', async () => { + const betEvent = {}; + Object.assign(betEvent, mockBettingStatusEvent, { currentRound: 1, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(betEvent); + await DBHelper.updateEventStatusPreResultSetting(betEvent.resultSetStartTime - 1); + event = await DBHelper.findEvent({ address: betEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(betEvent.address); + event[0].status.should.equal(betEvent.status); + }); + }); + + // ORACLE_RESULT_SETTING + describe('update event status to ORACLE_RESULT_SETTING', () => { + const mockPreResultSettingStatusEvent = { + txType: 'CREATE_EVENT', + txid: '0x1628812210d8e7d071ee343ece4d79c248191fdf76938cecd572158c475cb7f5', + txStatus: 'SUCCESS', + blockNum: 4404133, + address: '0x1c97ba43149c6eee920ef1e9d410316905c1ce8a', + ownerAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + version: 6, + name: 'TEST EVENT STATUS', + results: [ + 'Invalid', + '1', + '2', + ], + numOfResults: 3, + centralizedOracle: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + betStartTime: 1561585230, + betEndTime: 1561671614, + resultSetStartTime: 1561671714, + resultSetEndTime: 1561844414, + escrowAmount: '100000000', + arbitrationLength: 86400, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 0, + currentResultIndex: 255, + consensusThreshold: '10000000000', + arbitrationEndTime: 0, + status: 'PRE_RESULT_SETTING', + language: 'en-US', + withdrawnList: [ + ], + }; + + it('should not update event status to ORACLE_RESULT_SETTING if txStatus is FAIL', async () => { + const preResultSetEvent = {}; + Object.assign(preResultSetEvent, mockPreResultSettingStatusEvent, { txStatus: TX_STATUS.FAIL, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preResultSetEvent); + await DBHelper.updateEventStatusOracleResultSetting(preResultSetEvent.resultSetStartTime); + event = await DBHelper.findEvent({ address: preResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preResultSetEvent.address); + event[0].status.should.equal(preResultSetEvent.status); + }); + + it('should not update event status to ORACLE_RESULT_SETTING if txStatus is PENDING', async () => { + const preResultSetEvent = {}; + Object.assign(preResultSetEvent, mockPreResultSettingStatusEvent, { txStatus: TX_STATUS.PENDING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preResultSetEvent); + await DBHelper.updateEventStatusOracleResultSetting(preResultSetEvent.resultSetStartTime); + event = await DBHelper.findEvent({ address: preResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preResultSetEvent.address); + event[0].status.should.equal(preResultSetEvent.status); + }); + + it('should not update event status to ORACLE_RESULT_SETTING if status is already ORACLE_RESULT_SETTING', async () => { + const preResultSetEvent = {}; + Object.assign(preResultSetEvent, mockPreResultSettingStatusEvent, { status: EVENT_STATUS.ORACLE_RESULT_SETTING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preResultSetEvent); + await DBHelper.updateEventStatusOracleResultSetting(preResultSetEvent.resultSetStartTime); + event = await DBHelper.findEvent({ address: preResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preResultSetEvent.address); + event[0].status.should.equal(preResultSetEvent.status); + }); + + it('should not update event status to ORACLE_RESULT_SETTING if currBlockTime < resultSetStartTime', async () => { + const preResultSetEvent = {}; + Object.assign(preResultSetEvent, mockPreResultSettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preResultSetEvent); + await DBHelper.updateEventStatusOracleResultSetting(preResultSetEvent.resultSetStartTime - 1); + event = await DBHelper.findEvent({ address: preResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preResultSetEvent.address); + event[0].status.should.equal(preResultSetEvent.status); + }); + + it('should update event status to ORACLE_RESULT_SETTING if currBlockTime = resultSetStartTime', async () => { + const preResultSetEvent = {}; + Object.assign(preResultSetEvent, mockPreResultSettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preResultSetEvent); + await DBHelper.updateEventStatusOracleResultSetting(preResultSetEvent.resultSetStartTime); + event = await DBHelper.findEvent({ address: preResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preResultSetEvent.address); + event[0].status.should.equal(EVENT_STATUS.ORACLE_RESULT_SETTING); + }); + + it('should update event status to ORACLE_RESULT_SETTING if currBlockTime = resultSetEndTime - 1', async () => { + const preResultSetEvent = {}; + Object.assign(preResultSetEvent, mockPreResultSettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preResultSetEvent); + await DBHelper.updateEventStatusOracleResultSetting(preResultSetEvent.resultSetEndTime - 1); + event = await DBHelper.findEvent({ address: preResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preResultSetEvent.address); + event[0].status.should.equal(EVENT_STATUS.ORACLE_RESULT_SETTING); + }); + + it('should not update event status to ORACLE_RESULT_SETTING if currBlockTime = resultSetEndTime', async () => { + const preResultSetEvent = {}; + Object.assign(preResultSetEvent, mockPreResultSettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preResultSetEvent); + await DBHelper.updateEventStatusOracleResultSetting(preResultSetEvent.resultSetEndTime); + event = await DBHelper.findEvent({ address: preResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preResultSetEvent.address); + event[0].status.should.equal(preResultSetEvent.status); + }); + + it('should not update event status to ORACLE_RESULT_SETTING if currentRound > 0', async () => { + const preResultSetEvent = {}; + Object.assign(preResultSetEvent, mockPreResultSettingStatusEvent, { currentRound: 1, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(preResultSetEvent); + await DBHelper.updateEventStatusOracleResultSetting(preResultSetEvent.resultSetEndTime - 1); + event = await DBHelper.findEvent({ address: preResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(preResultSetEvent.address); + event[0].status.should.equal(preResultSetEvent.status); + }); + }); + + // OPEN_RESULT_SETTING + describe('update event status to OPEN_RESULT_SETTING', () => { + const mockOracleResultSettingStatusEvent = { + txType: 'CREATE_EVENT', + txid: '0x1628812210d8e7d071ee343ece4d79c248191fdf76938cecd572158c475cb7f5', + txStatus: 'SUCCESS', + blockNum: 4404133, + address: '0x1c97ba43149c6eee920ef1e9d410316905c1ce8a', + ownerAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + version: 6, + name: 'TEST EVENT STATUS', + results: [ + 'Invalid', + '1', + '2', + ], + numOfResults: 3, + centralizedOracle: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + betStartTime: 1561585230, + betEndTime: 1561671614, + resultSetStartTime: 1561671714, + resultSetEndTime: 1561844414, + escrowAmount: '100000000', + arbitrationLength: 86400, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 0, + currentResultIndex: 255, + consensusThreshold: '10000000000', + arbitrationEndTime: 0, + status: 'ORACLE_RESULT_SETTING', + language: 'en-US', + withdrawnList: [ + ], + }; + + it('should not update event status to OPEN_RESULT_SETTING if txStatus is FAIL', async () => { + const oracleResultSetEvent = {}; + Object.assign(oracleResultSetEvent, mockOracleResultSettingStatusEvent, { txStatus: TX_STATUS.FAIL, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(oracleResultSetEvent); + await DBHelper.updateEventStatusOpenResultSetting(oracleResultSetEvent.resultSetEndTime); + event = await DBHelper.findEvent({ address: oracleResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(oracleResultSetEvent.address); + event[0].status.should.equal(oracleResultSetEvent.status); + }); + + it('should not update event status to OPEN_RESULT_SETTING if txStatus is PENDING', async () => { + const oracleResultSetEvent = {}; + Object.assign(oracleResultSetEvent, mockOracleResultSettingStatusEvent, { txStatus: TX_STATUS.PENDING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(oracleResultSetEvent); + await DBHelper.updateEventStatusOpenResultSetting(oracleResultSetEvent.resultSetEndTime); + event = await DBHelper.findEvent({ address: oracleResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(oracleResultSetEvent.address); + event[0].status.should.equal(oracleResultSetEvent.status); + }); + + it('should not update event status to OPEN_RESULT_SETTING if status is already OPEN_RESULT_SETTING', async () => { + const oracleResultSetEvent = {}; + Object.assign(oracleResultSetEvent, mockOracleResultSettingStatusEvent, { status: EVENT_STATUS.OPEN_RESULT_SETTING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(oracleResultSetEvent); + await DBHelper.updateEventStatusOpenResultSetting(oracleResultSetEvent.resultSetEndTime); + event = await DBHelper.findEvent({ address: oracleResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(oracleResultSetEvent.address); + event[0].status.should.equal(oracleResultSetEvent.status); + }); + + it('should not update event status to OPEN_RESULT_SETTING if currBlockTime < resultSetEndTime', async () => { + const oracleResultSetEvent = {}; + Object.assign(oracleResultSetEvent, mockOracleResultSettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(oracleResultSetEvent); + await DBHelper.updateEventStatusOpenResultSetting(oracleResultSetEvent.resultSetEndTime - 1); + event = await DBHelper.findEvent({ address: oracleResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(oracleResultSetEvent.address); + event[0].status.should.equal(oracleResultSetEvent.status); + }); + + it('should update event status to OPEN_RESULT_SETTING if currBlockTime = resultSetEndTime', async () => { + const oracleResultSetEvent = {}; + Object.assign(oracleResultSetEvent, mockOracleResultSettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(oracleResultSetEvent); + await DBHelper.updateEventStatusOpenResultSetting(oracleResultSetEvent.resultSetEndTime); + event = await DBHelper.findEvent({ address: oracleResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(oracleResultSetEvent.address); + event[0].status.should.equal(EVENT_STATUS.OPEN_RESULT_SETTING); + }); + + it('should not update event status to OPEN_RESULT_SETTING if currentRound > 0', async () => { + const oracleResultSetEvent = {}; + Object.assign(oracleResultSetEvent, mockOracleResultSettingStatusEvent, { currentRound: 1, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(oracleResultSetEvent); + await DBHelper.updateEventStatusOpenResultSetting(oracleResultSetEvent.resultSetEndTime); + event = await DBHelper.findEvent({ address: oracleResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(oracleResultSetEvent.address); + event[0].status.should.equal(oracleResultSetEvent.status); + }); + }); + + // ARBITRATION + describe('update event status to ARBITRATION', () => { + const mockOpenResultSettingStatusEvent = { + txType: 'CREATE_EVENT', + txid: '0x2cb3d96ace9686a6f46cdab0c8e6a270e7658e3f50a2299e89b7f338b28032f8', + txStatus: 'SUCCESS', + blockNum: 3946349, + address: '0x39449d9fc354ebbdf85e92edbaa8eb4f93e3e782', + ownerAddress: '0x939592864c0bd3355b2d54e4fa2203e8343b6d6a', + version: 5, + name: 'zx', + results: [ + 'Invalid', + 'as', + 'qw', + ], + numOfResults: 3, + centralizedOracle: '0x939592864c0bd3355b2d54e4fa2203e8343b6d6a', + betStartTime: 1560193842, + betEndTime: 1560280242, + resultSetStartTime: 1560280242, + resultSetEndTime: 1560366642, + escrowAmount: '100000000', + arbitrationLength: 300, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 1, + currentResultIndex: 2, + consensusThreshold: '1100000000', + arbitrationEndTime: 1561679412, + status: 'OPEN_RESULT_SETTING', + language: 'zh-Hans-CN', + }; + + it('should not update event status to ARBITRATION if txStatus is FAIL', async () => { + const openResultSetEvent = {}; + Object.assign(openResultSetEvent, mockOpenResultSettingStatusEvent, { txStatus: TX_STATUS.FAIL, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(openResultSetEvent); + await DBHelper.updateEventStatusArbitration(openResultSetEvent.arbitrationEndTime - 1); + event = await DBHelper.findEvent({ address: openResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(openResultSetEvent.address); + event[0].status.should.equal(openResultSetEvent.status); + }); + + it('should not update event status to ARBITRATION if txStatus is PENDING', async () => { + const openResultSetEvent = {}; + Object.assign(openResultSetEvent, mockOpenResultSettingStatusEvent, { txStatus: TX_STATUS.PENDING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(openResultSetEvent); + await DBHelper.updateEventStatusArbitration(openResultSetEvent.arbitrationEndTime - 1); + event = await DBHelper.findEvent({ address: openResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(openResultSetEvent.address); + event[0].status.should.equal(openResultSetEvent.status); + }); + + it('should not update event status to ARBITRATION if status is already ARBITRATION', async () => { + const openResultSetEvent = {}; + Object.assign(openResultSetEvent, mockOpenResultSettingStatusEvent, { status: EVENT_STATUS.ARBITRATION, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(openResultSetEvent); + await DBHelper.updateEventStatusArbitration(openResultSetEvent.arbitrationEndTime - 1); + event = await DBHelper.findEvent({ address: openResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(openResultSetEvent.address); + event[0].status.should.equal(openResultSetEvent.status); + }); + + it('should update event status to ARBITRATION if currBlockTime < arbitrationEndTime', async () => { + const openResultSetEvent = {}; + Object.assign(openResultSetEvent, mockOpenResultSettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(openResultSetEvent); + await DBHelper.updateEventStatusArbitration(openResultSetEvent.arbitrationEndTime - 1); + event = await DBHelper.findEvent({ address: openResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(openResultSetEvent.address); + event[0].status.should.equal(EVENT_STATUS.ARBITRATION); + }); + + it('should not update event status to ARBITRATION if currBlockTime = arbitrationEndTime', async () => { + const openResultSetEvent = {}; + Object.assign(openResultSetEvent, mockOpenResultSettingStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(openResultSetEvent); + await DBHelper.updateEventStatusArbitration(openResultSetEvent.arbitrationEndTime); + event = await DBHelper.findEvent({ address: openResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(openResultSetEvent.address); + event[0].status.should.equal(openResultSetEvent.status); + }); + + it('should not update event status to ARBITRATION if currentRound = 0', async () => { + const openResultSetEvent = {}; + Object.assign(openResultSetEvent, mockOpenResultSettingStatusEvent, { currentRound: 0, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(openResultSetEvent); + await DBHelper.updateEventStatusArbitration(openResultSetEvent.arbitrationEndTime - 1); + event = await DBHelper.findEvent({ address: openResultSetEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(openResultSetEvent.address); + event[0].status.should.equal(openResultSetEvent.status); + }); + }); + + // WITHDRAWING + describe('update event status to WITHDRAWING', () => { + const mockArbitrationStatusEvent = { + txType: 'CREATE_EVENT', + txid: '0x2cb3d96ace9686a6f46cdab0c8e6a270e7658e3f50a2299e89b7f338b28032f8', + txStatus: 'SUCCESS', + blockNum: 3946349, + address: '0x39449d9fc354ebbdf85e92edbaa8eb4f93e3e782', + ownerAddress: '0x939592864c0bd3355b2d54e4fa2203e8343b6d6a', + version: 5, + name: 'zx', + results: [ + 'Invalid', + 'as', + 'qw', + ], + numOfResults: 3, + centralizedOracle: '0x939592864c0bd3355b2d54e4fa2203e8343b6d6a', + betStartTime: 1560193842, + betEndTime: 1560280242, + resultSetStartTime: 1560280242, + resultSetEndTime: 1560366642, + escrowAmount: '100000000', + arbitrationLength: 300, + thresholdPercentIncrease: '10', + arbitrationRewardPercentage: 10, + currentRound: 1, + currentResultIndex: 2, + consensusThreshold: '1100000000', + arbitrationEndTime: 1561679412, + status: 'OPEN_RESULT_SETTING', + language: 'zh-Hans-CN', + }; + + it('should not update event status to WITHDRAWING if txStatus is FAIL', async () => { + const arbitrationEvent = {}; + Object.assign(arbitrationEvent, mockArbitrationStatusEvent, { txStatus: TX_STATUS.FAIL, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(arbitrationEvent); + await DBHelper.updateEventStatusWithdrawing(arbitrationEvent.arbitrationEndTime); + event = await DBHelper.findEvent({ address: arbitrationEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(arbitrationEvent.address); + event[0].status.should.equal(arbitrationEvent.status); + }); + + it('should not update event status to WITHDRAWING if txStatus is PENDING', async () => { + const arbitrationEvent = {}; + Object.assign(arbitrationEvent, mockArbitrationStatusEvent, { txStatus: TX_STATUS.PENDING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(arbitrationEvent); + await DBHelper.updateEventStatusWithdrawing(arbitrationEvent.arbitrationEndTime); + event = await DBHelper.findEvent({ address: arbitrationEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(arbitrationEvent.address); + event[0].status.should.equal(arbitrationEvent.status); + }); + + it('should not update event status to WITHDRAWING if status is already WITHDRAWING', async () => { + const arbitrationEvent = {}; + Object.assign(arbitrationEvent, mockArbitrationStatusEvent, { status: EVENT_STATUS.WITHDRAWING, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(arbitrationEvent); + await DBHelper.updateEventStatusWithdrawing(arbitrationEvent.arbitrationEndTime); + event = await DBHelper.findEvent({ address: arbitrationEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(arbitrationEvent.address); + event[0].status.should.equal(arbitrationEvent.status); + }); + + it('should not update event status to WITHDRAWING if currBlockTime < arbitrationEndTime', async () => { + const arbitrationEvent = {}; + Object.assign(arbitrationEvent, mockArbitrationStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(arbitrationEvent); + await DBHelper.updateEventStatusWithdrawing(arbitrationEvent.arbitrationEndTime - 1); + event = await DBHelper.findEvent({ address: arbitrationEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(arbitrationEvent.address); + event[0].status.should.equal(arbitrationEvent.status); + }); + + it('should update event status to WITHDRAWING if currBlockTime = arbitrationEndTime', async () => { + const arbitrationEvent = {}; + Object.assign(arbitrationEvent, mockArbitrationStatusEvent, { address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(arbitrationEvent); + await DBHelper.updateEventStatusWithdrawing(arbitrationEvent.arbitrationEndTime); + event = await DBHelper.findEvent({ address: arbitrationEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(arbitrationEvent.address); + event[0].status.should.equal(EVENT_STATUS.WITHDRAWING); + }); + + it('should not update event status to WITHDRAWING if currentRound = 0', async () => { + const arbitrationEvent = {}; + Object.assign(arbitrationEvent, mockArbitrationStatusEvent, { currentRound: 0, address: padHex(40), txid: padHex(64) }); + await DBHelper.insertEvent(arbitrationEvent); + await DBHelper.updateEventStatusWithdrawing(arbitrationEvent.arbitrationEndTime - 1); + event = await DBHelper.findEvent({ address: arbitrationEvent.address }); + event.length.should.equal(1); + event[0].address.should.equal(arbitrationEvent.address); + event[0].status.should.equal(arbitrationEvent.status); + }); + }); + + describe('test event withdrawn list', () => { + const withdraw = { + eventAddress: '0xfef4a675dba91b91608dc75c40deaca0333af514', + winnerAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + }; + it('should update event withdrawnlist', async () => { + await DBHelper.updateEventWithdrawnList(withdraw); + event = await DBHelper.findOneEvent({ address: withdraw.eventAddress }); + event.withdrawnList[0].should.equal(withdraw.winnerAddress); + }); + it('does not add to withdrawnList if already on the list', async () => { + const old = await DBHelper.findOneEvent({ address: withdraw.eventAddress }); + await DBHelper.updateEventWithdrawnList(withdraw); + event = await DBHelper.findOneEvent({ address: withdraw.eventAddress }); + expect(event).excluding(['_id']).to.deep.equal(old); + }); + }); + }); + }); + + /* Bets */ + describe('test bets db', () => { + const mockBets = [ + { + txType: 'BET', + txid: '0x445ffdcfb4b3e30c3c8d73a7583230b60eff51054035389df7cf187f5d3f75b6', + txStatus: 'SUCCESS', + blockNum: 4154205, + eventAddress: '0xbeaa4358aa4434227c4545544e50c1b1a52a51c6', + betterAddress: '0x939592864c0bd3355b2d54e4fa2203e8343b6d6a', + resultIndex: 2, + amount: '1100000000', + eventRound: 0, + }, + { + txType: 'BET', + txid: '0xe314e29163785d1361880588f252c039016943bf4de494b7ae0869fc9897fe13', + txStatus: 'SUCCESS', + blockNum: 3810125, + eventAddress: '0xbbdfec793ef800769898795f469fc3951dc21eea', + betterAddress: '0x7937a1e86f2cb43d6c91d27ca7a4f93c7f7189c3', + resultIndex: 1, + amount: '10000000', + eventRound: 0, + }, + { + txType: 'BET', + txid: '0xccd0af2cb0299880101ff6558c3000a719e485677a9792bc24c4366ac78d1bf4', + txStatus: 'FAIL', + blockNum: null, + eventAddress: '0xeaf92b5aabe6028fdbe5889a6705fbc0e2e2da8d', + betterAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + resultIndex: 1, + amount: '300000000', + eventRound: 0, + }, + ]; + let bet; + let betCount; + + describe('find bet', () => { + it('should return empty when find in empty bets db', async () => { + betCount = await db.Bets.count({}); + betCount.should.equal(0); + bet = await DBHelper.findBet({}); + bet.length.should.equal(0); + }); + + it('should return existing bets if passing sort', async () => { + await DBHelper.insertBet(mockBets[0]); + await DBHelper.insertBet(mockBets[1]); + const foundBets = await DBHelper.findBet({}, { blockNum: -1 }); + foundBets.length.should.equal(2); + expect(foundBets[0]).excluding('_id').to.deep.equal(mockBets[0]); + expect(foundBets[1]).excluding('_id').to.deep.equal(mockBets[1]); + }); + + it('should return existing bets if not passing sort', async () => { + const foundBets = await DBHelper.findBet({ txid: mockBets[0].txid }); + foundBets.length.should.equal(1); + expect(foundBets[0]).excluding('_id').to.deep.equal(mockBets[0]); + }); + }); + + describe('find one bet', () => { + it('find existed bet', async () => { + bet = await DBHelper.findOneBet({ txid: mockBets[0].txid }); + should.exist(bet); + expect(bet).excluding('_id').to.deep.equal(mockBets[0]); + }); + + it('should return null when find non-existing bet', async () => { + bet = await DBHelper.findOneBet({ txid: '0x12333' }); + should.not.exist(bet); + }); + }); + + describe('count bet', () => { + it('bet counts should right', async () => { + betCount = await DBHelper.countBet({}); + betCount.should.equal(2); + }); + }); + + describe('insert bet', () => { + it('should insert new bet', async () => { + betCount = await db.Bets.count({}); + betCount.should.equal(2); + await DBHelper.insertBet(mockBets[2]); + betCount = await db.Bets.count({}); + betCount.should.equal(3); + bet = await DBHelper.findOneBet({ txid: mockBets[2].txid }); + should.exist(bet); + expect(bet).excluding('_id').to.deep.equal(mockBets[2]); + }); + + it('should not insert existing txid bet', async () => { + const newBetWithExistedTxid = { + txType: 'BET', + txid: '0xccd0af2cb0299880101ff6558c3000a719e485677a9792bc24c4366ac78d1bf4', + txStatus: 'SUCCESS', + blockNum: 1233242, + eventAddress: '0xeaf92b5aabe6028fdbe5889a6705f322e2da8d', + betterAddress: '0x47ba776b3ed5d5325345fee72fa483baffa7e', + resultIndex: 1, + amount: '300000000', + eventRound: 0, + }; + betCount = await db.Bets.count({}); + betCount.should.equal(3); + await DBHelper.insertBet(newBetWithExistedTxid); + betCount = await db.Bets.count({}); + betCount.should.equal(3); + bet = await DBHelper.findOneBet({ txid: newBetWithExistedTxid.txid }); + should.exist(bet); + expect(bet).excluding(['_id']).to.deep.equal(newBetWithExistedTxid); + }); + }); + + describe('update bet', () => { + it('should update bet when txid exists', async () => { + const updateNewBet = { + txType: 'BET', + txid: '0xccd0af2cb0299880101ff6558c3000a719e485677a9792bc24c4366ac78d1bf4', + txStatus: 'FAIL', + blockNum: null, + eventAddress: '0xeaf92b5aabe6028fdbe5889a6705fbc0e2e2da8d', + betterAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + resultIndex: 1, + amount: '300000000', + eventRound: 0, + }; + bet = await DBHelper.findOneBet({ txid: mockBets[2].txid }); + expect(bet).excluding(['_id']).to.deep.not.equal(updateNewBet); + await DBHelper.updateBet(mockBets[2].txid, updateNewBet); + betCount = await db.Bets.count({}); + betCount.should.equal(3); + bet = await DBHelper.findOneBet({ txid: updateNewBet.txid }); + should.exist(bet); + expect(bet).excluding(['_id']).to.deep.equal(updateNewBet); + }); + + it('should not update bet when txid not exists', async () => { + const updateNewBet = { + txType: 'BET', + txid: '0xccd0af2cb0299880101ff0abfc3000a719e485677a9792bc24c4366ac78d1bf4', + txStatus: 'FAIL', + blockNum: null, + eventAddress: '0xeaf92b5aabe6028fdbe5889a6705fbc0e2e2da8d', + betterAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + resultIndex: 1, + amount: '300000000', + eventRound: 0, + }; + betCount = await db.Bets.count({}); + betCount.should.equal(3); + await DBHelper.updateBet(updateNewBet.txid, updateNewBet); + betCount = await db.Bets.count({}); + betCount.should.equal(3); + bet = await DBHelper.findOneBet({ txid: updateNewBet.txid }); + should.not.exist(bet); + }); + }); + }); + + /* ResultSets */ + describe('test ResultSets db', () => { + const mockResultSets = [ + { + txType: 'RESULT_SET', + txid: '0xd3594c878efb45d8d38bd4c2e0698541b21d565914f71fe85e9033612d81fab0', + txStatus: 'SUCCESS', + blockNum: 4151388, + eventAddress: '0x72dd97e774f27b61bf58669be4dbabf9c3d349a4', + centralizedOracleAddress: '0x939592864c0bd3355b2d54e4fa2203e8343b6d6a', + resultIndex: 2, + amount: '1000000000', + eventRound: 0, + nextConsensusThreshold: '1100000000', + nextArbitrationEndTime: 1560808386, + }, + { + txType: 'RESULT_SET', + txid: '0xb296dd8bb6509f4fefe746f47c3d497d5f553c72d0b1fd2f8c000ae39e3ffd7f', + txStatus: 'SUCCESS', + blockNum: 3779203, + eventAddress: '0x069278634f2d9fcae31755596a88b53568fb7c76', + centralizedOracleAddress: null, + resultIndex: 1, + amount: '12100000000', + eventRound: 2, + nextConsensusThreshold: '13310000000', + nextArbitrationEndTime: 1559777920, + }, + { + txType: 'RESULT_SET', + txid: '0x913bb4c524f96e94cefa1bceb320b4c62945a1a76acfd51750c739455c4b94a8', + txStatus: 'SUCCESS', + blockNum: 4950806, + eventAddress: '0xcd4a3e87c45f701f2d3070372506b49f6d0d2c85', + centralizedOracleAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + resultIndex: 2, + amount: '1000000000', + eventRound: 0, + nextConsensusThreshold: '1100000000', + nextArbitrationEndTime: 1560206636, + }, + { + txType: 'RESULT_SET', + txid: '0x61e87de9febbbee5a6ed8aea010a59c18ad917962fed0060e44c97d1a51c7e7c', + txStatus: 'SUCCESS', + blockNum: 4835039, + eventAddress: '0x405c53142452e96e9c8cfcfd81d7db8326b8c6ce', + centralizedOracleAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + resultIndex: 2, + amount: '10000000000', + eventRound: 0, + nextConsensusThreshold: '11000000000', + nextArbitrationEndTime: 1559945430, + }, + ]; + let resultSet; + let resultSetCount; + + describe('find result set', () => { + it('find empty resultSets db', async () => { + resultSetCount = await db.ResultSets.count({}); + resultSetCount.should.equal(0); + resultSetCount = await DBHelper.findResultSet({}); + resultSetCount.length.should.equal(0); + }); + + it('should return existing resultSets if passing sort', async () => { + await DBHelper.insertResultSet(mockResultSets[0]); + await DBHelper.insertResultSet(mockResultSets[1]); + const foundResultSets = await DBHelper.findResultSet({}, { blockNum: -1 }); + foundResultSets.length.should.equal(2); + expect(foundResultSets[0]).excluding('_id').to.deep.equal(mockResultSets[0]); + expect(foundResultSets[1]).excluding('_id').to.deep.equal(mockResultSets[1]); + }); + + it('should return existing resultSets if not passing sort', async () => { + const foundResultSets = await DBHelper.findResultSet({ txid: mockResultSets[0].txid }); + foundResultSets.length.should.equal(1); + expect(foundResultSets[0]).excluding('_id').to.deep.equal(mockResultSets[0]); + }); + }); + + describe('find one result set', () => { + it('find existing result set', async () => { + resultSet = await DBHelper.findOneResultSet({ txid: mockResultSets[0].txid }); + should.exist(resultSet); + expect(resultSet).excluding('_id').to.deep.equal(mockResultSets[0]); + }); + + it('should not find on non-existing result set', async () => { + resultSet = await DBHelper.findOneResultSet({ txid: '0x12333' }); + should.not.exist(resultSet); + }); + }); + + describe('find latest result set', () => { + it('should find latest result set', async () => { + resultSet = await DBHelper.findLatestResultSet(); + resultSet.length.should.equal(1); + expect(resultSet[0]).excluding('_id').to.deep.equal(mockResultSets[0]); + await DBHelper.insertResultSet(mockResultSets[2]); + resultSet = await DBHelper.findLatestResultSet(); + resultSet.length.should.equal(1); + expect(resultSet[0]).excluding('_id').to.deep.equal(mockResultSets[2]); + }); + }); + + describe('count result set', () => { + it('result set counts should right', async () => { + resultSetCount = await DBHelper.countResultSet({}); + resultSetCount.should.equal(3); + }); + }); + + describe('insert result set', () => { + it('should insert new result set', async () => { + resultSetCount = await db.ResultSets.count({}); + resultSetCount.should.equal(3); + await DBHelper.insertResultSet(mockResultSets[3]); + resultSetCount = await db.ResultSets.count({}); + resultSetCount.should.equal(4); + resultSet = await DBHelper.findOneResultSet({ txid: mockResultSets[3].txid }); + should.exist(resultSet); + expect(resultSet).excluding('_id').to.deep.equal(mockResultSets[3]); + }); + + it('should not insert exisiting txid result set', async () => { + const newResultSetWithExistedTxid = { + txType: 'RESULT_SET', + txid: '0x61e87de9febbbee5a6ed8aea010a59c18ad917962fed0060e44c97d1a51c7e7c', + txStatus: 'FAIL', + blockNum: 3835039, + eventAddress: '0x405c53142452e96e9c8cfcfd81d7db8326b8c6ce', + centralizedOracleAddress: '0x47ba776b32323514d3e206ffee72fa483baffa7e', + resultIndex: 1, + amount: '1000230000000', + eventRound: 0, + nextConsensusThreshold: '11000000000', + nextArbitrationEndTime: 1559945430, + }; + await DBHelper.insertResultSet(newResultSetWithExistedTxid); + resultSetCount = await db.ResultSets.count({}); + resultSetCount.should.equal(4); + resultSet = await DBHelper.findOneResultSet({ txid: newResultSetWithExistedTxid.txid }); + should.exist(resultSet); + expect(resultSet).excluding(['_id']).to.deep.equal(newResultSetWithExistedTxid); + }); + }); + + describe('update result set', () => { + it('should update result set when txid exists', async () => { + const updateNewResultSet = { + txType: 'RESULT_SET', + txid: '0x61e87de9febbbee5a6ed8aea010a59c18ad917962fed0060e44c97d1a51c7e7c', + txStatus: 'SUCCESS', + blockNum: 2324243, + eventAddress: '0x405c53142452e96e9c8cfcfd81d7db8326b8c6ce', + centralizedOracleAddress: '0x8732763715473274928', + resultIndex: 0, + amount: '10000000000', + eventRound: 0, + nextConsensusThreshold: '11000000000', + nextArbitrationEndTime: 1559945430, + }; + resultSet = await DBHelper.findOneResultSet({ txid: mockResultSets[3].txid }); + expect(resultSet).excluding(['_id']).to.deep.not.equal(updateNewResultSet); + await DBHelper.updateResultSet(mockResultSets[3].txid, updateNewResultSet); + resultSetCount = await db.ResultSets.count({}); + resultSetCount.should.equal(4); + resultSet = await DBHelper.findOneResultSet({ txid: updateNewResultSet.txid }); + should.exist(resultSet); + expect(resultSet).excluding(['_id']).to.deep.equal(updateNewResultSet); + }); + + it('should not update result set when txid not exists', async () => { + const updateNewResultSet = { + txType: 'RESULT_SET', + txid: '0x61e87de9febbbee123458aea010a59c18ad917962fed0060e44c97d1a51c7e7c', + txStatus: 'SUCCESS', + blockNum: 2324243, + eventAddress: '0x405c53142452e96e9c8cfcfd81d7db8326b8c6ce', + centralizedOracleAddress: '0x8732763715473274928', + resultIndex: 0, + amount: '10000000000', + eventRound: 0, + nextConsensusThreshold: '11000000000', + nextArbitrationEndTime: 1559945430, + }; + resultSetCount = await db.ResultSets.count({}); + resultSetCount.should.equal(4); + await DBHelper.updateResultSet(updateNewResultSet.txid, updateNewResultSet); + resultSetCount = await db.ResultSets.count({}); + resultSetCount.should.equal(4); + resultSet = await DBHelper.findOneResultSet({ txid: updateNewResultSet.txid }); + should.not.exist(resultSet); + }); + }); + }); + + /* Withdraws */ + describe('test Withdraws db', () => { + const mockWithdraws = [ + { + txType: 'WITHDRAW', + txid: '0xa941da0b9d465ec5a394dbfe73032e25181e6f9eb5452e8313899a9f6b05e128', + txStatus: 'SUCCESS', + blockNum: 4153179, + eventAddress: '0x97c4810cbec1c767110f8aaaa6e1d400768f598c', + winnerAddress: '0x939592864c0bd3355b2d54e4fa2203e8343b6d6a', + winningAmount: '3310000000', + escrowWithdrawAmount: '100000000', + }, + { + txType: 'WITHDRAW', + txid: '0x46c8a1608bf4fe59295c50d50efbbc3ea47eff7d4d4079fb82165d7907b96d87', + txStatus: 'SUCCESS', + blockNum: 4185772, + eventAddress: '0x9376770714fe52bd43d7dab70bb7eec5773079f1', + winnerAddress: '0x939592864c0bd3355b2d54e4fa2203e8343b6d6a', + winningAmount: '46910000000', + escrowWithdrawAmount: '0', + }, + { + txType: 'WITHDRAW', + txid: '0x0b120d7a5417da6be968f24542d8f0b105228ee1c2d5e1aebd02c412c1b46950', + txStatus: 'SUCCESS', + blockNum: 4147411, + eventAddress: '0x3d18e57929f42fb58ddc242ca4a2904f5cf834a3', + winnerAddress: '0x47ba776b3ed5d514d3e206ffee72fa483baffa7e', + winningAmount: '21000000000', + escrowWithdrawAmount: '0', + }, + ]; + let withdraw; + let withdrawCount; + + describe('find withdraw', () => { + it('find empty withdraw db', async () => { + withdrawCount = await db.Withdraws.count({}); + withdrawCount.should.equal(0); + withdraw = await DBHelper.findWithdraw({}); + withdraw.length.should.equal(0); + }); + + it('should return existing withdraws if passing sort', async () => { + await DBHelper.insertWithdraw(mockWithdraws[0]); + await DBHelper.insertWithdraw(mockWithdraws[1]); + const foundWithdraws = await DBHelper.findWithdraw({}, { blockNum: -1 }); + foundWithdraws.length.should.equal(2); + expect(foundWithdraws[0]).excluding('_id').to.deep.equal(mockWithdraws[1]); + expect(foundWithdraws[1]).excluding('_id').to.deep.equal(mockWithdraws[0]); + }); + + it('should return existing withdraws if not passing sort', async () => { + const foundWithdraws = await DBHelper.findWithdraw({ txid: mockWithdraws[0].txid }); + foundWithdraws.length.should.equal(1); + expect(foundWithdraws[0]).excluding('_id').to.deep.equal(mockWithdraws[0]); + }); + }); + + describe('find one withdraw', () => { + it('find existed withdraw', async () => { + withdraw = await DBHelper.findOneWithdraw({ txid: mockWithdraws[0].txid }); + should.exist(withdraw); + expect(withdraw).excluding('_id').to.deep.equal(mockWithdraws[0]); + }); + + it('should find null when txid is not existed', async () => { + withdraw = await DBHelper.findOneWithdraw({ txid: '0x12333' }); + should.not.exist(withdraw); + }); + }); + + describe('count withdraw', () => { + it('withdraw counts should right', async () => { + withdrawCount = await DBHelper.countWithdraw({}); + withdrawCount.should.equal(2); + }); + }); + + describe('insert withdraw', () => { + it('should insert new withdraw', async () => { + withdrawCount = await db.Withdraws.count({}); + withdrawCount.should.equal(2); + await DBHelper.insertWithdraw(mockWithdraws[2]); + withdrawCount = await db.Withdraws.count({}); + withdrawCount.should.equal(3); + withdraw = await DBHelper.findOneWithdraw({ txid: mockWithdraws[2].txid }); + should.exist(withdraw); + expect(withdraw).excluding('_id').to.deep.equal(mockWithdraws[2]); + }); + + it('should not insert existed txid withdraw', async () => { + const newWithdrawWithExistedTxid = { + txType: 'WITHDRAW', + txid: '0x0b120d7a5417da6be968f24542d8f0b105228ee1c2d5e1aebd02c412c1b46950', + txStatus: 'SUCCESS', + blockNum: 435611, + eventAddress: '0x3d18e53519f42fb58ddc242ca4a2904f5cf834a3', + winnerAddress: '0x47ba77123ed5d514d3e206ffee72fa483baffa7e', + winningAmount: '21000000000', + escrowWithdrawAmount: '0', + }; + withdrawCount = await db.Withdraws.count({}); + withdrawCount.should.equal(3); + await DBHelper.insertWithdraw(newWithdrawWithExistedTxid); + withdrawCount = await db.Withdraws.count({}); + withdrawCount.should.equal(3); + withdraw = await DBHelper.findOneWithdraw({ txid: newWithdrawWithExistedTxid.txid }); + should.exist(withdraw); + expect(withdraw).excluding(['_id']).to.deep.equal(newWithdrawWithExistedTxid); + }); + }); + + describe('update withdraw', () => { + it('should update withdraw when txid is existed', async () => { + const updateNewWithdraw = { + txType: 'WITHDRAW', + txid: '0x00000d7a5417da6be968f24542d8f0b105228ee1c2d5e1aebd02c412c1b46950', + txStatus: 'SUCCESS', + blockNum: 4147411, + eventAddress: '0x3d18e57929f42fb58ddc242ca4a2904f5cf834a3', + winnerAddress: '0x47ba776b35555514d3e206ffee72fa483baffa7e', + winningAmount: '21000000000', + escrowWithdrawAmount: '0', + }; + withdraw = await DBHelper.findOneWithdraw({ txid: mockWithdraws[2].txid }); + expect(withdraw).excluding(['_id']).to.deep.not.equal(updateNewWithdraw); + await DBHelper.updateWithdraw(mockWithdraws[2].txid, updateNewWithdraw); + withdrawCount = await db.Withdraws.count({}); + withdrawCount.should.equal(3); + withdraw = await DBHelper.findOneWithdraw({ txid: updateNewWithdraw.txid }); + should.exist(withdraw); + expect(withdraw).excluding(['_id']).to.deep.equal(updateNewWithdraw); + }); + + it('should not update withdraw when txid is not existed', async () => { + const updateNewWithdraw = { + txType: 'WITHDRAW', + txid: '0x00000d7a5417da6be123424542d8f0b105228ee1c2d5e1aebd02c412c1b46950', + txStatus: 'SUCCESS', + blockNum: 4147411, + eventAddress: '0x3d18e57929f42fb58ddc242ca4a2904f5cf834a3', + winnerAddress: '0x47ba776b35555514d3e206ffee72fa483baffa7e', + winningAmount: '21000000000', + escrowWithdrawAmount: '0', + }; + withdrawCount = await db.Withdraws.count({}); + withdrawCount.should.equal(3); + await DBHelper.updateWithdraw(updateNewWithdraw.txid, updateNewWithdraw); + withdrawCount = await db.Withdraws.count({}); + withdrawCount.should.equal(3); + withdraw = await DBHelper.findOneWithdraw({ txid: updateNewWithdraw.txid }); + should.not.exist(withdraw); + }); + }); + }); + + after(async () => { + fs.removeSync(getDbDir()); + }); +}); diff --git a/test/graphql/mutations.tests.js b/test/graphql/mutations.tests.js new file mode 100644 index 00000000..cc9a8daa --- /dev/null +++ b/test/graphql/mutations.tests.js @@ -0,0 +1,2249 @@ +const EasyGraphQLTester = require('easygraphql-tester'); +const { + MULTIPLE_RESULTS_EVENT, + PAGINATED_EVENTS, + PAGINATED_BETS, + PAGINATED_RESULT_SETS, + PAGINATED_WITHDRAWS, + BET, + RESULT_SET, + WITHDRAW, +} = require('./schema-helper'); +const schema = require('../../src/graphql/schema'); + +const tester = new EasyGraphQLTester(schema); + +describe('graphql/mutations', () => { + describe('add-pending-event', () => { + it('It passes all arguments', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(true, valid, {}); + }); + + it('It should fail if txid missed', async () => { + const valid = ` + mutation { + addPendingEvent( + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if ownerAddress missed', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if name missed', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if results missed', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if numOfResults missed', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if centralizedOracle missed', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if betEndTime missed', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultSetStartTime missed', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if language missed', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is null', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: null + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is number', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: 1 + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is array', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is an object', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: {id: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if ownerAddress is null', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: null + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if ownerAddress is number', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: 1 + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if ownerAddress is array', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if ownerAddress is object', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: {id: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if name is null', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: null + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if name is number', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: 1 + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if name is array', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: ["a"] + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if name is object', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: {id: "a"} + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if results is null', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: null + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if results is number array', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: [1, 2] + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if results is object', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: {id: "1"} + numOfResults: 2 + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if numOfResults is null', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: null + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if numOfResults is string', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: "2" + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if numOfResults is array', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: ["2"] + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if numOfResults is object', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: {id: "2"} + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if centralizedOracle is null', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: null + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if centralizedOracle is number', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: 1 + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if centralizedOracle is array', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if centralizedOracle is object', async () => { + const valid = ` + mutation { + addPendingEvent( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + name: "General test" + results: ["1", "2"] + numOfResults: 2 + centralizedOracle: {id: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + betEndTime: 1560965704 + resultSetStartTime: 1560965704 + language: "en-US" + ) { + ${MULTIPLE_RESULTS_EVENT} + } + } + `; + tester.test(false, valid, {}); + }); + }); + + describe('add-pending-bet', () => { + it('It should pass if passing all correct arguments', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(true, valid, {}); + }); + + it('It should fail if txid is missing', async () => { + const valid = ` + mutation { + addPendingBet( + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is null', async () => { + const valid = ` + mutation { + addPendingBet( + txid: null + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is number', async () => { + const valid = ` + mutation { + addPendingBet( + txid: 1 + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is array', async () => { + const valid = ` + mutation { + addPendingBet( + txid: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is object', async () => { + const valid = ` + mutation { + addPendingBet( + txid: {id: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is missing', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is null', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: null + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is array', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is object', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is number', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: 1 + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if betterAddress is missing', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if betterAddress is null', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: null + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if betterAddress is number', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: 1 + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if betterAddress is array', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if betterAddress is object', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultIndex is missing', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultIndex is null', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: null + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultIndex is string', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: "2" + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultIndex is array', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: [2] + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultIndex is object', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: {id:2} + amount: "1000000" + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if amount is missing', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if amount is null', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: null + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if amount is number', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: 100000 + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if amount is array', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: ["100000"] + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if amount is object', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: {id:"100000"} + eventRound: 2 + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventRound is missing', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventRound is null', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + eventRound: null + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventRound is string', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + eventRound: "2" + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventRound is array', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + eventRound: [2] + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventRound is object', async () => { + const valid = ` + mutation { + addPendingBet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + eventRound: {id:2} + ) { + ${BET} + } + } + `; + tester.test(false, valid, {}); + }); + }); + + describe('add-pending-result-set', () => { + it('It should pass if passing all arguments correctly', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + eventRound: 0 + ) { + ${RESULT_SET} + } + } + `; + tester.test(true, valid, {}); + }); + + it('It should fail if txid is missing', async () => { + const valid = ` + mutation { + addPendingResultSet( + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is null', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: null + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is number', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: 1 + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is array', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is object', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: {id: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is missing', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is null', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: null + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is array', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is object', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is number', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: 1 + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if centralizedOracleAddress is missing', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if centralizedOracleAddress is null', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: null + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if centralizedOracleAddress is number', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: 1 + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if centralizedOracleAddress is array', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if centralizedOracleAddress is object', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + resultIndex: 2 + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultIndex is missing', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultIndex is null', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: null + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultIndex is string', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: "2" + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultIndex is array', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: [2] + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if resultIndex is object', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: {id:2} + amount: "1000000" + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if amount is missing', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if amount is null', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: null + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if amount is number', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: 100000 + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if amount is array', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: ["100000"] + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if amount is object', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: {id:"100000"} + eventRound: 2 + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventRound is missing', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventRound is null', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + eventRound: null + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventRound is string', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + eventRound: "2" + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventRound is array', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + eventRound: [2] + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventRound is object', async () => { + const valid = ` + mutation { + addPendingResultSet( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + centralizedOracleAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + resultIndex: 2 + amount: "100000" + eventRound: {id:2} + ) { + ${RESULT_SET} + } + } + `; + tester.test(false, valid, {}); + }); + }); + + describe('add-pending-withdraw', () => { + it('It should pass if passing all arguments correctly', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(true, valid, {}); + }); + + it('It should fail if txid is missing', async () => { + const valid = ` + mutation { + addPendingWithdraw( + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is null', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: null + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is number', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: 1 + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is array', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if txid is object', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: {id: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is missing', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is null', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: null + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is array', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is object', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if eventAddress is number', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: 1 + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if winnerAddress is missing', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if winnerAddress is null', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: null + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if winnerAddress is number', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: 1 + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if winnerAddress is array', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"] + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if winnerAddress is object', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"} + winningAmount: "100000" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if winningAmount is missing', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if winningAmount is null', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: null + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if winningAmount is number', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: 100000 + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if winningAmount is array', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: ["100000"] + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if winningAmount is object', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: {id:"100000"} + escrowAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if escrowAmount is missing', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winningAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if escrowAmount is null', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + escrowAmount: null + winningAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if escrowAmount is number', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + escrowAmount: 100000 + winningAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if escrowAmount is array', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + escrowAmount: ["100000"] + winningAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + + it('It should fail if escrowAmount is object', async () => { + const valid = ` + mutation { + addPendingWithdraw( + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428" + escrowAmount: {id:"100000"} + winningAmount: "100000" + ) { + ${WITHDRAW} + } + } + `; + tester.test(false, valid, {}); + }); + }); +}); diff --git a/test/graphql/schema-helper.js b/test/graphql/schema-helper.js index b3be88b2..94638297 100644 --- a/test/graphql/schema-helper.js +++ b/test/graphql/schema-helper.js @@ -73,58 +73,71 @@ const PAGINATED_EVENTS = ` } `; +const BET = ` + txType + txid + txStatus + ${TX_RECEIPT} + blockNum + ${BLOCK} + eventAddress + betterAddress + resultIndex + amount + eventRound + resultName + eventName +`; + const PAGINATED_BETS = ` totalCount ${PAGE_INFO} items { - txType - txid - txStatus - ${TX_RECEIPT} - blockNum - ${BLOCK} - eventAddress - betterAddress - resultIndex - amount - eventRound - resultName + ${BET} } `; +const RESULT_SET = ` + txType + txid + txStatus + ${TX_RECEIPT} + blockNum + ${BLOCK} + eventAddress + centralizedOracleAddress + resultIndex + amount + eventRound + resultName +`; + const PAGINATED_RESULT_SETS = ` totalCount ${PAGE_INFO} items { - txType - txid - txStatus - ${TX_RECEIPT} - blockNum - ${BLOCK} - eventAddress - centralizedOracleAddress - resultIndex - amount - eventRound - resultName + ${RESULT_SET} } `; +const WITHDRAW = ` + txType + txid + txStatus + ${TX_RECEIPT} + blockNum + ${BLOCK} + eventAddress + winnerAddress + winningAmount + escrowWithdrawAmount +`; + const PAGINATED_WITHDRAWS = ` totalCount ${PAGE_INFO} items { - txType - txid - txStatus - ${TX_RECEIPT} - blockNum - ${BLOCK} - eventAddress - winnerAddress - winningAmount - escrowWithdrawAmount + ${WITHDRAW} } `; @@ -137,4 +150,7 @@ module.exports = { PAGINATED_BETS, PAGINATED_RESULT_SETS, PAGINATED_WITHDRAWS, + BET, + RESULT_SET, + WITHDRAW, }; diff --git a/test/models/bet.test.js b/test/models/bet.test.js new file mode 100644 index 00000000..b7629bb2 --- /dev/null +++ b/test/models/bet.test.js @@ -0,0 +1,283 @@ +const { assert } = require('chai'); +const { isUndefined, isFinite, isString, map, filter } = require('lodash'); +const web3 = require('../../src/web3'); +const Bet = require('../../src/models/bet'); +const { TX_STATUS, TX_TYPE } = require('../../src/constants'); + +const rawInput = { + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + txStatus: TX_STATUS.SUCCESS, + blockNum: 5, + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + betterAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + resultIndex: 1, + amount: "1000000", + eventRound: 0, +}; + +describe('models/bet', () => { + describe('validate', () => { + let input; + + beforeEach(() => { + input = {}; + Object.assign(input, rawInput); + }); + + it('It should throw if txid is missing', () => { + delete input.txid; + assert.throws(() => new Bet(input), Error, "txid must be a String"); // must be double quotes + }); + + it('It should throw if txid is null', () => { + input.txid = null; + assert.throws(() => new Bet(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is undefined', () => { + input.txid = undefined; + assert.throws(() => new Bet(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is number', () => { + input.txid = 12; + assert.throws(() => new Bet(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is array', () => { + input.txid = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new Bet(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is object', () => { + input.txid = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new Bet(input), Error, "txid must be a String"); + }); + + it('It should throw if txStatus is missing', () => { + delete input.txStatus; + assert.throws(() => new Bet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is null', () => { + input.txStatus = null; + assert.throws(() => new Bet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is undefined', () => { + input.txStatus = undefined; + assert.throws(() => new Bet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is number', () => { + input.txStatus = 12; + assert.throws(() => new Bet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is array', () => { + input.txStatus = [TX_STATUS.SUCCESS]; + assert.throws(() => new Bet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is object', () => { + input.txStatus = {id:TX_STATUS.SUCCESS}; + assert.throws(() => new Bet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if amount is missing', () => { + delete input.amount; + assert.throws(() => new Bet(input), Error, "amount must be a String"); + }); + + it('It should throw if amount is null', () => { + input.amount = null; + assert.throws(() => new Bet(input), Error, "amount must be a String"); + }); + + it('It should throw if amount is undefined', () => { + input.amount = undefined; + assert.throws(() => new Bet(input), Error, "amount must be a String"); + }); + + it('It should throw if amount is number', () => { + input.amount = 12; + assert.throws(() => new Bet(input), Error, "amount must be a String"); + }); + + it('It should throw if amount is array', () => { + input.amount = ["100000"]; + assert.throws(() => new Bet(input), Error, "amount must be a String"); + }); + + it('It should throw if amount is object', () => { + input.amount = {id:"100000"}; + assert.throws(() => new Bet(input), Error, "amount must be a String"); + }); + + it('It should throw if eventAddress is missing', () => { + delete input.eventAddress; + assert.throws(() => new Bet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is null', () => { + input.eventAddress = null; + assert.throws(() => new Bet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is undefined', () => { + input.eventAddress = undefined; + assert.throws(() => new Bet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is number', () => { + input.eventAddress = 12; + assert.throws(() => new Bet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is array', () => { + input.eventAddress = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new Bet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is object', () => { + input.eventAddress = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new Bet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if betterAddress is missing', () => { + delete input.betterAddress; + assert.throws(() => new Bet(input), Error, "betterAddress must be a String"); + }); + + it('It should throw if betterAddress is null', () => { + input.betterAddress = null; + assert.throws(() => new Bet(input), Error, "betterAddress must be a String"); + }); + + it('It should throw if betterAddress is undefined', () => { + input.betterAddress = undefined; + assert.throws(() => new Bet(input), Error, "betterAddress must be a String"); + }); + + it('It should throw if betterAddress is number', () => { + input.betterAddress = 12; + assert.throws(() => new Bet(input), Error, "betterAddress must be a String"); + }); + + it('It should throw if betterAddress is array', () => { + input.betterAddress = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new Bet(input), Error, "betterAddress must be a String"); + }); + + it('It should throw if betterAddress is object', () => { + input.betterAddress = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new Bet(input), Error, "betterAddress must be a String"); + }); + + it('It should throw if resultIndex is missing', () => { + delete input.resultIndex; + assert.throws(() => new Bet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if resultIndex is null', () => { + input.resultIndex = null; + assert.throws(() => new Bet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if resultIndex is undefined', () => { + input.resultIndex = undefined; + assert.throws(() => new Bet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if resultIndex is string', () => { + input.resultIndex = "12"; + assert.throws(() => new Bet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if resultIndex is array', () => { + input.resultIndex = [2]; + assert.throws(() => new Bet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if resultIndex is object', () => { + input.resultIndex = {id:2}; + assert.throws(() => new Bet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if eventRound is missing', () => { + delete input.eventRound; + assert.throws(() => new Bet(input), Error, "eventRound must be a Number"); + }); + + it('It should throw if eventRound is null', () => { + input.eventRound = null; + assert.throws(() => new Bet(input), Error, "eventRound must be a Number"); + }); + + it('It should throw if eventRound is undefined', () => { + input.eventRound = undefined; + assert.throws(() => new Bet(input), Error, "eventRound must be a Number"); + }); + + it('It should throw if eventRound is string', () => { + input.eventRound = "12"; + assert.throws(() => new Bet(input), Error, "eventRound must be a Number"); + }); + + it('It should throw if eventRound is array', () => { + input.eventRound = [2]; + assert.throws(() => new Bet(input), Error, "eventRound must be a Number"); + }); + + it('It should throw if eventRound is object', () => { + input.eventRound = {id:2}; + assert.throws(() => new Bet(input), Error, "eventRound must be a Number"); + }); + }); + + describe('format', () => { + let input; + + beforeEach(() => { + input = {}; + Object.assign(input, rawInput); + }); + + it('it should format all the fields', () => { + const bet = new Bet(input); + assert.equal(bet.txid, input.txid); + assert.equal(bet.txStatus, input.txStatus); + assert.equal(bet.blockNum, input.blockNum); + assert.equal(bet.eventAddress, input.eventAddress); + assert.equal(bet.betterAddress, input.betterAddress); + assert.equal(bet.resultIndex, input.resultIndex); + assert.equal(bet.amount, input.amount); + assert.equal(bet.eventRound, input.eventRound); + assert.equal(bet.txType, TX_TYPE.BET); + }); + + it('It should format the type to be vote', () => { + input.eventRound = 1; + const bet = new Bet(input); + assert.equal(bet.txType, TX_TYPE.VOTE); + }); + + it('It should format the txid to be lowercase', () => { + input.txid = input.txid.toUpperCase(); + const bet = new Bet(input); + assert.equal(bet.txid, input.txid.toLowerCase()); + }); + + it('It should format the eventAddress to be lowercase', () => { + input.eventAddress = input.eventAddress.toUpperCase(); + const bet = new Bet(input); + assert.equal(bet.eventAddress, input.eventAddress.toLowerCase()); + }); + + it('It should format the eventAddress to be lowercase', () => { + input.betterAddress = input.betterAddress.toUpperCase(); + const bet = new Bet(input); + assert.equal(bet.betterAddress, input.betterAddress.toLowerCase()); + }); + }); +}); diff --git a/test/models/multiple-results-event.tests.js b/test/models/multiple-results-event.tests.js new file mode 100644 index 00000000..e52b954d --- /dev/null +++ b/test/models/multiple-results-event.tests.js @@ -0,0 +1,396 @@ +const { assert } = require('chai'); +const { isUndefined, isFinite, isString, map, filter } = require('lodash'); +const web3 = require('../../src/web3'); +const MultipleResultsEvent = require('../../src/models/multiple-results-event'); +const { TX_STATUS } = require('../../src/constants'); + +/** +The following fields are not validating in model + address + version + escrowAmount + arbitrationLength + thresholdPercentIncrease + arbitrationRewardPercentage + consensusThreshold + arbitrationEndTime + results ** +*/ + +const results = ['Invalid', '1', 'y']; +const rawInput = { + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + txStatus: TX_STATUS.SUCCESS, + blockNum: 5, + address: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + version: 6, + name: "Test", + results: map(results, (item) => web3.utils.utf8ToHex(item)), + numOfResults: 3, + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + betStartTime: 1560965704, + betEndTime: 1560965704, + resultSetStartTime: 1560965704, + resultSetEndTime: 1560965704, + escrowAmount: "1000000", + arbitrationLength: 172800, + thresholdPercentIncrease: "10", + arbitrationRewardPercentage: 10, + consensusThreshold: "100000000000", + arbitrationEndTime: 1560965704, +}; + +describe('models/multiple-results-event', () => { + describe('validate', () => { + let input; + + beforeEach(() => { + input = {}; + Object.assign(input, rawInput); + }); + + it('It should throw if txid is null', () => { + input.txid = null; + assert.throws(() => new MultipleResultsEvent(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is undefined', () => { + input.txid = undefined; + assert.throws(() => new MultipleResultsEvent(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is number', () => { + input.txid = 12; + assert.throws(() => new MultipleResultsEvent(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is array', () => { + input.txid = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new MultipleResultsEvent(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is object', () => { + input.txid = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new MultipleResultsEvent(input), Error, "txid must be a String"); + }); + + it('It should throw if txStatus is null', () => { + input.txStatus = null; + assert.throws(() => new MultipleResultsEvent(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is undefined', () => { + input.txStatus = undefined; + assert.throws(() => new MultipleResultsEvent(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is number', () => { + input.txStatus = 12; + assert.throws(() => new MultipleResultsEvent(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is array', () => { + input.txStatus = [TX_STATUS.SUCCESS]; + assert.throws(() => new MultipleResultsEvent(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is object', () => { + input.txStatus = {id:TX_STATUS.SUCCESS}; + assert.throws(() => new MultipleResultsEvent(input), Error, "txStatus must be a String"); + }); + + it('It should throw if ownerAddress is null', () => { + input.ownerAddress = null; + assert.throws(() => new MultipleResultsEvent(input), Error, "ownerAddress must be a String"); + }); + + it('It should throw if ownerAddress is undefined', () => { + input.ownerAddress = undefined; + assert.throws(() => new MultipleResultsEvent(input), Error, "ownerAddress must be a String"); + }); + + it('It should throw if ownerAddress is number', () => { + input.ownerAddress = 12; + assert.throws(() => new MultipleResultsEvent(input), Error, "ownerAddress must be a String"); + }); + + it('It should throw if ownerAddress is array', () => { + input.ownerAddress = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new MultipleResultsEvent(input), Error, "ownerAddress must be a String"); + }); + + it('It should throw if ownerAddress is object', () => { + input.ownerAddress = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new MultipleResultsEvent(input), Error, "ownerAddress must be a String"); + }); + + it('It should throw if name is null', () => { + input.name = null; + assert.throws(() => new MultipleResultsEvent(input), Error, "name must be a String"); + }); + + it('It should throw if name is undefined', () => { + input.name = undefined; + assert.throws(() => new MultipleResultsEvent(input), Error, "name must be a String"); + }); + + it('It should throw if name is number', () => { + input.name = 12; + assert.throws(() => new MultipleResultsEvent(input), Error, "name must be a String"); + }); + + it('It should throw if name is array', () => { + input.name = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new MultipleResultsEvent(input), Error, "name must be a String"); + }); + + it('It should throw if name is object', () => { + input.name = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new MultipleResultsEvent(input), Error, "name must be a String"); + }); + + it('It should throw if centralizedOracle is null', () => { + input.centralizedOracle = null; + assert.throws(() => new MultipleResultsEvent(input), Error, "centralizedOracle must be a String"); + }); + + it('It should throw if centralizedOracle is undefined', () => { + input.centralizedOracle = undefined; + assert.throws(() => new MultipleResultsEvent(input), Error, "centralizedOracle must be a String"); + }); + + it('It should throw if centralizedOracle is number', () => { + input.centralizedOracle = 12; + assert.throws(() => new MultipleResultsEvent(input), Error, "centralizedOracle must be a String"); + }); + + it('It should throw if centralizedOracle is array', () => { + input.centralizedOracle = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new MultipleResultsEvent(input), Error, "centralizedOracle must be a String"); + }); + + it('It should throw if centralizedOracle is object', () => { + input.centralizedOracle = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new MultipleResultsEvent(input), Error, "centralizedOracle must be a String"); + }); + + it('It should throw if numOfResults is null', () => { + input.numOfResults = null; + assert.throws(() => new MultipleResultsEvent(input), Error, "numOfResults must be a Number"); + }); + + it('It should throw if numOfResults is undefined', () => { + input.numOfResults = undefined; + assert.throws(() => new MultipleResultsEvent(input), Error, "numOfResults must be a Number"); + }); + + it('It should throw if numOfResults is string', () => { + input.numOfResults = "12"; + assert.throws(() => new MultipleResultsEvent(input), Error, "numOfResults must be a Number"); + }); + + it('It should throw if numOfResults is array', () => { + input.numOfResults = [2]; + assert.throws(() => new MultipleResultsEvent(input), Error, "numOfResults must be a Number"); + }); + + it('It should throw if numOfResults is object', () => { + input.numOfResults = {id:2}; + assert.throws(() => new MultipleResultsEvent(input), Error, "numOfResults must be a Number"); + }); + + it('It should throw if betEndTime is null', () => { + input.betEndTime = null; + assert.throws(() => new MultipleResultsEvent(input), Error, "betEndTime must be a Number"); + }); + + it('It should throw if betEndTime is undefined', () => { + input.betEndTime = undefined; + assert.throws(() => new MultipleResultsEvent(input), Error, "betEndTime must be a Number"); + }); + + it('It should throw if betEndTime is string', () => { + input.betEndTime = "12"; + assert.throws(() => new MultipleResultsEvent(input), Error, "betEndTime must be a Number"); + }); + + it('It should throw if betEndTime is array', () => { + input.betEndTime = [2]; + assert.throws(() => new MultipleResultsEvent(input), Error, "betEndTime must be a Number"); + }); + + it('It should throw if betEndTime is object', () => { + input.betEndTime = {id:2}; + assert.throws(() => new MultipleResultsEvent(input), Error, "betEndTime must be a Number"); + }); + + it('It should throw if resultSetStartTime is null', () => { + input.resultSetStartTime = null; + assert.throws(() => new MultipleResultsEvent(input), Error, "resultSetStartTime must be a Number"); + }); + + it('It should throw if resultSetStartTime is undefined', () => { + input.resultSetStartTime = undefined; + assert.throws(() => new MultipleResultsEvent(input), Error, "resultSetStartTime must be a Number"); + }); + + it('It should throw if resultSetStartTime is string', () => { + input.resultSetStartTime = "12"; + assert.throws(() => new MultipleResultsEvent(input), Error, "resultSetStartTime must be a Number"); + }); + + it('It should throw if resultSetStartTime is array', () => { + input.resultSetStartTime = [2]; + assert.throws(() => new MultipleResultsEvent(input), Error, "resultSetStartTime must be a Number"); + }); + + it('It should throw if resultSetStartTime is object', () => { + input.resultSetStartTime = {id:2}; + assert.throws(() => new MultipleResultsEvent(input), Error, "resultSetStartTime must be a Number"); + }); + + it('It should throw if betStartTime is null', () => { + input.betStartTime = null; + assert.throws(() => new MultipleResultsEvent(input), Error, "betStartTime must be a Number"); + }); + + it('It should throw if betStartTime is string', () => { + input.betStartTime = "12"; + assert.throws(() => new MultipleResultsEvent(input), Error, "betStartTime must be a Number"); + }); + + it('It should throw if betStartTime is array', () => { + input.betStartTime = [2]; + assert.throws(() => new MultipleResultsEvent(input), Error, "betStartTime must be a Number"); + }); + + it('It should throw if betStartTime is object', () => { + input.betStartTime = {id:2}; + assert.throws(() => new MultipleResultsEvent(input), Error, "betStartTime must be a Number"); + }); + + it('It should throw if resultSetEndTime is null', () => { + input.resultSetEndTime = null; + assert.throws(() => new MultipleResultsEvent(input), Error, "resultSetEndTime must be a Number"); + }); + + it('It should throw if resultSetEndTime is string', () => { + input.resultSetEndTime = "12"; + assert.throws(() => new MultipleResultsEvent(input), Error, "resultSetEndTime must be a Number"); + }); + + it('It should throw if resultSetEndTime is array', () => { + input.resultSetEndTime = [2]; + assert.throws(() => new MultipleResultsEvent(input), Error, "resultSetEndTime must be a Number"); + }); + + it('It should throw if resultSetEndTime is object', () => { + input.resultSetEndTime = {id:2}; + assert.throws(() => new MultipleResultsEvent(input), Error, "resultSetEndTime must be a Number"); + }); + }); + + describe('format', () => { + let input; + let mutationInput; + + beforeEach(() => { + input = {}; + Object.assign(input, rawInput); + + mutationInput = { + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + txStatus: TX_STATUS.SUCCESS, + blockNum: 5, + address: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + ownerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + version: 6, + name: "Test", + numOfResults: 3, + centralizedOracle: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + betEndTime: 1560965704, + resultSetStartTime: 1560965704, + escrowAmount: "1000000", + arbitrationLength: 172800, + thresholdPercentIncrease: "10", + arbitrationRewardPercentage: 10, + consensusThreshold: "100000000000", + arbitrationEndTime: 1560965704, + }; + mutationInput.results = input.results; + }); + + it('it should format synced input', () => { + const event = new MultipleResultsEvent(input); + assert.equal(event.txid, input.txid); + assert.equal(event.txStatus, input.txStatus); + assert.equal(event.blockNum, input.blockNum); + assert.equal(event.address, input.address); + assert.equal(event.ownerAddress, input.ownerAddress); + assert.equal(event.version, input.version); + assert.equal(event.name, input.name); + assert.deepEqual(event.results, results); + assert.equal(event.numOfResults, input.numOfResults); + assert.equal(event.centralizedOracle, input.centralizedOracle); + assert.equal(event.betStartTime, input.betStartTime); + assert.equal(event.betEndTime, input.betEndTime); + assert.equal(event.resultSetStartTime, input.resultSetStartTime); + assert.equal(event.resultSetEndTime, input.resultSetEndTime); + assert.equal(event.escrowAmount, input.escrowAmount); + assert.equal(event.arbitrationLength, input.arbitrationLength); + assert.equal(event.thresholdPercentIncrease, input.thresholdPercentIncrease); + assert.equal(event.arbitrationRewardPercentage, input.arbitrationRewardPercentage); + assert.isString(event.consensusThreshold); + assert.isNumber(event.arbitrationEndTime); + }); + + it('It should format mutation input', () => { + const event = new MultipleResultsEvent(mutationInput); + assert.equal(event.txid, input.txid); + assert.equal(event.txStatus, input.txStatus); + assert.equal(event.blockNum, input.blockNum); + assert.equal(event.address, input.address); + assert.equal(event.ownerAddress, input.ownerAddress); + assert.equal(event.version, input.version); + assert.equal(event.name, input.name); + assert.deepEqual(event.results, results); + assert.equal(event.numOfResults, input.numOfResults); + assert.equal(event.centralizedOracle, input.centralizedOracle); + assert.isUndefined(event.betStartTime); + assert.equal(event.betEndTime, input.betEndTime); + assert.equal(event.resultSetStartTime, input.resultSetStartTime); + assert.isUndefined(event.resultSetEndTime); + assert.equal(event.escrowAmount, input.escrowAmount); + assert.equal(event.arbitrationLength, input.arbitrationLength); + assert.equal(event.thresholdPercentIncrease, input.thresholdPercentIncrease); + assert.equal(event.arbitrationRewardPercentage, input.arbitrationRewardPercentage); + assert.isString(event.consensusThreshold); + assert.isNumber(event.arbitrationEndTime); + }); + + it('It should format the txid to be lowercase', () => { + input.txid = input.txid.toUpperCase(); + const event = new MultipleResultsEvent(input); + assert.equal(event.txid, input.txid.toLowerCase()); + }); + + it('It should format the address to be lowercase', () => { + input.address = input.address.toUpperCase(); + const event = new MultipleResultsEvent(input); + assert.equal(event.address, input.address.toLowerCase()); + }); + + it('It should format the ownerAddress to be lowercase', () => { + input.ownerAddress = input.ownerAddress.toUpperCase(); + const event = new MultipleResultsEvent(input); + assert.equal(event.ownerAddress, input.ownerAddress.toLowerCase()); + }); + + it('It should format the centralizedOracle to be lowercase', () => { + input.centralizedOracle = input.centralizedOracle.toUpperCase(); + const event = new MultipleResultsEvent(input); + assert.equal(event.centralizedOracle, input.centralizedOracle.toLowerCase()); + }); + }); +}); diff --git a/test/models/result-set.test.js b/test/models/result-set.test.js new file mode 100644 index 00000000..f62c13a5 --- /dev/null +++ b/test/models/result-set.test.js @@ -0,0 +1,256 @@ +const { assert } = require('chai'); +const { isUndefined, isFinite, isString, map, filter } = require('lodash'); +const web3 = require('../../src/web3'); +const ResultSet = require('../../src/models/result-set'); +const { TX_STATUS, TX_TYPE } = require('../../src/constants'); + +// result-set model not validating on +// 1. centralizedOracleAddress +// 2. nextConsensusThreshold +// 3. nextArbitrationEndTime + +const rawInput = { + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + txStatus: TX_STATUS.SUCCESS, + blockNum: 5, + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + resultIndex: 1, + amount: "1000000", + eventRound: 0, +}; + +describe('models/result-set', () => { + describe('validate', () => { + let input; + + beforeEach(() => { + input = {}; + Object.assign(input, rawInput); + }); + + it('It should throw if txid is missing', () => { + delete input.txid; + assert.throws(() => new ResultSet(input), Error, "txid must be a String"); // must be double quotes + }); + + it('It should throw if txid is null', () => { + input.txid = null; + assert.throws(() => new ResultSet(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is undefined', () => { + input.txid = undefined; + assert.throws(() => new ResultSet(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is number', () => { + input.txid = 12; + assert.throws(() => new ResultSet(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is array', () => { + input.txid = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new ResultSet(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is object', () => { + input.txid = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new ResultSet(input), Error, "txid must be a String"); + }); + + it('It should throw if txStatus is missing', () => { + delete input.txStatus; + assert.throws(() => new ResultSet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is null', () => { + input.txStatus = null; + assert.throws(() => new ResultSet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is undefined', () => { + input.txStatus = undefined; + assert.throws(() => new ResultSet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is number', () => { + input.txStatus = 12; + assert.throws(() => new ResultSet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is array', () => { + input.txStatus = [TX_STATUS.SUCCESS]; + assert.throws(() => new ResultSet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is object', () => { + input.txStatus = {id:TX_STATUS.SUCCESS}; + assert.throws(() => new ResultSet(input), Error, "txStatus must be a String"); + }); + + it('It should throw if amount is missing', () => { + delete input.amount; + assert.throws(() => new ResultSet(input), Error, "amount must be a String"); + }); + + it('It should throw if amount is null', () => { + input.amount = null; + assert.throws(() => new ResultSet(input), Error, "amount must be a String"); + }); + + it('It should throw if amount is undefined', () => { + input.amount = undefined; + assert.throws(() => new ResultSet(input), Error, "amount must be a String"); + }); + + it('It should throw if amount is number', () => { + input.amount = 12; + assert.throws(() => new ResultSet(input), Error, "amount must be a String"); + }); + + it('It should throw if amount is array', () => { + input.amount = ["100000"]; + assert.throws(() => new ResultSet(input), Error, "amount must be a String"); + }); + + it('It should throw if amount is object', () => { + input.amount = {id:"100000"}; + assert.throws(() => new ResultSet(input), Error, "amount must be a String"); + }); + + it('It should throw if eventAddress is missing', () => { + delete input.eventAddress; + assert.throws(() => new ResultSet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is null', () => { + input.eventAddress = null; + assert.throws(() => new ResultSet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is undefined', () => { + input.eventAddress = undefined; + assert.throws(() => new ResultSet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is number', () => { + input.eventAddress = 12; + assert.throws(() => new ResultSet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is array', () => { + input.eventAddress = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new ResultSet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is object', () => { + input.eventAddress = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new ResultSet(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if resultIndex is missing', () => { + delete input.resultIndex; + assert.throws(() => new ResultSet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if resultIndex is null', () => { + input.resultIndex = null; + assert.throws(() => new ResultSet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if resultIndex is undefined', () => { + input.resultIndex = undefined; + assert.throws(() => new ResultSet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if resultIndex is string', () => { + input.resultIndex = "12"; + assert.throws(() => new ResultSet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if resultIndex is array', () => { + input.resultIndex = [2]; + assert.throws(() => new ResultSet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if resultIndex is object', () => { + input.resultIndex = {id:2}; + assert.throws(() => new ResultSet(input), Error, "resultIndex must be a Number"); + }); + + it('It should throw if eventRound is missing', () => { + delete input.eventRound; + assert.throws(() => new ResultSet(input), Error, "eventRound must be a Number"); + }); + + it('It should throw if eventRound is null', () => { + input.eventRound = null; + assert.throws(() => new ResultSet(input), Error, "eventRound must be a Number"); + }); + + it('It should throw if eventRound is undefined', () => { + input.eventRound = undefined; + assert.throws(() => new ResultSet(input), Error, "eventRound must be a Number"); + }); + + it('It should throw if eventRound is string', () => { + input.eventRound = "12"; + assert.throws(() => new ResultSet(input), Error, "eventRound must be a Number"); + }); + + it('It should throw if eventRound is array', () => { + input.eventRound = [2]; + assert.throws(() => new ResultSet(input), Error, "eventRound must be a Number"); + }); + + it('It should throw if eventRound is object', () => { + input.eventRound = {id:2}; + assert.throws(() => new ResultSet(input), Error, "eventRound must be a Number"); + }); + }); + + describe('format', () => { + let input; + + beforeEach(() => { + input = {}; + Object.assign(input, rawInput); + }); + + it('It should format all the fields mimicing pending result-set', () => { + const resultSet = new ResultSet(input); + assert.equal(resultSet.txid, input.txid); + assert.equal(resultSet.txStatus, input.txStatus); + assert.equal(resultSet.blockNum, input.blockNum); + assert.equal(resultSet.eventAddress, input.eventAddress); + assert.equal(resultSet.resultIndex, input.resultIndex); + assert.equal(resultSet.amount, input.amount); + assert.equal(resultSet.eventRound, input.eventRound); + assert.equal(resultSet.txType, TX_TYPE.RESULT_SET); + }); + + it('It should format the eventAddress to lowercase mimicing pending result-set', () => { + input.eventAddress = input.eventAddress.toUpperCase(); + const resultSet = new ResultSet(input); + assert.equal(resultSet.eventAddress, input.eventAddress.toLowerCase()); + }); + + it('It should format all the fields mimicing synced result-set', () => { + input.centralizedOracleAddress = "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"; + input.nextConsensusThreshold = "10"; + input.nextArbitrationEndTime = 10; + const resultSet = new ResultSet(input); + assert.equal(resultSet.centralizedOracleAddress, input.centralizedOracleAddress); + assert.equal(resultSet.nextConsensusThreshold, input.nextConsensusThreshold); + assert.equal(resultSet.nextArbitrationEndTime, input.nextArbitrationEndTime); + }); + + it('It should format centralizedOracleAddress to lowercase mimicing synced result-set', () => { + input.centralizedOracleAddress = "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428".toUpperCase(); + input.nextConsensusThreshold = "10"; + input.nextArbitrationEndTime = 10; + const resultSet = new ResultSet(input); + assert.equal(resultSet.centralizedOracleAddress, input.centralizedOracleAddress.toLowerCase()); + }); + }); +}); diff --git a/test/models/tx-receipt.test.js b/test/models/tx-receipt.test.js new file mode 100644 index 00000000..a8aac647 --- /dev/null +++ b/test/models/tx-receipt.test.js @@ -0,0 +1,257 @@ +const { assert } = require('chai'); +const { isUndefined, isFinite, isString, map, filter } = require('lodash'); +const web3 = require('../../src/web3'); +const TxReceipt = require('../../src/models/tx-receipt'); +const { TX_STATUS, TX_TYPE } = require('../../src/constants'); + +const rawInput = { + status: true, + blockHash: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + transactionHash: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + blockNumber: 5, + from: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + to: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + contractAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + cumulativeGasUsed: 100000, + gasUsed: 1000, + gasPrice: "300000" +}; + +describe('models/tx-receipt', () => { + describe('validate', () => { + let input; + + beforeEach(() => { + input = {}; + Object.assign(input, rawInput); + }); + + it('It should not throw if blockHash is null', () => { + input.blockHash = null; + assert.doesNotThrow(() => new TxReceipt(input), Error, "blockHash must be a string|null"); + }); + + it('It should throw if blockHash is undefined', () => { + input.blockHash = undefined; + assert.throws(() => new TxReceipt(input), Error, "blockHash must be a string|null"); + }); + + it('It should throw if blockHash is number', () => { + input.blockHash = 1; + assert.throws(() => new TxReceipt(input), Error, "blockHash must be a string|null"); + }); + + it('It should throw if blockHash is array', () => { + input.blockHash = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new TxReceipt(input), Error, "blockHash must be a string|null"); + }); + + it('It should throw if blockHash is object', () => { + input.blockHash = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new TxReceipt(input), Error, "blockHash must be a string|null"); + }); + + it('It should not throw if blockNumber is null', () => { + input.blockNumber = null; + assert.doesNotThrow(() => new TxReceipt(input), Error, "blockNumber must be a number|null"); + }); + + it('It should throw if blockNumber is undefined', () => { + input.blockNumber = undefined; + assert.throws(() => new TxReceipt(input), Error, "blockNumber must be a number|null"); + }); + + it('It should throw if blockNumber is string', () => { + input.blockNumber = '1'; + assert.throws(() => new TxReceipt(input), Error, "blockNumber must be a number|null"); + }); + + it('It should throw if blockNumber is array', () => { + input.blockNumber = [1]; + assert.throws(() => new TxReceipt(input), Error, "blockNumber must be a number|null"); + }); + + it('It should throw if blockNumber is object', () => { + input.blockNumber = {id:1}; + assert.throws(() => new TxReceipt(input), Error, "blockNumber must be a number|null"); + }); + + it('It should throw if transactionHash is null', () => { + input.transactionHash = null; + assert.throws(() => new TxReceipt(input), Error, "transactionHash must be a string"); + }); + + it('It should throw if transactionHash is undefined', () => { + input.transactionHash = undefined; + assert.throws(() => new TxReceipt(input), Error, "transactionHash must be a string"); + }); + + it('It should throw if transactionHash is number', () => { + input.transactionHash = 1; + assert.throws(() => new TxReceipt(input), Error, "transactionHash must be a string"); + }); + + it('It should throw if transactionHash is array', () => { + input.transactionHash = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new TxReceipt(input), Error, "transactionHash must be a string"); + }); + + it('It should throw if transactionHash is object', () => { + input.transactionHash = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new TxReceipt(input), Error, "transactionHash must be a string"); + }); + + it('It should throw if eventAddress is null', () => { + input.from = null; + assert.throws(() => new TxReceipt(input), Error, "from must be a string"); + }); + + it('It should throw if eventAddress is undefined', () => { + input.from = undefined; + assert.throws(() => new TxReceipt(input), Error, "from must be a string"); + }); + + it('It should throw if eventAddress is number', () => { + input.from = 1; + assert.throws(() => new TxReceipt(input), Error, "from must be a string"); + }); + + it('It should throw if eventAddress is array', () => { + input.from = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new TxReceipt(input), Error, "from must be a string"); + }); + + it('It should throw if eventAddress is object', () => { + input.from = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new TxReceipt(input), Error, "from must be a string"); + }); + + it('It should not throw if to is null', () => { + input.to = null; + assert.doesNotThrow(() => new TxReceipt(input), Error, "to must be a string|null"); + }); + + it('It should throw if to is undefined', () => { + input.to = undefined; + assert.throws(() => new TxReceipt(input), Error, "to must be a string|null"); + }); + + it('It should throw if to is number', () => { + input.to = 1; + assert.throws(() => new TxReceipt(input), Error, "to must be a string|null"); + }); + + it('It should throw if to is array', () => { + input.to = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new TxReceipt(input), Error, "to must be a string|null"); + }); + + it('It should throw if to is object', () => { + input.to = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new TxReceipt(input), Error, "to must be a string|null"); + }); + + it('It should throw if cumulativeGasUsed is null', () => { + input.cumulativeGasUsed = null; + assert.throws(() => new TxReceipt(input), Error, "cumulativeGasUsed must be a number"); + }); + + it('It should throw if cumulativeGasUsed is undefined', () => { + input.cumulativeGasUsed = undefined; + assert.throws(() => new TxReceipt(input), Error, "cumulativeGasUsed must be a number"); + }); + + it('It should throw if cumulativeGasUsed is string', () => { + input.cumulativeGasUsed = "1"; + assert.throws(() => new TxReceipt(input), Error, "cumulativeGasUsed must be a number"); + }); + + it('It should throw if cumulativeGasUsed is array', () => { + input.cumulativeGasUsed = [1]; + assert.throws(() => new TxReceipt(input), Error, "cumulativeGasUsed must be a number"); + }); + + it('It should throw if cumulativeGasUsed is object', () => { + input.cumulativeGasUsed = {id:1}; + assert.throws(() => new TxReceipt(input), Error, "cumulativeGasUsed must be a number"); + }); + + it('It should throw if gasUsed is null', () => { + input.gasUsed = null; + assert.throws(() => new TxReceipt(input), Error, "gasUsed must be a number"); + }); + + it('It should throw if gasUsed is undefined', () => { + input.gasUsed = undefined; + assert.throws(() => new TxReceipt(input), Error, "gasUsed must be a number"); + }); + + it('It should throw if gasUsed is string', () => { + input.gasUsed = '1'; + assert.throws(() => new TxReceipt(input), Error, "gasUsed must be a number"); + }); + + it('It should throw if gasUsed is array', () => { + input.gasUsed = [1]; + assert.throws(() => new TxReceipt(input), Error, "gasUsed must be a number"); + }); + + it('It should throw if gasUsed is object', () => { + input.gasUsed = {id:1}; + assert.throws(() => new TxReceipt(input), Error, "gasUsed must be a number"); + }); + }); + + describe('format', () => { + let input; + + beforeEach(() => { + input = {}; + Object.assign(input, rawInput); + }); + + it('it should format all the fields', () => { + const txReceipt = new TxReceipt(input); + assert.equal(txReceipt.status, input.status); + assert.equal(txReceipt.blockHash, input.blockHash); + assert.equal(txReceipt.blockNum, input.blockNumber); + assert.equal(txReceipt.transactionHash, input.transactionHash); + assert.equal(txReceipt.from, input.from); + assert.equal(txReceipt.to, input.to); + assert.equal(txReceipt.contractAddress, input.contractAddress); + assert.equal(txReceipt.cumulativeGasUsed, input.cumulativeGasUsed); + assert.equal(txReceipt.gasUsed, input.gasUsed); + assert.equal(txReceipt.gasPrice, input.gasPrice); + }); + + it('It should format the blockHash to be lowercase', () => { + input.blockHash = input.blockHash.toUpperCase(); + const txReceipt = new TxReceipt(input); + assert.equal(txReceipt.blockHash, input.blockHash.toLowerCase()); + }); + + it('It should format the transactionHash to be lowercase', () => { + input.transactionHash = input.transactionHash.toUpperCase(); + const txReceipt = new TxReceipt(input); + assert.equal(txReceipt.transactionHash, input.transactionHash.toLowerCase()); + }); + + it('It should format the from to be lowercase', () => { + input.from = input.from.toUpperCase(); + const txReceipt = new TxReceipt(input); + assert.equal(txReceipt.from, input.from.toLowerCase()); + }); + + it('It should format the to to be lowercase', () => { + input.to = input.to.toUpperCase(); + const txReceipt = new TxReceipt(input); + assert.equal(txReceipt.to, input.to.toLowerCase()); + }); + + it('It should format the contractAddress to be lowercase', () => { + input.contractAddress = input.contractAddress.toUpperCase(); + const txReceipt = new TxReceipt(input); + assert.equal(txReceipt.contractAddress, input.contractAddress.toLowerCase()); + }); + }); +}); diff --git a/test/models/withdraw.test.js b/test/models/withdraw.test.js new file mode 100644 index 00000000..89ac1502 --- /dev/null +++ b/test/models/withdraw.test.js @@ -0,0 +1,245 @@ +const { assert } = require('chai'); +const { isUndefined, isFinite, isString, map, filter } = require('lodash'); +const web3 = require('../../src/web3'); +const Withdraw = require('../../src/models/withdraw'); +const { TX_STATUS, TX_TYPE } = require('../../src/constants'); + +const rawInput = { + txid: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + txStatus: TX_STATUS.SUCCESS, + blockNum: 5, + eventAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + winnerAddress: "0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428", + winningAmount: "1000000", + escrowWithdrawAmount: "1000000", +}; + +describe('models/withdraw', () => { + describe('validate', () => { + let input; + + beforeEach(() => { + input = {}; + Object.assign(input, rawInput); + }); + + it('It should throw if txid is missing', () => { + delete input.txid; + assert.throws(() => new Withdraw(input), Error, "txid must be a String"); // must be double quotes + }); + + it('It should throw if txid is null', () => { + input.txid = null; + assert.throws(() => new Withdraw(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is undefined', () => { + input.txid = undefined; + assert.throws(() => new Withdraw(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is number', () => { + input.txid = 12; + assert.throws(() => new Withdraw(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is array', () => { + input.txid = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new Withdraw(input), Error, "txid must be a String"); + }); + + it('It should throw if txid is object', () => { + input.txid = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new Withdraw(input), Error, "txid must be a String"); + }); + + it('It should throw if txStatus is missing', () => { + delete input.txStatus; + assert.throws(() => new Withdraw(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is null', () => { + input.txStatus = null; + assert.throws(() => new Withdraw(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is undefined', () => { + input.txStatus = undefined; + assert.throws(() => new Withdraw(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is number', () => { + input.txStatus = 12; + assert.throws(() => new Withdraw(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is array', () => { + input.txStatus = [TX_STATUS.SUCCESS]; + assert.throws(() => new Withdraw(input), Error, "txStatus must be a String"); + }); + + it('It should throw if txStatus is object', () => { + input.txStatus = {id:TX_STATUS.SUCCESS}; + assert.throws(() => new Withdraw(input), Error, "txStatus must be a String"); + }); + + it('It should throw if eventAddress is missing', () => { + delete input.eventAddress; + assert.throws(() => new Withdraw(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is null', () => { + input.eventAddress = null; + assert.throws(() => new Withdraw(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is undefined', () => { + input.eventAddress = undefined; + assert.throws(() => new Withdraw(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is number', () => { + input.eventAddress = 12; + assert.throws(() => new Withdraw(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is array', () => { + input.eventAddress = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new Withdraw(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if eventAddress is object', () => { + input.eventAddress = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new Withdraw(input), Error, "eventAddress must be a String"); + }); + + it('It should throw if winnerAddress is missing', () => { + delete input.winnerAddress; + assert.throws(() => new Withdraw(input), Error, "winnerAddress must be a String"); + }); + + it('It should throw if winnerAddress is null', () => { + input.winnerAddress = null; + assert.throws(() => new Withdraw(input), Error, "winnerAddress must be a String"); + }); + + it('It should throw if winnerAddress is undefined', () => { + input.winnerAddress = undefined; + assert.throws(() => new Withdraw(input), Error, "winnerAddress must be a String"); + }); + + it('It should throw if winnerAddress is number', () => { + input.winnerAddress = 12; + assert.throws(() => new Withdraw(input), Error, "winnerAddress must be a String"); + }); + + it('It should throw if winnerAddress is array', () => { + input.winnerAddress = ["0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"]; + assert.throws(() => new Withdraw(input), Error, "winnerAddress must be a String"); + }); + + it('It should throw if winnerAddress is object', () => { + input.winnerAddress = {id:"0xd5d087daabc73fc6cc5d9c1131b93acbd53a2428"}; + assert.throws(() => new Withdraw(input), Error, "winnerAddress must be a String"); + }); + + it('It should throw if winningAmount is missing', () => { + delete input.winningAmount; + assert.throws(() => new Withdraw(input), Error, "winningAmount must be a String"); + }); + + it('It should throw if winningAmount is null', () => { + input.winningAmount = null; + assert.throws(() => new Withdraw(input), Error, "winningAmount must be a String"); + }); + + it('It should throw if winningAmount is undefined', () => { + input.winningAmount = undefined; + assert.throws(() => new Withdraw(input), Error, "winningAmount must be a String"); + }); + + it('It should throw if winningAmount is number', () => { + input.winningAmount = 12; + assert.throws(() => new Withdraw(input), Error, "winningAmount must be a String"); + }); + + it('It should throw if winningAmount is array', () => { + input.winningAmount = ["100000"]; + assert.throws(() => new Withdraw(input), Error, "winningAmount must be a String"); + }); + + it('It should throw if winningAmount is object', () => { + input.winningAmount = {id:"100000"}; + assert.throws(() => new Withdraw(input), Error, "winningAmount must be a String"); + }); + + it('It should throw if escrowWithdrawAmount is missing', () => { + delete input.escrowWithdrawAmount; + assert.throws(() => new Withdraw(input), Error, "escrowWithdrawAmount must be a String"); + }); + + it('It should throw if escrowWithdrawAmount is null', () => { + input.escrowWithdrawAmount = null; + assert.throws(() => new Withdraw(input), Error, "escrowWithdrawAmount must be a String"); + }); + + it('It should throw if escrowWithdrawAmount is undefined', () => { + input.escrowWithdrawAmount = undefined; + assert.throws(() => new Withdraw(input), Error, "escrowWithdrawAmount must be a String"); + }); + + it('It should throw if escrowWithdrawAmount is number', () => { + input.escrowWithdrawAmount = 12; + assert.throws(() => new Withdraw(input), Error, "escrowWithdrawAmount must be a String"); + }); + + it('It should throw if escrowWithdrawAmount is array', () => { + input.escrowWithdrawAmount = ["100000"]; + assert.throws(() => new Withdraw(input), Error, "escrowWithdrawAmount must be a String"); + }); + + it('It should throw if escrowWithdrawAmount is object', () => { + input.escrowWithdrawAmount = {id:"100000"}; + assert.throws(() => new Withdraw(input), Error, "escrowWithdrawAmount must be a String"); + }); + }); + + describe('format', () => { + let input; + + beforeEach(() => { + input = {}; + Object.assign(input, rawInput); + }); + + it('It should format all the fields', () => { + const withdraw = new Withdraw(input); + assert.equal(withdraw.txid, input.txid); + assert.equal(withdraw.txStatus, input.txStatus); + assert.equal(withdraw.blockNum, input.blockNum); + assert.equal(withdraw.eventAddress, input.eventAddress); + assert.equal(withdraw.winnerAddress, input.winnerAddress); + assert.equal(withdraw.winningAmount, input.winningAmount); + assert.equal(withdraw.escrowWithdrawAmount, input.escrowWithdrawAmount); + assert.equal(withdraw.txType, TX_TYPE.WITHDRAW); + }); + + it('It should format the txid to lowercase', () => { + input.txid = input.txid.toUpperCase(); + const withdraw = new Withdraw(input); + assert.equal(withdraw.txid, input.txid.toLowerCase()); + }); + + it('It should format the eventAddress to lowercase', () => { + input.eventAddress = input.eventAddress.toUpperCase(); + const withdraw = new Withdraw(input); + assert.equal(withdraw.eventAddress, input.eventAddress.toLowerCase()); + }); + + it('It should format the eventAddress to lowercase', () => { + input.winnerAddress = input.winnerAddress.toUpperCase(); + const withdraw = new Withdraw(input); + assert.equal(withdraw.winnerAddress, input.winnerAddress.toLowerCase()); + }); + }); +});