denotify-client 1.0.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.
Files changed (37) hide show
  1. package/README.md +1 -0
  2. package/dist/alertbuilder.js +44 -0
  3. package/dist/denotifyclient.js +108 -0
  4. package/dist/examples/aave-healthcheck.js +50 -0
  5. package/dist/examples/delete-alert.js +13 -0
  6. package/dist/functionbuilder.js +30 -0
  7. package/dist/index.js +4215 -0
  8. package/dist/index.min.js +1 -0
  9. package/dist/index.mjs +4201 -0
  10. package/dist/notifications/notification.js +8 -0
  11. package/dist/notifications/notify_discord_webhook.js +10 -0
  12. package/dist/triggers/handler_function_call.js +1 -0
  13. package/dist/triggers/handler_function_call_v2.js +12 -0
  14. package/dist/triggers/handler_onchain_event.js +1 -0
  15. package/dist/triggers/trigger.js +10 -0
  16. package/dist/types/types.js +1 -0
  17. package/dist/util/filter.js +131 -0
  18. package/license +9 -0
  19. package/package.json +64 -0
  20. package/types/alertbuilder.d.ts +17 -0
  21. package/types/client.d.ts +14 -0
  22. package/types/denotifyclient.d.ts +27 -0
  23. package/types/examples/aave-healthcheck.d.ts +1 -0
  24. package/types/examples/delete-alert.d.ts +1 -0
  25. package/types/functionbuilder.d.ts +16 -0
  26. package/types/index.d.ts +2 -0
  27. package/types/notifications/notification.d.ts +15 -0
  28. package/types/notifications/notify_discord_webhook.d.ts +32 -0
  29. package/types/temp.d.ts +1 -0
  30. package/types/triggers/handler_function_call.d.ts +39 -0
  31. package/types/triggers/handler_function_call_v2.d.ts +65 -0
  32. package/types/triggers/handler_onchain_event.d.ts +31 -0
  33. package/types/triggers/trigger.d.ts +20 -0
  34. package/types/types/notification.d.ts +7 -0
  35. package/types/types/trigger.d.ts +29 -0
  36. package/types/types/types.d.ts +20 -0
  37. package/types/util/filter.d.ts +35 -0
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # denotify-client
@@ -0,0 +1,44 @@
1
+ export class AlertBuilder {
2
+ name;
3
+ network;
4
+ triggerId;
5
+ trigger;
6
+ notificationId;
7
+ notification;
8
+ constructor(name) {
9
+ this.name = name;
10
+ }
11
+ static create(name) {
12
+ return new AlertBuilder(name);
13
+ }
14
+ onNetwork(network) {
15
+ this.network = network;
16
+ return this;
17
+ }
18
+ withTrigger(id, options) {
19
+ this.triggerId = id;
20
+ this.trigger = options;
21
+ return this;
22
+ }
23
+ withNotification(id, options) {
24
+ this.notificationId = id;
25
+ this.notification = options;
26
+ return this;
27
+ }
28
+ config() {
29
+ if (this.trigger === undefined || this.triggerId === undefined)
30
+ throw new Error('Trigger not configured');
31
+ if (this.notification === undefined || this.notificationId === undefined)
32
+ throw new Error('Notification not configured');
33
+ if (this.network === undefined)
34
+ throw new Error('Network not configured');
35
+ return {
36
+ name: this.name,
37
+ network: this.network,
38
+ triggerId: this.triggerId,
39
+ trigger: this.trigger,
40
+ notificationId: this.notificationId,
41
+ notification: this.notification,
42
+ };
43
+ }
44
+ }
@@ -0,0 +1,108 @@
1
+ import { createClient } from "@supabase/supabase-js";
2
+ import axios from "axios";
3
+ import { Notification } from "./notifications/notification.js";
4
+ import { Trigger } from "./triggers/trigger.js";
5
+ const toFunctionsUrl = (id) => {
6
+ return `https://${id}.functions.supabase.co/`;
7
+ };
8
+ const toApiUrl = (id) => {
9
+ return `https://${id}.supabase.co/`;
10
+ };
11
+ const PROD_PROJECT_ID = 'fdgtrxmmrtlokhgkvcjz';
12
+ // const API_URL = ''
13
+ const ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZkZ3RyeG1tcnRsb2toZ2t2Y2p6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2NzMwODcwNzYsImV4cCI6MTk4ODY2MzA3Nn0.sAMxjlcJSSozBGr-LNcsudyxzUEM9e-UspMHHQLqLr4';
14
+ export class DeNotifyClient {
15
+ url;
16
+ token;
17
+ headers = {};
18
+ constructor(url, token) {
19
+ this.url = url;
20
+ this.token = token;
21
+ this.headers = {
22
+ 'Authorization': `Bearer ${token}`,
23
+ 'Content-Type': 'application/json'
24
+ };
25
+ }
26
+ static async create(options) {
27
+ if (options.key) {
28
+ // TODO
29
+ throw new Error('Auth by key not yet supported');
30
+ }
31
+ else if (options.email && options.password) {
32
+ const url = options.projectId ? toApiUrl(options.projectId) : toApiUrl(PROD_PROJECT_ID);
33
+ const functionsUrl = options.projectId ? toFunctionsUrl(options.projectId) : toFunctionsUrl(PROD_PROJECT_ID);
34
+ const anonKey = options.anonKey ? options.anonKey : ANON_KEY;
35
+ const supabase = createClient(url, anonKey);
36
+ const { data: login, error } = await supabase.auth.signInWithPassword({
37
+ email: options.email,
38
+ password: options.password,
39
+ });
40
+ if (error)
41
+ throw error;
42
+ if (login.session?.access_token === undefined)
43
+ throw new Error('Access token not found');
44
+ return new DeNotifyClient(functionsUrl, login.session?.access_token);
45
+ }
46
+ else {
47
+ throw new Error('Authentication Required. DeNotify supports either username/password or API key authentication');
48
+ }
49
+ }
50
+ async alertHistory(id, pagination = {}) {
51
+ const alerts = await this.request('get', `alert-history${id ? '/' + id : ''}`, { params: pagination });
52
+ return alerts;
53
+ }
54
+ async getAlert(id) {
55
+ const alerts = await this.request('get', `alerts/${id}`);
56
+ return alerts[0];
57
+ }
58
+ async getAlerts() {
59
+ const alerts = await this.request('get', 'alerts');
60
+ return alerts;
61
+ }
62
+ async createAlert(config) {
63
+ const trigger = Trigger.SimpleToRaw(config.name, config.triggerId, config.network, config.trigger);
64
+ const notification = Notification.SimpleToRaw(config.notificationId, config.notification);
65
+ const alert = await this.request('post', `alerts`, { body: { trigger, notification } });
66
+ return alert;
67
+ }
68
+ async deleteAlert(id) {
69
+ const alerts = await this.request('delete', `alerts/${id}`);
70
+ return alerts;
71
+ }
72
+ async request(method, path, options = {}) {
73
+ const url = new URL(`${this.url}${path}`);
74
+ // append params
75
+ if (options.params) {
76
+ for (const param of Object.keys(options.params)) {
77
+ url.searchParams.append(param, options.params[param]);
78
+ }
79
+ }
80
+ const payload = {
81
+ method,
82
+ url: url.toString(),
83
+ headers: this.headers
84
+ };
85
+ if (options.body)
86
+ payload.data = options.body;
87
+ const res = await axios(payload);
88
+ return res.data;
89
+ }
90
+ async getAbi(network, address) {
91
+ const ret = await this.request('get', `abi/${network}/${address}`);
92
+ return ret;
93
+ }
94
+ async getAbiHash(abi) {
95
+ const ret = await this.request('post', 'abi', { body: abi });
96
+ return ret.hash;
97
+ }
98
+ async setAlertName(triggerId, name) {
99
+ }
100
+ async enableAlert(triggerId) {
101
+ }
102
+ async disableAlert(triggerId) {
103
+ }
104
+ async updateTrigger(triggerId, update) {
105
+ const ret = await this.request('patch', `alerts/trigger-handler/${triggerId}`, { body: update });
106
+ return ret;
107
+ }
108
+ }
@@ -0,0 +1,50 @@
1
+ import { DeNotifyClient } from "../denotifyclient.js";
2
+ import { FilterBuilder } from "../util/filter.js";
3
+ // Simple App to demonstrate usage. Created a balance monitoring alert, updates it and deletes it
4
+ async function main() {
5
+ const api = await DeNotifyClient.create({
6
+ email: 's.battenally@gmail.com',
7
+ password: 'Password',
8
+ projectId: 'xfxplbmdcoukaitzxzei',
9
+ anonKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InhmeHBsYm1kY291a2FpdHp4emVpIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NzgwMDg4NzMsImV4cCI6MTk5MzU4NDg3M30.WLk7bR5syQ4YJ8_jNOAuaT1UMvl7E2MS_VYMs7sN56c'
10
+ });
11
+ // const network = 'avalanche'
12
+ // const address = '0x26985888d5b7019ff2A7444fB567D8F386c3b538'
13
+ // const myAddress = '0x7601630eC802952ba1ED2B6e4db16F699A0a5A87'
14
+ // const { abi } = await api.getAbi(network, address)
15
+ // const webhook = 'https://discord.com/api/webhooks/1063967722276388874/VrdsvfyCTEtnRIk5Vzhj1Y0Fi7pFueN5dH9Bz7OeXyNpwJUI7ucIzdIQwpOq8amVgCbW'
16
+ // const builder = FunctionBuilder.create(api)
17
+ // await builder.addFunction(address, 'getBalance', [myAddress], abi)
18
+ // // Create the Balance Monitor alert
19
+ // const alert = AlertBuilder.create('Test Alert')
20
+ // .onNetwork('avalanche')
21
+ // .withTrigger<PollFunctionV2>('PollFunctionV2', {
22
+ // timeBase: 'time',
23
+ // timePeriod: '100s',
24
+ // functions: builder.get(),
25
+ // triggerOn: 'always',
26
+ // })
27
+ // .withNotification<DiscordWebhook>('Discord', {
28
+ // url: webhook,
29
+ // message:
30
+ // `
31
+ // Your avax balance is [{func_0_ret_0 / 1e18}](https://snowtrace.io/address/${myAddress})
32
+ // `,
33
+ // })
34
+ // .config()
35
+ // // Create the alert with the API
36
+ // const triggerId = await api.createAlert(alert)
37
+ // console.log(triggerId)
38
+ // // Update the period to every 10s
39
+ // await api.updateTrigger(triggerId, { timePeriod: '10s' })
40
+ // Update the Filter using the filter builder
41
+ const filter = FilterBuilder.new()
42
+ .addCondition('WHERE', 'func_0_ret_0', 'Number', 'gt', 3)
43
+ .finalise();
44
+ await api.updateTrigger(13, { triggerOn: 'filter', filter, filterVersion: FilterBuilder.version() });
45
+ // Delete the filter in 10s
46
+ // setTimeout(async () => {
47
+ // await api.deleteAlert(triggerId)
48
+ // }, 10 * 1000)
49
+ }
50
+ main();
@@ -0,0 +1,13 @@
1
+ import { DeNotifyClient } from "../denotifyclient.js";
2
+ // Simple App to demonstrate deleting an alert
3
+ async function main() {
4
+ const api = await DeNotifyClient.create({
5
+ email: 's.battenally@gmail.com',
6
+ password: 'Password',
7
+ projectId: 'xfxplbmdcoukaitzxzei',
8
+ anonKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InhmeHBsYm1kY291a2FpdHp4emVpIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NzgwMDg4NzMsImV4cCI6MTk5MzU4NDg3M30.WLk7bR5syQ4YJ8_jNOAuaT1UMvl7E2MS_VYMs7sN56c'
9
+ });
10
+ const alertId = 11;
11
+ await api.deleteAlert(alertId);
12
+ }
13
+ main();
@@ -0,0 +1,30 @@
1
+ import { ethers } from "ethers";
2
+ export class FunctionBuilder {
3
+ api;
4
+ data = [];
5
+ constructor(api) {
6
+ this.api = api;
7
+ }
8
+ static create(api) {
9
+ return new FunctionBuilder(api);
10
+ }
11
+ getAbiHash(abi) {
12
+ if (this.api === undefined)
13
+ throw new Error('FunctionBuilder must be initialised with api');
14
+ return this.api.getAbiHash(abi);
15
+ }
16
+ async addFunction(address, func, args, abi) {
17
+ const contract = new ethers.Contract(address, abi);
18
+ contract.interface.encodeFunctionData(func, args);
19
+ this.data.push({
20
+ address,
21
+ bytecode: contract.interface.encodeFunctionData(func, args),
22
+ abiHash: await this.getAbiHash(abi),
23
+ function: func,
24
+ });
25
+ return this;
26
+ }
27
+ get() {
28
+ return this.data;
29
+ }
30
+ }