@sentio/sdk 2.1.5-rc.1 → 2.1.5-rc.3

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.
@@ -1,15 +1,26 @@
1
1
  import { Plugin, PluginManager } from '@sentio/runtime';
2
2
  import { MetricState } from './meter.js';
3
3
  import { ExporterState } from './exporter.js';
4
+ import { EventTrackerState } from './event-tracker.js';
4
5
  export class CorePlugin extends Plugin {
5
6
  name = 'CorePlugin';
6
7
  async configure(config) {
7
- // part 0, prepare metrics and event tracking configs
8
8
  for (const metric of MetricState.INSTANCE.getValues()) {
9
9
  config.metricConfigs.push({
10
10
  ...metric.config,
11
11
  });
12
12
  }
13
+ // eslint-disable-next-line deprecation/deprecation
14
+ for (const eventTracker of EventTrackerState.INSTANCE.getValues()) {
15
+ config.eventTrackingConfigs.push({
16
+ distinctAggregationByDays: eventTracker.options.distinctByDays || [],
17
+ eventName: eventTracker.name,
18
+ retentionConfig: undefined,
19
+ totalByDay: eventTracker.options.totalByDay || false,
20
+ totalPerEntity: undefined,
21
+ unique: eventTracker.options.unique || false,
22
+ });
23
+ }
13
24
  for (const exporter of ExporterState.INSTANCE.getValues()) {
14
25
  config.exportConfigs.push({
15
26
  name: exporter.name,
@@ -1 +1 @@
1
- {"version":3,"file":"core-plugin.js","sourceRoot":"","sources":["../../src/core/core-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAE7C,MAAM,OAAO,UAAW,SAAQ,MAAM;IACpC,IAAI,GAAW,YAAY,CAAA;IAE3B,KAAK,CAAC,SAAS,CAAC,MAA6B;QAC3C,qDAAqD;QACrD,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE;YACrD,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;gBACxB,GAAG,MAAM,CAAC,MAAM;aACjB,CAAC,CAAA;SACH;QAED,KAAK,MAAM,QAAQ,IAAI,aAAa,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE;YACzD,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;gBACxB,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,OAAO,EAAE,QAAQ,CAAC,OAAO;aAC1B,CAAC,CAAA;SACH;IACH,CAAC;CACF;AAED,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,UAAU,EAAE,CAAC,CAAA","sourcesContent":["import { Plugin, PluginManager } from '@sentio/runtime'\nimport { ProcessConfigResponse } from '@sentio/protos'\n\nimport { MetricState } from './meter.js'\nimport { ExporterState } from './exporter.js'\n\nexport class CorePlugin extends Plugin {\n name: string = 'CorePlugin'\n\n async configure(config: ProcessConfigResponse): Promise<void> {\n // part 0, prepare metrics and event tracking configs\n for (const metric of MetricState.INSTANCE.getValues()) {\n config.metricConfigs.push({\n ...metric.config,\n })\n }\n\n for (const exporter of ExporterState.INSTANCE.getValues()) {\n config.exportConfigs.push({\n name: exporter.name,\n channel: exporter.channel,\n })\n }\n }\n}\n\nPluginManager.INSTANCE.register(new CorePlugin())\n"]}
1
+ {"version":3,"file":"core-plugin.js","sourceRoot":"","sources":["../../src/core/core-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAEtD,MAAM,OAAO,UAAW,SAAQ,MAAM;IACpC,IAAI,GAAW,YAAY,CAAA;IAE3B,KAAK,CAAC,SAAS,CAAC,MAA6B;QAC3C,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE;YACrD,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;gBACxB,GAAG,MAAM,CAAC,MAAM;aACjB,CAAC,CAAA;SACH;QAED,mDAAmD;QACnD,KAAK,MAAM,YAAY,IAAI,iBAAiB,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE;YACjE,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC;gBAC/B,yBAAyB,EAAE,YAAY,CAAC,OAAO,CAAC,cAAc,IAAI,EAAE;gBACpE,SAAS,EAAE,YAAY,CAAC,IAAI;gBAC5B,eAAe,EAAE,SAAS;gBAC1B,UAAU,EAAE,YAAY,CAAC,OAAO,CAAC,UAAU,IAAI,KAAK;gBACpD,cAAc,EAAE,SAAS;gBACzB,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK;aAC7C,CAAC,CAAA;SACH;QAED,KAAK,MAAM,QAAQ,IAAI,aAAa,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE;YACzD,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;gBACxB,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,OAAO,EAAE,QAAQ,CAAC,OAAO;aAC1B,CAAC,CAAA;SACH;IACH,CAAC;CACF;AAED,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,UAAU,EAAE,CAAC,CAAA","sourcesContent":["import { Plugin, PluginManager } from '@sentio/runtime'\nimport { ProcessConfigResponse } from '@sentio/protos'\n\nimport { MetricState } from './meter.js'\nimport { ExporterState } from './exporter.js'\nimport { EventTrackerState } from './event-tracker.js'\n\nexport class CorePlugin extends Plugin {\n name: string = 'CorePlugin'\n\n async configure(config: ProcessConfigResponse): Promise<void> {\n for (const metric of MetricState.INSTANCE.getValues()) {\n config.metricConfigs.push({\n ...metric.config,\n })\n }\n\n // eslint-disable-next-line deprecation/deprecation\n for (const eventTracker of EventTrackerState.INSTANCE.getValues()) {\n config.eventTrackingConfigs.push({\n distinctAggregationByDays: eventTracker.options.distinctByDays || [],\n eventName: eventTracker.name,\n retentionConfig: undefined,\n totalByDay: eventTracker.options.totalByDay || false,\n totalPerEntity: undefined,\n unique: eventTracker.options.unique || false,\n })\n }\n\n for (const exporter of ExporterState.INSTANCE.getValues()) {\n config.exportConfigs.push({\n name: exporter.name,\n channel: exporter.channel,\n })\n }\n }\n}\n\nPluginManager.INSTANCE.register(new CorePlugin())\n"]}
@@ -1,5 +1,7 @@
1
1
  import { BaseContext } from './base-context.js';
2
2
  import { LogLevel } from '@sentio/protos';
3
+ import { MapStateStorage } from '@sentio/runtime';
4
+ import { NamedResultDescriptor } from './metadata.js';
3
5
  export interface Event {
4
6
  distinctId?: string;
5
7
  severity?: LogLevel;
@@ -11,3 +13,25 @@ export declare class BoundedEventTracker {
11
13
  constructor(ctx: BaseContext);
12
14
  track(eventName: string, event: Event): void;
13
15
  }
16
+ export interface TrackerOptions {
17
+ totalByDay?: boolean;
18
+ unique?: boolean;
19
+ distinctByDays?: number[];
20
+ }
21
+ /** @deprecated */
22
+ export declare class EventTrackerState extends MapStateStorage<EventTracker> {
23
+ static INSTANCE: EventTrackerState;
24
+ }
25
+ /** @deprecated */
26
+ export declare class EventTracker extends NamedResultDescriptor {
27
+ static DEFAULT_OPTIONS: TrackerOptions;
28
+ static register(eventName: string, options?: TrackerOptions): EventTracker;
29
+ options: TrackerOptions;
30
+ protected constructor(eventName: string, options: TrackerOptions);
31
+ trackEvent(ctx: BaseContext, event: Event): void;
32
+ }
33
+ /** @deprecated */
34
+ export declare class AccountEventTracker extends EventTracker {
35
+ static DEFAULT_OPTIONS: TrackerOptions;
36
+ static register(eventName?: string, options?: TrackerOptions): EventTracker;
37
+ }
@@ -1,4 +1,7 @@
1
1
  import { LogLevel } from '@sentio/protos';
2
+ import { MapStateStorage } from '@sentio/runtime';
3
+ import { NamedResultDescriptor } from './metadata.js';
4
+ import { normalizeAttribute } from './normalization.js';
2
5
  export class BoundedEventTracker {
3
6
  ctx;
4
7
  constructor(ctx) {
@@ -18,4 +21,63 @@ export class BoundedEventTracker {
18
21
  this.ctx._res.events.push(res);
19
22
  }
20
23
  }
24
+ /** @deprecated */
25
+ // eslint-disable-next-line deprecation/deprecation
26
+ export class EventTrackerState extends MapStateStorage {
27
+ // eslint-disable-next-line deprecation/deprecation
28
+ static INSTANCE = new EventTrackerState();
29
+ }
30
+ // Track Event with an identity associate with it
31
+ /** @deprecated */
32
+ export class EventTracker extends NamedResultDescriptor {
33
+ static DEFAULT_OPTIONS = {
34
+ totalByDay: true,
35
+ unique: true,
36
+ };
37
+ static register(eventName, options) {
38
+ // eslint-disable-next-line deprecation/deprecation
39
+ const tracker = new EventTracker(eventName, { ...EventTracker.DEFAULT_OPTIONS, ...options });
40
+ // eslint-disable-next-line deprecation/deprecation
41
+ return EventTrackerState.INSTANCE.getOrSetValue(eventName, tracker);
42
+ }
43
+ options;
44
+ constructor(eventName, options) {
45
+ super(eventName);
46
+ this.options = options;
47
+ }
48
+ trackEvent(ctx, event) {
49
+ const { distinctId, message, severity, ...payload } = event;
50
+ const res = {
51
+ message: message || '',
52
+ severity: severity || LogLevel.INFO,
53
+ metadata: ctx.getMetaData(this.name, {}),
54
+ distinctEntityId: distinctId || '',
55
+ attributes: normalizeAttribute(payload),
56
+ runtimeInfo: undefined,
57
+ noMetric: false,
58
+ };
59
+ ctx._res.events.push(res);
60
+ }
61
+ }
62
+ /** @deprecated */
63
+ // eslint-disable-next-line deprecation/deprecation
64
+ export class AccountEventTracker extends EventTracker {
65
+ static DEFAULT_OPTIONS = {
66
+ totalByDay: true,
67
+ unique: true,
68
+ distinctByDays: [1, 7, 30],
69
+ };
70
+ static register(eventName, options) {
71
+ if (eventName) {
72
+ eventName = ['user', eventName].join('_');
73
+ }
74
+ else {
75
+ eventName = 'user';
76
+ }
77
+ // eslint-disable-next-line deprecation/deprecation
78
+ const tracker = new AccountEventTracker(eventName, { ...AccountEventTracker.DEFAULT_OPTIONS, ...options });
79
+ // eslint-disable-next-line deprecation/deprecation
80
+ return EventTrackerState.INSTANCE.getOrSetValue(eventName, tracker);
81
+ }
82
+ }
21
83
  //# sourceMappingURL=event-tracker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"event-tracker.js","sourceRoot":"","sources":["../../src/core/event-tracker.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAa9D,MAAM,OAAO,mBAAmB;IACb,GAAG,CAAa;IAEjC,YAAY,GAAgB;QAC1B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,SAAiB,EAAE,KAAY;QACnC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,CAAA;QAE3D,MAAM,GAAG,GAAwB;YAC/B,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC;YAC7C,QAAQ,EAAE,QAAQ,IAAI,QAAQ,CAAC,IAAI;YACnC,OAAO,EAAE,OAAO,IAAI,EAAE;YACtB,gBAAgB,EAAE,UAAU,IAAI,EAAE;YAClC,UAAU,EAAE,OAAO;YACnB,WAAW,EAAE,SAAS;YACtB,QAAQ,EAAE,IAAI;SACf,CAAA;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAChC,CAAC;CACF","sourcesContent":["import { BaseContext } from './base-context.js'\nimport { EventTrackingResult, LogLevel } from '@sentio/protos'\n\nexport interface Event {\n // The unique identifier of main identity associate with an event\n // .e.g user id / token address / account address / contract address id\n //\n distinctId?: string\n severity?: LogLevel\n message?: string\n\n [key: string]: any\n}\n\nexport class BoundedEventTracker {\n private readonly ctx: BaseContext\n\n constructor(ctx: BaseContext) {\n this.ctx = ctx\n }\n\n track(eventName: string, event: Event) {\n const { distinctId, severity, message, ...payload } = event\n\n const res: EventTrackingResult = {\n metadata: this.ctx.getMetaData(eventName, {}),\n severity: severity || LogLevel.INFO,\n message: message || '',\n distinctEntityId: distinctId || '',\n attributes: payload,\n runtimeInfo: undefined,\n noMetric: true,\n }\n this.ctx._res.events.push(res)\n }\n}\n"]}
1
+ {"version":3,"file":"event-tracker.js","sourceRoot":"","sources":["../../src/core/event-tracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseContext } from './base-context.js'\nimport { EventTrackingResult, LogLevel } from '@sentio/protos'\nimport { MapStateStorage } from '@sentio/runtime'\nimport { NamedResultDescriptor } from './metadata.js'\nimport { normalizeAttribute } from './normalization.js'\n\nexport interface Event {\n // The unique identifier of main identity associate with an event\n // .e.g user id / token address / account address / contract address id\n //\n distinctId?: string\n severity?: LogLevel\n message?: string\n\n [key: string]: any\n}\n\nexport class BoundedEventTracker {\n private readonly ctx: BaseContext\n\n constructor(ctx: BaseContext) {\n this.ctx = ctx\n }\n\n track(eventName: string, event: Event) {\n const { distinctId, severity, message, ...payload } = event\n\n const res: EventTrackingResult = {\n metadata: this.ctx.getMetaData(eventName, {}),\n severity: severity || LogLevel.INFO,\n message: message || '',\n distinctEntityId: distinctId || '',\n attributes: payload,\n runtimeInfo: undefined,\n noMetric: true,\n }\n this.ctx._res.events.push(res)\n }\n}\n\nexport interface TrackerOptions {\n totalByDay?: boolean\n unique?: boolean\n distinctByDays?: number[]\n}\n\n/** @deprecated */\n// eslint-disable-next-line deprecation/deprecation\nexport class EventTrackerState extends MapStateStorage<EventTracker> {\n // eslint-disable-next-line deprecation/deprecation\n static INSTANCE = new EventTrackerState()\n}\n\n// Track Event with an identity associate with it\n/** @deprecated */\nexport class EventTracker extends NamedResultDescriptor {\n static DEFAULT_OPTIONS: TrackerOptions = {\n totalByDay: true,\n unique: true,\n }\n\n static register(eventName: string, options?: TrackerOptions) {\n // eslint-disable-next-line deprecation/deprecation\n const tracker = new EventTracker(eventName, { ...EventTracker.DEFAULT_OPTIONS, ...options })\n // eslint-disable-next-line deprecation/deprecation\n return EventTrackerState.INSTANCE.getOrSetValue(eventName, tracker)\n }\n\n options: TrackerOptions\n protected constructor(eventName: string, options: TrackerOptions) {\n super(eventName)\n this.options = options\n }\n\n trackEvent(ctx: BaseContext, event: Event) {\n const { distinctId, message, severity, ...payload } = event\n\n const res: EventTrackingResult = {\n message: message || '',\n severity: severity || LogLevel.INFO,\n metadata: ctx.getMetaData(this.name, {}),\n distinctEntityId: distinctId || '',\n attributes: normalizeAttribute(payload),\n runtimeInfo: undefined,\n noMetric: false,\n }\n ctx._res.events.push(res)\n }\n}\n/** @deprecated */\n// eslint-disable-next-line deprecation/deprecation\nexport class AccountEventTracker extends EventTracker {\n static DEFAULT_OPTIONS: TrackerOptions = {\n totalByDay: true,\n unique: true,\n distinctByDays: [1, 7, 30],\n }\n\n static register(eventName?: string, options?: TrackerOptions) {\n if (eventName) {\n eventName = ['user', eventName].join('_')\n } else {\n eventName = 'user'\n }\n // eslint-disable-next-line deprecation/deprecation\n const tracker = new AccountEventTracker(eventName, { ...AccountEventTracker.DEFAULT_OPTIONS, ...options })\n // eslint-disable-next-line deprecation/deprecation\n return EventTrackerState.INSTANCE.getOrSetValue(eventName, tracker)\n }\n}\n"]}
@@ -31,19 +31,56 @@ export function getProvider(networkish) {
31
31
  providers.set(network.chainId.toString(), provider);
32
32
  return provider;
33
33
  }
34
+ function getTag(prefix, value) {
35
+ return (prefix +
36
+ ':' +
37
+ JSON.stringify(value, (k, v) => {
38
+ if (v == null) {
39
+ return 'null';
40
+ }
41
+ if (typeof v === 'bigint') {
42
+ return `bigint:${v.toString()}`;
43
+ }
44
+ if (typeof v === 'string') {
45
+ return v.toLowerCase();
46
+ }
47
+ // Sort object keys
48
+ if (typeof v === 'object' && !Array.isArray(v)) {
49
+ const keys = Object.keys(v);
50
+ keys.sort();
51
+ return keys.reduce((accum, key) => {
52
+ accum[key] = v[key];
53
+ return accum;
54
+ }, {});
55
+ }
56
+ return v;
57
+ }));
58
+ }
34
59
  class QueuedStaticJsonRpcProvider extends JsonRpcProvider {
35
60
  executor;
61
+ #performCache = new Map();
36
62
  constructor(url, network, concurrency) {
37
63
  // TODO re-enable match when possible
38
64
  super(url, network, { staticNetwork: network, batchMaxCount: 1 });
39
65
  this.executor = new PQueue({ concurrency: concurrency });
40
66
  }
41
67
  async send(method, params) {
42
- const res = await this.executor.add(() => super.send(method, params));
43
- if (!res) {
68
+ const tag = getTag(method, params);
69
+ let perform = this.#performCache.get(tag);
70
+ if (!perform) {
71
+ perform = this.executor.add(() => super.send(method, params));
72
+ this.#performCache.set(tag, perform);
73
+ setTimeout(() => {
74
+ if (this.#performCache.get(tag) === perform) {
75
+ this.#performCache.delete(tag);
76
+ }
77
+ }, 500);
78
+ }
79
+ const result = await perform;
80
+ if (!result) {
44
81
  throw Error('Unexpected null response');
45
82
  }
46
- return res;
83
+ return result;
47
84
  }
48
85
  }
49
86
  //# sourceMappingURL=provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/eth/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AAG3D,OAAO,MAAM,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,eAAe,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;AAErE,MAAM,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAA;AAEpD,MAAM,UAAU,WAAW,CAAC,UAAuB;IACjD,IAAI,CAAC,UAAU,EAAE;QACf,UAAU,GAAG,CAAC,CAAA;KACf;IACD,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE;QAClC,MAAM,EAAE,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAA;QAC/B,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE;YACd,UAAU,GAAG,CAAC,CAAA;SACf;KACF;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACxC,iCAAiC;IAEjC,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC9E,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,OAAO,CAAA;IACtD,IAAI,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAEjC,IAAI,QAAQ,EAAE;QACZ,OAAO,QAAQ,CAAA;KAChB;IAED,IAAI,OAAO,KAAK,SAAS,EAAE;QACzB,MAAM,KAAK,CACT,+BAA+B;YAC7B,OAAO,CAAC,OAAO;YACf,uBAAuB;YACvB,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CACvD,CAAA;KACF;IACD,QAAQ,GAAG,IAAI,2BAA2B,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC1G,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAA;IACnD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,2BAA4B,SAAQ,eAAe;IACvD,QAAQ,CAAQ;IAEhB,YAAY,GAAW,EAAE,OAAgB,EAAE,WAAmB;QAC5D,qCAAqC;QACrC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAA;QACjE,IAAI,CAAC,QAAQ,GAAG,IAAI,MAAM,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAA;IAC1D,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAkB;QAC3C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;QACrE,IAAI,CAAC,GAAG,EAAE;YACR,MAAM,KAAK,CAAC,0BAA0B,CAAC,CAAA;SACxC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;CACF","sourcesContent":["import { Provider, Network, JsonRpcProvider } from 'ethers'\nimport { Networkish } from 'ethers/providers'\n\nimport PQueue from 'p-queue'\nimport { Endpoints } from '@sentio/runtime'\n\nexport const DummyProvider = new JsonRpcProvider('', Network.from(1))\n\nconst providers = new Map<string, JsonRpcProvider>()\n\nexport function getProvider(networkish?: Networkish): Provider {\n if (!networkish) {\n networkish = 1\n }\n if (typeof networkish === 'string') {\n const id = parseInt(networkish)\n if (!isNaN(id)) {\n networkish = 1\n }\n }\n const network = Network.from(networkish)\n // TODO check if other key needed\n\n const address = Endpoints.INSTANCE.chainServer.get(network.chainId.toString())\n const key = network.chainId.toString() + '-' + address\n let provider = providers.get(key)\n\n if (provider) {\n return provider\n }\n\n if (address === undefined) {\n throw Error(\n 'Provider not found for chain ' +\n network.chainId +\n ', configured chains: ' +\n [...Endpoints.INSTANCE.chainServer.keys()].join(' ')\n )\n }\n provider = new QueuedStaticJsonRpcProvider(address, Network.from(network), Endpoints.INSTANCE.concurrency)\n providers.set(network.chainId.toString(), provider)\n return provider\n}\n\nclass QueuedStaticJsonRpcProvider extends JsonRpcProvider {\n executor: PQueue\n\n constructor(url: string, network: Network, concurrency: number) {\n // TODO re-enable match when possible\n super(url, network, { staticNetwork: network, batchMaxCount: 1 })\n this.executor = new PQueue({ concurrency: concurrency })\n }\n\n async send(method: string, params: Array<any>): Promise<any> {\n const res = await this.executor.add(() => super.send(method, params))\n if (!res) {\n throw Error('Unexpected null response')\n }\n return res\n }\n}\n"]}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/eth/provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { Provider, Network, JsonRpcProvider } from 'ethers'\nimport { Networkish } from 'ethers/providers'\n\nimport PQueue from 'p-queue'\nimport { Endpoints } from '@sentio/runtime'\n\nexport const DummyProvider = new JsonRpcProvider('', Network.from(1))\n\nconst providers = new Map<string, JsonRpcProvider>()\n\nexport function getProvider(networkish?: Networkish): Provider {\n if (!networkish) {\n networkish = 1\n }\n if (typeof networkish === 'string') {\n const id = parseInt(networkish)\n if (!isNaN(id)) {\n networkish = 1\n }\n }\n const network = Network.from(networkish)\n // TODO check if other key needed\n\n const address = Endpoints.INSTANCE.chainServer.get(network.chainId.toString())\n const key = network.chainId.toString() + '-' + address\n let provider = providers.get(key)\n\n if (provider) {\n return provider\n }\n\n if (address === undefined) {\n throw Error(\n 'Provider not found for chain ' +\n network.chainId +\n ', configured chains: ' +\n [...Endpoints.INSTANCE.chainServer.keys()].join(' ')\n )\n }\n provider = new QueuedStaticJsonRpcProvider(address, Network.from(network), Endpoints.INSTANCE.concurrency)\n providers.set(network.chainId.toString(), provider)\n return provider\n}\n\nfunction getTag(prefix: string, value: any): string {\n return (\n prefix +\n ':' +\n JSON.stringify(value, (k, v) => {\n if (v == null) {\n return 'null'\n }\n if (typeof v === 'bigint') {\n return `bigint:${v.toString()}`\n }\n if (typeof v === 'string') {\n return v.toLowerCase()\n }\n\n // Sort object keys\n if (typeof v === 'object' && !Array.isArray(v)) {\n const keys = Object.keys(v)\n keys.sort()\n return keys.reduce((accum, key) => {\n accum[key] = v[key]\n return accum\n }, <any>{})\n }\n\n return v\n })\n )\n}\n\nclass QueuedStaticJsonRpcProvider extends JsonRpcProvider {\n executor: PQueue\n #performCache = new Map<string, Promise<any>>()\n\n constructor(url: string, network: Network, concurrency: number) {\n // TODO re-enable match when possible\n super(url, network, { staticNetwork: network, batchMaxCount: 1 })\n this.executor = new PQueue({ concurrency: concurrency })\n }\n\n async send(method: string, params: Array<any>): Promise<any> {\n const tag = getTag(method, params)\n let perform = this.#performCache.get(tag)\n if (!perform) {\n perform = this.executor.add(() => super.send(method, params))\n this.#performCache.set(tag, perform)\n\n setTimeout(() => {\n if (this.#performCache.get(tag) === perform) {\n this.#performCache.delete(tag)\n }\n }, 500)\n }\n\n const result = await perform\n if (!result) {\n throw Error('Unexpected null response')\n }\n return result\n }\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sentio/sdk",
3
3
  "license": "Apache-2.0",
4
- "version": "2.1.5-rc.1",
4
+ "version": "2.1.5-rc.3",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "compile": "tsc -p . && cp src/utils/*.csv lib/utils && cp src/tsup.config.ts lib",
@@ -18,9 +18,9 @@
18
18
  "@project-serum/anchor": "^0.26.0",
19
19
  "@sentio/bigdecimal": "^9.1.1-patch.3",
20
20
  "@sentio/ethers-v6": "^1.0.25",
21
- "@sentio/protos": "^2.1.5-rc.1",
22
- "@sentio/runtime": "^2.1.5-rc.1",
23
- "@sentio/sdk": "^2.1.5-rc.1",
21
+ "@sentio/protos": "^2.1.5-rc.3",
22
+ "@sentio/runtime": "^2.1.5-rc.3",
23
+ "@sentio/sdk": "^2.1.5-rc.3",
24
24
  "@solana/web3.js": "^1.47.3",
25
25
  "@types/prettier": "^2.7.2",
26
26
  "aptos-sdk": "npm:@sentio/aptos@^1.6.0",
@@ -71,5 +71,5 @@
71
71
  "typedoc": {
72
72
  "entryPoint": "./src/index.ts"
73
73
  },
74
- "gitHead": "35d954d73230fe9cec44d332199422dc5cff4140"
74
+ "gitHead": "2a56b34cc14f22e0da27e16a20e16009d027664e"
75
75
  }
@@ -3,18 +3,30 @@ import { ProcessConfigResponse } from '@sentio/protos'
3
3
 
4
4
  import { MetricState } from './meter.js'
5
5
  import { ExporterState } from './exporter.js'
6
+ import { EventTrackerState } from './event-tracker.js'
6
7
 
7
8
  export class CorePlugin extends Plugin {
8
9
  name: string = 'CorePlugin'
9
10
 
10
11
  async configure(config: ProcessConfigResponse): Promise<void> {
11
- // part 0, prepare metrics and event tracking configs
12
12
  for (const metric of MetricState.INSTANCE.getValues()) {
13
13
  config.metricConfigs.push({
14
14
  ...metric.config,
15
15
  })
16
16
  }
17
17
 
18
+ // eslint-disable-next-line deprecation/deprecation
19
+ for (const eventTracker of EventTrackerState.INSTANCE.getValues()) {
20
+ config.eventTrackingConfigs.push({
21
+ distinctAggregationByDays: eventTracker.options.distinctByDays || [],
22
+ eventName: eventTracker.name,
23
+ retentionConfig: undefined,
24
+ totalByDay: eventTracker.options.totalByDay || false,
25
+ totalPerEntity: undefined,
26
+ unique: eventTracker.options.unique || false,
27
+ })
28
+ }
29
+
18
30
  for (const exporter of ExporterState.INSTANCE.getValues()) {
19
31
  config.exportConfigs.push({
20
32
  name: exporter.name,
@@ -1,5 +1,8 @@
1
1
  import { BaseContext } from './base-context.js'
2
2
  import { EventTrackingResult, LogLevel } from '@sentio/protos'
3
+ import { MapStateStorage } from '@sentio/runtime'
4
+ import { NamedResultDescriptor } from './metadata.js'
5
+ import { normalizeAttribute } from './normalization.js'
3
6
 
4
7
  export interface Event {
5
8
  // The unique identifier of main identity associate with an event
@@ -34,3 +37,74 @@ export class BoundedEventTracker {
34
37
  this.ctx._res.events.push(res)
35
38
  }
36
39
  }
40
+
41
+ export interface TrackerOptions {
42
+ totalByDay?: boolean
43
+ unique?: boolean
44
+ distinctByDays?: number[]
45
+ }
46
+
47
+ /** @deprecated */
48
+ // eslint-disable-next-line deprecation/deprecation
49
+ export class EventTrackerState extends MapStateStorage<EventTracker> {
50
+ // eslint-disable-next-line deprecation/deprecation
51
+ static INSTANCE = new EventTrackerState()
52
+ }
53
+
54
+ // Track Event with an identity associate with it
55
+ /** @deprecated */
56
+ export class EventTracker extends NamedResultDescriptor {
57
+ static DEFAULT_OPTIONS: TrackerOptions = {
58
+ totalByDay: true,
59
+ unique: true,
60
+ }
61
+
62
+ static register(eventName: string, options?: TrackerOptions) {
63
+ // eslint-disable-next-line deprecation/deprecation
64
+ const tracker = new EventTracker(eventName, { ...EventTracker.DEFAULT_OPTIONS, ...options })
65
+ // eslint-disable-next-line deprecation/deprecation
66
+ return EventTrackerState.INSTANCE.getOrSetValue(eventName, tracker)
67
+ }
68
+
69
+ options: TrackerOptions
70
+ protected constructor(eventName: string, options: TrackerOptions) {
71
+ super(eventName)
72
+ this.options = options
73
+ }
74
+
75
+ trackEvent(ctx: BaseContext, event: Event) {
76
+ const { distinctId, message, severity, ...payload } = event
77
+
78
+ const res: EventTrackingResult = {
79
+ message: message || '',
80
+ severity: severity || LogLevel.INFO,
81
+ metadata: ctx.getMetaData(this.name, {}),
82
+ distinctEntityId: distinctId || '',
83
+ attributes: normalizeAttribute(payload),
84
+ runtimeInfo: undefined,
85
+ noMetric: false,
86
+ }
87
+ ctx._res.events.push(res)
88
+ }
89
+ }
90
+ /** @deprecated */
91
+ // eslint-disable-next-line deprecation/deprecation
92
+ export class AccountEventTracker extends EventTracker {
93
+ static DEFAULT_OPTIONS: TrackerOptions = {
94
+ totalByDay: true,
95
+ unique: true,
96
+ distinctByDays: [1, 7, 30],
97
+ }
98
+
99
+ static register(eventName?: string, options?: TrackerOptions) {
100
+ if (eventName) {
101
+ eventName = ['user', eventName].join('_')
102
+ } else {
103
+ eventName = 'user'
104
+ }
105
+ // eslint-disable-next-line deprecation/deprecation
106
+ const tracker = new AccountEventTracker(eventName, { ...AccountEventTracker.DEFAULT_OPTIONS, ...options })
107
+ // eslint-disable-next-line deprecation/deprecation
108
+ return EventTrackerState.INSTANCE.getOrSetValue(eventName, tracker)
109
+ }
110
+ }
@@ -42,8 +42,39 @@ export function getProvider(networkish?: Networkish): Provider {
42
42
  return provider
43
43
  }
44
44
 
45
+ function getTag(prefix: string, value: any): string {
46
+ return (
47
+ prefix +
48
+ ':' +
49
+ JSON.stringify(value, (k, v) => {
50
+ if (v == null) {
51
+ return 'null'
52
+ }
53
+ if (typeof v === 'bigint') {
54
+ return `bigint:${v.toString()}`
55
+ }
56
+ if (typeof v === 'string') {
57
+ return v.toLowerCase()
58
+ }
59
+
60
+ // Sort object keys
61
+ if (typeof v === 'object' && !Array.isArray(v)) {
62
+ const keys = Object.keys(v)
63
+ keys.sort()
64
+ return keys.reduce((accum, key) => {
65
+ accum[key] = v[key]
66
+ return accum
67
+ }, <any>{})
68
+ }
69
+
70
+ return v
71
+ })
72
+ )
73
+ }
74
+
45
75
  class QueuedStaticJsonRpcProvider extends JsonRpcProvider {
46
76
  executor: PQueue
77
+ #performCache = new Map<string, Promise<any>>()
47
78
 
48
79
  constructor(url: string, network: Network, concurrency: number) {
49
80
  // TODO re-enable match when possible
@@ -52,10 +83,23 @@ class QueuedStaticJsonRpcProvider extends JsonRpcProvider {
52
83
  }
53
84
 
54
85
  async send(method: string, params: Array<any>): Promise<any> {
55
- const res = await this.executor.add(() => super.send(method, params))
56
- if (!res) {
86
+ const tag = getTag(method, params)
87
+ let perform = this.#performCache.get(tag)
88
+ if (!perform) {
89
+ perform = this.executor.add(() => super.send(method, params))
90
+ this.#performCache.set(tag, perform)
91
+
92
+ setTimeout(() => {
93
+ if (this.#performCache.get(tag) === perform) {
94
+ this.#performCache.delete(tag)
95
+ }
96
+ }, 500)
97
+ }
98
+
99
+ const result = await perform
100
+ if (!result) {
57
101
  throw Error('Unexpected null response')
58
102
  }
59
- return res
103
+ return result
60
104
  }
61
105
  }