UNPKG

@ixily/activ

Version:

Alpha Capture Trade Idea Verification. Blockchain ownership proven trade ideas and strategies.

582 lines 26.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StrategyChainModule = void 0; const __1 = require("../.."); const version_contract_db_json_1 = require("../../../version-contract-db.json"); // import fs from 'fs' const getStrategyChain = async (contract, strategyKey, creator, inflateImages = true, nftIdReduceStep, cached) => { // console.log('{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}}{}{}') // console.log('cached') // console.log(cached) if (nftIdReduceStep !== undefined) { if (cached !== undefined) { if (nftIdReduceStep <= cached.cachedStrategy.lastNftId) { return { strategyKey, ideas: cached.ideas, }; } } } creator = creator || (await contract.gate.signer.getAddress()); // console.log('creator') // console.log(creator) // console.log('strategyKey') // console.log(strategyKey) // console.log('contract.gate?.address') // console.log(contract.gate?.address) const ideasListDirty = await __1.NftModule.view.general.listIdeas(creator, strategyKey, contract); const ideasList = []; // let ideasList: number[] = [] // console.log('ideasListDirty') // console.log(ideasListDirty) const alreadyIdeas = new Set(); for (const ideaKey of ideasListDirty) { if (!alreadyIdeas.has(ideaKey)) { ideasList.push(ideaKey); alreadyIdeas.add(ideaKey); } } __1.LogModule.dev('ideasList lenght: ', ideasList.length); __1.LogModule.dev('cached?.ideas.length', cached?.ideas.length); // TODO: REMOVE THIS HACK // cleaideasList = [ideasList[0]] const ideas = []; const promisesOfProccessIdeas = []; let ideaIndexInsideCacheOffset = 0; let howManyNullifiedIdeas = 0; if (cached !== undefined) { const alreadyCheckKeys = new Set(); for (const [key, value] of cached.nullifiedIdeas.entries()) { if (!alreadyCheckKeys.has(key)) { alreadyCheckKeys.add(key); const nullifiedStages = value; if (nullifiedStages.has(0)) { howManyNullifiedIdeas++; } } } } for (const ideaIndexFluid in ideasList) { const ideaIndex = Number(ideaIndexFluid); const ideaKey = ideasList[ideaIndex]; const promOfProcId = async () => { const tryFromCache = async () => { if (cached !== undefined) { if (cached.ideas.length + howManyNullifiedIdeas > ideaIndex) { const nullifiedStages = cached.nullifiedIdeas.get(ideaKey); if (nullifiedStages !== undefined) { if (nullifiedStages.has(0)) { ideaIndexInsideCacheOffset++; return true; } } const ideaIndexInsideCache = ideaIndex - ideaIndexInsideCacheOffset; //console.log('-------------------------') //console.log('-------------------------') //console.log('-------------------------') //console.log('howManyNullifiedIdeas') //console.log(howManyNullifiedIdeas) //console.log('howManyNullifiedIdeas') //console.log(howManyNullifiedIdeas) //console.log('ideaIndex') //console.log(ideaIndex) //console.log('cached.nullifiedIdeas:') //for (const [ // key, // value, //] of cached.nullifiedIdeas.entries()) { // console.log(' key') // console.log(key) // console.log(' value') // console.log(value) //} // console.log('cached.ideas.length') // console.log(cached.ideas.length) // console.log('cached.ideas[ideaIndex].ideaKey') // console.log(cached.ideas[ideaIndexInsideCache].ideaKey) // console.log('ideaKey') // console.log(ideaKey) // console.log( // 'cached.ideas[ideaIndexInsideCache].ideaKey === ideaKey', // ) // console.log( // cached.ideas[ideaIndexInsideCache].ideaKey === // ideaKey, // ) if (cached.ideas[ideaIndexInsideCache].ideaKey === ideaKey) { const isDecryptedStage = (stage) => { return typeof stage.ideaStage.idea !== 'string'; }; const firstEncryptedStage = cached.ideas[ideaIndexInsideCache].stages.find((one) => !isDecryptedStage(one)); if (firstEncryptedStage === undefined) { // console.log('cached.ideas[ideaIndex]') // console.log(cached.ideas[ideaIndex]) // console.log('ideaKey') // console.log(ideaKey) // console.log('firstEncryptedStage') // console.log(firstEncryptedStage) const closeStage = cached.ideas[ideaIndexInsideCache].stages.find((one) => one.ideaStage .idea.kind === 'close'); if (closeStage !== undefined) { ideas.push(cached.ideas[ideaIndexInsideCache]); return true; } else { // console.log('closeStage') // console.log(closeStage) // throw new Error('actually not closed') const stagesListDirty = await __1.NftModule.view.general.listStages(creator, strategyKey, ideaKey, contract); // eliminate nullified stages const stagesList = []; if (cached?.nullifiedIdeas !== undefined) { const nullifiedStages = cached.nullifiedIdeas.get(ideaKey); if (nullifiedStages !== undefined) { for (const stageKey of stagesListDirty) { if (!nullifiedStages.has(stageKey)) { stagesList.push(stageKey); } } } else { stagesList.push(...stagesListDirty); } } else { stagesList.push(...stagesListDirty); } // console.log('stagesList') // console.log(stagesList) const stages = await Promise.all(stagesList.map(async (ideaStageKey) => { const seekStage = cached.ideas[ideaIndexInsideCache].stages.find((one) => one.ideaStageKey === ideaStageKey); if (seekStage !== undefined) { return seekStage; } else { // console.log('ideaStageKey') // console.log(ideaStageKey) const id = await __1.NftModule.view.general.getIdeaNftIdByKeys(creator, strategyKey, ideaKey, ideaStageKey, contract); const ideaStage = await __1.CryptoIdeasModule.getRestoredIdeaByNftId(id, contract, inflateImages); // console.log('ideaStage:') // console.log(ideaStage) // if (ideaStageKey === 1) { // throw new Error('stop') // } ideaStage.content.ideaNftId = Number(id); ideaStage.nftId = Number(id); ideaStage.content.ideaKey = ideaKey; ideaStage.content.ideaStageKey = ideaStageKey; const stage = { ideaStageKey, ideaStage, }; return stage; } })); if (stages.length !== 0) { const idea = { ideaKey, stages, }; ideas.push(idea); } return true; } } } else { throw new Error('getStrategyChain: cached ideaKey does not match'); } } } return false; }; const gotFromCache = await tryFromCache(); // console.log('gotFromCache:') // console.log(gotFromCache) if (!gotFromCache) { const stagesList = await __1.NftModule.view.general.listStages(creator, strategyKey, ideaKey, contract); if (stagesList.length > 0) { const stages = await Promise.all(stagesList.map(async (ideaStageKey) => { __1.LogModule.dev('strategyKey: ' + strategyKey); __1.LogModule.dev('ideaKey: ' + ideaKey); __1.LogModule.dev('ideaStageKey: ' + ideaStageKey); // console.log('pre error Mark 1') const id = await __1.NftModule.view.general.getIdeaNftIdByKeys(creator, strategyKey, ideaKey, ideaStageKey, contract); // console.log('id') // console.log(id) // console.log('pre error Mark 2') const ideaStage = await __1.CryptoIdeasModule.getRestoredIdeaByNftId(id, contract, inflateImages); // console.log('pre error Mark 3') ideaStage.content.ideaNftId = Number(id); ideaStage.nftId = Number(id); ideaStage.content.ideaKey = ideaKey; ideaStage.content.ideaStageKey = ideaStageKey; const stage = { ideaStageKey, ideaStage, }; return stage; })); const idea = { ideaKey, stages, }; ideas.push(idea); } } }; promisesOfProccessIdeas.push(promOfProcId); } // console.log('promisesOfProccessIdeas.length') // console.log(promisesOfProccessIdeas.length) const MAX_PROMISES_PER_STEP = 200; // if the number of promises is too big, we need to split it into smaller steps const promisesCount = promisesOfProccessIdeas.length; if (promisesCount > MAX_PROMISES_PER_STEP) { const stepsCount = Math.ceil(promisesCount / MAX_PROMISES_PER_STEP); for (let i = 0; i < stepsCount; i++) { const start = i * MAX_PROMISES_PER_STEP; const end = Math.min((i + 1) * MAX_PROMISES_PER_STEP, promisesCount); await Promise.all(promisesOfProccessIdeas.slice(start, end).map((each) => each())); // rest a fair bit await new Promise((resolve) => setTimeout(resolve, 200)); } } else { await Promise.all(promisesOfProccessIdeas.map((each) => each())); } // for (const proc of promisesOfProccessIdeas) { // await proc() // } // sort to order by ideaKey ideas.sort((a, b) => { return a.ideaKey - b.ideaKey; }); __1.LogModule.dev('ideas', ideas); const strategy = { strategyKey, ideas, }; return strategy; }; const chronologicalIdeasFromChain = (chain) => { const results = []; for (const each of chain.ideas) { for (const eachIn of each.stages) { results.push(eachIn.ideaStage); } } results.sort((a, b) => { return a.content.ideaNftId - b.content.ideaNftId; }); return results; }; const getActiveIdeasFromChain = (chain) => { const results = []; const chronos = chronologicalIdeasFromChain(chain); const mapOfActiveTickers = new Map(); for (const each of chronos) { const ide = each.idea; if (ide.kind === 'close' && mapOfActiveTickers.has(ide.asset.ticker)) { mapOfActiveTickers.delete(ide.asset.ticker); } else { mapOfActiveTickers.set(ide.asset.ticker, each); } } for (const each of mapOfActiveTickers.entries()) { results.push(each[1]); } return results; }; const postValidationCalculateSummaryCalc = (strategyState) => { let totalIdeas = 0; let totalClosedIdeas = 0; let successIdeas = 0; let lossesIdeas = 0; let lossesPoints = 0; let successPoints = 0; const lastStages = __1.CONTRACT_TOOLS.queryChain.getOnlyLastStageOfEachIdea(strategyState); for (const lastStage of lastStages) { totalIdeas++; if (typeof lastStage.idea !== 'string') { const idea = lastStage.idea; if (idea.kind === 'close') { totalClosedIdeas++; const isProfit = idea.result.summary.profit; if (isProfit) { successIdeas++; successPoints += Math.abs(idea.result.summary.percentage); } else { lossesIdeas++; lossesPoints += Math.abs(idea.result.summary.percentage); } } } } const summaryCalc = { totalIdeas, totalClosedIdeas, successIdeas, lossesIdeas, lossesPoints, successPoints, }; return summaryCalc; }; const getValidatedStrategyChain = async (contract, strategyKey, creator, inflateImages = true, nftIdReduceStep, cached) => { // console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=') // console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=') // console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=') // console.log('=-=-=-=-=-=-=-=-=-=-=-=-=-=-=') // console.log('cached:') // console.log(cached) // console.log(cached?.ideas) // console.log(cached?.ideas[0]?.stages[0]?.ideaStage?.idea) // const strategyChain = await getStrategyChain(contract, strategyKey, creator, inflateImages, nftIdReduceStep, cached); // fs.writeFileSync('strategyChain.json', JSON.stringify(strategyChain)) // if (1 + 1 === 2) { // throw new Error('check temp chain stored') // } // const strategyChain = JSON.parse( // fs.readFileSync('strategyChain.json', 'utf8'), // ) as IStrategyChain // console.log('strategyChain:') // console.log(strategyChain) // console.log('strategyChain.ideas[0].ideaStages') // try { // for (const stuff of strategyChain.ideas[0].ideaStages) { // console.log(stuff) // } // } catch (e) { // throw e // } const chronos = chronologicalIdeasFromChain(strategyChain); // console.log('chronos.length:') // console.log(chronos.length) // console.log('cached?.ideas.length') // console.log(cached?.ideas.length) // console.log('cached?.cachedStrategy.totalIdeas') // console.log(cached?.cachedStrategy.totalIdeas) // console.log(chronos.map((each) => each.idea!)) //for (const eachIndex in chronos) { // const each = chronos[eachIndex] // console.log('============>') // console.log('Idea #' + eachIndex) // console.log('each.idea!') // console.log(each.idea!) // console.log('each.idea!.idea') // console.log(each.idea!.idea) // } // throw new Error('stop') const toCheck = chronos.slice(cached?.cachedStrategy !== undefined ? cached.cachedStrategy.totalIdeas - 1 : 0); // const chronos = JSON.parse( // fs.readFileSync('toCheck.json', 'utf8'), // ) as CONTRACT_INTERFACES.ITradeIdea[] // let toCheck = copyObj(chronos) // console.log('toCheck') // console.log(toCheck) // console.log('toCheck') // console.log(toCheck) // console.log('toCheck[0].creator.companyLogo') // console.log(toCheck[0]?.creator.companyLogo) // console.log('(toCheck[0].idea as ITradeIdeaIdea).asset.image') // console.log((toCheck[0].idea as ITradeIdeaIdea).asset.image) // console.log('toCheck[0].strategy.image') // console.log('toCheck[toCheck.length-2].strategy.image') // console.log(toCheck[toCheck.length - 2].strategy.image) // console.log('toCheck[toCheck.length-1].strategy.image') // console.log(toCheck[toCheck.length - 1].strategy.image) // console.log('cached?.cachedStrategy.strategy.image') // console.log(cached?.cachedStrategy.strategy.image) // fs.writeFileSync('toCheck.json', JSON.stringify(toCheck)) // if toCheck list of idea is greater than 50, we need to split it into smaller steps. // We do separate in ordered chunks of 50 ideas. // After that, we will calculate the hash of each chunk serialized. // We will use the hashes to check if the chunk is already in the cache. // we look for any chunk that is already in the cache. // if it is, we load the cache and continue from this cache and we calculate the rules with next chunk. // in a positive result, we do store it in cache using the chunk hash as key. // if we complete the rules calculation, we delete the cache and return the result. // we do this using following functions: // deserializeDataTool, // serializeDataTool, // cachePlusUpsert, // cachePlusRetrieve, // cachePlusRemove, let valid; const MAX_CHUNK_SIZE = 10; let toRemoveLaterPriorToReturn = undefined; if (toCheck.length > MAX_CHUNK_SIZE) { const chunks = []; for (let i = 0; i < toCheck.length; i += MAX_CHUNK_SIZE) { chunks.push(toCheck.slice(i, i + MAX_CHUNK_SIZE)); } const hashes = []; for (const chunk of chunks) { const chunkHash = 'ck-' + version_contract_db_json_1.contractDbVersion + '-' + contract.gate.address + '-' + __1.CryptoJs.SHA1((0, __1.serializeDataTool)(chunk)).toString(); hashes.push(chunkHash); } const featureKey = 'stgChaCks:'; let lastStrategyState = undefined; let lastChunkCalculated = -1; __1.LogModule.prod('Computing verify of strategy "' + strategyKey + '" with ' + chunks.length + ' chunks'); for (const hashIndex in hashes) { // try to find stored cache with this hash and const cachedChunkResult = await (0, __1.cachePlusRetrieve)(featureKey, featureKey + hashes[hashIndex]); if (cachedChunkResult !== undefined) { __1.LogModule.prod('Found cached chunk: ' + hashes[hashIndex] + ' (' + hashIndex + ')'); const cachedChunk = (0, __1.deserializeDataTool)(cachedChunkResult); valid = { valid: true, cachedStrategyState: cachedChunk, }; lastStrategyState = cachedChunk; lastChunkCalculated = +hashIndex; break; } } // console.log('---------- emergengy debug ----------') // const emergencyRead = deserializeDataTool( // fs.readFileSync('emergencySituationStore52.txt', 'utf8'), // ) as CONTRACT_INTERFACES.IStrategyState // valid = { // valid: true, // cachedStrategyState: emergencyRead, // } // lastStrategyState = emergencyRead // lastChunkCalculated = 52 // lastChunkCalculated always points to the last chunk calculated. while (lastChunkCalculated < chunks.length - 1) { __1.LogModule.prod('Calculating chunk: ' + (lastChunkCalculated + 1)); const chunk = chunks[lastChunkCalculated + 1]; valid = await __1.RULES.v1.rules(chunk, lastStrategyState); // if (typeof valid === 'string') { // console.log('valid') // console.log(valid) // throw new Error('ck') // } if (typeof valid === 'string') { // before thou, we do remove the cache if lastChunkCalculated is not -1 if (lastChunkCalculated !== -1) { await (0, __1.cachePlusRemove)(featureKey + hashes[lastChunkCalculated]); } throw new Error('CONTRACT RULES ERROR: Invalid strategy chain: ' + valid); } lastStrategyState = valid.cachedStrategyState; await (0, __1.cachePlusUpsert)(featureKey, featureKey + hashes[lastChunkCalculated + 1], (0, __1.serializeDataTool)(lastStrategyState)); await (0, __1.cachePlusRemove)(featureKey + hashes[lastChunkCalculated]); lastChunkCalculated++; if (lastChunkCalculated >= chunks.length - 1) { toRemoveLaterPriorToReturn = async () => { await (0, __1.cachePlusRemove)(featureKey + hashes[lastChunkCalculated]); }; } } __1.LogModule.prod('All chunks calculated'); } else { valid = toCheck.length === 0 ? { valid: true, cachedStrategyState: cached?.cachedStrategy, } : await __1.RULES.v1.rules(toCheck, cached?.cachedStrategy); } // console.log('chronos AFTER:') // console.log(chronos.map((each) => each.idea!)) // console.log('valid:') // console.log(valid!) if (typeof valid === 'string') { throw new Error('CONTRACT RULES ERROR: Invalid strategy chain: ' + valid); } // Now we need to validate pricing and apply right timestamps. // ACTUALLY above now happens on rules. /* const validatedPricing = cached?.validatedPricing !== undefined ? cached?.validatedPricing : new Set<number>() for (const idea of chronos) { if (idea.nftId === undefined) { throw new Error( 'getValidatedStrategyChain: idea.nftId is undefined', ) } if (!validatedPricing.has(idea.nftId!)) { await ProvableModule.validatePricingSignature(idea) validatedPricing.add(idea.nftId!) } } */ // Clean Up the nullified ideas. const nullifiedIdeas = cached !== undefined ? cached.nullifiedIdeas : new Map(); for (const ideaIndex in strategyChain.ideas) { for (const stageIndex in strategyChain.ideas[ideaIndex].stages) { const stage = strategyChain.ideas[ideaIndex].stages[stageIndex]; if (stage.ideaStage.nullified !== undefined) { strategyChain.ideas[ideaIndex].stages.splice(Number(stageIndex), 1); let nullifiedIdea = nullifiedIdeas.get(stage.ideaStage.content.ideaKey); if (nullifiedIdea === undefined) { nullifiedIdeas.set(stage.ideaStage.content.ideaKey, new Set()); nullifiedIdea = nullifiedIdeas.get(stage.ideaStage.content.ideaKey); } nullifiedIdea.add(stage.ideaStage.content.ideaStageKey); } if (strategyChain.ideas[ideaIndex].stages.length === 0) { strategyChain.ideas.splice(Number(ideaIndex), 1); } } } // Completing Missing PostProcessing Data // by computing summaryCalc if (valid.cachedStrategyState !== undefined) { valid.cachedStrategyState.strategy.summaryCalc = postValidationCalculateSummaryCalc(valid.cachedStrategyState); } if (toRemoveLaterPriorToReturn !== undefined) { await toRemoveLaterPriorToReturn(); } return { result: strategyChain, cache: { nullifiedIdeas, ideas: strategyChain.ideas, cachedStrategy: valid.cachedStrategyState, }, }; }; exports.StrategyChainModule = { getStrategyChain, getValidatedStrategyChain, chronologicalIdeasFromChain, getActiveIdeasFromChain, }; //# sourceMappingURL=strategy-chain.module.js.map