Skip to content

Commit 42a76cb

Browse files
authored
Merge pull request #283 from hypercerts-org/develop
Deploy to PROD
2 parents 91cc620 + f3470e0 commit 42a76cb

28 files changed

+1251
-2583
lines changed

package.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626
"commitlint": "commitlint --config commitlintrc.ts --edit"
2727
},
2828
"dependencies": {
29-
"@graphql-tools/merge": "^9.0.3",
30-
"@graphql-yoga/plugin-response-cache": "^3.5.0",
29+
"@graphql-tools/merge": "^9.0.19",
30+
"@graphql-yoga/plugin-response-cache": "^3.13.0",
3131
"@hypercerts-org/contracts": "2.0.0-alpha.12",
32-
"@hypercerts-org/marketplace-sdk": "0.3.37",
32+
"@hypercerts-org/marketplace-sdk": "0.5.1",
3333
"@hypercerts-org/sdk": "2.5.0-beta.6",
3434
"@ipld/car": "^5.2.5",
3535
"@openzeppelin/merkle-tree": "^1.0.5",
@@ -56,12 +56,12 @@
5656
"ethers": "^6.12.2",
5757
"express": "^4.19.2",
5858
"file-type": "^19.6.0",
59-
"gql.tada": "^1.2.1",
60-
"graphql": "^16.8.1",
59+
"gql.tada": "^1.8.10",
60+
"graphql": "^16.10.0",
6161
"graphql-filter": "^1.1.5",
6262
"graphql-middleware": "^6.1.35",
63-
"graphql-scalars": "^1.23.0",
64-
"graphql-yoga": "^5.1.1",
63+
"graphql-scalars": "^1.24.1",
64+
"graphql-yoga": "^5.11.0",
6565
"kysely": "^0.27.4",
6666
"lodash": "^4.17.21",
6767
"lru-cache": "^11.0.0",
@@ -83,17 +83,17 @@
8383
"node": "20.x"
8484
},
8585
"devDependencies": {
86-
"@0no-co/graphqlsp": "^1.4.1",
86+
"@0no-co/graphqlsp": "^1.12.16",
8787
"@commitlint/cli": "^19.4.1",
8888
"@commitlint/config-conventional": "^19.4.1",
89-
"@eddeee888/gcg-typescript-resolver-files": "^0.7.2",
89+
"@eddeee888/gcg-typescript-resolver-files": "^0.7.5",
9090
"@eslint/js": "^9.0.0",
9191
"@graphql-codegen/cli": "5.0.2",
92-
"@graphql-tools/delegate": "^10.0.3",
93-
"@graphql-tools/executor-http": "^1.0.8",
94-
"@graphql-tools/schema": "^10.0.2",
95-
"@graphql-tools/stitch": "^9.0.3",
96-
"@graphql-tools/wrap": "^10.0.1",
92+
"@graphql-tools/delegate": "^10.2.11",
93+
"@graphql-tools/executor-http": "^1.2.6",
94+
"@graphql-tools/schema": "^10.0.18",
95+
"@graphql-tools/stitch": "^9.4.16",
96+
"@graphql-tools/wrap": "^10.0.29",
9797
"@inquirer/prompts": "^7.2.3",
9898
"@rollup/plugin-typescript": "^11.1.6",
9999
"@sentry/types": "^8.2.1",

pnpm-lock.yaml

Lines changed: 772 additions & 2436 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/__generated__/routes/routes.ts

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/__generated__/swagger.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/client/evmClient.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,45 @@ class GlifProvider implements RpcProvider {
6464
}
6565
}
6666

67+
class AnkrProvider implements RpcProvider {
68+
getUrl(chainId: number): string | undefined {
69+
const urls: Record<number, string> = {
70+
314: "https://rpc.ankr.com/filecoin",
71+
314159: "https://rpc.ankr.com/filecoin_testnet",
72+
};
73+
return urls[chainId];
74+
}
75+
}
76+
77+
class ChainUpProvider implements RpcProvider {
78+
getUrl(chainId: number): string | undefined {
79+
const urls: Record<number, string> = {
80+
314: "https://filecoin.chainup.net/rpc/v1",
81+
314159: "https://filecoin-calibration.chainup.net/rpc/v1",
82+
};
83+
return urls[chainId];
84+
}
85+
}
86+
87+
class LavaProvider implements RpcProvider {
88+
getUrl(chainId: number): string | undefined {
89+
const urls: Record<number, string> = {
90+
314: "https://filecoin.lava.build",
91+
314159: "https://filecoin-testnet.lava.build",
92+
};
93+
return urls[chainId];
94+
}
95+
}
96+
6797
export class EvmClientFactory {
6898
private static readonly providers: RpcProvider[] = [
6999
new AlchemyProvider(),
70100
new InfuraProvider(),
71101
new DrpcProvider(),
72102
new GlifProvider(),
103+
new AnkrProvider(),
104+
new ChainUpProvider(),
105+
new LavaProvider(),
73106
];
74107

75108
static createViemClient(chainId: number): PublicClient {

src/client/supabase.ts

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const supabaseData = createClient<DataDatabaseTypes>(
2727
const handleChangeClaims = (
2828
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
2929
) => {
30-
console.log(payload);
30+
console.debug(payload);
3131
switch (payload.eventType) {
3232
case "INSERT":
3333
cache.invalidate([{ typename: "Hypercert" }]);
@@ -44,7 +44,7 @@ const handleChangeClaims = (
4444
const handleChangeFractions = (
4545
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
4646
) => {
47-
console.log(payload);
47+
console.debug(payload);
4848
switch (payload.eventType) {
4949
case "INSERT":
5050
cache.invalidate([{ typename: "Fraction" }]);
@@ -61,7 +61,7 @@ const handleChangeFractions = (
6161
const handleChangeMetadata = (
6262
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
6363
) => {
64-
console.log(payload);
64+
console.debug(payload);
6565
switch (payload.eventType) {
6666
case "INSERT":
6767
cache.invalidate([{ typename: "Metadata", id: payload.new.id }]);
@@ -78,7 +78,7 @@ const handleChangeMetadata = (
7878
const handleChangeSales = (
7979
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
8080
) => {
81-
console.log(payload);
81+
console.debug(payload);
8282
switch (payload.eventType) {
8383
case "INSERT":
8484
cache.invalidate([{ typename: "Sale" }]);
@@ -95,13 +95,22 @@ const handleChangeSales = (
9595
const handleChangeAllowlistRecords = (
9696
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
9797
) => {
98-
console.log(payload);
98+
console.debug(payload);
9999
switch (payload.eventType) {
100100
case "INSERT":
101-
cache.invalidate([{ typename: "AllowlistRecord" }]);
101+
cache.invalidate([
102+
{
103+
typename: "AllowlistRecord",
104+
},
105+
]);
102106
break;
103107
case "UPDATE":
104-
cache.invalidate([{ typename: "AllowlistRecord", id: payload.new.id }]);
108+
cache.invalidate([
109+
{
110+
typename: "AllowlistRecord",
111+
id: payload.new.id,
112+
},
113+
]);
105114
break;
106115
default:
107116
break;
@@ -112,7 +121,7 @@ const handleChangeAllowlistRecords = (
112121
const handleChangeAttestations = (
113122
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
114123
) => {
115-
console.log(payload);
124+
console.debug(payload);
116125
switch (payload.eventType) {
117126
case "INSERT":
118127
cache.invalidate([{ typename: "Attestation" }]);
@@ -129,7 +138,7 @@ const handleChangeAttestations = (
129138
const handleChangeUsers = (
130139
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
131140
) => {
132-
console.log(payload);
141+
console.debug(payload);
133142
switch (payload.eventType) {
134143
case "INSERT":
135144
cache.invalidate([{ typename: "User" }]);
@@ -146,7 +155,7 @@ const handleChangeUsers = (
146155
const handleChangeBlueprints = (
147156
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
148157
) => {
149-
console.log(payload);
158+
console.debug(payload);
150159
switch (payload.eventType) {
151160
case "INSERT":
152161
cache.invalidate([{ typename: "Blueprint" }]);
@@ -166,7 +175,7 @@ const handleChangeBlueprints = (
166175
const handleChangeHyperboards = (
167176
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
168177
) => {
169-
console.log(payload);
178+
console.debug(payload);
170179
switch (payload.eventType) {
171180
case "UPDATE":
172181
case "DELETE":
@@ -192,7 +201,8 @@ const handleChangeHyperboards = (
192201
const handleChangeOrders = (
193202
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
194203
) => {
195-
console.log(payload);
204+
console.debug(payload);
205+
196206
switch (payload.eventType) {
197207
case "INSERT":
198208
case "UPDATE":
@@ -208,6 +218,8 @@ const handleChangeOrders = (
208218
const handleChangeSignatureRequests = (
209219
payload: RealtimePostgresChangesPayload<{ [key: string]: any }>,
210220
) => {
221+
console.debug(payload);
222+
211223
switch (payload.eventType) {
212224
case "INSERT":
213225
case "UPDATE":
@@ -275,6 +287,15 @@ supabaseCaching
275287
},
276288
(payload) => handleChangeAllowlistRecords(payload),
277289
)
290+
.on(
291+
"postgres_changes",
292+
{
293+
event: "*",
294+
schema: "public",
295+
table: "hypercert_allow_list_records",
296+
},
297+
(payload) => handleChangeAllowlistRecords(payload),
298+
)
278299
.on(
279300
"postgres_changes",
280301
{
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Route, Get, Response } from "tsoa";
2+
3+
@Route("monitoring")
4+
export class MonitoringController {
5+
@Get("/health")
6+
@Response(200, "OK")
7+
public async healthCheck(): Promise<{
8+
status: string;
9+
uptime: number;
10+
timestamp: number;
11+
memory: NodeJS.MemoryUsage;
12+
}> {
13+
return {
14+
status: "OK",
15+
uptime: process.uptime(),
16+
timestamp: Date.now(),
17+
memory: process.memoryUsage(),
18+
};
19+
}
20+
}

src/cron/OrderInvalidation.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import cron from "node-cron";
2+
import { OrderValidatorCode } from "@hypercerts-org/marketplace-sdk";
3+
import { SupabaseDataService } from "../services/SupabaseDataService.js";
4+
import _ from "lodash";
5+
import { kyselyData } from "../client/kysely.js";
6+
import { sql } from "kysely";
7+
8+
/**
9+
* These error codes are considered temporary and should be
10+
* rechecked periodically so that they can be marked as valid again.
11+
*/
12+
export const TEMPORARILY_INVALID_ERROR_CODES = [
13+
OrderValidatorCode.ORDER_EXPECTED_TO_BE_VALID,
14+
OrderValidatorCode.TOO_EARLY_TO_EXECUTE_ORDER,
15+
];
16+
17+
export default class OrderInvalidationCronjob {
18+
private static instance: OrderInvalidationCronjob;
19+
private dataService: SupabaseDataService;
20+
21+
private constructor() {
22+
this.dataService = new SupabaseDataService();
23+
this.setupCronJob();
24+
}
25+
26+
private setupCronJob() {
27+
// Run every 30 seconds
28+
cron.schedule("*/30 * * * * *", async () => {
29+
try {
30+
await this.invalidateOrders();
31+
} catch (error) {
32+
console.error("Error in order invalidation cron job:", error);
33+
}
34+
});
35+
}
36+
37+
public static start(): void {
38+
if (!OrderInvalidationCronjob.instance) {
39+
OrderInvalidationCronjob.instance = new OrderInvalidationCronjob();
40+
}
41+
}
42+
43+
private async invalidateOrders() {
44+
const result = await kyselyData
45+
.selectFrom("marketplace_orders")
46+
.select(["itemIds", "invalidated", "validator_codes", "chainId"])
47+
.where((eb) =>
48+
eb.or([
49+
eb("invalidated", "=", false),
50+
// Include all orders that have been invalidated but only have validator codes that are in the accepted validator codes
51+
// Example: order has been validated because it hasn't openened yet. Will initially be invalidated, but should be rechecked
52+
// periodically so that it can be marked as valid again once it has opened.
53+
eb("invalidated", "=", true).and(
54+
"validator_codes",
55+
"<@",
56+
// @ts-expect-error Typing issue with sql arrays
57+
sql`ARRAY[${sql.join(TEMPORARILY_INVALID_ERROR_CODES)}]::int4[]`,
58+
),
59+
]),
60+
)
61+
.execute();
62+
const ordersByChain = _.groupBy(result, "chainId");
63+
64+
for (const chainId in ordersByChain) {
65+
const ordersForChain = ordersByChain[chainId];
66+
const tokenIds = _.uniq(ordersForChain.map((order) => order.itemIds[0]));
67+
await this.dataService.validateOrdersByTokenIds({
68+
tokenIds,
69+
chainId: parseInt(chainId, 10),
70+
});
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)