Skip to content

Commit

Permalink
Fix GraphQL webhook creation and support skip_empty_messages (#440)
Browse files Browse the repository at this point in the history
  • Loading branch information
thebrianchen committed Aug 5, 2024
1 parent ff5c576 commit 6118b89
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 20 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

### Minor Changes

- Fixed a bug with `NotifyNamespace.createWebhook()` when using `WebhookType.GRAPHQL`. Also added the option use `skipEmptyMessages` when creating graphQL webhooks to skip empty blocks.

## 3.3.1

### Minor Changes
Expand Down
39 changes: 22 additions & 17 deletions src/api/notify-namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,19 @@ export class NotifyNamespace {
}
);
}
/**
* Create a new {@link CustomGraphqlWebhook} to track any event on every block.
*
* @param url The URL that the webhook should send events to.
* @param type The type of webhook to create.
* @param params Parameters object containing the graphql query to be executed
* on every block
*/
createWebhook(
url: string,
type: WebhookType.GRAPHQL,
params: CustomGraphqlWebhookParams
): Promise<CustomGraphqlWebhook>;

/**
* Create a new {@link MinedTransactionWebhook} to track mined transactions
Expand Down Expand Up @@ -400,20 +413,6 @@ export class NotifyNamespace {
params: NftWebhookParams
): Promise<NftMetadataUpdateWebhook>;

/**
* Create a new {@link CustomGraphqlWebhook} to track any event on every block.
*
* @param url The URL that the webhook should send events to.
* @param type The type of webhook to create.
* @param params Parameters object containing the graphql query to be executed
* on every block
*/
createWebhook(
url: string,
type: WebhookType.GRAPHQL,
params: CustomGraphqlWebhookParams
): Promise<CustomGraphqlWebhook>;

/**
* Create a new {@link AddressActivityWebhook} to track address activity.
*
Expand Down Expand Up @@ -446,10 +445,11 @@ export class NotifyNamespace {
let appId;
if (
type === WebhookType.MINED_TRANSACTION ||
type === WebhookType.DROPPED_TRANSACTION
type === WebhookType.DROPPED_TRANSACTION ||
type === WebhookType.GRAPHQL
) {
if (!('appId' in params)) {
throw new Error('Transaction Webhooks require an app id.');
throw new Error('Transaction and GraphQL Webhooks require an app id.');
}
appId = params.appId;
}
Expand All @@ -458,6 +458,7 @@ export class NotifyNamespace {
let nftFilterObj;
let addresses;
let graphqlQuery;
let skipEmptyMessages;
if (
type === WebhookType.NFT_ACTIVITY ||
type === WebhookType.NFT_METADATA_UPDATE
Expand Down Expand Up @@ -510,6 +511,7 @@ export class NotifyNamespace {
? NETWORK_TO_WEBHOOK_NETWORK.get(params.network)
: network;
graphqlQuery = params.graphqlQuery;
skipEmptyMessages = params.skipEmptyMessages;
}

const data = {
Expand All @@ -521,7 +523,10 @@ export class NotifyNamespace {
// Only include the filters/addresses in the final response if they're defined
...nftFilterObj,
...(addresses && { addresses }),
...(graphqlQuery && { graphql_query: graphqlQuery })
...(graphqlQuery && {
graphql_query: graphqlQuery
}),
...(skipEmptyMessages && { skip_empty_messages: skipEmptyMessages })
};

const response = await this.sendWebhookRequest<RawCreateWebhookResponse>(
Expand Down
19 changes: 19 additions & 0 deletions src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,25 @@ export interface CustomGraphqlWebhookParams {
* created on network of the app provided in the api key config.
*/
network?: Network;
/**
* Whether to only receive webhooks if the query on the block is not empty.
* Defaults to false.
*/
skipEmptyMessages?: boolean;
/**
* App IDs are now required for graphQL webhooks. You can find the app ID
* following the steps here:
* {@link https://docs.alchemy.com/reference/notify-api-faq#where-can-i-find-the-app-id}.
*
* The webhook will be created on the app and network associated with the appId.
* To find the app id of a project, go to the Alchemy Dashboard in the Apps tab.
* After clicking on an app, the app id is the string in the URL following 'apps/'.
*
* Note that although this property is marked as optional, it is *actually required*
* for creating a custom GraphQL webhook. This is a workaround to avoid a breaking
* change in the API.
*/
appId?: string;
}

/**
Expand Down
16 changes: 13 additions & 3 deletions test/integration/notify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ describe('E2E integration tests', () => {
customWh = await alchemy.notify.createWebhook(
webhookUrl,
WebhookType.GRAPHQL,
{ graphqlQuery, network: Network.ETH_MAINNET }
{
graphqlQuery,
network: Network.ETH_MAINNET,
appId,
skipEmptyMessages: true
}
);
}

Expand Down Expand Up @@ -247,11 +252,16 @@ describe('E2E integration tests', () => {
const customWebhook = await alchemy.notify.createWebhook(
webhookUrl,
WebhookType.GRAPHQL,
{ graphqlQuery, network: Network.ETH_GOERLI }
{
graphqlQuery,
network: Network.ETH_MAINNET,
appId,
skipEmptyMessages: true
}
);
expect(customWebhook.url).toEqual(webhookUrl);
expect(customWebhook.type).toEqual(WebhookType.GRAPHQL);
expect(customWebhook.network).toEqual(Network.ETH_GOERLI);
expect(customWebhook.network).toEqual(Network.ETH_MAINNET);
let response = await alchemy.notify.getAllWebhooks();
expect(
response.webhooks.filter(wh => wh.id === customWebhook.id).length
Expand Down

0 comments on commit 6118b89

Please sign in to comment.