@@ -2,7 +2,7 @@ import { type Static, Type } from "@sinclair/typebox";
2
2
import type { FastifyInstance } from "fastify" ;
3
3
import { StatusCodes } from "http-status-codes" ;
4
4
import { getContract } from "thirdweb" ;
5
- import { isContractDeployed } from "thirdweb/utils" ;
5
+ import { isContractDeployed , shortenAddress } from "thirdweb/utils" ;
6
6
import { upsertChainIndexer } from "../../../../shared/db/chain-indexers/upsert-chain-indexer" ;
7
7
import { createContractSubscription } from "../../../../shared/db/contract-subscriptions/create-contract-subscription" ;
8
8
import { getContractSubscriptionsUniqueChainIds } from "../../../../shared/db/contract-subscriptions/get-contract-subscriptions" ;
@@ -21,16 +21,26 @@ import {
21
21
import { standardResponseSchema } from "../../../schemas/shared-api-schemas" ;
22
22
import { getChainIdFromChain } from "../../../utils/chain" ;
23
23
import { isValidWebhookUrl } from "../../../utils/validator" ;
24
+ import { getWebhook } from "../../../../shared/db/webhooks/get-webhook" ;
25
+ import type { Webhooks } from "@prisma/client" ;
24
26
25
27
const bodySchema = Type . Object ( {
26
28
chain : chainIdOrSlugSchema ,
27
29
contractAddress : {
28
30
...AddressSchema ,
29
31
description : "The address for the contract." ,
30
32
} ,
33
+ webhookId : Type . Optional (
34
+ Type . Number ( {
35
+ description :
36
+ "The ID of an existing webhook to use for this contract subscription. Either `webhookId` or `webhookUrl` must be provided." ,
37
+ examples : [ 1 ] ,
38
+ } ) ,
39
+ ) ,
31
40
webhookUrl : Type . Optional (
32
41
Type . String ( {
33
- description : "Webhook URL" ,
42
+ description :
43
+ "Creates a new webhook to call when new onchain data is detected. Either `webhookId` or `webhookUrl` must be provided." ,
34
44
examples : [ "https://example.com/webhook" ] ,
35
45
} ) ,
36
46
) ,
@@ -91,6 +101,7 @@ export async function addContractSubscription(fastify: FastifyInstance) {
91
101
const {
92
102
chain,
93
103
contractAddress,
104
+ webhookId,
94
105
webhookUrl,
95
106
processEventLogs,
96
107
filterEvents = [ ] ,
@@ -124,6 +135,25 @@ export async function addContractSubscription(fastify: FastifyInstance) {
124
135
) ;
125
136
}
126
137
138
+ // Get an existing webhook or create a new one.
139
+ let webhook : Webhooks | null = null ;
140
+ if ( webhookId ) {
141
+ webhook = await getWebhook ( webhookId ) ;
142
+ } else if ( webhookUrl && isValidWebhookUrl ( webhookUrl ) ) {
143
+ webhook = await insertWebhook ( {
144
+ eventType : WebhooksEventTypes . CONTRACT_SUBSCRIPTION ,
145
+ name : `(Generated) Subscription for ${ shortenAddress ( contractAddress ) } ` ,
146
+ url : webhookUrl ,
147
+ } ) ;
148
+ }
149
+ if ( ! webhook ) {
150
+ throw createCustomError (
151
+ 'Failed to get or create webhook for contract subscription. Make sure you provide an valid "webhookId" or "webhookUrl".' ,
152
+ StatusCodes . BAD_REQUEST ,
153
+ "INVALID_WEBHOOK" ,
154
+ ) ;
155
+ }
156
+
127
157
// If not currently indexed, upsert the latest block number.
128
158
const subscribedChainIds = await getContractSubscriptionsUniqueChainIds ( ) ;
129
159
if ( ! subscribedChainIds . includes ( chainId ) ) {
@@ -137,30 +167,11 @@ export async function addContractSubscription(fastify: FastifyInstance) {
137
167
}
138
168
}
139
169
140
- // Create the webhook (if provided).
141
- let webhookId : number | undefined ;
142
- if ( webhookUrl ) {
143
- if ( ! isValidWebhookUrl ( webhookUrl ) ) {
144
- throw createCustomError (
145
- "Invalid webhook URL. Make sure it starts with 'https://'." ,
146
- StatusCodes . BAD_REQUEST ,
147
- "BAD_REQUEST" ,
148
- ) ;
149
- }
150
-
151
- const webhook = await insertWebhook ( {
152
- eventType : WebhooksEventTypes . CONTRACT_SUBSCRIPTION ,
153
- name : "(Auto-generated)" ,
154
- url : webhookUrl ,
155
- } ) ;
156
- webhookId = webhook . id ;
157
- }
158
-
159
170
// Create the contract subscription.
160
171
const contractSubscription = await createContractSubscription ( {
161
172
chainId,
162
173
contractAddress : contractAddress . toLowerCase ( ) ,
163
- webhookId,
174
+ webhookId : webhook . id ,
164
175
processEventLogs,
165
176
filterEvents,
166
177
processTransactionReceipts,
0 commit comments