@ercworldio/blockchain-shared 1.0.0-dev.14 → 1.0.0-dev.16
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/build/chains/networks_dev.json +37 -11
- package/build/interfaces/config.d.ts +1 -0
- package/build/interfaces/config.d.ts.map +1 -1
- package/build/services/DepositAddressService.d.ts +8 -0
- package/build/services/DepositAddressService.d.ts.map +1 -1
- package/build/services/DepositAddressService.js +30 -0
- package/build/services/quicknode-notifications/QnNotificationsApi.d.ts +17 -0
- package/build/services/quicknode-notifications/QnNotificationsApi.d.ts.map +1 -0
- package/build/services/quicknode-notifications/QnNotificationsApi.js +125 -0
- package/build/services/quicknode-notifications/SetupNotifications.d.ts +39 -0
- package/build/services/quicknode-notifications/SetupNotifications.d.ts.map +1 -0
- package/build/services/quicknode-notifications/SetupNotifications.js +253 -0
- package/build/services/quicknode-notifications/types/index.d.ts +2 -0
- package/build/services/quicknode-notifications/types/index.d.ts.map +1 -0
- package/build/services/quicknode-notifications/types/index.js +17 -0
- package/build/services/quicknode-notifications/types/notification_types.d.ts +154 -0
- package/build/services/quicknode-notifications/types/notification_types.d.ts.map +1 -0
- package/build/services/quicknode-notifications/types/notification_types.js +2 -0
- package/package.json +1 -1
|
@@ -49,16 +49,7 @@
|
|
|
49
49
|
"rpcBaseUrl": "https://api.nileex.io",
|
|
50
50
|
"rpcBaseUrlWss": "",
|
|
51
51
|
"targetConfirmations": 20,
|
|
52
|
-
"quicknodeStreams": [
|
|
53
|
-
{
|
|
54
|
-
"network": "tron-mainnet",
|
|
55
|
-
"dataset": "logs",
|
|
56
|
-
"name": "tron-custodial-transfers",
|
|
57
|
-
"listConfig": {
|
|
58
|
-
"key": "custodial-addresses"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
],
|
|
52
|
+
"quicknodeStreams": [],
|
|
62
53
|
"custodialAlchemyWebhooks": [],
|
|
63
54
|
"contracts": [
|
|
64
55
|
{
|
|
@@ -131,7 +122,7 @@
|
|
|
131
122
|
],
|
|
132
123
|
"quicknodeNotificationConfig": [
|
|
133
124
|
{
|
|
134
|
-
"name": "qn-custodial-webhook-sol",
|
|
125
|
+
"name": "qn-custodial-webhook-sol-dev",
|
|
135
126
|
"network": "solana-devnet",
|
|
136
127
|
"template": "solanaWalletFilter"
|
|
137
128
|
}
|
|
@@ -215,6 +206,13 @@
|
|
|
215
206
|
"source": "wallet"
|
|
216
207
|
}
|
|
217
208
|
],
|
|
209
|
+
"quicknodeNotificationConfig": [
|
|
210
|
+
{
|
|
211
|
+
"name": "qn-custodial-webhook-bsc-dev",
|
|
212
|
+
"network": "bnbchain-testnet",
|
|
213
|
+
"template": "evmWalletFilter"
|
|
214
|
+
}
|
|
215
|
+
],
|
|
218
216
|
"contracts": [
|
|
219
217
|
{
|
|
220
218
|
"type": "Escrow",
|
|
@@ -367,6 +365,13 @@
|
|
|
367
365
|
"source": "wallet"
|
|
368
366
|
}
|
|
369
367
|
],
|
|
368
|
+
"quicknodeNotificationConfig": [
|
|
369
|
+
{
|
|
370
|
+
"name": "qn-custodial-webhook-avax-dev",
|
|
371
|
+
"network": "avalanche-fuji",
|
|
372
|
+
"template": "evmWalletFilter"
|
|
373
|
+
}
|
|
374
|
+
],
|
|
370
375
|
"contracts": [
|
|
371
376
|
{
|
|
372
377
|
"type": "Escrow",
|
|
@@ -461,6 +466,13 @@
|
|
|
461
466
|
"source": "wallet"
|
|
462
467
|
}
|
|
463
468
|
],
|
|
469
|
+
"quicknodeNotificationConfig": [
|
|
470
|
+
{
|
|
471
|
+
"name": "qn-custodial-webhook-eth-dev",
|
|
472
|
+
"network": "ethereum-sepolia",
|
|
473
|
+
"template": "evmWalletFilter"
|
|
474
|
+
}
|
|
475
|
+
],
|
|
464
476
|
"contracts": [
|
|
465
477
|
{
|
|
466
478
|
"type": "Escrow",
|
|
@@ -541,6 +553,13 @@
|
|
|
541
553
|
"source": "wallet"
|
|
542
554
|
}
|
|
543
555
|
],
|
|
556
|
+
"quicknodeNotificationConfig": [
|
|
557
|
+
{
|
|
558
|
+
"name": "qn-custodial-webhook-pol-dev",
|
|
559
|
+
"network": "polygon-amoy",
|
|
560
|
+
"template": "evmWalletFilter"
|
|
561
|
+
}
|
|
562
|
+
],
|
|
544
563
|
"contracts": [
|
|
545
564
|
{
|
|
546
565
|
"type": "Escrow",
|
|
@@ -620,6 +639,13 @@
|
|
|
620
639
|
"source": "wallet"
|
|
621
640
|
}
|
|
622
641
|
],
|
|
642
|
+
"quicknodeNotificationConfig": [
|
|
643
|
+
{
|
|
644
|
+
"name": "qn-custodial-webhook-mon-dev",
|
|
645
|
+
"network": "monad-testnet",
|
|
646
|
+
"template": "evmWalletFilter"
|
|
647
|
+
}
|
|
648
|
+
],
|
|
623
649
|
"contracts": [
|
|
624
650
|
{
|
|
625
651
|
"type": "Escrow",
|
|
@@ -20,6 +20,7 @@ export interface IConfigProvider {
|
|
|
20
20
|
}
|
|
21
21
|
export type EnvironmentVariableNames = "quicknodeEndpointApikey" | "quicknodeBaseUrl" | "keyVaultName" | "cryptoKeyVaultName" | "version" | "host" | "serverPort" | "localHost" | "tunnel" | "useTunnel" | "projectName" | "serviceName" | "environment" | "elasticUrl" | "maxInstructionsPerTxSolana" | "requiredContractTypes" | "depositEventHubName" | "transferLogsRawEventHubName" | "withdrawalEventHubName" | "rolesEventHubName" | "walletServiceMnemonicEvm" | "walletServiceMnemonicSolana" | "walletServiceMnemonicTron" | "alchemyApiKey" | "alchemyAccessToken" | "alchemyAccessTokenDev" | "syncableEventNames" | "ankrApiKey" | "azureConnectionStringNotifications" | "azureStorageAccount" | "elasticApiKey" | "rpcEthereum" | "rpcEthereumWss" | "rpcPolygon" | "rpcPolygonWss" | "rpcFantom" | "rpcFantomWss" | "rpcAvalanche" | "rpcAvalancheWss" | "rpcBsc" | "rpcBscWss" | "rpcPolygonMainnet" | "rpcBitlayer" | "rpcBitlayerWss" | "jwtSecret" | "blockchainDbConnectionString" | "customerBlockchainDbConnectionString" | "voltageWebhookSecret" | "redisConnectionstring" | "lndRestHost" | "lndRestHostLnbits" | "lndMacaroon" | "lndMacaroonLnbits" | "escrowFundingWalletPrivateKeyEvm" | "escrowFundingWalletPrivateKeySol" | "escrowFundingWalletPrivateKeyTron";
|
|
22
22
|
export interface EnvironmentVariables {
|
|
23
|
+
quicknodeApiKey: string;
|
|
23
24
|
quicknodeEndpointApikey?: string;
|
|
24
25
|
qnEndpointSolanaNetwork?: string;
|
|
25
26
|
quicknodeEndpointBaseUrl?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/interfaces/config.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/interfaces/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { DepositAddress } from "../entities/DepositAddress";
|
|
2
2
|
import { BlockchainType } from "../interfaces";
|
|
3
3
|
import { IDatabasePool } from "../interfaces/database";
|
|
4
|
+
import { Paginated } from "./types/claim_job_service";
|
|
5
|
+
export interface DepositAddressSearchFilters {
|
|
6
|
+
user_id?: number;
|
|
7
|
+
blockchain?: string;
|
|
8
|
+
address?: string;
|
|
9
|
+
}
|
|
4
10
|
interface CreateDepositResult {
|
|
5
11
|
id: number;
|
|
6
12
|
userId: number;
|
|
@@ -35,6 +41,8 @@ declare class DepositAddressService {
|
|
|
35
41
|
status: boolean;
|
|
36
42
|
address: string;
|
|
37
43
|
}>;
|
|
44
|
+
private paginate;
|
|
45
|
+
getDepositAddressesPaginated(page: number, page_size: number | undefined, filters: DepositAddressSearchFilters): Promise<Paginated<DepositAddress[]>>;
|
|
38
46
|
getDepositAddressByAddress(blockchain: BlockchainType, address: string): Promise<DepositAddress | null>;
|
|
39
47
|
findByBlockchainAndAddressRaw(blockchain: BlockchainType, address: string): Promise<DepositAddress | null>;
|
|
40
48
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DepositAddressService.d.ts","sourceRoot":"","sources":["../../src/services/DepositAddressService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAI5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"DepositAddressService.d.ts","sourceRoot":"","sources":["../../src/services/DepositAddressService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAI5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEtD,MAAM,WAAW,2BAA2B;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,mBAAmB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACnB;AACD,MAAM,WAAW,0BAA0B;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,mBAAoB,SAAQ,mBAAmB;CACxD;AAED,cAAM,qBAAqB;IACvB,OAAO,CAAC,MAAM,CAAgB;gBAClB,MAAM,EAAE,aAAa;IAKjC,OAAO,CAAC,gBAAgB;IAiBlB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAqB9E,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAazB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAkBzE,8BAA8B,CAAC,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM;YAyBtE,yBAAyB;IAqBjC,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA0D5H,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAmDtG,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;YA4B/F,QAAQ;IAwBhB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,YAAK,EAAE,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC;IAI9I,0BAA0B,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAkBvG,6BAA6B,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;CAanH;AAED,eAAe,qBAAqB,CAAC"}
|
|
@@ -242,6 +242,36 @@ class DepositAddressService {
|
|
|
242
242
|
}
|
|
243
243
|
});
|
|
244
244
|
}
|
|
245
|
+
paginate(page, page_size, filters) {
|
|
246
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
247
|
+
const repo = this.dbPool.accountsRepo;
|
|
248
|
+
if (!repo)
|
|
249
|
+
throw new Error(`Db Driver appDataSource is not initialized.`);
|
|
250
|
+
if (page === 0)
|
|
251
|
+
page = 1;
|
|
252
|
+
const [items, totalCount] = yield Promise.all([
|
|
253
|
+
repo.find({
|
|
254
|
+
take: page_size,
|
|
255
|
+
skip: (page - 1) * page_size,
|
|
256
|
+
where: Object.assign({}, filters),
|
|
257
|
+
order: { created_at: "DESC" }
|
|
258
|
+
}),
|
|
259
|
+
repo.count({ where: Object.assign({}, filters) })
|
|
260
|
+
]);
|
|
261
|
+
return {
|
|
262
|
+
total_count: totalCount,
|
|
263
|
+
pages_count: Math.ceil(totalCount / page_size),
|
|
264
|
+
has_next: totalCount > page * page_size,
|
|
265
|
+
current_page: page,
|
|
266
|
+
items: items || []
|
|
267
|
+
};
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
getDepositAddressesPaginated(page_1) {
|
|
271
|
+
return __awaiter(this, arguments, void 0, function* (page, page_size = 10, filters) {
|
|
272
|
+
return this.paginate(page, page_size, filters);
|
|
273
|
+
});
|
|
274
|
+
}
|
|
245
275
|
getDepositAddressByAddress(blockchain, address) {
|
|
246
276
|
return __awaiter(this, void 0, void 0, function* () {
|
|
247
277
|
try {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { QnNotificationCreateResponse, QnNotificationListResponse } from "./types/notification_types";
|
|
2
|
+
import { IConfig } from "../../interfaces/config";
|
|
3
|
+
import BaseErrors from "../../errors/errors";
|
|
4
|
+
declare class QnNotificationsApi extends BaseErrors {
|
|
5
|
+
private api_key;
|
|
6
|
+
private base_url;
|
|
7
|
+
private rate_limiter;
|
|
8
|
+
private rlc;
|
|
9
|
+
constructor(config: IConfig);
|
|
10
|
+
create_webhook(template: string, name: string, network: string, webhook_url: string, initial_addresses: string[]): Promise<QnNotificationCreateResponse>;
|
|
11
|
+
get_all_webhooks(): Promise<QnNotificationListResponse>;
|
|
12
|
+
update_webhook_addresses(webhook_id: string, template: string, all_addresses: string[]): Promise<void>;
|
|
13
|
+
delete_webhook(webhook_id: string): Promise<void>;
|
|
14
|
+
private call;
|
|
15
|
+
}
|
|
16
|
+
export default QnNotificationsApi;
|
|
17
|
+
//# sourceMappingURL=QnNotificationsApi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QnNotificationsApi.d.ts","sourceRoot":"","sources":["../../../src/services/quicknode-notifications/QnNotificationsApi.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACtG,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,UAAU,MAAM,qBAAqB,CAAC;AAG7C,cAAM,kBAAmB,SAAQ,UAAU;IACvC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAgD;IAChE,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,GAAG,CAA4D;gBAE3D,MAAM,EAAE,OAAO;IAOd,cAAc,CACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EAAE,GAC5B,OAAO,CAAC,4BAA4B,CAAC;IAY3B,gBAAgB,IAAI,OAAO,CAAC,0BAA0B,CAAC;IAIvD,wBAAwB,CACjC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC;IAQH,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAIhD,IAAI;CAsCrB;AAED,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
const errors_1 = __importDefault(require("../../errors/errors"));
|
|
49
|
+
const AsyncRateLimiter_1 = __importStar(require("../../utils/AsyncRateLimiter"));
|
|
50
|
+
class QnNotificationsApi extends errors_1.default {
|
|
51
|
+
constructor(config) {
|
|
52
|
+
super();
|
|
53
|
+
this.base_url = "https://api.quicknode.com/webhooks/rest/v1";
|
|
54
|
+
this.rlc = { maxConcurrent: 2, minDelayMs: 100 };
|
|
55
|
+
this.api_key = config.config.quicknodeApiKey;
|
|
56
|
+
if (!this.api_key)
|
|
57
|
+
throw new Error(`quicknode api key is required`);
|
|
58
|
+
this.rate_limiter = new AsyncRateLimiter_1.default(this.rlc);
|
|
59
|
+
}
|
|
60
|
+
create_webhook(template, name, network, webhook_url, initial_addresses) {
|
|
61
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
const template_arg_key = template === 'solanaWalletFilter' ? 'accounts' : 'wallets';
|
|
63
|
+
const body = {
|
|
64
|
+
name,
|
|
65
|
+
network,
|
|
66
|
+
status: 'active',
|
|
67
|
+
destination_attributes: { url: webhook_url, compression: 'none' },
|
|
68
|
+
templateArgs: { [template_arg_key]: initial_addresses }
|
|
69
|
+
};
|
|
70
|
+
return yield this.call(`/webhooks/template/${template}`, 'POST', { body });
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
get_all_webhooks() {
|
|
74
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
return yield this.call('/webhooks', 'GET', { query_params: { limit: 100, offset: 0 } });
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
update_webhook_addresses(webhook_id, template, all_addresses) {
|
|
79
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
80
|
+
const template_arg_key = template === 'solanaWalletFilter' ? 'accounts' : 'wallets';
|
|
81
|
+
const body = {
|
|
82
|
+
templateArgs: { [template_arg_key]: all_addresses }
|
|
83
|
+
};
|
|
84
|
+
yield this.call(`/webhooks/${webhook_id}/template/${template}`, 'PATCH', { body });
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
delete_webhook(webhook_id) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
yield this.call(`/webhooks/${webhook_id}`, 'DELETE');
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
call(endpoint, method, opts) {
|
|
93
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
94
|
+
const request_options = {
|
|
95
|
+
method,
|
|
96
|
+
headers: {
|
|
97
|
+
'accept': 'application/json',
|
|
98
|
+
'Content-Type': 'application/json',
|
|
99
|
+
'x-api-key': this.api_key
|
|
100
|
+
},
|
|
101
|
+
body: (opts === null || opts === void 0 ? void 0 : opts.body) ? JSON.stringify(opts.body) : undefined,
|
|
102
|
+
};
|
|
103
|
+
let url = `${this.base_url}${endpoint}`;
|
|
104
|
+
if (opts === null || opts === void 0 ? void 0 : opts.query_params) {
|
|
105
|
+
const params = new URLSearchParams();
|
|
106
|
+
Object.entries(opts.query_params).forEach(([k, v]) => {
|
|
107
|
+
if (v !== undefined && v !== null)
|
|
108
|
+
params.append(k, String(v));
|
|
109
|
+
});
|
|
110
|
+
const qs = params.toString();
|
|
111
|
+
if (qs)
|
|
112
|
+
url += `?${qs}`;
|
|
113
|
+
}
|
|
114
|
+
console.log(`QnNotificationsApi: ${method} ${url}`);
|
|
115
|
+
const res = yield this.rate_limiter.execute(() => (0, AsyncRateLimiter_1.withRetry)(() => __awaiter(this, void 0, void 0, function* () { return yield fetch(url, request_options); })));
|
|
116
|
+
if (!res.ok) {
|
|
117
|
+
const err = yield res.text();
|
|
118
|
+
throw new Error(`QnNotificationsApi: ${method} ${endpoint} failed [${res.status}]: ${err}`);
|
|
119
|
+
}
|
|
120
|
+
const text = yield res.text();
|
|
121
|
+
return text ? JSON.parse(text) : null;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.default = QnNotificationsApi;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import BaseErrors from "../../errors/errors";
|
|
2
|
+
import { BlockchainType } from "../../interfaces";
|
|
3
|
+
import { IConfig } from "../../interfaces/config";
|
|
4
|
+
import { IDatabasePool } from "../../interfaces/database";
|
|
5
|
+
export interface NotificationWebhookEntry {
|
|
6
|
+
webhook_id: string;
|
|
7
|
+
template: string;
|
|
8
|
+
network: string;
|
|
9
|
+
blockchain: BlockchainType;
|
|
10
|
+
address_set: Set<string>;
|
|
11
|
+
}
|
|
12
|
+
declare class SetupNotifications extends BaseErrors {
|
|
13
|
+
private static instance;
|
|
14
|
+
private api;
|
|
15
|
+
private webhook_map;
|
|
16
|
+
private by_blockchain;
|
|
17
|
+
private pending_configs;
|
|
18
|
+
private config;
|
|
19
|
+
private db;
|
|
20
|
+
private constructor();
|
|
21
|
+
static getInstance(config: IConfig, db: IDatabasePool): SetupNotifications;
|
|
22
|
+
get_all_webhook_ids(): string[];
|
|
23
|
+
get_entry_by_webhook_id(id: string): NotificationWebhookEntry | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Fetch all deposit addresses for a blockchain from the DB (paginated).
|
|
26
|
+
* The `blockchain` filter value in DepositAddressService is the string stored
|
|
27
|
+
* in the DB — e.g. "solana", "evm", "ethereum", etc.
|
|
28
|
+
*/
|
|
29
|
+
private fetch_all_db_addresses;
|
|
30
|
+
/**
|
|
31
|
+
* Register a newly-created webhook entry in the internal maps.
|
|
32
|
+
*/
|
|
33
|
+
private register_entry;
|
|
34
|
+
initialize(): Promise<void>;
|
|
35
|
+
add_address(blockchain: BlockchainType, address: string): Promise<void>;
|
|
36
|
+
remove_address(blockchain: BlockchainType, address: string): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
export default SetupNotifications;
|
|
39
|
+
//# sourceMappingURL=SetupNotifications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SetupNotifications.d.ts","sourceRoot":"","sources":["../../../src/services/quicknode-notifications/SetupNotifications.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAiB,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAQ1D,MAAM,WAAW,wBAAwB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAWD,cAAM,kBAAmB,SAAQ,UAAU;IACvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqB;IAC5C,OAAO,CAAC,GAAG,CAAqB;IAEhC,OAAO,CAAC,WAAW,CAAoD;IAEvE,OAAO,CAAC,aAAa,CAA8D;IAEnF,OAAO,CAAC,eAAe,CAAqD;IAC5E,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO;IAOP,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,GAAG,kBAAkB;IAOnE,mBAAmB,IAAI,MAAM,EAAE;IAI/B,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS;IAOhF;;;;OAIG;YACW,sBAAsB;IAuBpC;;OAEG;IACH,OAAO,CAAC,cAAc;IAOT,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAwH3B,WAAW,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyDvE,cAAc,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAe1F;AAED,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const errors_1 = __importDefault(require("../../errors/errors"));
|
|
16
|
+
const ChainManager_1 = __importDefault(require("../ChainManager"));
|
|
17
|
+
const DepositAddressService_1 = __importDefault(require("../DepositAddressService"));
|
|
18
|
+
const QuicknodeWebhookSignature_1 = __importDefault(require("../QuicknodeWebhookSignature"));
|
|
19
|
+
const QnNotificationsApi_1 = __importDefault(require("./QnNotificationsApi"));
|
|
20
|
+
const ADDRESS_SYNC_BATCH_SIZE = 500;
|
|
21
|
+
const ADDRESS_LOG_THRESHOLD = 1000;
|
|
22
|
+
class SetupNotifications extends errors_1.default {
|
|
23
|
+
constructor(config, db) {
|
|
24
|
+
super();
|
|
25
|
+
// keyed by notification config name (unique per network)
|
|
26
|
+
this.webhook_map = new Map();
|
|
27
|
+
// keyed by blockchain type → list of notification entries for that blockchain
|
|
28
|
+
this.by_blockchain = new Map();
|
|
29
|
+
// configs deferred because no addresses existed at startup
|
|
30
|
+
this.pending_configs = new Map();
|
|
31
|
+
this.config = config;
|
|
32
|
+
this.db = db;
|
|
33
|
+
this.api = new QnNotificationsApi_1.default(config);
|
|
34
|
+
}
|
|
35
|
+
static getInstance(config, db) {
|
|
36
|
+
if (!this.instance) {
|
|
37
|
+
this.instance = new SetupNotifications(config, db);
|
|
38
|
+
}
|
|
39
|
+
return this.instance;
|
|
40
|
+
}
|
|
41
|
+
get_all_webhook_ids() {
|
|
42
|
+
return Array.from(this.webhook_map.values()).map(e => e.webhook_id);
|
|
43
|
+
}
|
|
44
|
+
get_entry_by_webhook_id(id) {
|
|
45
|
+
for (const entry of this.webhook_map.values()) {
|
|
46
|
+
if (entry.webhook_id === id)
|
|
47
|
+
return entry;
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Fetch all deposit addresses for a blockchain from the DB (paginated).
|
|
53
|
+
* The `blockchain` filter value in DepositAddressService is the string stored
|
|
54
|
+
* in the DB — e.g. "solana", "evm", "ethereum", etc.
|
|
55
|
+
*/
|
|
56
|
+
fetch_all_db_addresses(blockchain) {
|
|
57
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
const service = new DepositAddressService_1.default(this.db);
|
|
59
|
+
const addresses = [];
|
|
60
|
+
let page = 1;
|
|
61
|
+
const page_size = ADDRESS_SYNC_BATCH_SIZE;
|
|
62
|
+
while (true) {
|
|
63
|
+
const result = yield service.getDepositAddressesPaginated(page, page_size, { blockchain });
|
|
64
|
+
for (const item of result.items) {
|
|
65
|
+
addresses.push(item.address);
|
|
66
|
+
}
|
|
67
|
+
if (!result.has_next)
|
|
68
|
+
break;
|
|
69
|
+
page++;
|
|
70
|
+
}
|
|
71
|
+
if (addresses.length > ADDRESS_LOG_THRESHOLD) {
|
|
72
|
+
console.warn(`SetupNotifications: ${addresses.length} addresses fetched for blockchain=${blockchain} — ensure QN webhook limit is sufficient`);
|
|
73
|
+
}
|
|
74
|
+
return addresses;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Register a newly-created webhook entry in the internal maps.
|
|
79
|
+
*/
|
|
80
|
+
register_entry(config_name, entry) {
|
|
81
|
+
this.webhook_map.set(config_name, entry);
|
|
82
|
+
const existing_by_bc = this.by_blockchain.get(entry.blockchain) || [];
|
|
83
|
+
existing_by_bc.push(entry);
|
|
84
|
+
this.by_blockchain.set(entry.blockchain, existing_by_bc);
|
|
85
|
+
}
|
|
86
|
+
initialize() {
|
|
87
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
+
var _a;
|
|
89
|
+
try {
|
|
90
|
+
const chain_manager = ChainManager_1.default.getInstance(this.config);
|
|
91
|
+
if (!chain_manager.contractsMap)
|
|
92
|
+
return;
|
|
93
|
+
// Collect all required notification configs from chain config
|
|
94
|
+
const required_notifications = Object.entries(chain_manager.contractsMap)
|
|
95
|
+
.filter(([_, cfg]) => { var _a; return ((_a = cfg.quicknodeNotificationConfig) === null || _a === void 0 ? void 0 : _a.length) > 0; })
|
|
96
|
+
.flatMap(([_, cfg]) => cfg.quicknodeNotificationConfig.map(n => (Object.assign(Object.assign({}, n), { blockchain: cfg.blockchainType }))));
|
|
97
|
+
if (required_notifications.length === 0) {
|
|
98
|
+
console.log(`SetupNotifications: No quicknodeNotifications config found. Skipping.`);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Deduplicate by name (multiple chains may share the same notification config name)
|
|
102
|
+
const unique_notifications = required_notifications.filter((n, i, arr) => arr.findIndex(x => x.name === n.name) === i);
|
|
103
|
+
// Fetch existing webhooks
|
|
104
|
+
let existing_webhooks = [];
|
|
105
|
+
try {
|
|
106
|
+
const res = yield this.api.get_all_webhooks();
|
|
107
|
+
existing_webhooks = res.data || [];
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
console.error(`SetupNotifications: Failed to fetch existing webhooks`, error);
|
|
111
|
+
}
|
|
112
|
+
const host = this.config.config.useTunnel ? this.config.config.tunnel : this.config.config.host;
|
|
113
|
+
const webhook_url = `${host}/webhook/quicknode/notifications`;
|
|
114
|
+
for (const notif_config of unique_notifications) {
|
|
115
|
+
const existing = existing_webhooks.find(w => {
|
|
116
|
+
var _a, _b;
|
|
117
|
+
return ((_a = w.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === notif_config.name.toLowerCase() &&
|
|
118
|
+
((_b = w.network) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === notif_config.network.toLowerCase();
|
|
119
|
+
});
|
|
120
|
+
// Fetch current addresses from the DB for this blockchain
|
|
121
|
+
const db_addresses = yield this.fetch_all_db_addresses(notif_config.blockchain);
|
|
122
|
+
console.log(`SetupNotifications: ${db_addresses.length} DB addresses for blockchain=${notif_config.blockchain}`);
|
|
123
|
+
let webhook_id;
|
|
124
|
+
if (existing) {
|
|
125
|
+
webhook_id = existing.id;
|
|
126
|
+
console.log(`SetupNotifications: Found existing webhook for ${notif_config.name} (id: ${webhook_id})`);
|
|
127
|
+
// Sync the webhook with the full DB address list to fix any drift
|
|
128
|
+
if (db_addresses.length > 0) {
|
|
129
|
+
try {
|
|
130
|
+
yield this.api.update_webhook_addresses(webhook_id, notif_config.template, db_addresses);
|
|
131
|
+
console.log(`SetupNotifications: Synced ${db_addresses.length} addresses to existing webhook ${notif_config.name}`);
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
console.error(`SetupNotifications: Failed to sync addresses to webhook ${notif_config.name}`, err);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const entry = {
|
|
138
|
+
webhook_id,
|
|
139
|
+
template: notif_config.template,
|
|
140
|
+
network: notif_config.network,
|
|
141
|
+
blockchain: notif_config.blockchain,
|
|
142
|
+
address_set: new Set(db_addresses),
|
|
143
|
+
};
|
|
144
|
+
this.register_entry(notif_config.name, entry);
|
|
145
|
+
}
|
|
146
|
+
else if (db_addresses.length === 0) {
|
|
147
|
+
// QN requires at least one address to create a webhook — defer until first address arrives
|
|
148
|
+
console.log(`SetupNotifications: No addresses for ${notif_config.name} — deferring webhook creation until first address is added`);
|
|
149
|
+
this.pending_configs.set(notif_config.name, { notif_config, webhook_url });
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// Create webhook with DB addresses as the initial set
|
|
153
|
+
console.log(`SetupNotifications: Creating webhook for ${notif_config.name} on ${notif_config.network} with ${db_addresses.length} initial addresses`);
|
|
154
|
+
try {
|
|
155
|
+
const res = yield this.api.create_webhook(notif_config.template, notif_config.name, notif_config.network, webhook_url, db_addresses);
|
|
156
|
+
webhook_id = res.id;
|
|
157
|
+
if ((_a = res.destination_attributes) === null || _a === void 0 ? void 0 : _a.security_token) {
|
|
158
|
+
yield QuicknodeWebhookSignature_1.default.getInstance().createSigningKey(this.config.config.keyVaultName, webhook_id, res.destination_attributes.security_token);
|
|
159
|
+
console.log(`SetupNotifications: Stored signing key for webhook ${webhook_id}`);
|
|
160
|
+
}
|
|
161
|
+
console.log(`SetupNotifications: Created webhook ${notif_config.name} (id: ${webhook_id})`);
|
|
162
|
+
const entry = {
|
|
163
|
+
webhook_id,
|
|
164
|
+
template: notif_config.template,
|
|
165
|
+
network: notif_config.network,
|
|
166
|
+
blockchain: notif_config.blockchain,
|
|
167
|
+
address_set: new Set(db_addresses),
|
|
168
|
+
};
|
|
169
|
+
this.register_entry(notif_config.name, entry);
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
console.error(`SetupNotifications: Failed to create webhook for ${notif_config.name}`, err);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
console.log(`SetupNotifications: Initialized ${this.webhook_map.size} notification webhooks, ${this.pending_configs.size} deferred.`);
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
console.error(`SetupNotifications: Error during initialization`, error);
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
add_address(blockchain, address) {
|
|
185
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
186
|
+
var _a;
|
|
187
|
+
// If any pending configs exist for this blockchain, create the webhook now
|
|
188
|
+
for (const [config_name, pending] of this.pending_configs.entries()) {
|
|
189
|
+
if (pending.notif_config.blockchain !== blockchain)
|
|
190
|
+
continue;
|
|
191
|
+
console.log(`SetupNotifications: Lazily creating deferred webhook ${config_name} for first address ${address}`);
|
|
192
|
+
try {
|
|
193
|
+
const res = yield this.api.create_webhook(pending.notif_config.template, pending.notif_config.name, pending.notif_config.network, pending.webhook_url, [address]);
|
|
194
|
+
if ((_a = res.destination_attributes) === null || _a === void 0 ? void 0 : _a.security_token) {
|
|
195
|
+
yield QuicknodeWebhookSignature_1.default.getInstance().createSigningKey(this.config.config.keyVaultName, res.id, res.destination_attributes.security_token);
|
|
196
|
+
}
|
|
197
|
+
const entry = {
|
|
198
|
+
webhook_id: res.id,
|
|
199
|
+
template: pending.notif_config.template,
|
|
200
|
+
network: pending.notif_config.network,
|
|
201
|
+
blockchain: pending.notif_config.blockchain,
|
|
202
|
+
address_set: new Set([address]),
|
|
203
|
+
};
|
|
204
|
+
this.register_entry(config_name, entry);
|
|
205
|
+
this.pending_configs.delete(config_name);
|
|
206
|
+
console.log(`SetupNotifications: Lazily created webhook ${config_name} (id: ${res.id})`);
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
console.error(`SetupNotifications: Failed to lazily create webhook ${config_name}`, err);
|
|
210
|
+
throw err;
|
|
211
|
+
}
|
|
212
|
+
// After lazy creation the address is already in the entry — continue to next pending
|
|
213
|
+
// but skip the update_webhook_addresses call below for this entry since it's already set
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const entries = this.by_blockchain.get(blockchain) || [];
|
|
217
|
+
for (const entry of entries) {
|
|
218
|
+
if (entry.address_set.has(address))
|
|
219
|
+
continue;
|
|
220
|
+
entry.address_set.add(address);
|
|
221
|
+
try {
|
|
222
|
+
yield this.api.update_webhook_addresses(entry.webhook_id, entry.template, Array.from(entry.address_set));
|
|
223
|
+
console.log(`SetupNotifications: Added ${address} to ${entry.network} webhook`);
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
entry.address_set.delete(address); // rollback on failure
|
|
227
|
+
console.error(`SetupNotifications: Failed to add ${address} to ${entry.network}`, error);
|
|
228
|
+
throw error;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
remove_address(blockchain, address) {
|
|
234
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
235
|
+
const entries = this.by_blockchain.get(blockchain) || [];
|
|
236
|
+
for (const entry of entries) {
|
|
237
|
+
if (!entry.address_set.has(address))
|
|
238
|
+
continue;
|
|
239
|
+
entry.address_set.delete(address);
|
|
240
|
+
try {
|
|
241
|
+
yield this.api.update_webhook_addresses(entry.webhook_id, entry.template, Array.from(entry.address_set));
|
|
242
|
+
console.log(`SetupNotifications: Removed ${address} from ${entry.network} webhook`);
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
entry.address_set.add(address); // rollback on failure
|
|
246
|
+
console.error(`SetupNotifications: Failed to remove ${address} from ${entry.network}`, error);
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
exports.default = SetupNotifications;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/quicknode-notifications/types/index.ts"],"names":[],"mappings":"AACA,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./notification_types"), exports);
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
export type QnEvmLog = {
|
|
2
|
+
address: string;
|
|
3
|
+
topics: string[];
|
|
4
|
+
data: string;
|
|
5
|
+
transactionHash: string;
|
|
6
|
+
blockNumber: string;
|
|
7
|
+
blockTimestamp: string;
|
|
8
|
+
logIndex: string;
|
|
9
|
+
removed: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type QnEvmReceipt = {
|
|
12
|
+
blockNumber: string;
|
|
13
|
+
from: string;
|
|
14
|
+
transactionHash: string;
|
|
15
|
+
to: string | null;
|
|
16
|
+
logs: QnEvmLog[];
|
|
17
|
+
status: string;
|
|
18
|
+
gasUsed: string;
|
|
19
|
+
logsBloom?: string;
|
|
20
|
+
contractAddress?: string | null;
|
|
21
|
+
};
|
|
22
|
+
export type QnEvmTransaction = {
|
|
23
|
+
blockNumber: string;
|
|
24
|
+
chainId: string;
|
|
25
|
+
from: string;
|
|
26
|
+
hash: string;
|
|
27
|
+
to: string;
|
|
28
|
+
value: string;
|
|
29
|
+
gas?: string;
|
|
30
|
+
gasPrice?: string;
|
|
31
|
+
nonce?: string;
|
|
32
|
+
};
|
|
33
|
+
export type QnEvmWalletFilterPayload = {
|
|
34
|
+
matchingReceipts: QnEvmReceipt[] | null;
|
|
35
|
+
matchingTransactions: QnEvmTransaction[] | null;
|
|
36
|
+
};
|
|
37
|
+
export type QnSolanaAccountKey = {
|
|
38
|
+
pubkey: string;
|
|
39
|
+
signer: boolean;
|
|
40
|
+
writable: boolean;
|
|
41
|
+
source: string;
|
|
42
|
+
};
|
|
43
|
+
export type QnSolanaTransferInfo = {
|
|
44
|
+
source?: string;
|
|
45
|
+
destination?: string;
|
|
46
|
+
lamports?: number;
|
|
47
|
+
mint?: string;
|
|
48
|
+
tokenAmount?: {
|
|
49
|
+
amount: string;
|
|
50
|
+
decimals: number;
|
|
51
|
+
uiAmount: number;
|
|
52
|
+
uiAmountString?: string;
|
|
53
|
+
};
|
|
54
|
+
authority?: string;
|
|
55
|
+
multisigAuthority?: string;
|
|
56
|
+
signers?: string[];
|
|
57
|
+
account?: string;
|
|
58
|
+
wallet?: string;
|
|
59
|
+
};
|
|
60
|
+
export type QnSolanaInstruction = {
|
|
61
|
+
parsed?: {
|
|
62
|
+
info: QnSolanaTransferInfo;
|
|
63
|
+
type: string;
|
|
64
|
+
};
|
|
65
|
+
program?: string;
|
|
66
|
+
programId: string;
|
|
67
|
+
stackHeight?: number;
|
|
68
|
+
accounts?: string[];
|
|
69
|
+
data?: string;
|
|
70
|
+
};
|
|
71
|
+
export type QnSolanaTokenBalance = {
|
|
72
|
+
accountIndex: number;
|
|
73
|
+
mint: string;
|
|
74
|
+
owner: string;
|
|
75
|
+
programId?: string;
|
|
76
|
+
uiTokenAmount: {
|
|
77
|
+
amount: string;
|
|
78
|
+
decimals: number;
|
|
79
|
+
uiAmount: number;
|
|
80
|
+
uiAmountString: string;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
export type QnSolanaTransaction = {
|
|
84
|
+
raw: {
|
|
85
|
+
meta: {
|
|
86
|
+
fee: number;
|
|
87
|
+
err: any;
|
|
88
|
+
computeUnitsConsumed?: number;
|
|
89
|
+
postTokenBalances?: QnSolanaTokenBalance[];
|
|
90
|
+
preTokenBalances?: QnSolanaTokenBalance[];
|
|
91
|
+
preBalances?: number[];
|
|
92
|
+
postBalances?: number[];
|
|
93
|
+
logMessages?: string[];
|
|
94
|
+
innerInstructions?: any[];
|
|
95
|
+
rewards?: any[];
|
|
96
|
+
status?: {
|
|
97
|
+
Ok: null;
|
|
98
|
+
} | {
|
|
99
|
+
Err: any;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
transaction: {
|
|
103
|
+
message: {
|
|
104
|
+
accountKeys: QnSolanaAccountKey[];
|
|
105
|
+
instructions: QnSolanaInstruction[];
|
|
106
|
+
recentBlockhash: string;
|
|
107
|
+
};
|
|
108
|
+
signatures: string[];
|
|
109
|
+
};
|
|
110
|
+
version: string;
|
|
111
|
+
};
|
|
112
|
+
wallets: string[];
|
|
113
|
+
};
|
|
114
|
+
export type QnSolanaBlockInfo = {
|
|
115
|
+
slot: number;
|
|
116
|
+
blockTime: number;
|
|
117
|
+
blockHeight: number;
|
|
118
|
+
blockhash?: string;
|
|
119
|
+
parentSlot?: number;
|
|
120
|
+
};
|
|
121
|
+
export type QnSolanaBlock = {
|
|
122
|
+
block: QnSolanaBlockInfo;
|
|
123
|
+
transactions: QnSolanaTransaction[];
|
|
124
|
+
};
|
|
125
|
+
export type QnSolanaWalletFilterPayload = QnSolanaBlock[];
|
|
126
|
+
export type QnNotificationPayload = QnEvmWalletFilterPayload | QnSolanaWalletFilterPayload;
|
|
127
|
+
export type QnNotificationWebhookInfo = {
|
|
128
|
+
id: string;
|
|
129
|
+
name: string;
|
|
130
|
+
network: string;
|
|
131
|
+
status: string;
|
|
132
|
+
destination_attributes: {
|
|
133
|
+
url: string;
|
|
134
|
+
security_token?: string;
|
|
135
|
+
};
|
|
136
|
+
templateArgs?: {
|
|
137
|
+
wallets?: string[];
|
|
138
|
+
accounts?: string[];
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
export type QnNotificationCreateResponse = {
|
|
142
|
+
id: string;
|
|
143
|
+
name: string;
|
|
144
|
+
network: string;
|
|
145
|
+
status: string;
|
|
146
|
+
destination_attributes: {
|
|
147
|
+
url: string;
|
|
148
|
+
security_token: string;
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
export type QnNotificationListResponse = {
|
|
152
|
+
data: QnNotificationWebhookInfo[];
|
|
153
|
+
};
|
|
154
|
+
//# sourceMappingURL=notification_types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification_types.d.ts","sourceRoot":"","sources":["../../../../src/services/quicknode-notifications/types/notification_types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACnC,gBAAgB,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IACxC,oBAAoB,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAC9B,MAAM,CAAC,EAAE;QACL,IAAI,EAAE,oBAAoB,CAAC;QAC3B,IAAI,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;CACjG,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAC9B,GAAG,EAAE;QACD,IAAI,EAAE;YACF,GAAG,EAAE,MAAM,CAAC;YACZ,GAAG,EAAE,GAAG,CAAC;YACT,oBAAoB,CAAC,EAAE,MAAM,CAAC;YAC9B,iBAAiB,CAAC,EAAE,oBAAoB,EAAE,CAAC;YAC3C,gBAAgB,CAAC,EAAE,oBAAoB,EAAE,CAAC;YAC1C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;YACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;YACxB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;YACvB,iBAAiB,CAAC,EAAE,GAAG,EAAE,CAAC;YAC1B,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;YAChB,MAAM,CAAC,EAAE;gBAAE,EAAE,EAAE,IAAI,CAAA;aAAE,GAAG;gBAAE,GAAG,EAAE,GAAG,CAAA;aAAE,CAAC;SACxC,CAAC;QACF,WAAW,EAAE;YACT,OAAO,EAAE;gBACL,WAAW,EAAE,kBAAkB,EAAE,CAAC;gBAClC,YAAY,EAAE,mBAAmB,EAAE,CAAC;gBACpC,eAAe,EAAE,MAAM,CAAC;aAC3B,CAAC;YACF,UAAU,EAAE,MAAM,EAAE,CAAC;SACxB,CAAC;QACF,OAAO,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IACxB,KAAK,EAAE,iBAAiB,CAAC;IACzB,YAAY,EAAE,mBAAmB,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,aAAa,EAAE,CAAC;AAE1D,MAAM,MAAM,qBAAqB,GAAG,wBAAwB,GAAG,2BAA2B,CAAC;AAE3F,MAAM,MAAM,yBAAyB,GAAG;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,EAAE;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,cAAc,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IACF,YAAY,CAAC,EAAE;QACX,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;CACL,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,EAAE;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,cAAc,EAAE,MAAM,CAAC;KAC1B,CAAC;CACL,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACrC,IAAI,EAAE,yBAAyB,EAAE,CAAC;CACrC,CAAC"}
|