@ixily/activ
Version:
Alpha Capture Trade Idea Verification. Blockchain ownership proven trade ideas and strategies.
582 lines • 26.5 kB
JavaScript
;
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