@layer-drone/protocol 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +192 -42
- package/dist/index.d.ts +192 -42
- package/dist/index.js +202 -27
- package/dist/index.mjs +193 -26
- package/package.json +1 -1
- package/src/client/sdk.gen.ts +171 -0
- package/src/client/transformers.gen.ts +106 -16
- package/src/client/types.gen.ts +262 -38
- package/src/event/parser.ts +62 -10
package/src/client/types.gen.ts
CHANGED
|
@@ -17,6 +17,10 @@ export type CreateApiTokenResponseDto = {
|
|
|
17
17
|
| "manageContracts"
|
|
18
18
|
| "redrive"
|
|
19
19
|
| "updateOnChainData"
|
|
20
|
+
| "syncEventProcessorState"
|
|
21
|
+
| "manageZones"
|
|
22
|
+
| "manageProposals"
|
|
23
|
+
| "approveProposals"
|
|
20
24
|
| "all"
|
|
21
25
|
>;
|
|
22
26
|
};
|
|
@@ -34,6 +38,10 @@ export type CreateApiTokenRequestDto = {
|
|
|
34
38
|
| "manageContracts"
|
|
35
39
|
| "redrive"
|
|
36
40
|
| "updateOnChainData"
|
|
41
|
+
| "syncEventProcessorState"
|
|
42
|
+
| "manageZones"
|
|
43
|
+
| "manageProposals"
|
|
44
|
+
| "approveProposals"
|
|
37
45
|
| "all"
|
|
38
46
|
>;
|
|
39
47
|
orgId: number;
|
|
@@ -52,6 +60,10 @@ export type UpdateApiTokenRequestDto = {
|
|
|
52
60
|
| "manageContracts"
|
|
53
61
|
| "redrive"
|
|
54
62
|
| "updateOnChainData"
|
|
63
|
+
| "syncEventProcessorState"
|
|
64
|
+
| "manageZones"
|
|
65
|
+
| "manageProposals"
|
|
66
|
+
| "approveProposals"
|
|
55
67
|
| "all"
|
|
56
68
|
>;
|
|
57
69
|
};
|
|
@@ -73,6 +85,10 @@ export type UpdateApiTokenResponseDto = {
|
|
|
73
85
|
| "manageContracts"
|
|
74
86
|
| "redrive"
|
|
75
87
|
| "updateOnChainData"
|
|
88
|
+
| "syncEventProcessorState"
|
|
89
|
+
| "manageZones"
|
|
90
|
+
| "manageProposals"
|
|
91
|
+
| "approveProposals"
|
|
76
92
|
| "all"
|
|
77
93
|
>;
|
|
78
94
|
};
|
|
@@ -300,6 +316,16 @@ export type FlightDto = {
|
|
|
300
316
|
block_number: number;
|
|
301
317
|
block_timestamp: number;
|
|
302
318
|
transaction_hash: string;
|
|
319
|
+
payout: {
|
|
320
|
+
id: string;
|
|
321
|
+
missionId: string;
|
|
322
|
+
flightReviewId: string;
|
|
323
|
+
recipient: string;
|
|
324
|
+
amount: string;
|
|
325
|
+
tokenContractAddress: string;
|
|
326
|
+
chainId: number;
|
|
327
|
+
createdAt: Date;
|
|
328
|
+
};
|
|
303
329
|
};
|
|
304
330
|
|
|
305
331
|
export type CreateFileRequestDto = {
|
|
@@ -571,26 +597,30 @@ export type GetProvenanceCryptoKeyResponse = {
|
|
|
571
597
|
|
|
572
598
|
export type GetMissionResponseDto = {
|
|
573
599
|
id: string;
|
|
574
|
-
|
|
600
|
+
vaultId: string;
|
|
601
|
+
requestor: string;
|
|
602
|
+
zoneId: string;
|
|
603
|
+
isOpen: boolean;
|
|
604
|
+
flightPlanId: number;
|
|
605
|
+
isReservable: boolean;
|
|
606
|
+
tags: {
|
|
607
|
+
[key: string]: string;
|
|
608
|
+
};
|
|
609
|
+
captureStartTime: Date;
|
|
610
|
+
captureEndTime: Date;
|
|
611
|
+
campaigns: Array<string>;
|
|
612
|
+
contractAddress: string;
|
|
613
|
+
chainId: number;
|
|
614
|
+
createdAt: Date;
|
|
615
|
+
updatedAt: Date;
|
|
616
|
+
payout: {
|
|
575
617
|
id: string;
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
isOpen: boolean;
|
|
580
|
-
flightPlanId: number;
|
|
581
|
-
isReservable: boolean;
|
|
582
|
-
tags: {
|
|
583
|
-
[key: string]: string;
|
|
584
|
-
};
|
|
585
|
-
captureStartTime: Date;
|
|
586
|
-
captureEndTime: Date;
|
|
587
|
-
campaigns: Array<string>;
|
|
588
|
-
contractAddress: string;
|
|
589
|
-
chainId: number;
|
|
618
|
+
recipient: string;
|
|
619
|
+
amount: string;
|
|
620
|
+
flightReviewId: string;
|
|
590
621
|
createdAt: Date;
|
|
591
|
-
updatedAt: Date;
|
|
592
622
|
};
|
|
593
|
-
vault
|
|
623
|
+
vault: {
|
|
594
624
|
id: string;
|
|
595
625
|
amount: string;
|
|
596
626
|
collateralTokenAddress: string;
|
|
@@ -600,32 +630,35 @@ export type GetMissionResponseDto = {
|
|
|
600
630
|
createdAt: Date;
|
|
601
631
|
updatedAt: Date;
|
|
602
632
|
};
|
|
603
|
-
payout?: null;
|
|
604
633
|
};
|
|
605
634
|
|
|
606
635
|
export type GetMissionsResponseDto = {
|
|
607
636
|
missions: Array<{
|
|
608
637
|
id: string;
|
|
609
|
-
|
|
638
|
+
vaultId: string;
|
|
639
|
+
requestor: string;
|
|
640
|
+
zoneId: string;
|
|
641
|
+
isOpen: boolean;
|
|
642
|
+
flightPlanId: number;
|
|
643
|
+
isReservable: boolean;
|
|
644
|
+
tags: {
|
|
645
|
+
[key: string]: string;
|
|
646
|
+
};
|
|
647
|
+
captureStartTime: Date;
|
|
648
|
+
captureEndTime: Date;
|
|
649
|
+
campaigns: Array<string>;
|
|
650
|
+
contractAddress: string;
|
|
651
|
+
chainId: number;
|
|
652
|
+
createdAt: Date;
|
|
653
|
+
updatedAt: Date;
|
|
654
|
+
payout: {
|
|
610
655
|
id: string;
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
isOpen: boolean;
|
|
615
|
-
flightPlanId: number;
|
|
616
|
-
isReservable: boolean;
|
|
617
|
-
tags: {
|
|
618
|
-
[key: string]: string;
|
|
619
|
-
};
|
|
620
|
-
captureStartTime: Date;
|
|
621
|
-
captureEndTime: Date;
|
|
622
|
-
campaigns: Array<string>;
|
|
623
|
-
contractAddress: string;
|
|
624
|
-
chainId: number;
|
|
656
|
+
recipient: string;
|
|
657
|
+
amount: string;
|
|
658
|
+
flightReviewId: string;
|
|
625
659
|
createdAt: Date;
|
|
626
|
-
updatedAt: Date;
|
|
627
660
|
};
|
|
628
|
-
vault
|
|
661
|
+
vault: {
|
|
629
662
|
id: string;
|
|
630
663
|
amount: string;
|
|
631
664
|
collateralTokenAddress: string;
|
|
@@ -635,7 +668,6 @@ export type GetMissionsResponseDto = {
|
|
|
635
668
|
createdAt: Date;
|
|
636
669
|
updatedAt: Date;
|
|
637
670
|
};
|
|
638
|
-
payout?: null;
|
|
639
671
|
}>;
|
|
640
672
|
hasNextPage: boolean;
|
|
641
673
|
};
|
|
@@ -791,6 +823,7 @@ export type GetWebhooksResponse = Array<{
|
|
|
791
823
|
active: boolean;
|
|
792
824
|
failure_count: number;
|
|
793
825
|
last_failure_reason: string;
|
|
826
|
+
previous_secret_expires_at: Date;
|
|
794
827
|
created_at: string;
|
|
795
828
|
updated_at: string;
|
|
796
829
|
}>;
|
|
@@ -811,6 +844,7 @@ export type GetWebhookResponse = {
|
|
|
811
844
|
active: boolean;
|
|
812
845
|
failure_count: number;
|
|
813
846
|
last_failure_reason: string;
|
|
847
|
+
previous_secret_expires_at: Date;
|
|
814
848
|
created_at: string;
|
|
815
849
|
updated_at: string;
|
|
816
850
|
};
|
|
@@ -846,6 +880,7 @@ export type UpdateWebhookResponse = {
|
|
|
846
880
|
active: boolean;
|
|
847
881
|
failure_count: number;
|
|
848
882
|
last_failure_reason: string;
|
|
883
|
+
previous_secret_expires_at: Date;
|
|
849
884
|
created_at: string;
|
|
850
885
|
updated_at: string;
|
|
851
886
|
};
|
|
@@ -854,8 +889,15 @@ export type DeleteWebhookResponse = {
|
|
|
854
889
|
message: string;
|
|
855
890
|
};
|
|
856
891
|
|
|
892
|
+
export type RegenerateWebhookSecretBody =
|
|
893
|
+
| {
|
|
894
|
+
previous_secret_expires_at?: Date;
|
|
895
|
+
}
|
|
896
|
+
| unknown;
|
|
897
|
+
|
|
857
898
|
export type RegenerateWebhookSecretResponseDto = {
|
|
858
899
|
secret: string;
|
|
900
|
+
previous_secret_expires_at: Date;
|
|
859
901
|
};
|
|
860
902
|
|
|
861
903
|
export type TestWebhookResponse = {
|
|
@@ -867,6 +909,51 @@ export type GetWebhookStatusResponse = {
|
|
|
867
909
|
error?: string;
|
|
868
910
|
};
|
|
869
911
|
|
|
912
|
+
export type CreateZoneDto = {
|
|
913
|
+
id: string;
|
|
914
|
+
region_id: number;
|
|
915
|
+
is_flyable?: boolean;
|
|
916
|
+
};
|
|
917
|
+
|
|
918
|
+
export type ZoneResponseDto = {
|
|
919
|
+
id: string;
|
|
920
|
+
region_id: number;
|
|
921
|
+
is_flyable: boolean;
|
|
922
|
+
created_at: Date;
|
|
923
|
+
updated_at: Date;
|
|
924
|
+
};
|
|
925
|
+
|
|
926
|
+
export type UpdateZoneDto = {
|
|
927
|
+
is_flyable: boolean;
|
|
928
|
+
};
|
|
929
|
+
|
|
930
|
+
export type SyncEventProcessorMissionsRequestDto = {
|
|
931
|
+
missionIds: Array<string>;
|
|
932
|
+
missionDataContractAddress: string;
|
|
933
|
+
missionEscrowContractAddress: string;
|
|
934
|
+
};
|
|
935
|
+
|
|
936
|
+
export type SyncEventProcessorMissionsResponseDto = {
|
|
937
|
+
succeeded: Array<string>;
|
|
938
|
+
failed: Array<{
|
|
939
|
+
missionId: string;
|
|
940
|
+
error: string;
|
|
941
|
+
}>;
|
|
942
|
+
};
|
|
943
|
+
|
|
944
|
+
export type SyncEventProcessorFlightReviewsRequestDto = {
|
|
945
|
+
flightIds: Array<string>;
|
|
946
|
+
flightReviewContractAddress: string;
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
export type SyncEventProcessorFlightReviewsResponseDto = {
|
|
950
|
+
succeeded: Array<string>;
|
|
951
|
+
failed: Array<{
|
|
952
|
+
flightId: string;
|
|
953
|
+
error: string;
|
|
954
|
+
}>;
|
|
955
|
+
};
|
|
956
|
+
|
|
870
957
|
export type AlchemyWebhookBodyDto = {
|
|
871
958
|
[key: string]: unknown;
|
|
872
959
|
};
|
|
@@ -1501,7 +1588,13 @@ export type MissionsControllerGetMissionData = {
|
|
|
1501
1588
|
path: {
|
|
1502
1589
|
id: string;
|
|
1503
1590
|
};
|
|
1504
|
-
query?:
|
|
1591
|
+
query?: {
|
|
1592
|
+
relations?:
|
|
1593
|
+
| "vault"
|
|
1594
|
+
| "payout"
|
|
1595
|
+
| "campaigns"
|
|
1596
|
+
| Array<"vault" | "payout" | "campaigns">;
|
|
1597
|
+
};
|
|
1505
1598
|
url: "/missions/{id}";
|
|
1506
1599
|
};
|
|
1507
1600
|
|
|
@@ -1533,6 +1626,11 @@ export type MissionsControllerGetMissionsData = {
|
|
|
1533
1626
|
zoneIds?: string | Array<string>;
|
|
1534
1627
|
flightPlanId?: number;
|
|
1535
1628
|
page?: number;
|
|
1629
|
+
relations?:
|
|
1630
|
+
| "vault"
|
|
1631
|
+
| "payout"
|
|
1632
|
+
| "campaigns"
|
|
1633
|
+
| Array<"vault" | "payout" | "campaigns">;
|
|
1536
1634
|
};
|
|
1537
1635
|
url: "/missions";
|
|
1538
1636
|
};
|
|
@@ -1845,7 +1943,7 @@ export type WebhooksControllerUpdateResponse =
|
|
|
1845
1943
|
WebhooksControllerUpdateResponses[keyof WebhooksControllerUpdateResponses];
|
|
1846
1944
|
|
|
1847
1945
|
export type WebhooksControllerRegenerateSecretData = {
|
|
1848
|
-
body
|
|
1946
|
+
body: RegenerateWebhookSecretBody;
|
|
1849
1947
|
path: {
|
|
1850
1948
|
org_id: number;
|
|
1851
1949
|
id: number;
|
|
@@ -1910,6 +2008,132 @@ export type WebhooksControllerGetStatusResponses = {
|
|
|
1910
2008
|
export type WebhooksControllerGetStatusResponse =
|
|
1911
2009
|
WebhooksControllerGetStatusResponses[keyof WebhooksControllerGetStatusResponses];
|
|
1912
2010
|
|
|
2011
|
+
export type ZonesControllerCreateZoneData = {
|
|
2012
|
+
body: CreateZoneDto;
|
|
2013
|
+
path?: never;
|
|
2014
|
+
query?: never;
|
|
2015
|
+
url: "/zones";
|
|
2016
|
+
};
|
|
2017
|
+
|
|
2018
|
+
export type ZonesControllerCreateZoneErrors = {
|
|
2019
|
+
/**
|
|
2020
|
+
* Invalid zone id (must be a valid level-9 H3 cell)
|
|
2021
|
+
*/
|
|
2022
|
+
400: unknown;
|
|
2023
|
+
401: unknown;
|
|
2024
|
+
403: unknown;
|
|
2025
|
+
/**
|
|
2026
|
+
* Zone already exists
|
|
2027
|
+
*/
|
|
2028
|
+
409: unknown;
|
|
2029
|
+
};
|
|
2030
|
+
|
|
2031
|
+
export type ZonesControllerCreateZoneResponses = {
|
|
2032
|
+
201: ZoneResponseDto;
|
|
2033
|
+
};
|
|
2034
|
+
|
|
2035
|
+
export type ZonesControllerCreateZoneResponse =
|
|
2036
|
+
ZonesControllerCreateZoneResponses[keyof ZonesControllerCreateZoneResponses];
|
|
2037
|
+
|
|
2038
|
+
export type ZonesControllerDeleteZoneData = {
|
|
2039
|
+
body?: never;
|
|
2040
|
+
path: {
|
|
2041
|
+
id: string;
|
|
2042
|
+
};
|
|
2043
|
+
query?: never;
|
|
2044
|
+
url: "/zones/{id}";
|
|
2045
|
+
};
|
|
2046
|
+
|
|
2047
|
+
export type ZonesControllerDeleteZoneErrors = {
|
|
2048
|
+
401: unknown;
|
|
2049
|
+
403: unknown;
|
|
2050
|
+
/**
|
|
2051
|
+
* Zone not found
|
|
2052
|
+
*/
|
|
2053
|
+
404: unknown;
|
|
2054
|
+
};
|
|
2055
|
+
|
|
2056
|
+
export type ZonesControllerDeleteZoneResponses = {
|
|
2057
|
+
/**
|
|
2058
|
+
* Zone deleted
|
|
2059
|
+
*/
|
|
2060
|
+
204: void;
|
|
2061
|
+
};
|
|
2062
|
+
|
|
2063
|
+
export type ZonesControllerDeleteZoneResponse =
|
|
2064
|
+
ZonesControllerDeleteZoneResponses[keyof ZonesControllerDeleteZoneResponses];
|
|
2065
|
+
|
|
2066
|
+
export type ZonesControllerUpdateZoneData = {
|
|
2067
|
+
body: UpdateZoneDto;
|
|
2068
|
+
path: {
|
|
2069
|
+
id: string;
|
|
2070
|
+
};
|
|
2071
|
+
query?: never;
|
|
2072
|
+
url: "/zones/{id}";
|
|
2073
|
+
};
|
|
2074
|
+
|
|
2075
|
+
export type ZonesControllerUpdateZoneErrors = {
|
|
2076
|
+
401: unknown;
|
|
2077
|
+
403: unknown;
|
|
2078
|
+
/**
|
|
2079
|
+
* Zone not found
|
|
2080
|
+
*/
|
|
2081
|
+
404: unknown;
|
|
2082
|
+
};
|
|
2083
|
+
|
|
2084
|
+
export type ZonesControllerUpdateZoneResponses = {
|
|
2085
|
+
200: ZoneResponseDto;
|
|
2086
|
+
};
|
|
2087
|
+
|
|
2088
|
+
export type ZonesControllerUpdateZoneResponse =
|
|
2089
|
+
ZonesControllerUpdateZoneResponses[keyof ZonesControllerUpdateZoneResponses];
|
|
2090
|
+
|
|
2091
|
+
export type EventProcessorMissionsSyncControllerResyncMissionsData = {
|
|
2092
|
+
body: SyncEventProcessorMissionsRequestDto;
|
|
2093
|
+
path?: never;
|
|
2094
|
+
query?: never;
|
|
2095
|
+
url: "/event-processor/missions/sync";
|
|
2096
|
+
};
|
|
2097
|
+
|
|
2098
|
+
export type EventProcessorMissionsSyncControllerResyncMissionsErrors = {
|
|
2099
|
+
401: unknown;
|
|
2100
|
+
403: unknown;
|
|
2101
|
+
};
|
|
2102
|
+
|
|
2103
|
+
export type EventProcessorMissionsSyncControllerResyncMissionsResponses = {
|
|
2104
|
+
/**
|
|
2105
|
+
* Per-mission success or failure.
|
|
2106
|
+
*/
|
|
2107
|
+
200: SyncEventProcessorMissionsResponseDto;
|
|
2108
|
+
};
|
|
2109
|
+
|
|
2110
|
+
export type EventProcessorMissionsSyncControllerResyncMissionsResponse =
|
|
2111
|
+
EventProcessorMissionsSyncControllerResyncMissionsResponses[keyof EventProcessorMissionsSyncControllerResyncMissionsResponses];
|
|
2112
|
+
|
|
2113
|
+
export type EventProcessorFlightReviewsSyncControllerResyncFlightReviewsData = {
|
|
2114
|
+
body: SyncEventProcessorFlightReviewsRequestDto;
|
|
2115
|
+
path?: never;
|
|
2116
|
+
query?: never;
|
|
2117
|
+
url: "/event-processor/flightreviews";
|
|
2118
|
+
};
|
|
2119
|
+
|
|
2120
|
+
export type EventProcessorFlightReviewsSyncControllerResyncFlightReviewsErrors =
|
|
2121
|
+
{
|
|
2122
|
+
401: unknown;
|
|
2123
|
+
403: unknown;
|
|
2124
|
+
};
|
|
2125
|
+
|
|
2126
|
+
export type EventProcessorFlightReviewsSyncControllerResyncFlightReviewsResponses =
|
|
2127
|
+
{
|
|
2128
|
+
/**
|
|
2129
|
+
* Per-flight success or failure.
|
|
2130
|
+
*/
|
|
2131
|
+
200: SyncEventProcessorFlightReviewsResponseDto;
|
|
2132
|
+
};
|
|
2133
|
+
|
|
2134
|
+
export type EventProcessorFlightReviewsSyncControllerResyncFlightReviewsResponse =
|
|
2135
|
+
EventProcessorFlightReviewsSyncControllerResyncFlightReviewsResponses[keyof EventProcessorFlightReviewsSyncControllerResyncFlightReviewsResponses];
|
|
2136
|
+
|
|
1913
2137
|
export type AlchemyControllerHandleWebhookData = {
|
|
1914
2138
|
body: AlchemyWebhookBodyDto;
|
|
1915
2139
|
path?: never;
|
package/src/event/parser.ts
CHANGED
|
@@ -2,28 +2,80 @@ import type { Request } from "express";
|
|
|
2
2
|
|
|
3
3
|
import { Event } from "./types.gen";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/** Primary signing secret for this delivery (current secret). */
|
|
6
|
+
export const WEBHOOK_SECRET_HEADER = "X-Webhook-Secret";
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* During rotation, the prior secret value still valid for receivers who have not
|
|
10
|
+
* updated their stored secret yet (must be sent together with the expiry header).
|
|
11
|
+
*/
|
|
12
|
+
export const WEBHOOK_PREVIOUS_SECRET_HEADER = "X-Webhook-Previous-Secret";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* ISO-8601 instant; after this time the previous secret must no longer be accepted.
|
|
16
|
+
*/
|
|
17
|
+
export const WEBHOOK_PREVIOUS_SECRET_EXPIRES_AT_HEADER =
|
|
18
|
+
"X-Webhook-Previous-Secret-Expires-At";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Verify an inbound webhook using the signing secret your app has configured.
|
|
22
|
+
*
|
|
23
|
+
* Compares `X-Webhook-Secret` to `webhookSecret`. If that fails, checks optional
|
|
24
|
+
* rotation headers from LayerDrone: when both `X-Webhook-Previous-Secret` and
|
|
25
|
+
* `X-Webhook-Previous-Secret-Expires-At` are present, the request is accepted if
|
|
26
|
+
* your configured secret still matches the announced previous secret (same value
|
|
27
|
+
* as in `X-Webhook-Previous-Secret`) and the expiry has not passed.
|
|
28
|
+
*/
|
|
7
29
|
export function parseWebhookEvent(req: Request, webhookSecret: string) {
|
|
8
|
-
const
|
|
9
|
-
if (typeof
|
|
30
|
+
const incoming = getFirstHeader(req.headers, WEBHOOK_SECRET_HEADER);
|
|
31
|
+
if (typeof incoming !== "string") {
|
|
10
32
|
throw new Error("Webhook request signature is not a string");
|
|
11
33
|
}
|
|
12
34
|
if (!Buffer.isBuffer(req.body)) {
|
|
13
35
|
throw new Error("Webhook request body is not a Buffer");
|
|
14
36
|
}
|
|
15
|
-
|
|
37
|
+
|
|
38
|
+
if (incoming === webhookSecret) {
|
|
39
|
+
return Event.parse(JSON.parse(req.body.toString("utf-8")));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const announcedPrevious = getFirstHeader(
|
|
43
|
+
req.headers,
|
|
44
|
+
WEBHOOK_PREVIOUS_SECRET_HEADER,
|
|
45
|
+
);
|
|
46
|
+
const expiresRaw = getFirstHeader(
|
|
47
|
+
req.headers,
|
|
48
|
+
WEBHOOK_PREVIOUS_SECRET_EXPIRES_AT_HEADER,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (announcedPrevious === undefined || expiresRaw === undefined) {
|
|
16
52
|
throw new Error("Invalid webhook secret");
|
|
17
53
|
}
|
|
18
|
-
|
|
54
|
+
|
|
55
|
+
const expiresAt = new Date(expiresRaw);
|
|
56
|
+
if (Number.isNaN(expiresAt.getTime())) {
|
|
57
|
+
throw new Error("Invalid webhook secret");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (Date.now() >= expiresAt.getTime()) {
|
|
61
|
+
throw new Error("Invalid webhook secret");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (webhookSecret === announcedPrevious) {
|
|
65
|
+
return Event.parse(JSON.parse(req.body.toString("utf-8")));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
throw new Error("Invalid webhook secret");
|
|
19
69
|
}
|
|
20
70
|
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
71
|
+
function getFirstHeader(
|
|
72
|
+
headers: Request["headers"],
|
|
73
|
+
canonicalName: string,
|
|
74
|
+
): string | undefined {
|
|
75
|
+
const lower = canonicalName.toLowerCase();
|
|
76
|
+
let value = headers[canonicalName] ?? headers[lower];
|
|
25
77
|
if (Array.isArray(value)) {
|
|
26
78
|
value = value[0];
|
|
27
79
|
}
|
|
28
|
-
return value;
|
|
80
|
+
return typeof value === "string" ? value : undefined;
|
|
29
81
|
}
|