Search
Search

Transaction: Aw384Uy...Ksyq

Status
Succeeded
Transaction Fee
0.00076 
Deposit Value
0 
Gas Used
7 Tgas
Attached Gas
200 Tgas
Created
May 15, 2024 at 4:44:38am
Hash
Aw384UyMqDzvvmok5FYxXNqbq1SKayi1NWhocJjaKsyq

Actions

Called method: 'register' in contract: query…tform.near
Arguments:
{ "function_name": "devhub_objects", "code": "\n console.log(\"Start handling block\");\n const rfpOps = getRFPOps(block);\n const proposalOps = getProposalOps(block);\n\n const rfpOpsLen = rfpOps.length;\n const proposalOpsLen = proposalOps.length;\n\n if (rfpOpsLen > 0 || proposalOpsLen > 0) {\n const authorToRFPId = buildAuthorToRFPIdMap(block);\n const authorToProposalId = buildAuthorToProposalIdMap(block);\n const blockHeight = block.blockHeight;\n const blockTimestamp = block.header().timestampNanosec;\n try {\n await Promise.all(\n rfpOps\n .map((op) =>\n indexRFPsOp(op, authorToRFPId, blockHeight, blockTimestamp, context)\n )\n .concat(\n proposalOps.map((op) =>\n indexProposalsOp(\n op,\n authorToProposalId,\n blockHeight,\n blockTimestamp,\n context\n )\n )\n )\n );\n } catch (error) {\n console.error(\"Error processing block operations:\", error);\n }\n }\n console.log(\"Finish handling block\");\n}\n\nfunction getAddOrEditObject(block, startsWith) {\n const stateChanges = block.streamerMessage.shards\n .flatMap((e) => e.stateChanges)\n .filter(\n (stateChange) =>\n stateChange.change.accountId === \"truedove38.near\" &&\n stateChange.type === \"data_update\"\n );\n\n const addOrEditObject = stateChanges\n .map((stateChange) => stateChange.change)\n // In devhub contract there is a field rfps: Vector<VersionedRFP> ( initially = rfps: Vector::new(StorageKey::RFPs) )\n // In StorageKey enum it comes on 17th position (0x11 in hex).\n // So 0x11 is used as a prefix for the collection keys (https://docs.near.org/sdk/rust/contract-structure/collections).\n .filter((change) => base64toHex(change.keyBase64).startsWith(startsWith))\n .map((c) => ({\n k: Buffer.from(c.keyBase64, \"base64\"),\n v: Buffer.from(c.valueBase64, \"base64\"),\n }));\n\n return addOrEditObject;\n}\n\n// Borsh https://github.com/near/borsh#specification\nfunction buildAuthorToRFPIdMap(block) {\n return Object.fromEntries(\n getAddOrEditObject(block, \"11\").map((kv) => {\n return [\n // Here we read enum VersionedRFP. So we skip enum byte. This enum has just one variant RFP.\n // It contains id: u32 (4 bytes) and then account_id which is string.\n // String is serialized as length: u32 (4 bytes) and then content of the string\n kv.v.slice(9, 9 + kv.v.slice(5, 9).readUInt32LE()).toString(\"utf-8\"),\n // In Vector, key is prefix + index, where index is u32 in little-endian format.\n // So we skip prefix with slice(1) and read index with readBigUint64LE().\n Number(kv.k.slice(1).readBigUInt64LE()),\n ];\n })\n );\n}\n\nfunction buildAuthorToProposalIdMap(block) {\n return Object.fromEntries(\n getAddOrEditObject(block, \"0e\").map((kv) => {\n return [\n kv.v.slice(9, 9 + kv.v.slice(5, 9).readUInt32LE()).toString(\"utf-8\"),\n Number(kv.k.slice(1).readBigUInt64LE()),\n ];\n })\n );\n}\n\nfunction base64decode(encodedValue) {\n let buff = Buffer.from(encodedValue, \"base64\");\n return JSON.parse(buff.toString(\"utf-8\"));\n}\n\nfunction base64toHex(encodedValue) {\n let buff = Buffer.from(encodedValue, \"base64\");\n return buff.toString(\"hex\");\n}\n\nfunction getDevHubOps(block, methodNames, callbackNames) {\n return block\n .actions()\n .filter((action) => action.receiverId === \"truedove38.near\")\n .flatMap((action) =>\n action.operations\n .filter((operation) => operation[\"FunctionCall\"])\n .map((operation) => ({\n ...operation[\"FunctionCall\"],\n caller: action.predecessorId,\n }))\n .map((operation) => ({\n ...operation,\n methodName: operation.methodName || operation.method_name,\n }))\n .filter(\n (operation) =>\n methodNames.includes(operation.methodName) ||\n (callbackNames.includes(operation.methodName) &&\n operation.caller === \"truedove38.near\")\n )\n .map((functionCallOperation) => ({\n ...functionCallOperation,\n args: base64decode(functionCallOperation.args),\n receiptId: action.receiptId,\n }))\n );\n}\n\nfunction getProposalOps(block) {\n return getDevHubOps(\n block,\n [\n \"edit_proposal\",\n \"edit_proposal_internal\",\n \"edit_proposal_linked_rfp\",\n \"edit_proposal_timeline\",\n ],\n [\"set_block_height_callback\"]\n );\n}\n\nfunction getRFPOps(block) {\n return getDevHubOps(\n block,\n [\"edit_rfp\", \"edit_rfp_timeline\", \"edit_rfp_internal\"],\n [\"set_rfp_block_height_callback\"]\n );\n}\n\nasync function indexProposalsOp(\n op,\n authorToProposalId,\n blockHeight,\n blockTimestamp,\n context\n) {\n let receipt_id = op.receiptId;\n let args = op.args;\n let author = Object.keys(authorToProposalId)[0];\n console.log(`Indexing ${op.methodName} by ${author} at ${blockHeight}`);\n console.log(authorToProposalId);\n let proposal_id = authorToProposalId[author] ?? null;\n let method_name = op.methodName;\n\n let err = await createDump(context, {\n receipt_id,\n method_name,\n block_height: blockHeight,\n block_timestamp: blockTimestamp,\n args: JSON.stringify(args),\n author,\n proposal_id,\n });\n if (err !== null) {\n return;\n }\n\n // currently Query API cannot tell if it's a failed receipt, so we estimate by looking the state changes.\n if (proposal_id === null) {\n console.log(\n `Receipt to ${method_name} with receipt_id ${receipt_id} at ${blockHeight} doesn't result in a state change, it's probably a failed receipt, please check`\n );\n return;\n }\n\n if (method_name === \"set_block_height_callback\") {\n let proposal = {\n id: proposal_id,\n author_id: author,\n };\n\n let err = await createProposal(context, proposal);\n if (err !== null) {\n return;\n }\n\n let linked_rfp = args.proposal.snapshot.linked_rfp;\n let linked_proposals = args.proposal.snapshot.linked_proposals;\n linked_proposals =\n linked_proposals && linked_proposals.length\n ? linked_proposals.join(\",\")\n : \"\"; // Vec<ProposalId>\n\n await createProposalSnapshot(context, {\n proposal_id,\n block_height: blockHeight,\n ts: blockTimestamp,\n views: 1,\n linked_proposals,\n ...args.proposal.snapshot,\n });\n\n await checkAndUpdateLinkedProposals(\n proposal_id,\n linked_rfp,\n blockHeight,\n blockTimestamp\n );\n }\n\n if (method_name === \"edit_proposal\") {\n let linked_rfp = args.body.linked_rfp;\n\n let result = await queryLatestProposalViews(proposal_id);\n let latest_snapshot =\n result.polyprogrammist_near_devhub_objects_proposal_snapshots[0];\n let labels =\n linked_rfp === undefined ? args.labels : latest_snapshot[0].labels;\n\n let linked_proposals = args.proposal.snapshot.linked_proposals;\n linked_proposals =\n linked_proposals && linked_proposals.length\n ? linked_proposals.join(\",\")\n : \"\"; // Vec<ProposalId>\n\n let proposal_snapshot = {\n proposal_id,\n block_height: blockHeight,\n ts: blockTimestamp, // Timestamp\n editor_id: author,\n labels,\n linked_rfp,\n linked_proposals,\n views: latest_snapshot[0].views + 1,\n ...args.body,\n };\n await createProposalSnapshot(context, proposal_snapshot);\n await checkAndUpdateLinkedProposals(\n proposal_id,\n linked_rfp,\n blockHeight,\n blockTimestamp\n );\n }\n\n if (method_name === \"edit_proposal_internal\") {\n let linked_rfp = args.body.linked_rfp;\n\n let result = await queryLatestProposalViews(proposal_id);\n let latest_snapshot =\n result.polyprogrammist_near_devhub_objects_proposal_snapshots[0];\n let labels =\n linked_rfp === undefined ? args.labels : latest_snapshot[0].labels;\n let linked_proposals = args.proposal.snapshot.linked_proposals;\n linked_proposals =\n linked_proposals && linked_proposals.length\n ? linked_proposals.join(\",\")\n : \"\"; // Vec<ProposalId>\n\n let proposal_snapshot = {\n proposal_id,\n block_height: blockHeight,\n ts: blockTimestamp, // Timestamp\n editor_id: author,\n labels,\n linked_rfp,\n linked_proposals,\n views: latest_snapshot[0].views + 1,\n ...args.body,\n };\n await createProposalSnapshot(context, proposal_snapshot);\n await checkAndUpdateLinkedProposals(\n proposal_id,\n linked_rfp,\n blockHeight,\n blockTimestamp\n );\n }\n\n if (method_name === \"edit_proposal_timeline\") {\n let result = await queryLatestProposalSnapshot(proposal_id);\n\n if (Object.keys(result).length !== 0) {\n let latest_proposal_snapshot =\n result.polyprogrammist_near_devhub_objects_proposal_snapshots[0];\n console.log({\n method: \"edit_proposal_timeline\",\n latest_proposal_snapshot,\n });\n let proposal_snapshot = {\n proposal_id,\n block_height: blockHeight,\n ts: blockTimestamp,\n editor_id: author,\n timeline: args.timeline, // TimelineStatus\n views: latest_proposal_snapshot.views + 1,\n ...latest_proposal_snapshot,\n };\n await createProposalSnapshot(context, proposal_snapshot);\n } else {\n console.log(\"Empty object latest_proposal_snapshot result\", { result });\n }\n }\n if (method_name == \"edit_proposal_linked_rfp\") {\n let result = await queryLatestProposalSnapshot(proposal_id);\n\n if (Object.keys(result).length !== 0) {\n let linked_rfp = args.rfp_id;\n let latest_proposal_snapshot =\n result.polyprogrammist_near_devhub_objects_proposal_snapshots[0];\n console.log({\n method: \"edit_proposal_linked_rfp\",\n latest_proposal_snapshot,\n });\n let proposal_snapshot = {\n proposal_id,\n linked_rfp: linked_rfp,\n block_height: blockHeight,\n ts: blockTimestamp,\n editor_id: author,\n timeline: args.timeline, // TimelineStatus\n views: latest_proposal_snapshot.views + 1,\n ...latest_proposal_snapshot,\n };\n await createProposalSnapshot(context, proposal_snapshot);\n await checkAndUpdateLinkedProposals(\n proposal_id,\n linked_rfp,\n blockHeight,\n blockTimestamp\n );\n }\n }\n}\n\nasync function indexRFPsOp(\n op,\n authorToRFPId,\n blockHeight,\n blockTimestamp,\n context\n) {\n let receipt_id = op.receiptId;\n let author = Object.keys(authorToRFPId)[0];\n let args = op.args;\n let rfp_id = authorToRFPId[author] ?? null;\n let method_name = op.methodName;\n\n console.log(\n `Indexing ${method_name} by ${author} at ${blockHeight}, rfp_id = ${rfp_id}`\n );\n\n let err = await createRFPDump(context, {\n receipt_id,\n method_name,\n block_height: blockHeight,\n block_timestamp: blockTimestamp,\n args: JSON.stringify(args),\n author,\n rfp_id,\n });\n if (err !== null) {\n return;\n }\n\n // currently Query API cannot tell if it's a failed receipt, so we estimate by looking the state changes.\n if (rfp_id === null) {\n console.log(\n `Receipt to ${method_name} with receipt_id ${receipt_id} at ${blockHeight} doesn't result in a state change, it's probably a failed receipt, please check`\n );\n return;\n }\n\n if (method_name === \"set_rfp_block_height_callback\") {\n let rfp = {\n id: rfp_id,\n author_id: author,\n };\n\n let err = await createRFP(context, rfp);\n if (err !== null) {\n return;\n }\n\n await createrfpSnapshot(context, {\n rfp_id,\n block_height: blockHeight,\n ts: blockTimestamp,\n views: 1,\n ...args.rfp.snapshot,\n });\n }\n\n if (method_name === \"edit_rfp\") {\n let labels = args.labels;\n\n let result = await queryLatestRFPViews(rfp_id);\n let rfp_snapshot = {\n rfp_id,\n block_height: blockHeight,\n ts: blockTimestamp, // Timestamp\n editor_id: author,\n labels,\n views:\n result.polyprogrammist_near_devhub_objects_rfp_snapshots[0].views + 1,\n ...args.body,\n };\n await createrfpSnapshot(context, rfp_snapshot);\n }\n\n if (method_name === \"edit_rfp_timeline\") {\n try {\n let result = await queryLatestRFPSnapshot(rfp_id);\n if (Object.keys(result).length !== 0) {\n let latest_rfp_snapshot =\n result.polyprogrammist_near_devhub_objects_rfp_snapshots[0];\n console.log({\n method: \"edit_rfp_timeline\",\n latest_rfp_snapshot,\n });\n let rfp_snapshot = {\n rfp_id,\n block_height: blockHeight,\n ts: blockTimestamp,\n editor_id: author,\n timeline: args.timeline, // TimelineStatus\n views: latest_rfp_snapshot.views + 1,\n ...latest_rfp_snapshot,\n };\n await createrfpSnapshot(context, rfp_snapshot);\n } else {\n console.log(\"Empty object latest_rfp_snapshot result\", { result });\n }\n } catch (error) {\n console.error(\"Error editing rfp timeline:\", error);\n }\n }\n}\n\nfunction addToLinkedProposals(linked_proposals, proposal_id) {\n linked_proposals.push(proposal_id);\n return linked_proposals;\n}\n\nfunction removeFromLinkedProposals(linked_proposals, proposal_id) {\n return linked_proposals.filter((id) => id !== proposal_id);\n}\n\nasync function modifySnapshotLinkedProposal(\n rfp_id,\n proposal_id,\n blockHeight,\n blockTimestamp,\n modifyCallback\n) {\n let result = await queryLatestRFPSnapshot(rfp_id);\n\n if (Object.keys(result).length !== 0) {\n let latest_rfp_snapshot =\n result.polyprogrammist_near_devhub_objects_rfp_snapshots[0];\n\n let linked_proposals = modifyCallback(\n latest_rfp_snapshot.linked_proposals,\n proposal_id\n );\n let rfp_snapshot = {\n rfp_id,\n linked_proposals: linked_proposals,\n block_height: blockHeight,\n ts: blockTimestamp,\n ...latest_rfp_snapshot,\n };\n await createrfpSnapshot(context, rfp_snapshot);\n } else {\n console.log(\"Empty object latest_rfp_snapshot result\", { result });\n }\n}\n\nasync function addLinkedProposalToSnapshot(\n rfp_id,\n new_linked_proposal,\n blockHeight,\n blockTimestamp\n) {\n await modifySnapshotLinkedProposal(\n rfp_id,\n new_linked_proposal,\n blockHeight,\n blockTimestamp,\n addToLinkedProposals\n );\n}\n\nasync function removeLinkedProposalFromSnapshot(\n rfp_id,\n proposal_id,\n blockHeight,\n blockTimestamp\n) {\n await modifySnapshotLinkedProposal(\n rfp_id,\n proposal_id,\n blockHeight,\n blockTimestamp,\n removeFromLinkedProposals\n );\n}\n\nasync function checkAndUpdateLinkedProposals(\n proposal_id,\n new_linked_rfp,\n blockHeight,\n blockTimestamp\n) {\n try {\n let latest_linked_rfp = await queryLatestLinkedRFP(\n proposal_id,\n blockTimestamp\n );\n let last_snapshot =\n latest_linked_rfp\n .polyprogrammist_near_devhub_objects_proposal_snapshots[0];\n let latest_linked_rfp_id = undefined;\n if (last_snapshot != undefined) {\n latest_linked_rfp_id = last_snapshot.linked_rfp;\n }\n\n if (new_linked_rfp !== latest_linked_rfp_id) {\n if (new_linked_rfp !== undefined) {\n console.log(\n `Adding linked_rfp ${new_linked_rfp} to proposal ${proposal_id}`\n );\n await addLinkedProposalToSnapshot(\n new_linked_rfp,\n proposal_id,\n blockHeight,\n blockTimestamp\n );\n console.log(`Proposal added to new RFP snapshot`);\n }\n if (latest_linked_rfp_id !== undefined) {\n console.log(\n `Removing linked_rfp ${latest_linked_rfp_id} from proposal ${proposal_id}`\n );\n await removeLinkedProposalFromSnapshot(\n latest_linked_rfp_id,\n proposal_id,\n blockHeight,\n blockTimestamp\n );\n console.log(`Proposal removed from old RFP snapshot`);\n }\n }\n } catch (error) {\n console.error(\"Error checking and updating linked proposals:\", error);\n }\n}\n\nasync function createDump(\n context,\n {\n receipt_id,\n method_name,\n block_height,\n block_timestamp,\n args,\n author,\n proposal_id,\n }\n) {\n const dump = {\n receipt_id,\n method_name,\n block_height,\n block_timestamp,\n args,\n author,\n proposal_id,\n };\n try {\n console.log(\"Creating a dump...\");\n\n const mutationData = {\n dump,\n };\n await context.graphql(\n `\n mutation CreateDump($dump: polyprogrammist_near_devhub_objects_dumps_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_dumps_one(\n object: $dump\n ) {\n receipt_id\n }\n }\n `,\n mutationData\n );\n console.log(\n `Dump ${author} ${method_name} proposal ${proposal_id} has been added to the database`\n );\n return null;\n } catch (e) {\n console.log(\n `Error creating ${author} ${method_name} proposal ${proposal_id}: ${e}`\n );\n return e;\n }\n}\n\nasync function createProposal(context, { id, author_id }) {\n const proposal = { id, author_id };\n try {\n console.log(\"Creating a Proposal\");\n const mutationData = {\n proposal,\n };\n await context.graphql(\n `\n mutation CreateProposal($proposal: polyprogrammist_near_devhub_objects_proposals_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_proposals_one(object: $proposal) {id}\n }\n `,\n mutationData\n );\n console.log(`Proposal ${id} has been added to the database`);\n return null;\n } catch (e) {\n console.log(`Error creating Proposal with id ${id}: ${e}`);\n return e;\n }\n}\n\nasync function createProposalSnapshot(\n context,\n {\n proposal_id,\n block_height,\n ts, // Timestamp\n editor_id,\n labels,\n name,\n category,\n summary,\n description,\n linked_proposals, // Vec<ProposalId>\n linked_rfp, // Option<RFPId>\n requested_sponsorship_usd_amount, // u32\n requested_sponsorship_paid_in_currency, // ProposalFundingCurrency\n requested_sponsor, // AccountId\n receiver_account, // AccountId\n supervisor, // Option\n timeline, // TimelineStatus\n views,\n }\n) {\n const proposal_snapshot = {\n proposal_id,\n block_height,\n ts,\n editor_id,\n labels,\n name,\n category,\n summary,\n description,\n linked_proposals: linked_proposals,\n linked_rfp, // Option<RFPId>\n requested_sponsorship_usd_amount, // u32\n requested_sponsorship_paid_in_currency, // ProposalFundingCurrency\n requested_sponsor, // AccountId\n receiver_account, // AccountId\n supervisor, // Option<AccountId>\n views,\n timeline: JSON.stringify(timeline), // TimelineStatus\n };\n console.log(proposal_snapshot.linked_proposals);\n try {\n console.log(\"Creating a ProposalSnapshot\");\n const mutationData = {\n proposal_snapshot,\n };\n await context.graphql(\n `\n mutation CreateProposalSnapshot($proposal_snapshot: polyprogrammist_near_devhub_objects_proposal_snapshots_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_proposal_snapshots_one(object: $proposal_snapshot) {proposal_id, block_height}\n }\n `,\n mutationData\n );\n console.log(\n `Proposal Snapshot with proposal_id ${proposal_id} at block_height ${block_height} has been added to the database`\n );\n return null;\n } catch (e) {\n console.log(\n `Error creating Proposal Snapshot with proposal_id ${proposal_id} at block_height ${block_height}: ${e}`\n );\n return e;\n }\n}\n\nconst queryLatestProposalSnapshot = async (proposal_id) => {\n const queryData = {\n proposal_id,\n };\n try {\n const result = await context.graphql(\n `\n query GetLatestSnapshot($proposal_id: Int!) {\n polyprogrammist_near_devhub_objects_proposal_snapshots(where: {proposal_id: {_eq: $proposal_id}}, order_by: {ts: desc}, limit: 1) {\n proposal_id\n block_height\n ts\n editor_id\n labels\n name\n category\n summary\n description\n linked_proposals\n linked_rfp\n requested_sponsorship_usd_amount\n requested_sponsorship_paid_in_currency\n requested_sponsor\n receiver_account\n supervisor\n timeline\n views\n }\n }\n `,\n queryData\n );\n console.log({ result });\n return result;\n } catch (e) {\n console.log(\"Error retrieving latest Proposal snapshot:\", e);\n return null;\n }\n};\n\nconst queryLatestProposalViews = async (proposal_id) => {\n const queryData = {\n proposal_id,\n };\n try {\n const result = await context.graphql(\n `\n query GetLatestSnapshot($proposal_id: Int!) {\n polyprogrammist_near_devhub_objects_proposal_snapshots(where: {proposal_id: {_eq: $proposal_id}}, order_by: {ts: desc}, limit: 1) {\n proposal_id\n views\n }\n }\n `,\n queryData\n );\n console.log({ result });\n return result;\n } catch (e) {\n console.log(\"Error retrieving latest Proposal snapshot for views:\", e);\n return null;\n }\n};\n\nasync function createRFPDump(\n context,\n {\n receipt_id,\n method_name,\n block_height,\n block_timestamp,\n args,\n author,\n rfp_id,\n }\n) {\n const dump = {\n receipt_id,\n method_name,\n block_height,\n block_timestamp,\n args,\n author,\n rfp_id,\n };\n try {\n console.log(\"Creating a dump...\");\n\n const mutationData = {\n dump,\n };\n await context.graphql(\n `\n mutation CreateDump($dump: polyprogrammist_near_devhub_objects_rfp_dumps_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_rfp_dumps_one(\n object: $dump\n ) {\n receipt_id\n }\n }\n `,\n mutationData\n );\n console.log(\n `Dump ${author} ${method_name} rfp ${rfp_id} has been added to the database`\n );\n return null;\n } catch (e) {\n console.log(`Error creating ${author} ${method_name} rfp ${rfp_id}: ${e}`);\n return e;\n }\n}\n\nasync function createRFP(context, { id, author_id }) {\n const rfp = { id, author_id };\n try {\n console.log(\"Creating a rfp\");\n const mutationData = {\n rfp,\n };\n await context.graphql(\n `\n mutation Createrfp($rfp: polyprogrammist_near_devhub_objects_rfps_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_rfps_one(object: $rfp) {id}\n }\n `,\n mutationData\n );\n console.log(`rfp ${id} has been added to the database`);\n return null;\n } catch (e) {\n console.log(`Error creating rfp with id ${id}: ${e}`);\n return e;\n }\n}\n\nasync function createrfpSnapshot(\n context,\n {\n rfp_id,\n block_height,\n ts, // Timestamp\n editor_id,\n labels,\n linked_proposals,\n name,\n category,\n summary,\n description,\n timeline, // TimelineStatus\n submission_deadline,\n views,\n }\n) {\n const rfp_snapshot = {\n rfp_id,\n block_height,\n ts,\n editor_id,\n labels,\n linked_proposals:\n linked_proposals && linked_proposals.length\n ? linked_proposals.join(\",\")\n : \"\", // Vec<ProposalId> name,\n category,\n summary,\n description,\n views,\n timeline: JSON.stringify(timeline), // TimelineStatus\n submission_deadline,\n };\n try {\n console.log(\"Creating a rfpSnapshot\");\n const mutationData = {\n rfp_snapshot,\n };\n await context.graphql(\n `\n mutation CreaterfpSnapshot($rfp_snapshot: polyprogrammist_near_devhub_objects_rfp_snapshots_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_rfp_snapshots_one(object: $rfp_snapshot) {rfp_id, block_height}\n }\n `,\n mutationData\n );\n console.log(\n `rfp Snapshot with rfp_id ${rfp_id} at block_height ${block_height} has been added to the database`\n );\n return null;\n } catch (e) {\n console.log(\n `Error creating rfp Snapshot with rfp_id ${rfp_id} at block_height ${block_height}: ${e}`\n );\n return e;\n }\n}\n\nconst queryLatestLinkedRFP = async (proposal_id, blockTimestamp) => {\n const queryData = {\n proposal_id,\n timestamp: blockTimestamp,\n };\n try {\n const result = await context.graphql(\n `\n query GetLatestLinkedRFP($proposal_id: Int!, $timestamp: numeric!) {\n polyprogrammist_near_devhub_objects_proposal_snapshots(where: {proposal_id: {_eq: $proposal_id}, ts: {_lt: $timestamp}}, order_by: {ts: desc}, limit: 1) {\n proposal_id\n linked_rfp\n }\n }\n `,\n queryData\n );\n console.log({ result });\n return result;\n } catch (e) {\n console.log(\"Error retrieving latest linked RFP:\", e);\n return null;\n }\n};\n\nconst queryLatestRFPSnapshot = async (rfp_id) => {\n const queryData = {\n rfp_id,\n };\n try {\n const result = await context.graphql(\n `\n query GetLatestSnapshot($rfp_id: Int!) {\n polyprogrammist_near_devhub_objects_rfp_snapshots(where: {rfp_id: {_eq: $rfp_id}}, order_by: {ts: desc}, limit: 1) {\n rfp_id\n block_height\n ts\n editor_id\n labels\n linked_proposals\n name\n category\n summary\n description\n timeline\n submission_deadline\n views\n }\n }\n `,\n queryData\n );\n console.log({ result });\n return result;\n } catch (e) {\n console.log(\"Error retrieving latest RFP snapshot:\", e);\n return null;\n }\n};\n\nconst queryLatestRFPViews = async (rfp_id) => {\n const queryData = {\n rfp_id,\n };\n try {\n const result = await context.graphql(\n `\n query GetLatestSnapshot($rfp_id: Int!) {\n polyprogrammist_near_devhub_objects_rfp_snapshots(where: {rfp_id: {_eq: $rfp_id}}, order_by: {ts: desc}, limit: 1) {\n rfp_id\n views\n }\n }\n `,\n queryData\n );\n console.log({ result });\n return result;\n } catch (e) {\n console.log(\"Error retrieving latest RFP snapshot for views:\", e);\n return null;\n }\n", "schema": "CREATE TABLE\n proposals (id serial primary key, author_id VARCHAR not null);\n\nCREATE TABLE\n proposal_snapshots (\n -- due to how query api runs, an edit_proposal can be processed by the worker before corresponding add_proposal, so we can't enforce proposal_id as foreign key\n proposal_id int,\n block_height bigint,\n ts decimal(20, 0),\n editor_id varchar,\n labels jsonb,\n \"name\" text,\n category varchar,\n summary text,\n description text,\n linked_proposals varchar, -- array of proposal ids \"1,2,3,4\"\n linked_rfp int,\n requested_sponsorship_usd_amount decimal,\n requested_sponsorship_paid_in_currency varchar,\n requested_sponsor varchar,\n receiver_account varchar,\n supervisor varchar,\n timeline jsonb,\n views int,\n primary key (proposal_id, ts)\n );\n\nCREATE TABLE\n dumps (\n receipt_id varchar primary key,\n method_name varchar,\n block_height bigint,\n block_timestamp decimal(20, 0),\n args varchar,\n author varchar,\n proposal_id bigint\n );\n\nCREATE INDEX\n idx_proposals_author_id ON proposals (author_id);\n\nCREATE INDEX\n idx_proposal_snapshots_proposal_id ON proposal_snapshots (proposal_id);\n\nCREATE INDEX\n idx_proposal_snapshots_category ON proposal_snapshots (category);\n\nCREATE INDEX\n idx_proposal_snapshots_ts ON proposal_snapshots (ts);\n\nCREATE INDEX\n idx_proposal_snapshots_editor_id ON proposal_snapshots (editor_id);\n\nCREATE INDEX\n idx_proposal_snapshots_labels ON proposal_snapshots USING GIN (labels);\n\nCREATE INDEX\n idx_fulltext_proposal_snapshots_description ON proposal_snapshots USING gin (to_tsvector('english', description));\n\nCREATE INDEX\n idx_fulltext_proposal_snapshots_summary ON proposal_snapshots USING gin (to_tsvector('english', summary));\n\nCREATE INDEX\n idx_fulltext_proposal_snapshots_timeline ON proposal_snapshots USING gin (to_tsvector('english', timeline));\n\nCREATE INDEX\n idx_fulltext_proposal_snapshots_name ON proposal_snapshots USING gin (to_tsvector('english', name));\n\nCREATE INDEX\n idx_proposal_snapshots_sponsorship_supervisor ON proposal_snapshots (supervisor);\n\nCREATE INDEX\n idx_proposal_snapshots_sponsorship_receiver_account ON proposal_snapshots (receiver_account);\n\nCREATE INDEX\n idx_proposal_snapshots_views ON proposal_snapshots (views);\n\nCREATE VIEW\n proposals_with_latest_snapshot AS\nSELECT\n ps.proposal_id,\n p.author_id,\n ps.block_height,\n ps.ts,\n ps.editor_id,\n ps.labels,\n ps.name,\n ps.category,\n ps.summary,\n ps.description,\n ps.linked_proposals,\n ps.linked_rfp,\n ps.requested_sponsorship_usd_amount,\n ps.requested_sponsorship_paid_in_currency,\n ps.requested_sponsor,\n ps.receiver_account,\n ps.supervisor,\n ps.timeline,\n ps.views\nFROM\n proposals p\n INNER JOIN (\n SELECT\n proposal_id,\n MAX(ts) AS max_ts\n FROM\n proposal_snapshots\n GROUP BY\n proposal_id\n ) latest_snapshots ON p.id = latest_snapshots.proposal_id\n INNER JOIN proposal_snapshots ps ON latest_snapshots.proposal_id = ps.proposal_id\n AND latest_snapshots.max_ts = ps.ts;\n\nCREATE TABLE\n rfps (id serial primary key, author_id VARCHAR not null);\n\nCREATE TABLE\n rfp_snapshots (\n -- due to how query api runs, an edit_rfp can be processed by the worker before corresponding add_rfp, so we can't enforce rfp_id as foreign key\n rfp_id int REFERENCES rfps (id),\n block_height bigint,\n ts decimal(20, 0),\n editor_id varchar,\n labels jsonb,\n linked_proposals jsonb,\n \"name\" text,\n category varchar,\n summary text,\n description text,\n timeline jsonb,\n submission_deadline decimal(20, 0),\n views int,\n primary key (rfp_id, ts)\n );\n\nCREATE INDEX\n idx_rfps_author_id ON rfps (author_id);\n\nCREATE INDEX\n idx_rfp_snapshots_rfp_id ON rfp_snapshots (rfp_id);\n\nCREATE INDEX\n idx_rfp_snapshots_category ON rfp_snapshots (category);\n\nCREATE INDEX\n idx_rfp_snapshots_ts ON rfp_snapshots (ts);\n\nCREATE INDEX\n idx_rfp_snapshots_editor_id ON rfp_snapshots (editor_id);\n\nCREATE INDEX\n idx_rfp_snapshots_labels ON rfp_snapshots USING GIN (labels);\n\nCREATE INDEX\n idx_fulltext_rfp_snapshots_description ON rfp_snapshots USING gin (to_tsvector('english', description));\n\nCREATE INDEX\n idx_fulltext_rfp_snapshots_summary ON rfp_snapshots USING gin (to_tsvector('english', summary));\n\nCREATE INDEX\n idx_fulltext_rfp_snapshots_timeline ON rfp_snapshots USING gin (to_tsvector('english', timeline));\n\nCREATE INDEX\n idx_fulltext_rfp_snapshots_name ON rfp_snapshots USING gin (to_tsvector('english', name));\n\nCREATE INDEX\n idx_rfp_snapshots_views ON rfp_snapshots (views);\n\nCREATE VIEW\n rfps_with_latest_snapshot AS\nSELECT\n ps.rfp_id,\n p.author_id,\n ps.block_height,\n ps.ts,\n ps.editor_id,\n ps.labels,\n ps.linked_proposals,\n ps.name,\n ps.category,\n ps.summary,\n ps.description,\n ps.timeline,\n ps.views,\n ps.submission_deadline\nFROM\n rfps p\n INNER JOIN (\n SELECT\n rfp_id,\n MAX(ts) AS max_ts\n FROM\n rfp_snapshots\n GROUP BY\n rfp_id\n ) latest_snapshots ON p.id = latest_snapshots.rfp_id\n INNER JOIN rfp_snapshots ps ON latest_snapshots.rfp_id = ps.rfp_id\n AND latest_snapshots.max_ts = ps.ts;\n\nCREATE TABLE\n rfp_dumps (\n receipt_id varchar primary key,\n method_name varchar,\n block_height bigint,\n block_timestamp decimal(20, 0),\n args varchar,\n author varchar,\n rfp_id bigint\n );\n", "start_block": { "HEIGHT": 118538701 }, "rule": { "kind": "ACTION_ANY", "affected_account_id": "truedove38.near", "status": "SUCCESS" } }

Transaction Execution Plan

Convert Transaction To Receipt
Gas Burned:
381 Ggas
Tokens Burned:
0.00004 
Receipt:
Predecessor ID:
Receiver ID:
Gas Burned:
7 Tgas
Tokens Burned:
0.00073 
Called method: 'register' in contract: query…tform.near
Arguments:
{ "function_name": "devhub_objects", "code": "\n console.log(\"Start handling block\");\n const rfpOps = getRFPOps(block);\n const proposalOps = getProposalOps(block);\n\n const rfpOpsLen = rfpOps.length;\n const proposalOpsLen = proposalOps.length;\n\n if (rfpOpsLen > 0 || proposalOpsLen > 0) {\n const authorToRFPId = buildAuthorToRFPIdMap(block);\n const authorToProposalId = buildAuthorToProposalIdMap(block);\n const blockHeight = block.blockHeight;\n const blockTimestamp = block.header().timestampNanosec;\n try {\n await Promise.all(\n rfpOps\n .map((op) =>\n indexRFPsOp(op, authorToRFPId, blockHeight, blockTimestamp, context)\n )\n .concat(\n proposalOps.map((op) =>\n indexProposalsOp(\n op,\n authorToProposalId,\n blockHeight,\n blockTimestamp,\n context\n )\n )\n )\n );\n } catch (error) {\n console.error(\"Error processing block operations:\", error);\n }\n }\n console.log(\"Finish handling block\");\n}\n\nfunction getAddOrEditObject(block, startsWith) {\n const stateChanges = block.streamerMessage.shards\n .flatMap((e) => e.stateChanges)\n .filter(\n (stateChange) =>\n stateChange.change.accountId === \"truedove38.near\" &&\n stateChange.type === \"data_update\"\n );\n\n const addOrEditObject = stateChanges\n .map((stateChange) => stateChange.change)\n // In devhub contract there is a field rfps: Vector<VersionedRFP> ( initially = rfps: Vector::new(StorageKey::RFPs) )\n // In StorageKey enum it comes on 17th position (0x11 in hex).\n // So 0x11 is used as a prefix for the collection keys (https://docs.near.org/sdk/rust/contract-structure/collections).\n .filter((change) => base64toHex(change.keyBase64).startsWith(startsWith))\n .map((c) => ({\n k: Buffer.from(c.keyBase64, \"base64\"),\n v: Buffer.from(c.valueBase64, \"base64\"),\n }));\n\n return addOrEditObject;\n}\n\n// Borsh https://github.com/near/borsh#specification\nfunction buildAuthorToRFPIdMap(block) {\n return Object.fromEntries(\n getAddOrEditObject(block, \"11\").map((kv) => {\n return [\n // Here we read enum VersionedRFP. So we skip enum byte. This enum has just one variant RFP.\n // It contains id: u32 (4 bytes) and then account_id which is string.\n // String is serialized as length: u32 (4 bytes) and then content of the string\n kv.v.slice(9, 9 + kv.v.slice(5, 9).readUInt32LE()).toString(\"utf-8\"),\n // In Vector, key is prefix + index, where index is u32 in little-endian format.\n // So we skip prefix with slice(1) and read index with readBigUint64LE().\n Number(kv.k.slice(1).readBigUInt64LE()),\n ];\n })\n );\n}\n\nfunction buildAuthorToProposalIdMap(block) {\n return Object.fromEntries(\n getAddOrEditObject(block, \"0e\").map((kv) => {\n return [\n kv.v.slice(9, 9 + kv.v.slice(5, 9).readUInt32LE()).toString(\"utf-8\"),\n Number(kv.k.slice(1).readBigUInt64LE()),\n ];\n })\n );\n}\n\nfunction base64decode(encodedValue) {\n let buff = Buffer.from(encodedValue, \"base64\");\n return JSON.parse(buff.toString(\"utf-8\"));\n}\n\nfunction base64toHex(encodedValue) {\n let buff = Buffer.from(encodedValue, \"base64\");\n return buff.toString(\"hex\");\n}\n\nfunction getDevHubOps(block, methodNames, callbackNames) {\n return block\n .actions()\n .filter((action) => action.receiverId === \"truedove38.near\")\n .flatMap((action) =>\n action.operations\n .filter((operation) => operation[\"FunctionCall\"])\n .map((operation) => ({\n ...operation[\"FunctionCall\"],\n caller: action.predecessorId,\n }))\n .map((operation) => ({\n ...operation,\n methodName: operation.methodName || operation.method_name,\n }))\n .filter(\n (operation) =>\n methodNames.includes(operation.methodName) ||\n (callbackNames.includes(operation.methodName) &&\n operation.caller === \"truedove38.near\")\n )\n .map((functionCallOperation) => ({\n ...functionCallOperation,\n args: base64decode(functionCallOperation.args),\n receiptId: action.receiptId,\n }))\n );\n}\n\nfunction getProposalOps(block) {\n return getDevHubOps(\n block,\n [\n \"edit_proposal\",\n \"edit_proposal_internal\",\n \"edit_proposal_linked_rfp\",\n \"edit_proposal_timeline\",\n ],\n [\"set_block_height_callback\"]\n );\n}\n\nfunction getRFPOps(block) {\n return getDevHubOps(\n block,\n [\"edit_rfp\", \"edit_rfp_timeline\", \"edit_rfp_internal\"],\n [\"set_rfp_block_height_callback\"]\n );\n}\n\nasync function indexProposalsOp(\n op,\n authorToProposalId,\n blockHeight,\n blockTimestamp,\n context\n) {\n let receipt_id = op.receiptId;\n let args = op.args;\n let author = Object.keys(authorToProposalId)[0];\n console.log(`Indexing ${op.methodName} by ${author} at ${blockHeight}`);\n console.log(authorToProposalId);\n let proposal_id = authorToProposalId[author] ?? null;\n let method_name = op.methodName;\n\n let err = await createDump(context, {\n receipt_id,\n method_name,\n block_height: blockHeight,\n block_timestamp: blockTimestamp,\n args: JSON.stringify(args),\n author,\n proposal_id,\n });\n if (err !== null) {\n return;\n }\n\n // currently Query API cannot tell if it's a failed receipt, so we estimate by looking the state changes.\n if (proposal_id === null) {\n console.log(\n `Receipt to ${method_name} with receipt_id ${receipt_id} at ${blockHeight} doesn't result in a state change, it's probably a failed receipt, please check`\n );\n return;\n }\n\n if (method_name === \"set_block_height_callback\") {\n let proposal = {\n id: proposal_id,\n author_id: author,\n };\n\n let err = await createProposal(context, proposal);\n if (err !== null) {\n return;\n }\n\n let linked_rfp = args.proposal.snapshot.linked_rfp;\n let linked_proposals = args.proposal.snapshot.linked_proposals;\n linked_proposals =\n linked_proposals && linked_proposals.length\n ? linked_proposals.join(\",\")\n : \"\"; // Vec<ProposalId>\n\n await createProposalSnapshot(context, {\n proposal_id,\n block_height: blockHeight,\n ts: blockTimestamp,\n views: 1,\n linked_proposals,\n ...args.proposal.snapshot,\n });\n\n await checkAndUpdateLinkedProposals(\n proposal_id,\n linked_rfp,\n blockHeight,\n blockTimestamp\n );\n }\n\n if (method_name === \"edit_proposal\") {\n let linked_rfp = args.body.linked_rfp;\n\n let result = await queryLatestProposalViews(proposal_id);\n let latest_snapshot =\n result.polyprogrammist_near_devhub_objects_proposal_snapshots[0];\n let labels =\n linked_rfp === undefined ? args.labels : latest_snapshot[0].labels;\n\n let linked_proposals = args.proposal.snapshot.linked_proposals;\n linked_proposals =\n linked_proposals && linked_proposals.length\n ? linked_proposals.join(\",\")\n : \"\"; // Vec<ProposalId>\n\n let proposal_snapshot = {\n proposal_id,\n block_height: blockHeight,\n ts: blockTimestamp, // Timestamp\n editor_id: author,\n labels,\n linked_rfp,\n linked_proposals,\n views: latest_snapshot[0].views + 1,\n ...args.body,\n };\n await createProposalSnapshot(context, proposal_snapshot);\n await checkAndUpdateLinkedProposals(\n proposal_id,\n linked_rfp,\n blockHeight,\n blockTimestamp\n );\n }\n\n if (method_name === \"edit_proposal_internal\") {\n let linked_rfp = args.body.linked_rfp;\n\n let result = await queryLatestProposalViews(proposal_id);\n let latest_snapshot =\n result.polyprogrammist_near_devhub_objects_proposal_snapshots[0];\n let labels =\n linked_rfp === undefined ? args.labels : latest_snapshot[0].labels;\n let linked_proposals = args.proposal.snapshot.linked_proposals;\n linked_proposals =\n linked_proposals && linked_proposals.length\n ? linked_proposals.join(\",\")\n : \"\"; // Vec<ProposalId>\n\n let proposal_snapshot = {\n proposal_id,\n block_height: blockHeight,\n ts: blockTimestamp, // Timestamp\n editor_id: author,\n labels,\n linked_rfp,\n linked_proposals,\n views: latest_snapshot[0].views + 1,\n ...args.body,\n };\n await createProposalSnapshot(context, proposal_snapshot);\n await checkAndUpdateLinkedProposals(\n proposal_id,\n linked_rfp,\n blockHeight,\n blockTimestamp\n );\n }\n\n if (method_name === \"edit_proposal_timeline\") {\n let result = await queryLatestProposalSnapshot(proposal_id);\n\n if (Object.keys(result).length !== 0) {\n let latest_proposal_snapshot =\n result.polyprogrammist_near_devhub_objects_proposal_snapshots[0];\n console.log({\n method: \"edit_proposal_timeline\",\n latest_proposal_snapshot,\n });\n let proposal_snapshot = {\n proposal_id,\n block_height: blockHeight,\n ts: blockTimestamp,\n editor_id: author,\n timeline: args.timeline, // TimelineStatus\n views: latest_proposal_snapshot.views + 1,\n ...latest_proposal_snapshot,\n };\n await createProposalSnapshot(context, proposal_snapshot);\n } else {\n console.log(\"Empty object latest_proposal_snapshot result\", { result });\n }\n }\n if (method_name == \"edit_proposal_linked_rfp\") {\n let result = await queryLatestProposalSnapshot(proposal_id);\n\n if (Object.keys(result).length !== 0) {\n let linked_rfp = args.rfp_id;\n let latest_proposal_snapshot =\n result.polyprogrammist_near_devhub_objects_proposal_snapshots[0];\n console.log({\n method: \"edit_proposal_linked_rfp\",\n latest_proposal_snapshot,\n });\n let proposal_snapshot = {\n proposal_id,\n linked_rfp: linked_rfp,\n block_height: blockHeight,\n ts: blockTimestamp,\n editor_id: author,\n timeline: args.timeline, // TimelineStatus\n views: latest_proposal_snapshot.views + 1,\n ...latest_proposal_snapshot,\n };\n await createProposalSnapshot(context, proposal_snapshot);\n await checkAndUpdateLinkedProposals(\n proposal_id,\n linked_rfp,\n blockHeight,\n blockTimestamp\n );\n }\n }\n}\n\nasync function indexRFPsOp(\n op,\n authorToRFPId,\n blockHeight,\n blockTimestamp,\n context\n) {\n let receipt_id = op.receiptId;\n let author = Object.keys(authorToRFPId)[0];\n let args = op.args;\n let rfp_id = authorToRFPId[author] ?? null;\n let method_name = op.methodName;\n\n console.log(\n `Indexing ${method_name} by ${author} at ${blockHeight}, rfp_id = ${rfp_id}`\n );\n\n let err = await createRFPDump(context, {\n receipt_id,\n method_name,\n block_height: blockHeight,\n block_timestamp: blockTimestamp,\n args: JSON.stringify(args),\n author,\n rfp_id,\n });\n if (err !== null) {\n return;\n }\n\n // currently Query API cannot tell if it's a failed receipt, so we estimate by looking the state changes.\n if (rfp_id === null) {\n console.log(\n `Receipt to ${method_name} with receipt_id ${receipt_id} at ${blockHeight} doesn't result in a state change, it's probably a failed receipt, please check`\n );\n return;\n }\n\n if (method_name === \"set_rfp_block_height_callback\") {\n let rfp = {\n id: rfp_id,\n author_id: author,\n };\n\n let err = await createRFP(context, rfp);\n if (err !== null) {\n return;\n }\n\n await createrfpSnapshot(context, {\n rfp_id,\n block_height: blockHeight,\n ts: blockTimestamp,\n views: 1,\n ...args.rfp.snapshot,\n });\n }\n\n if (method_name === \"edit_rfp\") {\n let labels = args.labels;\n\n let result = await queryLatestRFPViews(rfp_id);\n let rfp_snapshot = {\n rfp_id,\n block_height: blockHeight,\n ts: blockTimestamp, // Timestamp\n editor_id: author,\n labels,\n views:\n result.polyprogrammist_near_devhub_objects_rfp_snapshots[0].views + 1,\n ...args.body,\n };\n await createrfpSnapshot(context, rfp_snapshot);\n }\n\n if (method_name === \"edit_rfp_timeline\") {\n try {\n let result = await queryLatestRFPSnapshot(rfp_id);\n if (Object.keys(result).length !== 0) {\n let latest_rfp_snapshot =\n result.polyprogrammist_near_devhub_objects_rfp_snapshots[0];\n console.log({\n method: \"edit_rfp_timeline\",\n latest_rfp_snapshot,\n });\n let rfp_snapshot = {\n rfp_id,\n block_height: blockHeight,\n ts: blockTimestamp,\n editor_id: author,\n timeline: args.timeline, // TimelineStatus\n views: latest_rfp_snapshot.views + 1,\n ...latest_rfp_snapshot,\n };\n await createrfpSnapshot(context, rfp_snapshot);\n } else {\n console.log(\"Empty object latest_rfp_snapshot result\", { result });\n }\n } catch (error) {\n console.error(\"Error editing rfp timeline:\", error);\n }\n }\n}\n\nfunction addToLinkedProposals(linked_proposals, proposal_id) {\n linked_proposals.push(proposal_id);\n return linked_proposals;\n}\n\nfunction removeFromLinkedProposals(linked_proposals, proposal_id) {\n return linked_proposals.filter((id) => id !== proposal_id);\n}\n\nasync function modifySnapshotLinkedProposal(\n rfp_id,\n proposal_id,\n blockHeight,\n blockTimestamp,\n modifyCallback\n) {\n let result = await queryLatestRFPSnapshot(rfp_id);\n\n if (Object.keys(result).length !== 0) {\n let latest_rfp_snapshot =\n result.polyprogrammist_near_devhub_objects_rfp_snapshots[0];\n\n let linked_proposals = modifyCallback(\n latest_rfp_snapshot.linked_proposals,\n proposal_id\n );\n let rfp_snapshot = {\n rfp_id,\n linked_proposals: linked_proposals,\n block_height: blockHeight,\n ts: blockTimestamp,\n ...latest_rfp_snapshot,\n };\n await createrfpSnapshot(context, rfp_snapshot);\n } else {\n console.log(\"Empty object latest_rfp_snapshot result\", { result });\n }\n}\n\nasync function addLinkedProposalToSnapshot(\n rfp_id,\n new_linked_proposal,\n blockHeight,\n blockTimestamp\n) {\n await modifySnapshotLinkedProposal(\n rfp_id,\n new_linked_proposal,\n blockHeight,\n blockTimestamp,\n addToLinkedProposals\n );\n}\n\nasync function removeLinkedProposalFromSnapshot(\n rfp_id,\n proposal_id,\n blockHeight,\n blockTimestamp\n) {\n await modifySnapshotLinkedProposal(\n rfp_id,\n proposal_id,\n blockHeight,\n blockTimestamp,\n removeFromLinkedProposals\n );\n}\n\nasync function checkAndUpdateLinkedProposals(\n proposal_id,\n new_linked_rfp,\n blockHeight,\n blockTimestamp\n) {\n try {\n let latest_linked_rfp = await queryLatestLinkedRFP(\n proposal_id,\n blockTimestamp\n );\n let last_snapshot =\n latest_linked_rfp\n .polyprogrammist_near_devhub_objects_proposal_snapshots[0];\n let latest_linked_rfp_id = undefined;\n if (last_snapshot != undefined) {\n latest_linked_rfp_id = last_snapshot.linked_rfp;\n }\n\n if (new_linked_rfp !== latest_linked_rfp_id) {\n if (new_linked_rfp !== undefined) {\n console.log(\n `Adding linked_rfp ${new_linked_rfp} to proposal ${proposal_id}`\n );\n await addLinkedProposalToSnapshot(\n new_linked_rfp,\n proposal_id,\n blockHeight,\n blockTimestamp\n );\n console.log(`Proposal added to new RFP snapshot`);\n }\n if (latest_linked_rfp_id !== undefined) {\n console.log(\n `Removing linked_rfp ${latest_linked_rfp_id} from proposal ${proposal_id}`\n );\n await removeLinkedProposalFromSnapshot(\n latest_linked_rfp_id,\n proposal_id,\n blockHeight,\n blockTimestamp\n );\n console.log(`Proposal removed from old RFP snapshot`);\n }\n }\n } catch (error) {\n console.error(\"Error checking and updating linked proposals:\", error);\n }\n}\n\nasync function createDump(\n context,\n {\n receipt_id,\n method_name,\n block_height,\n block_timestamp,\n args,\n author,\n proposal_id,\n }\n) {\n const dump = {\n receipt_id,\n method_name,\n block_height,\n block_timestamp,\n args,\n author,\n proposal_id,\n };\n try {\n console.log(\"Creating a dump...\");\n\n const mutationData = {\n dump,\n };\n await context.graphql(\n `\n mutation CreateDump($dump: polyprogrammist_near_devhub_objects_dumps_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_dumps_one(\n object: $dump\n ) {\n receipt_id\n }\n }\n `,\n mutationData\n );\n console.log(\n `Dump ${author} ${method_name} proposal ${proposal_id} has been added to the database`\n );\n return null;\n } catch (e) {\n console.log(\n `Error creating ${author} ${method_name} proposal ${proposal_id}: ${e}`\n );\n return e;\n }\n}\n\nasync function createProposal(context, { id, author_id }) {\n const proposal = { id, author_id };\n try {\n console.log(\"Creating a Proposal\");\n const mutationData = {\n proposal,\n };\n await context.graphql(\n `\n mutation CreateProposal($proposal: polyprogrammist_near_devhub_objects_proposals_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_proposals_one(object: $proposal) {id}\n }\n `,\n mutationData\n );\n console.log(`Proposal ${id} has been added to the database`);\n return null;\n } catch (e) {\n console.log(`Error creating Proposal with id ${id}: ${e}`);\n return e;\n }\n}\n\nasync function createProposalSnapshot(\n context,\n {\n proposal_id,\n block_height,\n ts, // Timestamp\n editor_id,\n labels,\n name,\n category,\n summary,\n description,\n linked_proposals, // Vec<ProposalId>\n linked_rfp, // Option<RFPId>\n requested_sponsorship_usd_amount, // u32\n requested_sponsorship_paid_in_currency, // ProposalFundingCurrency\n requested_sponsor, // AccountId\n receiver_account, // AccountId\n supervisor, // Option\n timeline, // TimelineStatus\n views,\n }\n) {\n const proposal_snapshot = {\n proposal_id,\n block_height,\n ts,\n editor_id,\n labels,\n name,\n category,\n summary,\n description,\n linked_proposals: linked_proposals,\n linked_rfp, // Option<RFPId>\n requested_sponsorship_usd_amount, // u32\n requested_sponsorship_paid_in_currency, // ProposalFundingCurrency\n requested_sponsor, // AccountId\n receiver_account, // AccountId\n supervisor, // Option<AccountId>\n views,\n timeline: JSON.stringify(timeline), // TimelineStatus\n };\n console.log(proposal_snapshot.linked_proposals);\n try {\n console.log(\"Creating a ProposalSnapshot\");\n const mutationData = {\n proposal_snapshot,\n };\n await context.graphql(\n `\n mutation CreateProposalSnapshot($proposal_snapshot: polyprogrammist_near_devhub_objects_proposal_snapshots_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_proposal_snapshots_one(object: $proposal_snapshot) {proposal_id, block_height}\n }\n `,\n mutationData\n );\n console.log(\n `Proposal Snapshot with proposal_id ${proposal_id} at block_height ${block_height} has been added to the database`\n );\n return null;\n } catch (e) {\n console.log(\n `Error creating Proposal Snapshot with proposal_id ${proposal_id} at block_height ${block_height}: ${e}`\n );\n return e;\n }\n}\n\nconst queryLatestProposalSnapshot = async (proposal_id) => {\n const queryData = {\n proposal_id,\n };\n try {\n const result = await context.graphql(\n `\n query GetLatestSnapshot($proposal_id: Int!) {\n polyprogrammist_near_devhub_objects_proposal_snapshots(where: {proposal_id: {_eq: $proposal_id}}, order_by: {ts: desc}, limit: 1) {\n proposal_id\n block_height\n ts\n editor_id\n labels\n name\n category\n summary\n description\n linked_proposals\n linked_rfp\n requested_sponsorship_usd_amount\n requested_sponsorship_paid_in_currency\n requested_sponsor\n receiver_account\n supervisor\n timeline\n views\n }\n }\n `,\n queryData\n );\n console.log({ result });\n return result;\n } catch (e) {\n console.log(\"Error retrieving latest Proposal snapshot:\", e);\n return null;\n }\n};\n\nconst queryLatestProposalViews = async (proposal_id) => {\n const queryData = {\n proposal_id,\n };\n try {\n const result = await context.graphql(\n `\n query GetLatestSnapshot($proposal_id: Int!) {\n polyprogrammist_near_devhub_objects_proposal_snapshots(where: {proposal_id: {_eq: $proposal_id}}, order_by: {ts: desc}, limit: 1) {\n proposal_id\n views\n }\n }\n `,\n queryData\n );\n console.log({ result });\n return result;\n } catch (e) {\n console.log(\"Error retrieving latest Proposal snapshot for views:\", e);\n return null;\n }\n};\n\nasync function createRFPDump(\n context,\n {\n receipt_id,\n method_name,\n block_height,\n block_timestamp,\n args,\n author,\n rfp_id,\n }\n) {\n const dump = {\n receipt_id,\n method_name,\n block_height,\n block_timestamp,\n args,\n author,\n rfp_id,\n };\n try {\n console.log(\"Creating a dump...\");\n\n const mutationData = {\n dump,\n };\n await context.graphql(\n `\n mutation CreateDump($dump: polyprogrammist_near_devhub_objects_rfp_dumps_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_rfp_dumps_one(\n object: $dump\n ) {\n receipt_id\n }\n }\n `,\n mutationData\n );\n console.log(\n `Dump ${author} ${method_name} rfp ${rfp_id} has been added to the database`\n );\n return null;\n } catch (e) {\n console.log(`Error creating ${author} ${method_name} rfp ${rfp_id}: ${e}`);\n return e;\n }\n}\n\nasync function createRFP(context, { id, author_id }) {\n const rfp = { id, author_id };\n try {\n console.log(\"Creating a rfp\");\n const mutationData = {\n rfp,\n };\n await context.graphql(\n `\n mutation Createrfp($rfp: polyprogrammist_near_devhub_objects_rfps_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_rfps_one(object: $rfp) {id}\n }\n `,\n mutationData\n );\n console.log(`rfp ${id} has been added to the database`);\n return null;\n } catch (e) {\n console.log(`Error creating rfp with id ${id}: ${e}`);\n return e;\n }\n}\n\nasync function createrfpSnapshot(\n context,\n {\n rfp_id,\n block_height,\n ts, // Timestamp\n editor_id,\n labels,\n linked_proposals,\n name,\n category,\n summary,\n description,\n timeline, // TimelineStatus\n submission_deadline,\n views,\n }\n) {\n const rfp_snapshot = {\n rfp_id,\n block_height,\n ts,\n editor_id,\n labels,\n linked_proposals:\n linked_proposals && linked_proposals.length\n ? linked_proposals.join(\",\")\n : \"\", // Vec<ProposalId> name,\n category,\n summary,\n description,\n views,\n timeline: JSON.stringify(timeline), // TimelineStatus\n submission_deadline,\n };\n try {\n console.log(\"Creating a rfpSnapshot\");\n const mutationData = {\n rfp_snapshot,\n };\n await context.graphql(\n `\n mutation CreaterfpSnapshot($rfp_snapshot: polyprogrammist_near_devhub_objects_rfp_snapshots_insert_input!) {\n insert_polyprogrammist_near_devhub_objects_rfp_snapshots_one(object: $rfp_snapshot) {rfp_id, block_height}\n }\n `,\n mutationData\n );\n console.log(\n `rfp Snapshot with rfp_id ${rfp_id} at block_height ${block_height} has been added to the database`\n );\n return null;\n } catch (e) {\n console.log(\n `Error creating rfp Snapshot with rfp_id ${rfp_id} at block_height ${block_height}: ${e}`\n );\n return e;\n }\n}\n\nconst queryLatestLinkedRFP = async (proposal_id, blockTimestamp) => {\n const queryData = {\n proposal_id,\n timestamp: blockTimestamp,\n };\n try {\n const result = await context.graphql(\n `\n query GetLatestLinkedRFP($proposal_id: Int!, $timestamp: numeric!) {\n polyprogrammist_near_devhub_objects_proposal_snapshots(where: {proposal_id: {_eq: $proposal_id}, ts: {_lt: $timestamp}}, order_by: {ts: desc}, limit: 1) {\n proposal_id\n linked_rfp\n }\n }\n `,\n queryData\n );\n console.log({ result });\n return result;\n } catch (e) {\n console.log(\"Error retrieving latest linked RFP:\", e);\n return null;\n }\n};\n\nconst queryLatestRFPSnapshot = async (rfp_id) => {\n const queryData = {\n rfp_id,\n };\n try {\n const result = await context.graphql(\n `\n query GetLatestSnapshot($rfp_id: Int!) {\n polyprogrammist_near_devhub_objects_rfp_snapshots(where: {rfp_id: {_eq: $rfp_id}}, order_by: {ts: desc}, limit: 1) {\n rfp_id\n block_height\n ts\n editor_id\n labels\n linked_proposals\n name\n category\n summary\n description\n timeline\n submission_deadline\n views\n }\n }\n `,\n queryData\n );\n console.log({ result });\n return result;\n } catch (e) {\n console.log(\"Error retrieving latest RFP snapshot:\", e);\n return null;\n }\n};\n\nconst queryLatestRFPViews = async (rfp_id) => {\n const queryData = {\n rfp_id,\n };\n try {\n const result = await context.graphql(\n `\n query GetLatestSnapshot($rfp_id: Int!) {\n polyprogrammist_near_devhub_objects_rfp_snapshots(where: {rfp_id: {_eq: $rfp_id}}, order_by: {ts: desc}, limit: 1) {\n rfp_id\n views\n }\n }\n `,\n queryData\n );\n console.log({ result });\n return result;\n } catch (e) {\n console.log(\"Error retrieving latest RFP snapshot for views:\", e);\n return null;\n }\n", "schema": "CREATE TABLE\n proposals (id serial primary key, author_id VARCHAR not null);\n\nCREATE TABLE\n proposal_snapshots (\n -- due to how query api runs, an edit_proposal can be processed by the worker before corresponding add_proposal, so we can't enforce proposal_id as foreign key\n proposal_id int,\n block_height bigint,\n ts decimal(20, 0),\n editor_id varchar,\n labels jsonb,\n \"name\" text,\n category varchar,\n summary text,\n description text,\n linked_proposals varchar, -- array of proposal ids \"1,2,3,4\"\n linked_rfp int,\n requested_sponsorship_usd_amount decimal,\n requested_sponsorship_paid_in_currency varchar,\n requested_sponsor varchar,\n receiver_account varchar,\n supervisor varchar,\n timeline jsonb,\n views int,\n primary key (proposal_id, ts)\n );\n\nCREATE TABLE\n dumps (\n receipt_id varchar primary key,\n method_name varchar,\n block_height bigint,\n block_timestamp decimal(20, 0),\n args varchar,\n author varchar,\n proposal_id bigint\n );\n\nCREATE INDEX\n idx_proposals_author_id ON proposals (author_id);\n\nCREATE INDEX\n idx_proposal_snapshots_proposal_id ON proposal_snapshots (proposal_id);\n\nCREATE INDEX\n idx_proposal_snapshots_category ON proposal_snapshots (category);\n\nCREATE INDEX\n idx_proposal_snapshots_ts ON proposal_snapshots (ts);\n\nCREATE INDEX\n idx_proposal_snapshots_editor_id ON proposal_snapshots (editor_id);\n\nCREATE INDEX\n idx_proposal_snapshots_labels ON proposal_snapshots USING GIN (labels);\n\nCREATE INDEX\n idx_fulltext_proposal_snapshots_description ON proposal_snapshots USING gin (to_tsvector('english', description));\n\nCREATE INDEX\n idx_fulltext_proposal_snapshots_summary ON proposal_snapshots USING gin (to_tsvector('english', summary));\n\nCREATE INDEX\n idx_fulltext_proposal_snapshots_timeline ON proposal_snapshots USING gin (to_tsvector('english', timeline));\n\nCREATE INDEX\n idx_fulltext_proposal_snapshots_name ON proposal_snapshots USING gin (to_tsvector('english', name));\n\nCREATE INDEX\n idx_proposal_snapshots_sponsorship_supervisor ON proposal_snapshots (supervisor);\n\nCREATE INDEX\n idx_proposal_snapshots_sponsorship_receiver_account ON proposal_snapshots (receiver_account);\n\nCREATE INDEX\n idx_proposal_snapshots_views ON proposal_snapshots (views);\n\nCREATE VIEW\n proposals_with_latest_snapshot AS\nSELECT\n ps.proposal_id,\n p.author_id,\n ps.block_height,\n ps.ts,\n ps.editor_id,\n ps.labels,\n ps.name,\n ps.category,\n ps.summary,\n ps.description,\n ps.linked_proposals,\n ps.linked_rfp,\n ps.requested_sponsorship_usd_amount,\n ps.requested_sponsorship_paid_in_currency,\n ps.requested_sponsor,\n ps.receiver_account,\n ps.supervisor,\n ps.timeline,\n ps.views\nFROM\n proposals p\n INNER JOIN (\n SELECT\n proposal_id,\n MAX(ts) AS max_ts\n FROM\n proposal_snapshots\n GROUP BY\n proposal_id\n ) latest_snapshots ON p.id = latest_snapshots.proposal_id\n INNER JOIN proposal_snapshots ps ON latest_snapshots.proposal_id = ps.proposal_id\n AND latest_snapshots.max_ts = ps.ts;\n\nCREATE TABLE\n rfps (id serial primary key, author_id VARCHAR not null);\n\nCREATE TABLE\n rfp_snapshots (\n -- due to how query api runs, an edit_rfp can be processed by the worker before corresponding add_rfp, so we can't enforce rfp_id as foreign key\n rfp_id int REFERENCES rfps (id),\n block_height bigint,\n ts decimal(20, 0),\n editor_id varchar,\n labels jsonb,\n linked_proposals jsonb,\n \"name\" text,\n category varchar,\n summary text,\n description text,\n timeline jsonb,\n submission_deadline decimal(20, 0),\n views int,\n primary key (rfp_id, ts)\n );\n\nCREATE INDEX\n idx_rfps_author_id ON rfps (author_id);\n\nCREATE INDEX\n idx_rfp_snapshots_rfp_id ON rfp_snapshots (rfp_id);\n\nCREATE INDEX\n idx_rfp_snapshots_category ON rfp_snapshots (category);\n\nCREATE INDEX\n idx_rfp_snapshots_ts ON rfp_snapshots (ts);\n\nCREATE INDEX\n idx_rfp_snapshots_editor_id ON rfp_snapshots (editor_id);\n\nCREATE INDEX\n idx_rfp_snapshots_labels ON rfp_snapshots USING GIN (labels);\n\nCREATE INDEX\n idx_fulltext_rfp_snapshots_description ON rfp_snapshots USING gin (to_tsvector('english', description));\n\nCREATE INDEX\n idx_fulltext_rfp_snapshots_summary ON rfp_snapshots USING gin (to_tsvector('english', summary));\n\nCREATE INDEX\n idx_fulltext_rfp_snapshots_timeline ON rfp_snapshots USING gin (to_tsvector('english', timeline));\n\nCREATE INDEX\n idx_fulltext_rfp_snapshots_name ON rfp_snapshots USING gin (to_tsvector('english', name));\n\nCREATE INDEX\n idx_rfp_snapshots_views ON rfp_snapshots (views);\n\nCREATE VIEW\n rfps_with_latest_snapshot AS\nSELECT\n ps.rfp_id,\n p.author_id,\n ps.block_height,\n ps.ts,\n ps.editor_id,\n ps.labels,\n ps.linked_proposals,\n ps.name,\n ps.category,\n ps.summary,\n ps.description,\n ps.timeline,\n ps.views,\n ps.submission_deadline\nFROM\n rfps p\n INNER JOIN (\n SELECT\n rfp_id,\n MAX(ts) AS max_ts\n FROM\n rfp_snapshots\n GROUP BY\n rfp_id\n ) latest_snapshots ON p.id = latest_snapshots.rfp_id\n INNER JOIN rfp_snapshots ps ON latest_snapshots.rfp_id = ps.rfp_id\n AND latest_snapshots.max_ts = ps.ts;\n\nCREATE TABLE\n rfp_dumps (\n receipt_id varchar primary key,\n method_name varchar,\n block_height bigint,\n block_timestamp decimal(20, 0),\n args varchar,\n author varchar,\n rfp_id bigint\n );\n", "start_block": { "HEIGHT": 118538701 }, "rule": { "kind": "ACTION_ANY", "affected_account_id": "truedove38.near", "status": "SUCCESS" } }
Empty result
Registering function devhub_objects for account polyprogrammist.near
Receipt:
Predecessor ID:
Gas Burned:
223 Ggas
Tokens Burned:
0 
Transferred 0.06882  to polyprogrammist.near
Empty result
No logs