From ea2baefa1ca833e3db54d09a9c382b3f0e6f2954 Mon Sep 17 00:00:00 2001 From: Nik Graf Date: Tue, 20 Jan 2026 19:07:51 +0100 Subject: [PATCH 1/6] add value type IDs --- src/core/ids/system.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/core/ids/system.ts b/src/core/ids/system.ts index 3801fbb..05b35b7 100644 --- a/src/core/ids/system.ts +++ b/src/core/ids/system.ts @@ -17,11 +17,23 @@ export const BLOCKS = Id('beaba5cba67741a8b35377030613fc70'); /** Value types */ +export const BOOLEAN = Id('7aa4792eeacd41868272fa7fc18298ac'); +export const INTEGER = Id('149fd752d9d04f80820d1d942eea7841'); +export const FLOAT64 = Id('9b597aaec31c46c88565a370da0c2a65'); +export const DECIMAL = Id('a3288c22a0564f6fb409fbcccb2c118c'); +export const TEXT = Id('9edb6fcce4544aa5861139d7f024c010'); +export const BYTES = Id('66b433247667496899b48a89bd1de22b'); +export const DATE = Id('e661d10292794449a22367dbae1be05a'); +export const TIME = Id('ad75102b03c04d59903813ede9482742'); +export const DATETIME = Id('167664f668f840e1976b20bd16ed8d47'); +export const SCHEDULE = Id('caf4dd12ba4844b99171aff6c1313b50'); +export const POINT = Id('df250d17e364413d97792ddaae841e34'); +export const EMBEDDING = Id('f732849378ba4577a33fac5f1c964f18'); +export const RELATION = Id('4b6d9fc1fbfe474c861c83398e1b50d9'); + export const URL = Id('283127c96142468492ed90b0ebc7f29a'); export const IMAGE = Id('f3f790c4c74e4d23a0a91e8ef84e30d9'); -export const RELATION = Id('4b6d9fc1fbfe474c861c83398e1b50d9'); - export const SPACE_TYPE = Id('362c1dbddc6444bba3c4652f38a642d7'); /** From 1be91ddab1cedac48dc3d39f539d98f0c261cf12 Mon Sep 17 00:00:00 2001 From: Nik Graf Date: Tue, 20 Jan 2026 21:06:25 +0100 Subject: [PATCH 2/6] fix create property --- scripts/setup-rank-types.ts | 18 ++++++------ src/core/ids/system.ts | 5 ++-- src/graph/create-property.test.ts | 49 +++++++++++++++++++++++-------- src/graph/create-property.ts | 45 ++++++++++++++++++++++++++-- src/types.ts | 14 ++++++++- 5 files changed, 105 insertions(+), 26 deletions(-) diff --git a/scripts/setup-rank-types.ts b/scripts/setup-rank-types.ts index 13a649a..29b24a9 100644 --- a/scripts/setup-rank-types.ts +++ b/scripts/setup-rank-types.ts @@ -2,10 +2,10 @@ * Setup script for Rank types in the knowledge graph. * * This script generates the Ops needed to create the Rank schema types: - * - RANK_TYPE_PROPERTY: A STRING property storing ORDINAL/WEIGHTED + * - RANK_TYPE_PROPERTY: A TEXT property storing ORDINAL/WEIGHTED * - RANK_VOTES_RELATION_TYPE: A RELATION property linking rank to voted entities - * - VOTE_ORDINAL_VALUE_PROPERTY: A STRING property storing fractional indexing position - * - VOTE_WEIGHTED_VALUE_PROPERTY: A NUMBER property storing numeric score + * - VOTE_ORDINAL_VALUE_PROPERTY: A TEXT property storing fractional indexing position + * - VOTE_WEIGHTED_VALUE_PROPERTY: A FLOAT64 property storing numeric score * - RANK_TYPE: A Type entity representing a Rank * * Usage: import { ops } from './scripts/setup-rank-types.js' @@ -25,12 +25,12 @@ import { createType } from '../src/graph/create-type.js'; const generateRankTypeOps = (): GrcOp[] => { const ops: GrcOp[] = []; - // 1. Create RANK_TYPE_PROPERTY - A STRING property storing ORDINAL/WEIGHTED + // 1. Create RANK_TYPE_PROPERTY - A TEXT property storing ORDINAL/WEIGHTED const rankTypeProperty = createProperty({ id: RANK_TYPE_PROPERTY, name: 'Rank Type', description: 'The type of rank: ORDINAL (ordered list) or WEIGHTED (scored values)', - dataType: 'STRING', + dataType: 'TEXT', }); ops.push(...rankTypeProperty.ops); @@ -43,21 +43,21 @@ const generateRankTypeOps = (): GrcOp[] => { }); ops.push(...rankVotesRelationType.ops); - // 3. Create VOTE_ORDINAL_VALUE_PROPERTY - A STRING property for fractional indexing + // 3. Create VOTE_ORDINAL_VALUE_PROPERTY - A TEXT property for fractional indexing const voteOrdinalValueProperty = createProperty({ id: VOTE_ORDINAL_VALUE_PROPERTY, name: 'Vote Ordinal Value', description: 'Fractional indexing string for ordered rank positions', - dataType: 'STRING', + dataType: 'TEXT', }); ops.push(...voteOrdinalValueProperty.ops); - // 4. Create VOTE_WEIGHTED_VALUE_PROPERTY - A NUMBER property for numeric scores + // 4. Create VOTE_WEIGHTED_VALUE_PROPERTY - A FLOAT64 property for numeric scores const voteWeightedValueProperty = createProperty({ id: VOTE_WEIGHTED_VALUE_PROPERTY, name: 'Vote Weighted Value', description: 'Numeric score for weighted rank values', - dataType: 'NUMBER', + dataType: 'FLOAT64', }); ops.push(...voteWeightedValueProperty.ops); diff --git a/src/core/ids/system.ts b/src/core/ids/system.ts index 05b35b7..5c6d4cc 100644 --- a/src/core/ids/system.ts +++ b/src/core/ids/system.ts @@ -15,8 +15,7 @@ export const TABS_PROPERTY = Id('4d9cba1c4766469881cd3273891a018b'); export const BLOCKS = Id('beaba5cba67741a8b35377030613fc70'); -/** Value types */ - +/** Data types */ export const BOOLEAN = Id('7aa4792eeacd41868272fa7fc18298ac'); export const INTEGER = Id('149fd752d9d04f80820d1d942eea7841'); export const FLOAT64 = Id('9b597aaec31c46c88565a370da0c2a65'); @@ -31,6 +30,8 @@ export const POINT = Id('df250d17e364413d97792ddaae841e34'); export const EMBEDDING = Id('f732849378ba4577a33fac5f1c964f18'); export const RELATION = Id('4b6d9fc1fbfe474c861c83398e1b50d9'); +export const DATA_TYPE = Id('6d29d57849bb4959baf72cc696b1671a'); + export const URL = Id('283127c96142468492ed90b0ebc7f29a'); export const IMAGE = Id('f3f790c4c74e4d23a0a91e8ef84e30d9'); diff --git a/src/graph/create-property.test.ts b/src/graph/create-property.test.ts index d45af0c..241cb5b 100644 --- a/src/graph/create-property.test.ts +++ b/src/graph/create-property.test.ts @@ -1,7 +1,15 @@ import type { CreateEntity, CreateRelation } from '@geoprotocol/grc-20'; import { describe, expect, it } from 'vitest'; import { JOB_TYPE, ROLES_PROPERTY } from '../core/ids/content.js'; -import { NAME_PROPERTY, PROPERTY, RELATION_VALUE_RELATIONSHIP_TYPE, TYPES_PROPERTY } from '../core/ids/system.js'; +import { + DATA_TYPE, + FLOAT64, + NAME_PROPERTY, + PROPERTY, + RELATION_VALUE_RELATIONSHIP_TYPE, + TEXT, + TYPES_PROPERTY, +} from '../core/ids/system.js'; import { Id } from '../id.js'; import { toGrcId } from '../id-utils.js'; import { createProperty } from './create-property.js'; @@ -11,13 +19,13 @@ describe('createProperty', () => { const property = createProperty({ name: 'Disclaimer', description: 'This is a disclaimer', - dataType: 'STRING', + dataType: 'TEXT', }); expect(property).toBeDefined(); expect(typeof property.id).toBe('string'); expect(property.ops).toBeDefined(); - // 1 createEntity + 1 createRelation (type) - expect(property.ops.length).toBe(2); + // 1 createEntity + 1 createRelation (type) + 1 createRelation (data type) + expect(property.ops.length).toBe(3); // Check entity creation const entityOp = property.ops[0] as CreateEntity; @@ -41,20 +49,27 @@ describe('createProperty', () => { expect(typeRelOp.from).toEqual(toGrcId(property.id)); expect(typeRelOp.to).toEqual(toGrcId(PROPERTY)); expect(typeRelOp.relationType).toEqual(toGrcId(TYPES_PROPERTY)); + + // Check data type relation to TEXT + const dataTypeRelOp = property.ops[2] as CreateRelation; + expect(dataTypeRelOp.type).toBe('createRelation'); + expect(dataTypeRelOp.from).toEqual(toGrcId(property.id)); + expect(dataTypeRelOp.to).toEqual(toGrcId(TEXT)); + expect(dataTypeRelOp.relationType).toEqual(toGrcId(DATA_TYPE)); }); - it('creates a NUMBER property', async () => { + it('creates a FLOAT64 property', async () => { const property = createProperty({ name: 'Price', description: 'The price of the product', - dataType: 'NUMBER', + dataType: 'FLOAT64', }); expect(property).toBeDefined(); expect(typeof property.id).toBe('string'); expect(property.ops).toBeDefined(); - // 1 createEntity + 1 createRelation (type) - expect(property.ops.length).toBe(2); + // 1 createEntity + 1 createRelation (type) + 1 createRelation (data type) + expect(property.ops.length).toBe(3); // Check entity creation const entityOp = property.ops[0] as CreateEntity; @@ -67,6 +82,13 @@ describe('createProperty', () => { expect(typeRelOp.from).toEqual(toGrcId(property.id)); expect(typeRelOp.to).toEqual(toGrcId(PROPERTY)); expect(typeRelOp.relationType).toEqual(toGrcId(TYPES_PROPERTY)); + + // Check data type relation to FLOAT64 + const dataTypeRelOp = property.ops[2] as CreateRelation; + expect(dataTypeRelOp.type).toBe('createRelation'); + expect(dataTypeRelOp.from).toEqual(toGrcId(property.id)); + expect(dataTypeRelOp.to).toEqual(toGrcId(FLOAT64)); + expect(dataTypeRelOp.relationType).toEqual(toGrcId(DATA_TYPE)); }); it('creates a RELATION property', async () => { @@ -140,7 +162,7 @@ describe('createProperty', () => { const property = createProperty({ id: providedId, name: 'Price', - dataType: 'NUMBER', + dataType: 'FLOAT64', }); expect(property).toBeDefined(); @@ -187,7 +209,8 @@ describe('createProperty', () => { }); expect(property).toBeDefined(); - expect(property.ops.length).toBe(2); + // 1 createEntity + 1 createRelation (type) + 1 createRelation (data type) + expect(property.ops.length).toBe(3); const entityOp = property.ops[0] as CreateEntity; expect(entityOp.type).toBe('createEntity'); @@ -204,7 +227,8 @@ describe('createProperty', () => { }); expect(property).toBeDefined(); - expect(property.ops.length).toBe(2); + // 1 createEntity + 1 createRelation (type) + 1 createRelation (data type) + expect(property.ops.length).toBe(3); const typeRelOp = property.ops[1] as CreateRelation; expect(typeRelOp.type).toBe('createRelation'); @@ -218,7 +242,8 @@ describe('createProperty', () => { }); expect(property).toBeDefined(); - expect(property.ops.length).toBe(2); + // 1 createEntity + 1 createRelation (type) + 1 createRelation (data type) + expect(property.ops.length).toBe(3); const typeRelOp = property.ops[1] as CreateRelation; expect(typeRelOp.type).toBe('createRelation'); diff --git a/src/graph/create-property.ts b/src/graph/create-property.ts index 2326abf..1ca3b8a 100644 --- a/src/graph/create-property.ts +++ b/src/graph/create-property.ts @@ -1,11 +1,43 @@ import { type Op as GrcOp, createRelation as grcCreateRelation } from '@geoprotocol/grc-20'; -import { PROPERTY, RELATION_VALUE_RELATIONSHIP_TYPE, TYPES_PROPERTY } from '../core/ids/system.js'; +import { + BOOLEAN, + BYTES, + DATA_TYPE, + DATE, + DATETIME, + DECIMAL, + EMBEDDING, + FLOAT64, + INTEGER, + POINT, + PROPERTY, + RELATION_VALUE_RELATIONSHIP_TYPE, + SCHEDULE, + TEXT, + TIME, + TYPES_PROPERTY, +} from '../core/ids/system.js'; import { Id } from '../id.js'; import { assertValid, generate, toGrcId } from '../id-utils.js'; -import type { CreatePropertyParams, CreateResult } from '../types.js'; +import type { CreatePropertyParams, CreateResult, ValueDataType } from '../types.js'; import { createEntity } from './create-entity.js'; import { createRelation } from './create-relation.js'; +const VALUE_DATA_TYPE_TO_ID: Record = { + BOOLEAN, + INTEGER, + FLOAT64, + DECIMAL, + TEXT, + BYTES, + DATE, + TIME, + DATETIME, + SCHEDULE, + POINT, + EMBEDDING, +}; + /** * Creates a property with the given name, description, cover, and dataType. * All IDs passed to this function (cover, relation value types, properties) are validated. @@ -90,6 +122,15 @@ export const createProperty = (params: CreatePropertyParams): CreateResult => { ops.push(...relationOps); } } + } else { + // add the data type relation for value types + const dataTypeId = VALUE_DATA_TYPE_TO_ID[params.dataType]; + const { ops: relationOps } = createRelation({ + fromEntity: entityId, + toEntity: dataTypeId, + type: DATA_TYPE, + }); + ops.push(...relationOps); } return { id: Id(entityId), ops }; diff --git a/src/types.ts b/src/types.ts index 6b9a1bb..60c7a59 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,7 +7,19 @@ import type { Id } from './id.js'; export type { GrcOp }; -export type ValueDataType = 'STRING' | 'NUMBER' | 'BOOLEAN' | 'TIME' | 'POINT'; +export type ValueDataType = + | 'BOOLEAN' + | 'INTEGER' + | 'FLOAT64' + | 'DECIMAL' + | 'TEXT' + | 'BYTES' + | 'DATE' + | 'TIME' + | 'DATETIME' + | 'SCHEDULE' + | 'POINT' + | 'EMBEDDING'; export type DataType = ValueDataType | 'RELATION'; From a510640d9986d94a2cb8f8dabae93adcdb073116 Mon Sep 17 00:00:00 2001 From: Nik Graf Date: Tue, 20 Jan 2026 21:07:29 +0100 Subject: [PATCH 3/6] add changeset --- .changeset/short-cycles-happen.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/short-cycles-happen.md diff --git a/.changeset/short-cycles-happen.md b/.changeset/short-cycles-happen.md new file mode 100644 index 0000000..6332b7a --- /dev/null +++ b/.changeset/short-cycles-happen.md @@ -0,0 +1,5 @@ +--- +"@graphprotocol/grc-20": patch +--- + +fix Graph.createProperty to work with the new grc-20 spec. It not accepts the new data types From 5331c581ef76ea932ffafa36c9e1bfa3dc252ab6 Mon Sep 17 00:00:00 2001 From: Nik Graf Date: Tue, 20 Jan 2026 21:09:58 +0100 Subject: [PATCH 4/6] update the readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 52aa413..9ed8917 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ import { Graph } from '@graphprotocol/grc-20'; // create a property const propertyResult = Graph.createProperty({ name: 'name of the property', - dataType: 'STRING', // STRING | NUMBER | TIME | POINT | BOOLEAN | RELATION, + dataType: 'TEXT', // BOOLEAN | INTEGER | FLOAT64 | DECIMAL | TEXT | BYTES | DATE | TIME | DATETIME | SCHEDULE | POINT | EMBEDDING | RELATION }); // create a type @@ -174,7 +174,7 @@ const ops: Array = []; // create an age property const { id: agePropertyId, ops: createAgePropertyOps } = Graph.createProperty({ - dataType: 'NUMBER', + dataType: 'INTEGER', name: 'Age', }); ops.push(...createAgePropertyOps); From 73ae28bda794d81aded28d41ddae0f68bde41482 Mon Sep 17 00:00:00 2001 From: Nik Graf Date: Tue, 20 Jan 2026 21:13:22 +0100 Subject: [PATCH 5/6] fix changeset --- .changeset/short-cycles-happen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/short-cycles-happen.md b/.changeset/short-cycles-happen.md index 6332b7a..609ed35 100644 --- a/.changeset/short-cycles-happen.md +++ b/.changeset/short-cycles-happen.md @@ -2,4 +2,4 @@ "@graphprotocol/grc-20": patch --- -fix Graph.createProperty to work with the new grc-20 spec. It not accepts the new data types +fix Graph.createProperty to work with the new grc-20 spec. It accepts the new data types From de4b69c6b972b840ac8a8eee7a1f42110dd3f113 Mon Sep 17 00:00:00 2001 From: Nik Graf Date: Tue, 20 Jan 2026 21:40:02 +0100 Subject: [PATCH 6/6] migrate from INTEGER to INT64 --- README.md | 4 ++-- src/core/ids/system.ts | 2 +- src/graph/create-property.ts | 4 ++-- src/types.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9ed8917..e4396c6 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ import { Graph } from '@graphprotocol/grc-20'; // create a property const propertyResult = Graph.createProperty({ name: 'name of the property', - dataType: 'TEXT', // BOOLEAN | INTEGER | FLOAT64 | DECIMAL | TEXT | BYTES | DATE | TIME | DATETIME | SCHEDULE | POINT | EMBEDDING | RELATION + dataType: 'TEXT', // BOOLEAN | INT64 | FLOAT64 | DECIMAL | TEXT | BYTES | DATE | TIME | DATETIME | SCHEDULE | POINT | EMBEDDING | RELATION }); // create a type @@ -174,7 +174,7 @@ const ops: Array = []; // create an age property const { id: agePropertyId, ops: createAgePropertyOps } = Graph.createProperty({ - dataType: 'INTEGER', + dataType: 'INT64', name: 'Age', }); ops.push(...createAgePropertyOps); diff --git a/src/core/ids/system.ts b/src/core/ids/system.ts index 5c6d4cc..f04f744 100644 --- a/src/core/ids/system.ts +++ b/src/core/ids/system.ts @@ -17,7 +17,7 @@ export const BLOCKS = Id('beaba5cba67741a8b35377030613fc70'); /** Data types */ export const BOOLEAN = Id('7aa4792eeacd41868272fa7fc18298ac'); -export const INTEGER = Id('149fd752d9d04f80820d1d942eea7841'); +export const INT64 = Id('149fd752d9d04f80820d1d942eea7841'); export const FLOAT64 = Id('9b597aaec31c46c88565a370da0c2a65'); export const DECIMAL = Id('a3288c22a0564f6fb409fbcccb2c118c'); export const TEXT = Id('9edb6fcce4544aa5861139d7f024c010'); diff --git a/src/graph/create-property.ts b/src/graph/create-property.ts index 1ca3b8a..7ecb894 100644 --- a/src/graph/create-property.ts +++ b/src/graph/create-property.ts @@ -8,7 +8,7 @@ import { DECIMAL, EMBEDDING, FLOAT64, - INTEGER, + INT64, POINT, PROPERTY, RELATION_VALUE_RELATIONSHIP_TYPE, @@ -25,7 +25,7 @@ import { createRelation } from './create-relation.js'; const VALUE_DATA_TYPE_TO_ID: Record = { BOOLEAN, - INTEGER, + INT64, FLOAT64, DECIMAL, TEXT, diff --git a/src/types.ts b/src/types.ts index 60c7a59..feb8394 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,7 +9,7 @@ export type { GrcOp }; export type ValueDataType = | 'BOOLEAN' - | 'INTEGER' + | 'INT64' | 'FLOAT64' | 'DECIMAL' | 'TEXT'