Skip to content

Commit 12f4e1f

Browse files
committed
feat(orders): migrate order fetchin to kysely flow
1 parent 1797348 commit 12f4e1f

File tree

5 files changed

+86
-125
lines changed

5 files changed

+86
-125
lines changed

src/controllers/MarketplaceController.ts

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import {
2+
addressesByNetwork,
3+
HypercertExchangeClient,
4+
utils,
5+
} from "@hypercerts-org/marketplace-sdk";
6+
import { ethers, verifyTypedData } from "ethers";
17
import {
28
Body,
39
Controller,
@@ -8,21 +14,15 @@ import {
814
SuccessResponse,
915
Tags,
1016
} from "tsoa";
11-
import { ApiResponse } from "../types/api.js";
12-
import {
13-
addressesByNetwork,
14-
HypercertExchangeClient,
15-
utils,
16-
} from "@hypercerts-org/marketplace-sdk";
17-
import { ethers, verifyTypedData } from "ethers";
1817
import { z } from "zod";
18+
import { ApiResponse } from "../types/api.js";
1919

20-
import { SupabaseDataService } from "../services/SupabaseDataService.js";
2120
import { isAddress, verifyMessage } from "viem";
22-
import { isParsableToBigInt } from "../utils/isParsableToBigInt.js";
21+
import { SupabaseDataService } from "../services/SupabaseDataService.js";
2322
import { getFractionsById } from "../utils/getFractionsById.js";
24-
import { getHypercertTokenId } from "../utils/tokenIds.js";
2523
import { getRpcUrl } from "../utils/getRpcUrl.js";
24+
import { isParsableToBigInt } from "../utils/isParsableToBigInt.js";
25+
import { getHypercertTokenId } from "../utils/tokenIds.js";
2626

2727
export interface CreateOrderRequest {
2828
signature: string;
@@ -435,15 +435,15 @@ export class MarketplaceController extends Controller {
435435
const { orderId, signature } = parsedQuery.data;
436436

437437
const supabase = new SupabaseDataService();
438-
const orderRes = await supabase.getOrders({
438+
const orders = await supabase.getOrders({
439439
where: {
440440
id: {
441441
eq: orderId,
442442
},
443443
},
444444
});
445445

446-
if (!orderRes.data?.length) {
446+
if (!orders.data?.length) {
447447
this.setStatus(404);
448448
return {
449449
success: false,
@@ -452,16 +452,7 @@ export class MarketplaceController extends Controller {
452452
};
453453
}
454454

455-
if (orderRes.error) {
456-
this.setStatus(500);
457-
return {
458-
success: false,
459-
message: "Could not fetch order",
460-
data: null,
461-
};
462-
}
463-
464-
const signerAddress = orderRes.data[0].signer;
455+
const signerAddress = orders.data[0].signer;
465456

466457
const signatureCorrect = await verifyMessage({
467458
message: `Delete listing ${orderId}`,

src/graphql/schemas/resolvers/baseTypes.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,33 @@ export function createBaseResolver<T extends ClassType>(
332332
}
333333
}
334334

335+
getOrders(args: GetOrdersArgs, single: boolean = false) {
336+
console.debug(`[${entityFieldName}Resolver::getOrders] Fetching orders`);
337+
338+
try {
339+
const queries = this.supabaseDataService.getOrders(args);
340+
if (single) {
341+
return queries.data.executeTakeFirst();
342+
}
343+
344+
return this.supabaseDataService.db
345+
.transaction()
346+
.execute(async (transaction) => {
347+
const dataRes = await transaction.executeQuery(queries.data);
348+
const countRes = await transaction.executeQuery(queries.count);
349+
return {
350+
data: dataRes.rows,
351+
count: countRes.rows[0].count,
352+
};
353+
});
354+
} catch (e) {
355+
const error = e as Error;
356+
throw new Error(
357+
`[${entityFieldName}Resolver::getOrders] Error fetching orders: ${error.message}`,
358+
);
359+
}
360+
}
361+
335362
parseAttestation(item: { [K in keyof T]: T[K] }) {
336363
const decodedData = item?.data;
337364
// TODO cleaner handling of bigints in created attestations

src/graphql/schemas/resolvers/hypercertResolver.ts

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ class HypercertResolver extends HypercertBaseResolver {
9292
};
9393

9494
try {
95-
console.log("Getting fractions for hypercert", hypercert.hypercert_id);
9695
const { data: fractionsRes } = await this.getFractions({
9796
where: { hypercert_id: { eq: hypercert.hypercert_id } },
9897
});
@@ -105,39 +104,21 @@ class HypercertResolver extends HypercertBaseResolver {
105104
return defaultValue;
106105
}
107106

108-
console.log(
109-
`[HypercertResolver::orders] Fetching orders for ${hypercert.hypercert_id}`,
110-
);
111-
112-
const ordersRes = await this.supabaseDataService.getOrders({
107+
const orders = await this.getOrders({
113108
where: { hypercert_id: { eq: hypercert.hypercert_id } },
114109
});
115110

116-
if (!ordersRes) {
111+
if (!orders) {
117112
console.warn(
118113
`[HypercertResolver::orders] Error fetching orders for ${hypercert.hypercert_id}`,
119-
ordersRes,
120-
);
121-
return defaultValue;
122-
}
123-
124-
const {
125-
data: ordersData,
126-
error: ordersError,
127-
count: ordersCount,
128-
} = ordersRes;
129-
130-
if (ordersError) {
131-
console.error(
132-
`[HypercertResolver::orders] Error fetching orders for ${hypercert.hypercert_id}: `,
133-
ordersError,
114+
orders,
134115
);
135116
return defaultValue;
136117
}
137118

138-
const validOrders = ordersData.filter((order) => !order.invalidated);
119+
const { data: ordersData, count: ordersCount } = orders;
139120

140-
const ordersByFraction = _.groupBy(validOrders, (order) =>
121+
const ordersByFraction = _.groupBy(ordersData, (order) =>
141122
order.itemIds[0].toString(),
142123
);
143124

@@ -149,10 +130,15 @@ class HypercertResolver extends HypercertBaseResolver {
149130
priceInUSD: string;
150131
pricePerPercentInUSD: string;
151132
})[] = [];
133+
134+
const activeOrders = ordersData.filter((order) => !order.invalidated);
135+
const activeOrdersByFraction = _.groupBy(activeOrders, (order) =>
136+
order.itemIds[0].toString(),
137+
);
152138
// For each fraction, find all orders and find the max units for sale for that fraction
153139
const totalUnitsForSale = (
154140
await Promise.all(
155-
Object.keys(ordersByFraction).map(async (tokenId) => {
141+
Object.keys(activeOrdersByFraction).map(async (tokenId) => {
156142
const fractionId = `${chainId}-${contractAddress}-${tokenId}`;
157143
const fraction = fractionsRes.find(
158144
(fraction) => fraction.fraction_id === fractionId,

src/graphql/schemas/resolvers/orderResolver.ts

Lines changed: 12 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ import { Order } from "../typeDefs/orderTypeDefs.js";
1010
import { GetOrdersArgs } from "../args/orderArgs.js";
1111
import { getHypercertTokenId } from "../../../utils/tokenIds.js";
1212
import { getAddress } from "viem";
13-
import { HypercertExchangeClient } from "@hypercerts-org/marketplace-sdk";
14-
import { ethers } from "ethers";
15-
import { getRpcUrl } from "../../../utils/getRpcUrl.js";
1613
import { addPriceInUsdToOrder } from "../../../utils/addPriceInUSDToOrder.js";
1714
import _ from "lodash";
1815
import { createBaseResolver, DataResponse } from "./baseTypes.js";
@@ -25,29 +22,20 @@ const OrderBaseResolver = createBaseResolver("order");
2522
@Resolver(() => Order)
2623
class OrderResolver extends OrderBaseResolver {
2724
@Query(() => GetOrdersResponse)
28-
async orders(@Args() args: GetOrdersArgs) {
25+
async orders(@Args() args: GetOrdersArgs, single: boolean = false) {
2926
try {
30-
const res = await this.supabaseDataService.getOrders(args);
27+
const ordersRes = await this.getOrders(args, single);
3128

32-
const { data: orders, error, count } = res;
33-
34-
if (error) {
35-
console.warn(`[OrderResolver::orders] Error fetching orders: `, error);
36-
return { orders };
29+
if (!ordersRes) {
30+
return {
31+
data: [],
32+
count: 0,
33+
};
3734
}
3835

39-
const groupedOrders = orders.reduce(
40-
(acc, order) => {
41-
if (!acc[order.chainId]) {
42-
acc[order.chainId] = [];
43-
}
44-
acc[order.chainId].push(order);
45-
return acc;
46-
},
47-
{} as Record<string, (typeof orders)[number][]>,
48-
);
36+
const { data, count } = ordersRes;
4937

50-
const allHypercertIds = _.uniq(orders.map((order) => order.hypercert_id));
38+
const allHypercertIds = _.uniq(data.map((order) => order.hypercert_id));
5139
// TODO: Update this once array filters are available
5240
const allHypercerts = await Promise.all(
5341
allHypercertIds.map(async (hypercertId) => {
@@ -69,44 +57,8 @@ class OrderResolver extends OrderBaseResolver {
6957
),
7058
);
7159

72-
const ordersAfterCheckingValidity = await Promise.all(
73-
Object.entries(groupedOrders).map(async ([chainId, ordersForChain]) => {
74-
const chainIdParsed = parseInt(chainId);
75-
const hypercertExchangeClient = new HypercertExchangeClient(
76-
chainIdParsed,
77-
// @ts-expect-error - TODO: fix these types
78-
new ethers.JsonRpcProvider(getRpcUrl(chainIdParsed)),
79-
);
80-
81-
const validityResults =
82-
await hypercertExchangeClient.checkOrdersValidity(
83-
ordersForChain.filter((order) => !order.invalidated),
84-
);
85-
const tokenIdsWithInvalidOrder = validityResults
86-
.filter((result) => !result.valid)
87-
.map((result) => BigInt(result.order.itemIds[0]));
88-
if (tokenIdsWithInvalidOrder.length) {
89-
console.log(
90-
"[OrderResolver::orders]:: Found invalid orders",
91-
tokenIdsWithInvalidOrder,
92-
);
93-
// Fire off the validation but don't wait for it to finish
94-
this.supabaseDataService.validateOrdersByTokenIds({
95-
tokenIds: tokenIdsWithInvalidOrder.map((id) => id.toString()),
96-
chainId: chainIdParsed,
97-
});
98-
}
99-
return ordersForChain.map((order) => {
100-
if (tokenIdsWithInvalidOrder.includes(BigInt(order.itemIds[0]))) {
101-
return { ...order, invalidated: true };
102-
}
103-
return order;
104-
});
105-
}),
106-
).then((res) => res.flat());
107-
10860
const ordersWithPrices = await Promise.all(
109-
orders.map(async (order) => {
61+
data.map(async (order) => {
11062
const hypercert = allHypercerts[order.hypercert_id.toLowerCase()];
11163
if (!hypercert?.units) {
11264
console.warn(
@@ -120,11 +72,11 @@ class OrderResolver extends OrderBaseResolver {
12072

12173
return {
12274
data: ordersWithPrices,
123-
count: count ? count : ordersAfterCheckingValidity?.length,
75+
count: count ? count : ordersWithPrices?.length,
12476
};
12577
} catch (e) {
12678
throw new Error(
127-
`[ContractResolver::orders] Error fetching orders: ${(e as Error).message}`,
79+
`[OrderResolver::orders] Error fetching orders: ${(e as Error).message}`,
12880
);
12981
}
13082
}

src/services/SupabaseDataService.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,10 @@ export class SupabaseDataService extends BaseSupabaseService<KyselyDataDatabase>
150150
}
151151

152152
getOrders(args: GetOrdersArgs) {
153-
let query = this.supabaseData.from("marketplace_orders").select("*");
154-
155-
const { where, sort, offset, first } = args;
156-
157-
query = applyFilters({ query, where });
158-
query = applySorting({ query, sort });
159-
query = applyPagination({ query, pagination: { first, offset } });
160-
161-
return query;
153+
return {
154+
data: this.handleGetData("marketplace_orders", args),
155+
count: this.handleGetCount("marketplace_orders", args),
156+
};
162157
}
163158

164159
getOrdersByTokenId({
@@ -674,11 +669,14 @@ export class SupabaseDataService extends BaseSupabaseService<KyselyDataDatabase>
674669
// eslint-disable-next-line @typescript-eslint/no-unused-vars
675670
>(tableName: T, args: BaseArgs<A>) {
676671
switch (tableName) {
677-
case "users":
678-
return this.db.selectFrom("users").selectAll();
679672
case "blueprints_with_admins":
680673
case "blueprints":
681674
return this.db.selectFrom("blueprints_with_admins").selectAll();
675+
case "orders":
676+
case "marketplace_orders":
677+
return this.db.selectFrom("marketplace_orders").selectAll();
678+
case "users":
679+
return this.db.selectFrom("users").selectAll();
682680
default:
683681
throw new Error(`Table ${tableName.toString()} not found`);
684682
}
@@ -691,21 +689,28 @@ export class SupabaseDataService extends BaseSupabaseService<KyselyDataDatabase>
691689
// eslint-disable-next-line @typescript-eslint/no-unused-vars
692690
>(tableName: T, args: BaseArgs<A>) {
693691
switch (tableName) {
694-
case "users":
695-
return this.db.selectFrom("users").select((expressionBuilder) => {
696-
return expressionBuilder.fn.countAll().as("count");
697-
});
692+
case "blueprints_with_admins":
693+
case "blueprints":
694+
return this.db
695+
.selectFrom("blueprints_with_admins")
696+
.select((expressionBuilder) => {
697+
return expressionBuilder.fn.countAll().as("count");
698+
});
698699
case "hyperboards":
699700
return this.db.selectFrom("hyperboards").select((expressionBuilder) => {
700701
return expressionBuilder.fn.countAll().as("count");
701702
});
702-
case "blueprints_with_admins":
703-
case "blueprints":
703+
case "orders":
704+
case "marketplace_orders":
704705
return this.db
705-
.selectFrom("blueprints_with_admins")
706+
.selectFrom("marketplace_orders")
706707
.select((expressionBuilder) => {
707708
return expressionBuilder.fn.countAll().as("count");
708709
});
710+
case "users":
711+
return this.db.selectFrom("users").select((expressionBuilder) => {
712+
return expressionBuilder.fn.countAll().as("count");
713+
});
709714
default:
710715
throw new Error(`Table ${tableName.toString()} not found`);
711716
}

0 commit comments

Comments
 (0)