Skip to content

Commit

Permalink
Merge pull request #770 from near/develop
Browse files Browse the repository at this point in the history
weekly promotion of develop to main
  • Loading branch information
charleslavon authored Apr 18, 2024
2 parents 41d1026 + 1741292 commit 2492e54
Show file tree
Hide file tree
Showing 17 changed files with 1,014 additions and 197 deletions.
91 changes: 78 additions & 13 deletions indexers/entities/entities.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Block } from "@near-lake/primitives";
/**
* Note: We only support javascript at the moment. We will support Rust, Typescript in a further release.
*/
Expand All @@ -12,19 +11,29 @@ import { Block } from "@near-lake/primitives";
*
* @param {block} Block - A Near Protocol Block
*/
async function getBlock(block: Block) {
export default async function getBlock(block) {
function base64decode(encodedValue) {
try {
const buff = Buffer.from(encodedValue, "base64");
const str = buff.toString("utf-8").replace(/\\xa0/g, " ");
return JSON.parse(str);
} catch (error) {
console.log(
console.error(
'Error parsing JSON - skipping data for "functionCallOperation.args"',
error
);
}
}
function arrayInPostgresForm(a) {
if (!a) return a;
try {
const stringArray = JSON.stringify(a);
return stringArray.replaceAll("[", "{").replaceAll("]", "}");
} catch (error) {
console.error("Error parsing JSON - skipping array field", error);
return "";
}
}

const getFunctionCallsFunction = (block, contract, method) => {
return block
Expand Down Expand Up @@ -60,13 +69,19 @@ async function getBlock(block: Block) {
!Object.keys(functionCall.args.data) ||
!Object.keys(functionCall.args.data)[0]
) {
console.log("Set operation did not have arg data in expected format");
console.error(
"Set operation did not have arg data in expected format"
);
return;
}
const accountId = Object.keys(functionCall.args.data)[0];
if (!functionCall.args.data[accountId]) {
console.error("Set operation did not have arg data for accountId");
return;
}
const accountData = functionCall.args.data[accountId];
if (!accountData) {
console.log(
console.error(
"Set operation did not have arg data for accountId in expected format"
);
return;
Expand All @@ -75,6 +90,12 @@ async function getBlock(block: Block) {
})
.map((functionCall) => {
const accountId = Object.keys(functionCall.args.data)[0];
if (!functionCall.args.data[accountId]) {
console.error(
"Set operation did not have arg data for accountId, in map op"
);
return;
}
return {
accountId,
data: functionCall.args.data[accountId][operation],
Expand All @@ -90,15 +111,46 @@ async function getBlock(block: Block) {
}
const dataArray = Array.isArray(data) ? data : [data];
dataArray.map(async (data) => {
if (!data) {
console.error("missing entity data");
return;
}
const namespaces = Object.keys(data);
namespaces.map(async (namespace) => {
if (!namespace) {
console.error("missing entity namespace");
return;
}
const namespaceData = data[namespace];
if (!namespaceData) {
console.error("data not found for namespace " + namespace);
return;
}
const entityTypes = Object.keys(namespaceData);
entityTypes.map(async (entityType) => {
if (!entityType) {
console.error("missing entity entityType");
return;
}
const entityTypeData = namespaceData[entityType];
if (!entityTypeData) {
console.error(
"namespaceData not found for entityType " + entityType
);
return;
}
const entities = Object.keys(entityTypeData);
entities.map(async (name) => {
if (!name) {
console.error("missing entity name");
return;
}
const entityProps = entityTypeData[name];
if (!entityProps) {
console.error("entityProps not found for entity named " + name);
return;
}

if (entityProps["operation"]) {
switch (entityProps["operation"]) {
case "delete":
Expand All @@ -119,20 +171,34 @@ async function getBlock(block: Block) {
return;
}
}
const { displayName, logoUrl, ...entityAttributes } = entityProps;
const {
displayName,
logoUrl,
description,
tags,
...entityAttributes
} = entityProps;
const entity = {
namespace: namespace,
namespace,
entity_type: entityType,
account_id: accountId,
name: name,
display_name: displayName,
logo_url: logoUrl,
description,
tags: arrayInPostgresForm(tags),
attributes: entityAttributes,
};
await context.db.Entities.upsert(
entity,
["entity_type", "account_id", "name"],
["display_name", "logo_url", "attributes"]
[
"display_name",
"logo_url",
"description",
"tags",
"attributes",
]
);

console.log(
Expand All @@ -143,7 +209,7 @@ async function getBlock(block: Block) {
});
});
} catch (e) {
console.log(
console.error(
`Failed to store entity from ${accountId} to the database`,
e
);
Expand All @@ -161,15 +227,15 @@ async function getBlock(block: Block) {
const type = "star";
const starData = data[type];
if (!starData) {
console.log("No star data found");
console.error("No star data found");
return;
}
const star = JSON.parse(starData);
// "{\"key\":{\"type\":\"social\",\"path\":\"flatirons.near/examples/favoriteCar/delorean\"},\"value\":{\"type\":\"star\"}}"
const starArray = typeof star === "object" ? [star] : star;
starArray.map(async ({ key, value }) => {
if (!key || !value || !key.path || !value.type) {
console.log("Required fields not found for star", key, value);
console.error("Required fields not found for star", key, value);
return;
}
const { path } = key;
Expand All @@ -193,11 +259,10 @@ async function getBlock(block: Block) {
}
}
`;
console.log("mutation is", incDecQuery);
await context.graphql(incDecQuery, {});
});
} catch (e) {
console.log(
console.error(
`Failed to process star of entity from ${accountId} to the database`,
e
);
Expand Down
11 changes: 10 additions & 1 deletion indexers/entities/entities.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,22 @@ CREATE TABLE "entities"
"logo_url" TEXT,
"attributes" JSONB,
"stars" integer, -- default 0
"tags" text[],
-- "created_at" timestamp with time zone default now(),
-- "updated_at" timestamp with time zone default now(),
PRIMARY KEY ("entity_type", "account_id", "name")
);

CREATE INDEX
idx_tags_array ON entities USING GIN (tags);

-- CREATE TRIGGER set_dataplatform_near_agents_entities_updated_at
-- BEFORE UPDATE
-- ON dataplatform_near_agents.entities
-- FOR EACH ROW
-- EXECUTE FUNCTION dataplatform_near_agents.set_current_timestamp_updated_at();
-- EXECUTE FUNCTION dataplatform_near_agents.set_current_timestamp_updated_at();

-- CREATE VIEW dataplatform_near_entities."tags" as
-- select namespace, entity_type, unnest(tags) as tag, count(*)
-- from dataplatform_near_entities.entities
-- group by namespace, entity_type, tag
10 changes: 10 additions & 0 deletions indexers/entities/entities_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import getBlock from './entities.js';
import testBlock from './test_block.js';

describe('entities.js indexer', () => {

it('accepts data with an empty namespace', () => {
getBlock(testBlock);
// successful if it does not throw an error
});
});
Loading

0 comments on commit 2492e54

Please sign in to comment.