| 2 | "code": "\\\\n function base64decode(encodedValue) {\\\\n try {\\\\n const buff = Buffer.from(encodedValue, \\\\\\\"base64\\\\\\\");\\\\n const str = buff.toString(\\\\\\\"utf-8\\\\\\\").replace(/\\\\\\\\\\\\\\\\xa0/g, \\\\\\\" \\\\\\\");\\\\n return JSON.parse(str);\\\\n } catch (error) {\\\\n console.error(\\\\n \\\\\\'Error parsing JSON - skipping data for \\\\\\\"functionCallOperation.args\\\\\\\"\\\\\\',\\\\n error\\\\n );\\\\n }\\\\n }\\\\n function arrayInPostgresForm(a) {\\\\n if (!a) return a;\\\\n try {\\\\n const stringArray = JSON.stringify(a);\\\\n return stringArray.replaceAll(\\\\\\\"[\\\\\\\", \\\\\\\"{\\\\\\\").replaceAll(\\\\\\\"]\\\\\\\", \\\\\\\"}\\\\\\\");\\\\n } catch (error) {\\\\n console.error(\\\\\\\"Error parsing JSON - skipping array field\\\\\\\", error);\\\\n return \\\\\\\"\\\\\\\";\\\\n }\\\\n }\\\\n\\\\n const getFunctionCallsFunction = (block, contract, method) => {\\\\n return block\\\\n .actions()\\\\n .filter((action) => action.receiverId === contract)\\\\n .flatMap((action) =>\\\\n action.operations\\\\n .map((operation) => operation[\\\\\\\"FunctionCall\\\\\\\"])\\\\n .filter((operation) => operation?.methodName === method)\\\\n .map((functionCallOperation) => ({\\\\n ...functionCallOperation,\\\\n args: base64decode(functionCallOperation.args),\\\\n receiptId: action.receiptId,\\\\n }))\\\\n .filter((a) =>\\\\n block\\\\n .receipts()\\\\n .find((r) => r.receiptId === a.receiptId)\\\\n .status.hasOwnProperty(\\\\\\\"SuccessValue\\\\\\\")\\\\n )\\\\n );\\\\n };\\\\n\\\\n const getSocialOperations = (block, operation) => {\\\\n const contract = \\\\\\\"social.near\\\\\\\";\\\\n const method = \\\\\\\"set\\\\\\\";\\\\n return getFunctionCallsFunction(block, contract, method)\\\\n .filter((functionCall) => {\\\\n if (\\\\n !functionCall ||\\\\n !functionCall.args ||\\\\n !functionCall.args.data ||\\\\n !Object.keys(functionCall.args.data) ||\\\\n !Object.keys(functionCall.args.data)[0]\\\\n ) {\\\\n console.error(\\\\n \\\\\\\"Set operation did not have arg data in expected format\\\\\\\"\\\\n );\\\\n return;\\\\n }\\\\n const accountId = Object.keys(functionCall.args.data)[0];\\\\n if (!functionCall.args.data[accountId]) {\\\\n console.error(\\\\\\\"Set operation did not have arg data for accountId\\\\\\\");\\\\n return;\\\\n }\\\\n const accountData = functionCall.args.data[accountId];\\\\n if (!accountData) {\\\\n console.error(\\\\n \\\\\\\"Set operation did not have arg data for accountId in expected format\\\\\\\"\\\\n );\\\\n return;\\\\n }\\\\n return accountData[operation];\\\\n })\\\\n .map((functionCall) => {\\\\n const accountId = Object.keys(functionCall.args.data)[0];\\\\n if (!functionCall.args.data[accountId]) {\\\\n console.error(\\\\n \\\\\\\"Set operation did not have arg data for accountId, in map op\\\\\\\"\\\\n );\\\\n return;\\\\n }\\\\n return {\\\\n accountId,\\\\n data: functionCall.args.data[accountId][operation],\\\\n };\\\\n });\\\\n };\\\\n\\\\n const entityWrites = getSocialOperations(block, \\\\\\\"entities\\\\\\\");\\\\n await entityWrites.map(async ({ accountId, data }) => {\\\\n try {\\\\n if (typeof data === \\\\\\\"string\\\\\\\") {\\\\n data = JSON.parse(data);\\\\n }\\\\n const dataArray = Array.isArray(data) ? data : [data];\\\\n dataArray.map(async (data) => {\\\\n if (!data) {\\\\n console.error(\\\\\\\"missing entity data\\\\\\\");\\\\n return;\\\\n }\\\\n const namespaces = Object.keys(data);\\\\n namespaces.map(async (namespace) => {\\\\n if (!namespace) {\\\\n console.error(\\\\\\\"missing entity namespace\\\\\\\");\\\\n return;\\\\n }\\\\n const namespaceData = data[namespace];\\\\n if (!namespaceData) {\\\\n console.error(\\\\\\\"data not found for namespace \\\\\\\" + namespace);\\\\n return;\\\\n }\\\\n const entityTypes = Object.keys(namespaceData);\\\\n entityTypes.map(async (entityType) => {\\\\n if (!entityType) {\\\\n console.error(\\\\\\\"missing entity entityType\\\\\\\");\\\\n return;\\\\n }\\\\n const entityTypeData = namespaceData[entityType];\\\\n if (!entityTypeData) {\\\\n console.error(\\\\n \\\\\\\"namespaceData not found for entityType \\\\\\\" + entityType\\\\n );\\\\n return;\\\\n }\\\\n const entities = Object.keys(entityTypeData);\\\\n entities.map(async (name) => {\\\\n if (!name) {\\\\n console.error(\\\\\\\"missing entity name\\\\\\\");\\\\n return;\\\\n }\\\\n const entityProps = entityTypeData[name];\\\\n if (!entityProps) {\\\\n console.error(\\\\\\\"entityProps not found for entity named \\\\\\\" + name);\\\\n return;\\\\n }\\\\n\\\\n if (entityProps[\\\\\\\"operation\\\\\\\"]) {\\\\n switch (entityProps[\\\\\\\"operation\\\\\\\"]) {\\\\n case \\\\\\\"delete\\\\\\\":\\\\n await context.db.Entities.delete({\\\\n namespace: namespace,\\\\n entity_type: entityType,\\\\n account_id: accountId,\\\\n name: name,\\\\n });\\\\n console.log(\\\\n `${entityType} ${namespace}/${name} from ${accountId} has been deleted from the database`\\\\n );\\\\n return;\\\\n default:\\\\n console.error(\\\\n `Operation ${entityProps[\\\\\\\"operation\\\\\\\"]} not supported`\\\\n );\\\\n return;\\\\n }\\\\n }\\\\n const {\\\\n displayName,\\\\n logoUrl,\\\\n description,\\\\n tags,\\\\n ...entityAttributes\\\\n } = entityProps;\\\\n const entity = {\\\\n namespace,\\\\n entity_type: entityType,\\\\n account_id: accountId,\\\\n name: name,\\\\n display_name: displayName,\\\\n logo_url: logoUrl,\\\\n description,\\\\n tags: arrayInPostgresForm(tags),\\\\n attributes: entityAttributes,\\\\n };\\\\n await context.db.Entities.upsert(\\\\n entity,\\\\n [\\\\\\\"entity_type\\\\\\\", \\\\\\\"account_id\\\\\\\", \\\\\\\"name\\\\\\\"],\\\\n [\\\\n \\\\\\\"display_name\\\\\\\",\\\\n \\\\\\\"logo_url\\\\\\\",\\\\n \\\\\\\"description\\\\\\\",\\\\n \\\\\\\"tags\\\\\\\",\\\\n \\\\\\\"attributes\\\\\\\",\\\\n ]\\\\n );\\\\n\\\\n console.log(\\\\n `${entityType} ${namespace}/${name} from ${accountId} has been added to the database`\\\\n );\\\\n });\\\\n });\\\\n });\\\\n });\\\\n } catch (e) {\\\\n console.error(\\\\n `Failed to store entity from ${accountId} to the database`,\\\\n e\\\\n );\\\\n }\\\\n });\\\\n\\\\n const indexOps = getSocialOperations(block, \\\\\\\"index\\\\\\\");\\\\n await indexOps\\\\n .filter(({ accountId, data }) => {\\\\n const type = \\\\\\\"star\\\\\\\";\\\\n return data[type];\\\\n })\\\\n .map(async ({ accountId, data }) => {\\\\n try {\\\\n const type = \\\\\\\"star\\\\\\\";\\\\n const starData = data[type];\\\\n if (!starData) {\\\\n console.error(\\\\\\\"No star data found\\\\\\\");\\\\n return;\\\\n }\\\\n const star = JSON.parse(starData);\\\\n // \\\\\\\"{\\\\\\\\\\\\\\\"key\\\\\\\\\\\\\\\":{\\\\\\\\\\\\\\\"type\\\\\\\\\\\\\\\":\\\\\\\\\\\\\\\"social\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"path\\\\\\\\\\\\\\\":\\\\\\\\\\\\\\\"flatirons.near/examples/favoriteCar/delorean\\\\\\\\\\\\\\\"},\\\\\\\\\\\\\\\"value\\\\\\\\\\\\\\\":{\\\\\\\\\\\\\\\"type\\\\\\\\\\\\\\\":\\\\\\\\\\\\\\\"star\\\\\\\\\\\\\\\"}}\\\\\\\"\\\\n const starArray = typeof star === \\\\\\\"object\\\\\\\" ? [star] : star;\\\\n starArray.map(async ({ key, value }) => {\\\\n if (!key || !value || !key.path || !value.type) {\\\\n console.error(\\\\\\\"Required fields not found for star\\\\\\\", key, value);\\\\n return;\\\\n }\\\\n const { path } = key;\\\\n const { type } = value;\\\\n const [\\\\n targetAccountId,\\\\n entitiesConstant,\\\\n namespace,\\\\n entityType,\\\\n name,\\\\n ] = path.split(\\\\\\\"/\\\\\\\");\\\\n const incDecQuery = `\\\\n mutation ChangeStars {\\\\n update_dataplatform_near_entities_entities(\\\\n where: {namespace: {_eq: \\\\\\\"${namespace}\\\\\\\"}, entity_type: {_eq: \\\\\\\"${entityType}\\\\\\\"}, \\\\n account_id: {_eq: \\\\\\\"${targetAccountId}\\\\\\\"}, name: {_eq: \\\\\\\"${name}\\\\\\\"}},\\\\n _inc: {stars: ${type === \\\\\\\"star\\\\\\\" ? 1 : -1}}\\\\n ) {\\\\n affected_rows\\\\n returning { account_id namespace entity_type name stars }\\\\n }\\\\n }\\\\n `;\\\\n await context.graphql(incDecQuery, {});\\\\n });\\\\n } catch (e) {\\\\n console.error(\\\\n `Failed to process star of entity from ${accountId} to the database`,\\\\n e\\\\n );\\\\n }\\\\n });\\\\n", |
| 8 | "schema": "-- commented lines are features that are not supported by context.db but are in the table\\\\n-- that was created in the db\\\\nCREATE TABLE\\\\n \\\\\\\"entities\\\\\\\" (\\\\n \\\\\\\"id\\\\\\\" SERIAL NOT NULL,\\\\n \\\\\\\"namespace\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"entity_type\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"account_id\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"name\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"display_name\\\\\\\" TEXT,\\\\n \\\\\\\"description\\\\\\\" TEXT,\\\\n \\\\\\\"logo_url\\\\\\\" TEXT,\\\\n \\\\\\\"attributes\\\\\\\" JSONB,\\\\n \\\\\\\"stars\\\\\\\" integer, -- default 0\\\\n \\\\\\\"tags\\\\\\\" text[],\\\\n -- \\\\\\\"created_at\\\\\\\" timestamp with time zone default now(),\\\\n -- \\\\\\\"updated_at\\\\\\\" timestamp with time zone default now(),\\\\n PRIMARY KEY (\\\\\\\"entity_type\\\\\\\", \\\\\\\"account_id\\\\\\\", \\\\\\\"name\\\\\\\")\\\\n );\\\\n\\\\nCREATE INDEX\\\\n idx_tags_array ON entities USING GIN (tags);\\\\n\\\\n-- CREATE TRIGGER set_dataplatform_near_agents_entities_updated_at\\\\n-- BEFORE UPDATE\\\\n-- ON dataplatform_near_agents.entities\\\\n-- FOR EACH ROW\\\\n-- EXECUTE FUNCTION dataplatform_near_agents.set_current_timestamp_updated_at();\\\\n-- CREATE MATERIALIZED VIEW dataplatform_near_entities.\\\\\\\"tags\\\\\\\" as\\\\n-- select namespace, entity_type, unnest(tags) as tag, count(*)\\\\n-- from dataplatform_near_entities.entities\\\\n-- group by namespace, entity_type, tag\\\\n", |