Skip to content

Feature/frontend compatibility with v2 #294

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jun 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 69 additions & 2 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ type AllowlistRecord {
"""The hypercert ID the claimable fraction belongs to"""
hypercert_id: String

"""The ID of the allow list record"""
id: String

"""The leaf of the Merkle tree for the claimable fraction"""
leaf: String

Expand Down Expand Up @@ -168,6 +171,7 @@ type AttestationSchema {

input AttestationSchemaAttestationWhereInput {
attester: StringSearchOptions
contract_address: StringSearchOptions
creation_block_number: BigIntSearchOptions
creation_block_timestamp: BigIntSearchOptions
id: StringSearchOptions
Expand Down Expand Up @@ -217,6 +221,7 @@ input AttestationSchemaWhereInput {

input AttestationSortOptions {
attester: SortOrder = null
contract_address: SortOrder = null
creation_block_number: SortOrder = null
creation_block_timestamp: SortOrder = null
id: SortOrder = null
Expand All @@ -230,6 +235,7 @@ input AttestationSortOptions {

input AttestationWhereInput {
attester: StringSearchOptions
contract_address: StringSearchOptions
creation_block_number: BigIntSearchOptions
creation_block_timestamp: BigIntSearchOptions
eas_schema: AttestationAttestationSchemaWhereInput = {}
Expand Down Expand Up @@ -268,6 +274,7 @@ type Blueprint {
}

input BlueprintSortOptions {
admin_address: SortOrder = null
created_at: SortOrder = null
id: SortOrder = null
minted: SortOrder = null
Expand All @@ -282,6 +289,7 @@ input BlueprintUserWhereInput {
}

input BlueprintWhereInput {
admin_address: StringSearchOptions
admins: BlueprintUserWhereInput = {}
created_at: StringSearchOptions
id: NumberSearchOptions
Expand Down Expand Up @@ -314,6 +322,7 @@ type Collection {
}

input CollectionBlueprintWhereInput {
admin_address: StringSearchOptions
created_at: StringSearchOptions
id: NumberSearchOptions
minted: BooleanSearchOptions
Expand Down Expand Up @@ -628,6 +637,7 @@ type HyperboardOwner {
}

input HyperboardSortOptions {
admin_address: SortOrder = null
chain_ids: SortOrder = null
id: SortOrder = null
}
Expand All @@ -640,6 +650,7 @@ input HyperboardUserWhereInput {
}

input HyperboardWhereInput {
admin_address: StringSearchOptions
admins: HyperboardUserWhereInput = {}
chain_ids: NumberArraySearchOptions
collections: HyperboardCollectionWhereInput = {}
Expand Down Expand Up @@ -702,6 +713,7 @@ type Hypercert {

input HypercertAttestationWhereInput {
attester: StringSearchOptions
contract_address: StringSearchOptions
creation_block_number: BigIntSearchOptions
creation_block_timestamp: BigIntSearchOptions
id: StringSearchOptions
Expand Down Expand Up @@ -816,6 +828,45 @@ input HypercertWhereInput {
uri: StringSearchOptions
}

"""
Hypercert with metadata, contract, orders, sales and fraction information
"""
type HypercertWithMetadata {
"""Count of attestations referencing this hypercert"""
attestations_count: Int

"""The UUID of the contract as stored in the database"""
contracts_id: ID
creation_block_number: EthBigInt
creation_block_timestamp: EthBigInt

"""The address of the creator of the hypercert"""
creator_address: String

"""
Concatenation of [chainID]-[contractAddress]-[tokenID] to discern hypercerts across chains
"""
hypercert_id: ID
id: ID
last_update_block_number: EthBigInt
last_update_block_timestamp: EthBigInt

"""The metadata for the hypercert as referenced by the uri"""
metadata: Metadata

"""Count of sales of fractions that belong to this hypercert"""
sales_count: Int

"""The token ID of the hypercert"""
token_id: EthBigInt

"""The total units held by the hypercert"""
units: EthBigInt

"""References the metadata for this claim"""
uri: String
}

"""
Hypercert without metadata, contract, orders, sales and fraction information
"""
Expand Down Expand Up @@ -878,6 +929,21 @@ type Metadata {
work_timeframe_to: EthBigInt
}

input MetadataHypercertWhereInput {
attestations_count: NumberSearchOptions
creation_block_number: BigIntSearchOptions
creation_block_timestamp: BigIntSearchOptions
creator_address: StringSearchOptions
hypercert_id: StringSearchOptions
id: StringSearchOptions
last_update_block_number: BigIntSearchOptions
last_update_block_timestamp: BigIntSearchOptions
sales_count: NumberSearchOptions
token_id: BigIntSearchOptions
units: BigIntSearchOptions
uri: StringSearchOptions
}

input MetadataSortOptions {
allow_list_uri: SortOrder = null
contributors: SortOrder = null
Expand All @@ -900,6 +966,7 @@ input MetadataWhereInput {
contributors: StringArraySearchOptions
description: StringSearchOptions
external_url: StringSearchOptions
hypercert: MetadataHypercertWhereInput = {}
id: StringSearchOptions
impact_scope: StringArraySearchOptions
impact_timeframe_from: BigIntSearchOptions
Expand Down Expand Up @@ -942,7 +1009,7 @@ type Order {
globalNonce: String!

"""The hypercert associated with this order"""
hypercert: HypercertBaseType
hypercert: HypercertWithMetadata
hypercert_id: String!
id: ID
invalidated: Boolean!
Expand Down Expand Up @@ -1058,7 +1125,7 @@ type Sale {
currency_amount: EthBigInt!

"""The hypercert associated with this order"""
hypercert: HypercertBaseType
hypercert: HypercertWithMetadata

"""The ID of the hypercert token referenced in the order"""
hypercert_id: String
Expand Down
26 changes: 24 additions & 2 deletions src/controllers/HyperboardController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,14 @@ export class HyperboardController extends Controller {
}

const { signature, adminAddress } = parsedBody.data;
const chainId = hyperboard.chain_ids[0];
const chainId = hyperboard.chain_ids?.[0];
if (!chainId) {
this.setStatus(400);
return {
success: false,
message: "Hyperboard must have a chain id",
};
}
const success = await verifyAuthSignedData({
address: adminAddress as `0x${string}`,
signature: signature as `0x${string}`,
Expand Down Expand Up @@ -700,6 +707,14 @@ export class HyperboardController extends Controller {
};
}

if (!hyperboard.chain_ids) {
this.setStatus(400);
return {
success: false,
message: "Hyperboard must have a chain id",
};
}

try {
await this.hyperboardsService.upsertHyperboard([
{
Expand Down Expand Up @@ -967,7 +982,14 @@ export class HyperboardController extends Controller {
const { data: admins } =
await this.hyperboardsService.getHyperboardAdmins(hyperboardId);

const chain_id = hyperboard.chain_ids[0];
const chain_id = hyperboard.chain_ids?.[0];
if (!chain_id) {
this.setStatus(400);
return {
success: false,
message: "Hyperboard must have a chain id",
};
}

if (
!admins.find(
Expand Down
8 changes: 8 additions & 0 deletions src/graphql/schemas/args/metadataArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@ import { ArgsType } from "type-graphql";
import { BaseQueryArgs } from "../../../lib/graphql/BaseQueryArgs.js";
import { createEntityArgs } from "../../../lib/graphql/createEntityArgs.js";
import { WhereFieldDefinitions } from "../../../lib/graphql/whereFieldDefinitions.js";
import { EntityTypeDefs } from "../typeDefs/typeDefs.js";

const { WhereInput: MetadataWhereInput, SortOptions: MetadataSortOptions } =
createEntityArgs("Metadata", {
...WhereFieldDefinitions.Metadata.fields,
hypercert: {
type: "id",
references: {
entity: EntityTypeDefs.Hypercert,
fields: WhereFieldDefinitions.Hypercert.fields,
},
},
});

@ArgsType()
Expand Down
5 changes: 5 additions & 0 deletions src/graphql/schemas/typeDefs/allowlistRecordTypeDefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import { Hypercert } from "./hypercertTypeDefs.js";
simpleResolvers: true,
})
export class AllowlistRecord {
@Field({
nullable: true,
description: "The ID of the allow list record",
})
id?: string;
@Field({
nullable: true,
description: "The hypercert ID the claimable fraction belongs to",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ObjectType } from "type-graphql";

import { Field } from "type-graphql";
import { Metadata } from "../metadataTypeDefs.js";
import { HypercertBaseType } from "./hypercertBaseType.js";

@ObjectType({
description:
"Hypercert with metadata, contract, orders, sales and fraction information",
simpleResolvers: true,
})
export class HypercertWithMetadata extends HypercertBaseType {
// Resolved fields
@Field(() => Metadata, {
nullable: true,
description: "The metadata for the hypercert as referenced by the uri",
})
metadata?: Metadata;
}
3 changes: 2 additions & 1 deletion src/graphql/schemas/typeDefs/orderTypeDefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DataResponse } from "../../../lib/graphql/DataResponse.js";
import { EthBigInt } from "../../scalars/ethBigInt.js";
import { BasicTypeDef } from "./baseTypes/basicTypeDef.js";
import { HypercertBaseType } from "./baseTypes/hypercertBaseType.js";
import { HypercertWithMetadata } from "./baseTypes/hypercertBaseWithMetadata.js";

@ObjectType({
description: "Marketplace order for a hypercert",
Expand Down Expand Up @@ -56,7 +57,7 @@ export class Order extends BasicTypeDef {
@Field()
pricePerPercentInToken?: string;

@Field(() => HypercertBaseType, {
@Field(() => HypercertWithMetadata, {
nullable: true,
description: "The hypercert associated with this order",
})
Expand Down
5 changes: 3 additions & 2 deletions src/graphql/schemas/typeDefs/salesTypeDefs.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Field, ObjectType } from "type-graphql";
import { EthBigInt } from "../../scalars/ethBigInt.js";
import { BasicTypeDef } from "./baseTypes/basicTypeDef.js";
import { HypercertBaseType } from "./baseTypes/hypercertBaseType.js";
import { DataResponse } from "../../../lib/graphql/DataResponse.js";
import { HypercertBaseType } from "./baseTypes/hypercertBaseType.js";
import { HypercertWithMetadata } from "./baseTypes/hypercertBaseWithMetadata.js";

@ObjectType()
export class Sale extends BasicTypeDef {
Expand Down Expand Up @@ -51,7 +52,7 @@ export class Sale extends BasicTypeDef {
})
creation_block_timestamp?: bigint | number | string;

@Field(() => HypercertBaseType, {
@Field(() => HypercertWithMetadata, {
nullable: true,
description: "The hypercert associated with this order",
})
Expand Down
3 changes: 3 additions & 0 deletions src/lib/graphql/whereFieldDefinitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const WhereFieldDefinitions = {
recipient: "string",
resolver: "string",
supported_schemas_id: "string",
contract_address: "string",
},
},
AttestationSchema: {
Expand All @@ -64,6 +65,7 @@ export const WhereFieldDefinitions = {
created_at: "string",
minter_address: "string",
minted: "boolean",
admin_address: "string",
},
},
Collection: {
Expand Down Expand Up @@ -115,6 +117,7 @@ export const WhereFieldDefinitions = {
fields: {
id: "string",
chain_ids: "numberArray",
admin_address: "string",
},
},
Metadata: {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/strategies/isWhereEmpty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ export function isWhereEmpty(
): boolean {
if (!where) return true;
if (Array.isArray(where)) return where.length === 0;
return Object.keys(where).length === 0;
return Object.values(where).filter((x) => x !== undefined).length === 0;
}
5 changes: 1 addition & 4 deletions src/services/database/entities/AttestationEntityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,7 @@ export class AttestationService {
"token_id" in data &&
data.token_id
) {
const tokenId =
typeof data.token_id === "string"
? data.token_id
: String(data.token_id);
const tokenId = Number(data.token_id);
return { ...data, token_id: BigInt(tokenId).toString() };
}
return data;
Expand Down
15 changes: 11 additions & 4 deletions src/services/database/entities/BlueprintsEntityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export type BlueprintAdminSelect = Selectable<DataDatabase["users"]>;
@singleton()
export class BlueprintsService {
private entityService: EntityService<
DataDatabase["blueprints"],
DataDatabase["blueprints_with_admins"],
GetBlueprintsArgs
>;

Expand All @@ -44,9 +44,9 @@ export class BlueprintsService {
) {
this.entityService = createEntityService<
DataDatabase,
"blueprints",
"blueprints_with_admins",
GetBlueprintsArgs
>("blueprints", "BlueprintsEntityService", kyselyData);
>("blueprints_with_admins", "BlueprintsEntityService", kyselyData);
}

/**
Expand Down Expand Up @@ -87,7 +87,14 @@ export class BlueprintsService {
.where("blueprint_id", "=", blueprintId)
.innerJoin("users", "blueprint_admins.user_id", "users.id")
.selectAll("users")
.execute();
.execute()
.then((res) =>
res.map((admin) => ({
...admin,
// TODO: Investigate why chain_id is returned as a string
chain_id: Number(admin.chain_id),
})),
);
}

/**
Expand Down
Loading