Search
Search

Transaction: EWc6JTm...pvwu

Receiver
Status
Succeeded
Transaction Fee
0.00101 
Deposit Value
0 
Gas Used
14 Tgas
Attached Gas
100 Tgas
Created
December 04, 2023 at 5:47:41pm
Hash
EWc6JTmKFU4N1qC2f64JjisEFrkWLdYuitNkpKnqpvwu

Actions

Called method: 'set' in contract: social.near
Arguments:
{ "data": { "f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb": { "widget": { "lib.article": { "": "// lib.article\r\n\r\nconst {\r\n mainStateUpdate,\r\n isTest,\r\n stateUpdate,\r\n functionsToCallByLibrary,\r\n callLibs,\r\n baseAction,\r\n kanbanColumns,\r\n widgets,\r\n usersSBTs,\r\n} = props;\r\n\r\nconst libName = \"article\"; // EDIT: set lib name\r\nconst functionsToCall = functionsToCallByLibrary[libName];\r\n\r\nlet resultFunctionsToCallByLibrary = Object.assign(\r\n {},\r\n functionsToCallByLibrary\r\n);\r\nlet resultFunctionsToCall = [];\r\n\r\nconst currentVersion = \"0.0.2\"; // EDIT: Set version\r\n\r\nconst prodAction = `${baseAction}_v${currentVersion}`;\r\nconst testAction = `test_${prodAction}`;\r\nconst versionsBaseActions = isTest ? `test_${baseAction}` : baseAction;\r\nconst action = isTest ? testAction : prodAction;\r\n// START LIB CALLS SECTION\r\n// interface FunctionCall {\r\n// functionName: string,\r\n// key: string, // The state of the caller will be updated with this string as a key\r\n// props: Record<string, any> // function parameters as object\r\n// }\r\n\r\n// type LibsCalls = Record<string, FunctionCall> // Key is lib name after lib.\r\n\r\nconst libSrcArray = [widgets.libSBT]; // string to lib widget // EDIT: set libs to call\r\n\r\nconst libCalls = {};\r\nlibSrcArray.forEach((libSrc) => {\r\n const libName = libSrc.split(\"lib.\")[1];\r\n libCalls[libName] = [];\r\n});\r\n\r\nState.init({\r\n libCalls, // is a LibsCalls object\r\n});\r\n// END LIB CALLS SECTION\r\n\r\nfunction log(message) {\r\n console.log(`lib.${libName}`, message);\r\n}\r\n\r\nfunction logError(message) {\r\n console.error(`lib.${libName}`, message);\r\n}\r\n\r\nfunction libStateUpdate(obj) {\r\n State.update(obj);\r\n}\r\n\r\n// START LIB FUNCTIONS: EDIT set functions you need\r\nfunction canUserCreateArticle(props) {\r\n const { env, accountId, sbtsNames } = props;\r\n\r\n if (accountId) {\r\n setAreValidUsers([accountId], sbtsNames);\r\n } else {\r\n return false;\r\n }\r\n\r\n const result = state[`isValidUser-${accountId}`];\r\n resultFunctionsToCall = resultFunctionsToCall.filter((call) => {\r\n const discardCondition =\r\n call.functionName === \"canUserCreateArticle\" && result !== undefined;\r\n return !discardCondition;\r\n });\r\n\r\n return result;\r\n}\r\n\r\nfunction setAreValidUsers(accountIds, sbtsNames) {\r\n const newLibsCalls = Object.assign({}, state.libCalls);\r\n if (!newLibsCalls.SBT) {\r\n logError(\"Key SBT is not set in lib.\", libName);\r\n }\r\n\r\n accountIds.forEach((accountId) => {\r\n const isCallPushed =\r\n newLibsCalls.SBT.find((libCall) => {\r\n return (\r\n libCall.functionName === \"isValidUser\" &&\r\n libCall.props.accountId === accountId\r\n );\r\n }) !== undefined;\r\n const isCallReturned = state[`isValidUser-${accountId}`] !== undefined;\r\n\r\n if (isCallPushed || isCallReturned) {\r\n return;\r\n }\r\n\r\n const existingUserSBTs = usersSBTs.find(\r\n (userSBTs) => userSBTs.user === accountId\r\n );\r\n\r\n if (!existingUserSBTs) {\r\n newLibsCalls.SBT.push({\r\n functionName: \"isValidUser\",\r\n key: `isValidUser-${accountId}`,\r\n props: {\r\n accountId,\r\n sbtsNames,\r\n },\r\n });\r\n }\r\n });\r\n State.update({ libCalls: newLibsCalls });\r\n}\r\n\r\nfunction createArticle(props) {\r\n const { article, onCommit, onCancel } = props;\r\n\r\n saveHandler(article, onCommit, onCancel);\r\n\r\n resultFunctionsToCall = resultFunctionsToCall.filter((call) => {\r\n return call.functionName !== \"createArticle\";\r\n });\r\n\r\n return article;\r\n}\r\n\r\nconst saveHandler = (article, onCommit, onCancel) => {\r\n if (article.title && article.body) {\r\n const newData = composeData(article);\r\n\r\n Social.set(newData, {\r\n force: true,\r\n onCommit,\r\n onCancel,\r\n });\r\n } else {\r\n logError(\"Article is missing title or body\");\r\n }\r\n};\r\n\r\nfunction composeData(article) {\r\n let data;\r\n data = {\r\n [action]: {\r\n main: JSON.stringify(article),\r\n },\r\n index: {\r\n [action]: JSON.stringify({\r\n key: \"main\",\r\n value: {\r\n type: \"md\",\r\n id: article.id ?? `${context.accountId}-${Date.now()}`,\r\n },\r\n }),\r\n },\r\n };\r\n\r\n return data;\r\n}\r\n\r\nfunction getArticleBlackListByBlockHeight() {\r\n return [\r\n 91092435, 91092174, 91051228, 91092223, 91051203, 98372095, 96414482,\r\n 96412953, 103131250, 106941548,\r\n ];\r\n}\r\n\r\nfunction getArticleBlackListByRealArticleId() {\r\n return [\r\n \"blaze.near-1690410074090\",\r\n \"blaze.near-1690409577184\",\r\n \"blaze.near-1690803928696\",\r\n \"blaze.near-1690803872147\",\r\n \"blaze.near-1690574978421\",\r\n \"f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb-1691703303485\",\r\n \"f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb-1691702619510\",\r\n \"f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb-1691702487944\",\r\n \"f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb-1691707918243\",\r\n \"f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb-1691707889297\",\r\n \"blaze.near-1697211386373\",\r\n \"silkking.near-1696797896796\",\r\n \"silkking.near-1696797784589\",\r\n \"silkking.near-1696797350661\",\r\n \"silkking.near-1696797276482\",\r\n \"silkking.near-1696797155012\",\r\n \"silkking.near-1696796793605\",\r\n \"silkking.near-1696796543546\",\r\n \"silkking.near-1696795954175\",\r\n \"silkking.near-1696794571874\",\r\n \"silkking.near-1696792789177\",\r\n \"zarmade.near-1690578803015\",\r\n ];\r\n}\r\n\r\nfunction canUserEditArticle(props) {\r\n const { article } = props;\r\n\r\n return article.author === context.accountId;\r\n}\r\n\r\nfunction getArticlesIndexes(action, subscribe) {\r\n return Social.index(action, \"main\", {\r\n order: \"desc\",\r\n subscribe,\r\n // limit: 10,\r\n });\r\n}\r\n\r\nfunction getArticlesNormalized(env) {\r\n const articlesByVersion = Object.keys(versions).map((version, index, arr) => {\r\n const action = versions[version].action;\r\n const subscribe = index + 1 === arr.length;\r\n const articlesIndexes = getArticlesIndexes(action, subscribe);\r\n if (!articlesIndexes) return [];\r\n const validArticlesIndexes = filterInvalidArticlesIndexes(\r\n env,\r\n articlesIndexes\r\n );\r\n\r\n const validLatestEdits = getLatestEdits(validArticlesIndexes);\r\n\r\n const articles = validLatestEdits\r\n .map((article) => {\r\n return getArticle(article, action);\r\n })\r\n .filter((article) => {\r\n return article !== undefined;\r\n });\r\n return articles;\r\n });\r\n\r\n return normalizeLibData(articlesByVersion);\r\n}\r\n\r\nfunction getArticle(articleIndex, action) {\r\n const article = Social.get(\r\n `${articleIndex.accountId}/${action}/main`,\r\n articleIndex.blockHeight\r\n );\r\n\r\n let articleParsed = undefined;\r\n if (article) {\r\n articleParsed = JSON.parse(article);\r\n articleParsed.blockHeight = articleIndex.blockHeight;\r\n articleParsed.id = articleIndex.value.id;\r\n }\r\n\r\n if (articleParsed) {\r\n return articleParsed;\r\n }\r\n}\r\n\r\nfunction getLatestEdits(newFormatArticlesIndexes) {\r\n return newFormatArticlesIndexes.filter((articleIndex) => {\r\n const latestEditForThisArticle = newFormatArticlesIndexes.find(\r\n (newArticleData) => newArticleData.value.id === articleIndex.value.id\r\n );\r\n return (\r\n JSON.stringify(articleIndex) === JSON.stringify(latestEditForThisArticle)\r\n );\r\n });\r\n}\r\n\r\nfunction filterInvalidArticlesIndexes(env, articlesIndexes) {\r\n return articlesIndexes\r\n .filter((articleIndex) => articleIndex.value.id) // Has id\r\n .filter(\r\n (articleIndex) =>\r\n articleIndex.value.id.split(\"-\")[0] === articleIndex.accountId\r\n ) // id begins with same accountId as index object\r\n .filter(\r\n (articleIndex) =>\r\n !getArticleBlackListByBlockHeight().includes(articleIndex.blockHeight) // Blockheight is not in blacklist\r\n )\r\n .filter(\r\n (articleIndex) =>\r\n !getArticleBlackListByRealArticleId().includes(articleIndex.value.id) // Article id is not in blacklist\r\n );\r\n}\r\n\r\nfunction getArticles(props) {\r\n const { env, sbtsNames } = props;\r\n // Call other libs\r\n const normArticles = getArticlesNormalized(env);\r\n\r\n // Keep last edit from every article\r\n const lastEditionArticles = normArticles.filter((article) => {\r\n return normArticles.find(\r\n (compArticle) => JSON.stringify(compArticle) === JSON.stringify(article)\r\n );\r\n });\r\n\r\n const lastEditionArticlesAuthors = lastEditionArticles.map((article) => {\r\n return article.author;\r\n });\r\n\r\n setAreValidUsers(lastEditionArticlesAuthors, sbtsNames);\r\n\r\n resultFunctionsToCall = resultFunctionsToCall.filter((call) => {\r\n const discardCondition =\r\n call.functionName === \"getArticles\" &&\r\n state[`isValidUser-${call.props.accountId}`] !== undefined;\r\n return !discardCondition;\r\n });\r\n\r\n const finalArticles = filterValidArticles(lastEditionArticles);\r\n const finalArticlesMapped = {};\r\n sbtsNames.forEach((sbtName) => {\r\n const sbtArticles = finalArticles.filter((article) => {\r\n if (!article.sbts) return false;\r\n return article.sbts.indexOf(sbtName) !== -1;\r\n });\r\n finalArticlesMapped[sbtName] = sbtArticles;\r\n });\r\n\r\n return finalArticlesMapped;\r\n}\r\n\r\nfunction filterValidator(articles) {\r\n return articles.filter((article) => {\r\n return (\r\n article.sbts.find((articleSbt) => {\r\n return (\r\n state[`isValidUser-${article.author}`][articleSbt] ||\r\n articleSbt === \"public\"\r\n );\r\n }) !== undefined\r\n );\r\n });\r\n}\r\n\r\nfunction filterValidArticles(articles) {\r\n let filteredArticles = filterValidator(filteredArticles ?? articles);\r\n\r\n return filteredArticles;\r\n}\r\n\r\nfunction filterMultipleKanbanTags(articleTags, kanbanTags) {\r\n const normalizedKanbanTag = [];\r\n\r\n kanbanTags.forEach((tag) => {\r\n normalizedKanbanTag.push(tag.replace(` `, \"-\"));\r\n });\r\n\r\n const kanbanTagsInArticleTags = articleTags.filter((tag) =>\r\n normalizedKanbanTag.includes(tag.toLowerCase().replace(` `, \"-\"))\r\n );\r\n\r\n const nonKanbanTags = articleTags.filter(\r\n (tag) => !normalizedKanbanTag.includes(tag.toLowerCase().replace(` `, \"-\"))\r\n );\r\n\r\n const result = [...nonKanbanTags, kanbanTagsInArticleTags[0]];\r\n\r\n return result;\r\n}\r\n\r\nfunction normalizeOldToV_0_0_1(article) {\r\n article.realArticleId = `${article.author}-${article.timeCreate}`;\r\n article.sbts = [\"public\"];\r\n\r\n return article;\r\n}\r\n\r\nfunction normalizeFromV0_0_1ToV0_0_2(article) {\r\n article.title = article.articleId;\r\n article.id = article.realArticleId;\r\n if (article.sbts[0] !== \"public\") {\r\n article.sbts[0] = article.sbts[0] + \" - class 1\";\r\n } // There is only one article that is not public and only has class 1\r\n\r\n delete article.articleId;\r\n delete article.realArticleId;\r\n\r\n return article;\r\n}\r\n\r\nfunction normalizeFromV0_0_2ToV0_0_3(article) {\r\n if (!Array.isArray(article.tags) && typeof article.tags === \"object\") {\r\n article.tags = Object.keys(article.tags);\r\n }\r\n\r\n article.tags = article.tags.filter(\r\n (tag) => tag !== undefined && tag !== null\r\n );\r\n\r\n if (kanbanColumns) {\r\n const lowerCaseColumns = [];\r\n kanbanColumns.forEach((cl) => {\r\n lowerCaseColumns.push(cl.toLowerCase());\r\n });\r\n\r\n article.tags = filterMultipleKanbanTags(article.tags, lowerCaseColumns);\r\n }\r\n\r\n if (article.blockHeight < 105654020 && article.sbts.includes(\"public\")) {\r\n article.sbts = [\"fractal.i-am-human.near - class 1\"];\r\n }\r\n\r\n return article;\r\n}\r\n\r\n// END LIB FUNCTIONS\r\n\r\n// EDIT: set functions you want to export\r\nfunction callFunction(call) {\r\n if (call.functionName === \"canUserCreateArticle\") {\r\n return canUserCreateArticle(call.props);\r\n } else if (call.functionName === \"createArticle\") {\r\n return createArticle(call.props);\r\n } else if (call.functionName === \"canUserEditArticle\") {\r\n return canUserEditArticle(call.props);\r\n } else if (call.functionName === \"getArticles\") {\r\n return getArticles(call.props);\r\n }\r\n}\r\n\r\n// EDIT: set versions you want to handle, considering their action to Social.index and the way to transform to one version to another (normalization)\r\nconst versions = {\r\n old: {\r\n normalizationFunction: normalizeOldToV_0_0_1,\r\n action: versionsBaseActions,\r\n },\r\n \"v0.0.1\": {\r\n normalizationFunction: normalizeFromV0_0_1ToV0_0_2,\r\n action: `${versionsBaseActions}_v0.0.1`,\r\n },\r\n \"v0.0.2\": {\r\n normalizationFunction: normalizeFromV0_0_2ToV0_0_3,\r\n action: `${versionsBaseActions}_v0.0.2`,\r\n },\r\n};\r\n\r\nfunction normalizeLibData(libDataByVersion) {\r\n let libData;\r\n\r\n Object.keys(versions).forEach((version, index, array) => {\r\n const normFn = versions[version].normalizationFunction;\r\n const normLibData = libDataByVersion[index].map((libData, i) => {\r\n return normFn(libData);\r\n });\r\n\r\n if (index + 1 === array.length) {\r\n // Last index\r\n libData = normLibData;\r\n return;\r\n }\r\n libDataByVersion[index + 1] =\r\n libDataByVersion[index + 1].concat(normLibData);\r\n });\r\n\r\n return libData;\r\n}\r\n\r\nif (functionsToCall && functionsToCall.length > 0) {\r\n const updateObj = Object.assign({}, functionsToCallByLibrary);\r\n resultFunctionsToCall = [...functionsToCall];\r\n functionsToCall.forEach((call) => {\r\n updateObj[call.key] = callFunction(call);\r\n });\r\n\r\n resultFunctionsToCallByLibrary[libName] = resultFunctionsToCall;\r\n updateObj.functionsToCallByLibrary = resultFunctionsToCallByLibrary;\r\n\r\n const oldUsersSBTs = usersSBTs;\r\n // {\r\n // user: string,\r\n // credentials: {},\r\n // }\r\n\r\n const newUsersSBTs = Object.keys(state).map((key) => {\r\n if (key.includes(\"isValidUser-\")) {\r\n if (state[key] !== undefined) {\r\n const user = key.split(\"isValidUser-\")[1];\r\n const credentials = state[key];\r\n\r\n const oldUsers = oldUsersSBTs.map((userSbts) => userSbts.user);\r\n\r\n if (!oldUsers.includes(user)) {\r\n return {\r\n user,\r\n credentials,\r\n };\r\n }\r\n }\r\n }\r\n });\r\n\r\n const finalUsersSBTs = [...oldUsersSBTs, ...newUsersSBTs].filter(\r\n (userSBTs) => userSBTs !== undefined\r\n );\r\n\r\n if (finalUsersSBTs[0]) {\r\n mainStateUpdate({ usersSBTs: finalUsersSBTs });\r\n }\r\n\r\n stateUpdate(updateObj);\r\n}\r\n\r\nreturn (\r\n <>\r\n {libSrcArray.map((src) => {\r\n return callLibs(\r\n src,\r\n libStateUpdate,\r\n state.libCalls,\r\n {},\r\n `lib.${libName}`\r\n );\r\n })}\r\n </>\r\n);\r\n" } } } } }

Transaction Execution Plan

Convert Transaction To Receipt
Gas Burned:
2 Tgas
Tokens Burned:
0.00025 
Receipt:
Predecessor ID:
Receiver ID:
Gas Burned:
7 Tgas
Tokens Burned:
0.00077 
Called method: 'set' in contract: social.near
Arguments:
{ "data": { "f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb": { "widget": { "lib.article": { "": "// lib.article\r\n\r\nconst {\r\n mainStateUpdate,\r\n isTest,\r\n stateUpdate,\r\n functionsToCallByLibrary,\r\n callLibs,\r\n baseAction,\r\n kanbanColumns,\r\n widgets,\r\n usersSBTs,\r\n} = props;\r\n\r\nconst libName = \"article\"; // EDIT: set lib name\r\nconst functionsToCall = functionsToCallByLibrary[libName];\r\n\r\nlet resultFunctionsToCallByLibrary = Object.assign(\r\n {},\r\n functionsToCallByLibrary\r\n);\r\nlet resultFunctionsToCall = [];\r\n\r\nconst currentVersion = \"0.0.2\"; // EDIT: Set version\r\n\r\nconst prodAction = `${baseAction}_v${currentVersion}`;\r\nconst testAction = `test_${prodAction}`;\r\nconst versionsBaseActions = isTest ? `test_${baseAction}` : baseAction;\r\nconst action = isTest ? testAction : prodAction;\r\n// START LIB CALLS SECTION\r\n// interface FunctionCall {\r\n// functionName: string,\r\n// key: string, // The state of the caller will be updated with this string as a key\r\n// props: Record<string, any> // function parameters as object\r\n// }\r\n\r\n// type LibsCalls = Record<string, FunctionCall> // Key is lib name after lib.\r\n\r\nconst libSrcArray = [widgets.libSBT]; // string to lib widget // EDIT: set libs to call\r\n\r\nconst libCalls = {};\r\nlibSrcArray.forEach((libSrc) => {\r\n const libName = libSrc.split(\"lib.\")[1];\r\n libCalls[libName] = [];\r\n});\r\n\r\nState.init({\r\n libCalls, // is a LibsCalls object\r\n});\r\n// END LIB CALLS SECTION\r\n\r\nfunction log(message) {\r\n console.log(`lib.${libName}`, message);\r\n}\r\n\r\nfunction logError(message) {\r\n console.error(`lib.${libName}`, message);\r\n}\r\n\r\nfunction libStateUpdate(obj) {\r\n State.update(obj);\r\n}\r\n\r\n// START LIB FUNCTIONS: EDIT set functions you need\r\nfunction canUserCreateArticle(props) {\r\n const { env, accountId, sbtsNames } = props;\r\n\r\n if (accountId) {\r\n setAreValidUsers([accountId], sbtsNames);\r\n } else {\r\n return false;\r\n }\r\n\r\n const result = state[`isValidUser-${accountId}`];\r\n resultFunctionsToCall = resultFunctionsToCall.filter((call) => {\r\n const discardCondition =\r\n call.functionName === \"canUserCreateArticle\" && result !== undefined;\r\n return !discardCondition;\r\n });\r\n\r\n return result;\r\n}\r\n\r\nfunction setAreValidUsers(accountIds, sbtsNames) {\r\n const newLibsCalls = Object.assign({}, state.libCalls);\r\n if (!newLibsCalls.SBT) {\r\n logError(\"Key SBT is not set in lib.\", libName);\r\n }\r\n\r\n accountIds.forEach((accountId) => {\r\n const isCallPushed =\r\n newLibsCalls.SBT.find((libCall) => {\r\n return (\r\n libCall.functionName === \"isValidUser\" &&\r\n libCall.props.accountId === accountId\r\n );\r\n }) !== undefined;\r\n const isCallReturned = state[`isValidUser-${accountId}`] !== undefined;\r\n\r\n if (isCallPushed || isCallReturned) {\r\n return;\r\n }\r\n\r\n const existingUserSBTs = usersSBTs.find(\r\n (userSBTs) => userSBTs.user === accountId\r\n );\r\n\r\n if (!existingUserSBTs) {\r\n newLibsCalls.SBT.push({\r\n functionName: \"isValidUser\",\r\n key: `isValidUser-${accountId}`,\r\n props: {\r\n accountId,\r\n sbtsNames,\r\n },\r\n });\r\n }\r\n });\r\n State.update({ libCalls: newLibsCalls });\r\n}\r\n\r\nfunction createArticle(props) {\r\n const { article, onCommit, onCancel } = props;\r\n\r\n saveHandler(article, onCommit, onCancel);\r\n\r\n resultFunctionsToCall = resultFunctionsToCall.filter((call) => {\r\n return call.functionName !== \"createArticle\";\r\n });\r\n\r\n return article;\r\n}\r\n\r\nconst saveHandler = (article, onCommit, onCancel) => {\r\n if (article.title && article.body) {\r\n const newData = composeData(article);\r\n\r\n Social.set(newData, {\r\n force: true,\r\n onCommit,\r\n onCancel,\r\n });\r\n } else {\r\n logError(\"Article is missing title or body\");\r\n }\r\n};\r\n\r\nfunction composeData(article) {\r\n let data;\r\n data = {\r\n [action]: {\r\n main: JSON.stringify(article),\r\n },\r\n index: {\r\n [action]: JSON.stringify({\r\n key: \"main\",\r\n value: {\r\n type: \"md\",\r\n id: article.id ?? `${context.accountId}-${Date.now()}`,\r\n },\r\n }),\r\n },\r\n };\r\n\r\n return data;\r\n}\r\n\r\nfunction getArticleBlackListByBlockHeight() {\r\n return [\r\n 91092435, 91092174, 91051228, 91092223, 91051203, 98372095, 96414482,\r\n 96412953, 103131250, 106941548,\r\n ];\r\n}\r\n\r\nfunction getArticleBlackListByRealArticleId() {\r\n return [\r\n \"blaze.near-1690410074090\",\r\n \"blaze.near-1690409577184\",\r\n \"blaze.near-1690803928696\",\r\n \"blaze.near-1690803872147\",\r\n \"blaze.near-1690574978421\",\r\n \"f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb-1691703303485\",\r\n \"f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb-1691702619510\",\r\n \"f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb-1691702487944\",\r\n \"f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb-1691707918243\",\r\n \"f2bc8abdb8ba64fe5aac9689ded9491ff0e6fdcd7a5c680b7cf364142d1789fb-1691707889297\",\r\n \"blaze.near-1697211386373\",\r\n \"silkking.near-1696797896796\",\r\n \"silkking.near-1696797784589\",\r\n \"silkking.near-1696797350661\",\r\n \"silkking.near-1696797276482\",\r\n \"silkking.near-1696797155012\",\r\n \"silkking.near-1696796793605\",\r\n \"silkking.near-1696796543546\",\r\n \"silkking.near-1696795954175\",\r\n \"silkking.near-1696794571874\",\r\n \"silkking.near-1696792789177\",\r\n \"zarmade.near-1690578803015\",\r\n ];\r\n}\r\n\r\nfunction canUserEditArticle(props) {\r\n const { article } = props;\r\n\r\n return article.author === context.accountId;\r\n}\r\n\r\nfunction getArticlesIndexes(action, subscribe) {\r\n return Social.index(action, \"main\", {\r\n order: \"desc\",\r\n subscribe,\r\n // limit: 10,\r\n });\r\n}\r\n\r\nfunction getArticlesNormalized(env) {\r\n const articlesByVersion = Object.keys(versions).map((version, index, arr) => {\r\n const action = versions[version].action;\r\n const subscribe = index + 1 === arr.length;\r\n const articlesIndexes = getArticlesIndexes(action, subscribe);\r\n if (!articlesIndexes) return [];\r\n const validArticlesIndexes = filterInvalidArticlesIndexes(\r\n env,\r\n articlesIndexes\r\n );\r\n\r\n const validLatestEdits = getLatestEdits(validArticlesIndexes);\r\n\r\n const articles = validLatestEdits\r\n .map((article) => {\r\n return getArticle(article, action);\r\n })\r\n .filter((article) => {\r\n return article !== undefined;\r\n });\r\n return articles;\r\n });\r\n\r\n return normalizeLibData(articlesByVersion);\r\n}\r\n\r\nfunction getArticle(articleIndex, action) {\r\n const article = Social.get(\r\n `${articleIndex.accountId}/${action}/main`,\r\n articleIndex.blockHeight\r\n );\r\n\r\n let articleParsed = undefined;\r\n if (article) {\r\n articleParsed = JSON.parse(article);\r\n articleParsed.blockHeight = articleIndex.blockHeight;\r\n articleParsed.id = articleIndex.value.id;\r\n }\r\n\r\n if (articleParsed) {\r\n return articleParsed;\r\n }\r\n}\r\n\r\nfunction getLatestEdits(newFormatArticlesIndexes) {\r\n return newFormatArticlesIndexes.filter((articleIndex) => {\r\n const latestEditForThisArticle = newFormatArticlesIndexes.find(\r\n (newArticleData) => newArticleData.value.id === articleIndex.value.id\r\n );\r\n return (\r\n JSON.stringify(articleIndex) === JSON.stringify(latestEditForThisArticle)\r\n );\r\n });\r\n}\r\n\r\nfunction filterInvalidArticlesIndexes(env, articlesIndexes) {\r\n return articlesIndexes\r\n .filter((articleIndex) => articleIndex.value.id) // Has id\r\n .filter(\r\n (articleIndex) =>\r\n articleIndex.value.id.split(\"-\")[0] === articleIndex.accountId\r\n ) // id begins with same accountId as index object\r\n .filter(\r\n (articleIndex) =>\r\n !getArticleBlackListByBlockHeight().includes(articleIndex.blockHeight) // Blockheight is not in blacklist\r\n )\r\n .filter(\r\n (articleIndex) =>\r\n !getArticleBlackListByRealArticleId().includes(articleIndex.value.id) // Article id is not in blacklist\r\n );\r\n}\r\n\r\nfunction getArticles(props) {\r\n const { env, sbtsNames } = props;\r\n // Call other libs\r\n const normArticles = getArticlesNormalized(env);\r\n\r\n // Keep last edit from every article\r\n const lastEditionArticles = normArticles.filter((article) => {\r\n return normArticles.find(\r\n (compArticle) => JSON.stringify(compArticle) === JSON.stringify(article)\r\n );\r\n });\r\n\r\n const lastEditionArticlesAuthors = lastEditionArticles.map((article) => {\r\n return article.author;\r\n });\r\n\r\n setAreValidUsers(lastEditionArticlesAuthors, sbtsNames);\r\n\r\n resultFunctionsToCall = resultFunctionsToCall.filter((call) => {\r\n const discardCondition =\r\n call.functionName === \"getArticles\" &&\r\n state[`isValidUser-${call.props.accountId}`] !== undefined;\r\n return !discardCondition;\r\n });\r\n\r\n const finalArticles = filterValidArticles(lastEditionArticles);\r\n const finalArticlesMapped = {};\r\n sbtsNames.forEach((sbtName) => {\r\n const sbtArticles = finalArticles.filter((article) => {\r\n if (!article.sbts) return false;\r\n return article.sbts.indexOf(sbtName) !== -1;\r\n });\r\n finalArticlesMapped[sbtName] = sbtArticles;\r\n });\r\n\r\n return finalArticlesMapped;\r\n}\r\n\r\nfunction filterValidator(articles) {\r\n return articles.filter((article) => {\r\n return (\r\n article.sbts.find((articleSbt) => {\r\n return (\r\n state[`isValidUser-${article.author}`][articleSbt] ||\r\n articleSbt === \"public\"\r\n );\r\n }) !== undefined\r\n );\r\n });\r\n}\r\n\r\nfunction filterValidArticles(articles) {\r\n let filteredArticles = filterValidator(filteredArticles ?? articles);\r\n\r\n return filteredArticles;\r\n}\r\n\r\nfunction filterMultipleKanbanTags(articleTags, kanbanTags) {\r\n const normalizedKanbanTag = [];\r\n\r\n kanbanTags.forEach((tag) => {\r\n normalizedKanbanTag.push(tag.replace(` `, \"-\"));\r\n });\r\n\r\n const kanbanTagsInArticleTags = articleTags.filter((tag) =>\r\n normalizedKanbanTag.includes(tag.toLowerCase().replace(` `, \"-\"))\r\n );\r\n\r\n const nonKanbanTags = articleTags.filter(\r\n (tag) => !normalizedKanbanTag.includes(tag.toLowerCase().replace(` `, \"-\"))\r\n );\r\n\r\n const result = [...nonKanbanTags, kanbanTagsInArticleTags[0]];\r\n\r\n return result;\r\n}\r\n\r\nfunction normalizeOldToV_0_0_1(article) {\r\n article.realArticleId = `${article.author}-${article.timeCreate}`;\r\n article.sbts = [\"public\"];\r\n\r\n return article;\r\n}\r\n\r\nfunction normalizeFromV0_0_1ToV0_0_2(article) {\r\n article.title = article.articleId;\r\n article.id = article.realArticleId;\r\n if (article.sbts[0] !== \"public\") {\r\n article.sbts[0] = article.sbts[0] + \" - class 1\";\r\n } // There is only one article that is not public and only has class 1\r\n\r\n delete article.articleId;\r\n delete article.realArticleId;\r\n\r\n return article;\r\n}\r\n\r\nfunction normalizeFromV0_0_2ToV0_0_3(article) {\r\n if (!Array.isArray(article.tags) && typeof article.tags === \"object\") {\r\n article.tags = Object.keys(article.tags);\r\n }\r\n\r\n article.tags = article.tags.filter(\r\n (tag) => tag !== undefined && tag !== null\r\n );\r\n\r\n if (kanbanColumns) {\r\n const lowerCaseColumns = [];\r\n kanbanColumns.forEach((cl) => {\r\n lowerCaseColumns.push(cl.toLowerCase());\r\n });\r\n\r\n article.tags = filterMultipleKanbanTags(article.tags, lowerCaseColumns);\r\n }\r\n\r\n if (article.blockHeight < 105654020 && article.sbts.includes(\"public\")) {\r\n article.sbts = [\"fractal.i-am-human.near - class 1\"];\r\n }\r\n\r\n return article;\r\n}\r\n\r\n// END LIB FUNCTIONS\r\n\r\n// EDIT: set functions you want to export\r\nfunction callFunction(call) {\r\n if (call.functionName === \"canUserCreateArticle\") {\r\n return canUserCreateArticle(call.props);\r\n } else if (call.functionName === \"createArticle\") {\r\n return createArticle(call.props);\r\n } else if (call.functionName === \"canUserEditArticle\") {\r\n return canUserEditArticle(call.props);\r\n } else if (call.functionName === \"getArticles\") {\r\n return getArticles(call.props);\r\n }\r\n}\r\n\r\n// EDIT: set versions you want to handle, considering their action to Social.index and the way to transform to one version to another (normalization)\r\nconst versions = {\r\n old: {\r\n normalizationFunction: normalizeOldToV_0_0_1,\r\n action: versionsBaseActions,\r\n },\r\n \"v0.0.1\": {\r\n normalizationFunction: normalizeFromV0_0_1ToV0_0_2,\r\n action: `${versionsBaseActions}_v0.0.1`,\r\n },\r\n \"v0.0.2\": {\r\n normalizationFunction: normalizeFromV0_0_2ToV0_0_3,\r\n action: `${versionsBaseActions}_v0.0.2`,\r\n },\r\n};\r\n\r\nfunction normalizeLibData(libDataByVersion) {\r\n let libData;\r\n\r\n Object.keys(versions).forEach((version, index, array) => {\r\n const normFn = versions[version].normalizationFunction;\r\n const normLibData = libDataByVersion[index].map((libData, i) => {\r\n return normFn(libData);\r\n });\r\n\r\n if (index + 1 === array.length) {\r\n // Last index\r\n libData = normLibData;\r\n return;\r\n }\r\n libDataByVersion[index + 1] =\r\n libDataByVersion[index + 1].concat(normLibData);\r\n });\r\n\r\n return libData;\r\n}\r\n\r\nif (functionsToCall && functionsToCall.length > 0) {\r\n const updateObj = Object.assign({}, functionsToCallByLibrary);\r\n resultFunctionsToCall = [...functionsToCall];\r\n functionsToCall.forEach((call) => {\r\n updateObj[call.key] = callFunction(call);\r\n });\r\n\r\n resultFunctionsToCallByLibrary[libName] = resultFunctionsToCall;\r\n updateObj.functionsToCallByLibrary = resultFunctionsToCallByLibrary;\r\n\r\n const oldUsersSBTs = usersSBTs;\r\n // {\r\n // user: string,\r\n // credentials: {},\r\n // }\r\n\r\n const newUsersSBTs = Object.keys(state).map((key) => {\r\n if (key.includes(\"isValidUser-\")) {\r\n if (state[key] !== undefined) {\r\n const user = key.split(\"isValidUser-\")[1];\r\n const credentials = state[key];\r\n\r\n const oldUsers = oldUsersSBTs.map((userSbts) => userSbts.user);\r\n\r\n if (!oldUsers.includes(user)) {\r\n return {\r\n user,\r\n credentials,\r\n };\r\n }\r\n }\r\n }\r\n });\r\n\r\n const finalUsersSBTs = [...oldUsersSBTs, ...newUsersSBTs].filter(\r\n (userSBTs) => userSBTs !== undefined\r\n );\r\n\r\n if (finalUsersSBTs[0]) {\r\n mainStateUpdate({ usersSBTs: finalUsersSBTs });\r\n }\r\n\r\n stateUpdate(updateObj);\r\n}\r\n\r\nreturn (\r\n <>\r\n {libSrcArray.map((src) => {\r\n return callLibs(\r\n src,\r\n libStateUpdate,\r\n state.libCalls,\r\n {},\r\n `lib.${libName}`\r\n );\r\n })}\r\n </>\r\n);\r\n" } } } } }
Empty result
No logs
Receipt:
Predecessor ID:
Receiver ID:
Gas Burned:
4 Tgas
Tokens Burned:
0 
Transferred 0.01829  to f2bc8…142d1789fb
Empty result
No logs