@sentio/sdk 2.57.9-rc.1 → 2.57.9-rc.11

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 (94) hide show
  1. package/lib/aptos/aptos-plugin.d.ts.map +1 -1
  2. package/lib/aptos/aptos-plugin.js +4 -2
  3. package/lib/aptos/aptos-plugin.js.map +1 -1
  4. package/lib/aptos/aptos-processor.d.ts +8 -2
  5. package/lib/aptos/aptos-processor.d.ts.map +1 -1
  6. package/lib/aptos/aptos-processor.js +11 -4
  7. package/lib/aptos/aptos-processor.js.map +1 -1
  8. package/lib/aptos/builtin/0x1.d.ts +155 -155
  9. package/lib/aptos/builtin/0x1.d.ts.map +1 -1
  10. package/lib/aptos/builtin/0x1.js +395 -308
  11. package/lib/aptos/builtin/0x1.js.map +1 -1
  12. package/lib/aptos/builtin/0x3.d.ts +52 -52
  13. package/lib/aptos/builtin/0x3.d.ts.map +1 -1
  14. package/lib/aptos/builtin/0x3.js +135 -102
  15. package/lib/aptos/builtin/0x3.js.map +1 -1
  16. package/lib/aptos/builtin/0x4.d.ts +12 -12
  17. package/lib/aptos/builtin/0x4.d.ts.map +1 -1
  18. package/lib/aptos/builtin/0x4.js +22 -22
  19. package/lib/aptos/builtin/0x4.js.map +1 -1
  20. package/lib/core/normalization.d.ts.map +1 -1
  21. package/lib/core/normalization.js +69 -3
  22. package/lib/core/normalization.js.map +1 -1
  23. package/lib/core/normalization.test.js.map +1 -1
  24. package/lib/eth/abi-decoder/decode-worker.d.ts +27 -0
  25. package/lib/eth/abi-decoder/decode-worker.d.ts.map +1 -0
  26. package/lib/eth/abi-decoder/decode-worker.js +63 -0
  27. package/lib/eth/abi-decoder/decode-worker.js.map +1 -0
  28. package/lib/eth/abi-decoder/index.d.ts +4 -0
  29. package/lib/eth/abi-decoder/index.d.ts.map +1 -0
  30. package/lib/eth/abi-decoder/index.js +134 -0
  31. package/lib/eth/abi-decoder/index.js.map +1 -0
  32. package/lib/eth/base-processor.d.ts.map +1 -1
  33. package/lib/eth/base-processor.js +7 -7
  34. package/lib/eth/base-processor.js.map +1 -1
  35. package/lib/move/filter.d.ts +1 -0
  36. package/lib/move/filter.d.ts.map +1 -1
  37. package/lib/move/filter.js.map +1 -1
  38. package/lib/move/shared-network-codegen.js +3 -3
  39. package/lib/move/shared-network-codegen.js.map +1 -1
  40. package/lib/store/codegen.js +1 -1
  41. package/lib/store/codegen.js.map +1 -1
  42. package/lib/store/convert.d.ts +1 -0
  43. package/lib/store/convert.d.ts.map +1 -1
  44. package/lib/store/convert.js +16 -0
  45. package/lib/store/convert.js.map +1 -1
  46. package/lib/store/decorators.d.ts +1 -0
  47. package/lib/store/decorators.d.ts.map +1 -1
  48. package/lib/store/decorators.js +2 -1
  49. package/lib/store/decorators.js.map +1 -1
  50. package/lib/store/schema.js +1 -1
  51. package/lib/store/schema.js.map +1 -1
  52. package/lib/store/types.d.ts +1 -0
  53. package/lib/store/types.d.ts.map +1 -1
  54. package/lib/store/types.js +3 -0
  55. package/lib/store/types.js.map +1 -1
  56. package/lib/sui/builtin/0x1.d.ts +7 -7
  57. package/lib/sui/builtin/0x1.d.ts.map +1 -1
  58. package/lib/sui/builtin/0x1.js +12 -12
  59. package/lib/sui/builtin/0x1.js.map +1 -1
  60. package/lib/sui/builtin/0x2.d.ts +34 -34
  61. package/lib/sui/builtin/0x2.d.ts.map +1 -1
  62. package/lib/sui/builtin/0x2.js +72 -66
  63. package/lib/sui/builtin/0x2.js.map +1 -1
  64. package/lib/sui/builtin/0x3.d.ts +14 -14
  65. package/lib/sui/builtin/0x3.d.ts.map +1 -1
  66. package/lib/sui/builtin/0x3.js +44 -26
  67. package/lib/sui/builtin/0x3.js.map +1 -1
  68. package/lib/sui/sui-plugin.d.ts.map +1 -1
  69. package/lib/sui/sui-plugin.js +2 -1
  70. package/lib/sui/sui-plugin.js.map +1 -1
  71. package/lib/tsup.config.ts +1 -1
  72. package/package.json +5 -3
  73. package/src/aptos/aptos-plugin.ts +4 -2
  74. package/src/aptos/aptos-processor.ts +18 -4
  75. package/src/aptos/builtin/0x1.ts +644 -155
  76. package/src/aptos/builtin/0x3.ts +208 -52
  77. package/src/aptos/builtin/0x4.ts +59 -12
  78. package/src/bundle.config.ts +1 -1
  79. package/src/core/normalization.ts +69 -4
  80. package/src/eth/abi-decoder/decode-worker.ts +85 -0
  81. package/src/eth/abi-decoder/index.ts +133 -0
  82. package/src/eth/base-processor.ts +19 -20
  83. package/src/move/filter.ts +1 -0
  84. package/src/move/shared-network-codegen.ts +3 -3
  85. package/src/store/codegen.ts +1 -1
  86. package/src/store/convert.ts +17 -0
  87. package/src/store/decorators.ts +2 -0
  88. package/src/store/schema.ts +1 -1
  89. package/src/store/types.ts +4 -0
  90. package/src/sui/builtin/0x1.ts +33 -7
  91. package/src/sui/builtin/0x2.ts +177 -34
  92. package/src/sui/builtin/0x3.ts +45 -14
  93. package/src/sui/sui-plugin.ts +2 -1
  94. package/src/tsup.config.ts +1 -1
@@ -4,7 +4,7 @@
4
4
 
5
5
  /* Generated types for 0x4, original address 0x4 */
6
6
 
7
- import { CallFilter, MoveFetchConfig } from "@sentio/sdk/move";
7
+ import { CallFilter, MoveFetchConfig, EventFilter } from "@sentio/sdk/move";
8
8
  import {
9
9
  AptosBindOptions,
10
10
  AptosBaseProcessor,
@@ -45,16 +45,26 @@ export class token extends AptosBaseProcessor {
45
45
  onEventMutation(
46
46
  func: (event: token.MutationInstance, ctx: AptosContext) => void,
47
47
  fetchConfig?: Partial<MoveFetchConfig>,
48
+ eventFilter?: Omit<EventFilter, "type" | "account">,
48
49
  ): token {
49
- this.onMoveEvent(func, { type: "token::Mutation" }, fetchConfig);
50
+ this.onMoveEvent(
51
+ func,
52
+ { ...(eventFilter ?? {}), type: "token::Mutation" },
53
+ fetchConfig,
54
+ );
50
55
  return this;
51
56
  }
52
57
 
53
58
  onEventMutationEvent(
54
59
  func: (event: token.MutationEventInstance, ctx: AptosContext) => void,
55
60
  fetchConfig?: Partial<MoveFetchConfig>,
61
+ eventFilter?: Omit<EventFilter, "type" | "account">,
56
62
  ): token {
57
- this.onMoveEvent(func, { type: "token::MutationEvent" }, fetchConfig);
63
+ this.onMoveEvent(
64
+ func,
65
+ { ...(eventFilter ?? {}), type: "token::MutationEvent" },
66
+ fetchConfig,
67
+ );
58
68
  return this;
59
69
  }
60
70
  }
@@ -436,16 +446,26 @@ export class collection extends AptosBaseProcessor {
436
446
  onEventBurn(
437
447
  func: (event: collection.BurnInstance, ctx: AptosContext) => void,
438
448
  fetchConfig?: Partial<MoveFetchConfig>,
449
+ eventFilter?: Omit<EventFilter, "type" | "account">,
439
450
  ): collection {
440
- this.onMoveEvent(func, { type: "collection::Burn" }, fetchConfig);
451
+ this.onMoveEvent(
452
+ func,
453
+ { ...(eventFilter ?? {}), type: "collection::Burn" },
454
+ fetchConfig,
455
+ );
441
456
  return this;
442
457
  }
443
458
 
444
459
  onEventBurnEvent(
445
460
  func: (event: collection.BurnEventInstance, ctx: AptosContext) => void,
446
461
  fetchConfig?: Partial<MoveFetchConfig>,
462
+ eventFilter?: Omit<EventFilter, "type" | "account">,
447
463
  ): collection {
448
- this.onMoveEvent(func, { type: "collection::BurnEvent" }, fetchConfig);
464
+ this.onMoveEvent(
465
+ func,
466
+ { ...(eventFilter ?? {}), type: "collection::BurnEvent" },
467
+ fetchConfig,
468
+ );
449
469
  return this;
450
470
  }
451
471
 
@@ -455,10 +475,11 @@ export class collection extends AptosBaseProcessor {
455
475
  ctx: AptosContext,
456
476
  ) => void,
457
477
  fetchConfig?: Partial<MoveFetchConfig>,
478
+ eventFilter?: Omit<EventFilter, "type" | "account">,
458
479
  ): collection {
459
480
  this.onMoveEvent(
460
481
  func,
461
- { type: "collection::ConcurrentBurnEvent" },
482
+ { ...(eventFilter ?? {}), type: "collection::ConcurrentBurnEvent" },
462
483
  fetchConfig,
463
484
  );
464
485
  return this;
@@ -470,10 +491,11 @@ export class collection extends AptosBaseProcessor {
470
491
  ctx: AptosContext,
471
492
  ) => void,
472
493
  fetchConfig?: Partial<MoveFetchConfig>,
494
+ eventFilter?: Omit<EventFilter, "type" | "account">,
473
495
  ): collection {
474
496
  this.onMoveEvent(
475
497
  func,
476
- { type: "collection::ConcurrentMintEvent" },
498
+ { ...(eventFilter ?? {}), type: "collection::ConcurrentMintEvent" },
477
499
  fetchConfig,
478
500
  );
479
501
  return this;
@@ -482,40 +504,65 @@ export class collection extends AptosBaseProcessor {
482
504
  onEventMint(
483
505
  func: (event: collection.MintInstance, ctx: AptosContext) => void,
484
506
  fetchConfig?: Partial<MoveFetchConfig>,
507
+ eventFilter?: Omit<EventFilter, "type" | "account">,
485
508
  ): collection {
486
- this.onMoveEvent(func, { type: "collection::Mint" }, fetchConfig);
509
+ this.onMoveEvent(
510
+ func,
511
+ { ...(eventFilter ?? {}), type: "collection::Mint" },
512
+ fetchConfig,
513
+ );
487
514
  return this;
488
515
  }
489
516
 
490
517
  onEventMintEvent(
491
518
  func: (event: collection.MintEventInstance, ctx: AptosContext) => void,
492
519
  fetchConfig?: Partial<MoveFetchConfig>,
520
+ eventFilter?: Omit<EventFilter, "type" | "account">,
493
521
  ): collection {
494
- this.onMoveEvent(func, { type: "collection::MintEvent" }, fetchConfig);
522
+ this.onMoveEvent(
523
+ func,
524
+ { ...(eventFilter ?? {}), type: "collection::MintEvent" },
525
+ fetchConfig,
526
+ );
495
527
  return this;
496
528
  }
497
529
 
498
530
  onEventMutation(
499
531
  func: (event: collection.MutationInstance, ctx: AptosContext) => void,
500
532
  fetchConfig?: Partial<MoveFetchConfig>,
533
+ eventFilter?: Omit<EventFilter, "type" | "account">,
501
534
  ): collection {
502
- this.onMoveEvent(func, { type: "collection::Mutation" }, fetchConfig);
535
+ this.onMoveEvent(
536
+ func,
537
+ { ...(eventFilter ?? {}), type: "collection::Mutation" },
538
+ fetchConfig,
539
+ );
503
540
  return this;
504
541
  }
505
542
 
506
543
  onEventMutationEvent(
507
544
  func: (event: collection.MutationEventInstance, ctx: AptosContext) => void,
508
545
  fetchConfig?: Partial<MoveFetchConfig>,
546
+ eventFilter?: Omit<EventFilter, "type" | "account">,
509
547
  ): collection {
510
- this.onMoveEvent(func, { type: "collection::MutationEvent" }, fetchConfig);
548
+ this.onMoveEvent(
549
+ func,
550
+ { ...(eventFilter ?? {}), type: "collection::MutationEvent" },
551
+ fetchConfig,
552
+ );
511
553
  return this;
512
554
  }
513
555
 
514
556
  onEventSetMaxSupply(
515
557
  func: (event: collection.SetMaxSupplyInstance, ctx: AptosContext) => void,
516
558
  fetchConfig?: Partial<MoveFetchConfig>,
559
+ eventFilter?: Omit<EventFilter, "type" | "account">,
517
560
  ): collection {
518
- this.onMoveEvent(func, { type: "collection::SetMaxSupply" }, fetchConfig);
561
+ this.onMoveEvent(
562
+ func,
563
+ { ...(eventFilter ?? {}), type: "collection::SetMaxSupply" },
564
+ fetchConfig,
565
+ );
519
566
  return this;
520
567
  }
521
568
  }
@@ -21,5 +21,5 @@ export default defineConfig({
21
21
  // dts: true,
22
22
  format: 'esm',
23
23
  keepNames: true,
24
- external: [...external, /^@sentio\/(chain|runtime).*$/]
24
+ external: [...external, /^@sentio\/(chain|runtime).*$/, /^piscina.*$/]
25
25
  })
@@ -1,7 +1,7 @@
1
1
  import { Labels } from './meter.js'
2
2
  import { BigDecimal } from './big-decimal.js'
3
3
  import { BN } from 'fuels'
4
- import { RichStruct, RichValue, RichValue_NullValue } from '@sentio/protos'
4
+ import { CoinID, RichStruct, RichValue, RichValue_NullValue, TokenAmount } from '@sentio/protos'
5
5
  import { toBigInteger, toBigDecimal } from './numberish.js'
6
6
 
7
7
  export const SENTIO_BIGINT_STRING_SUFFIX = ':sto_bi'
@@ -116,6 +116,9 @@ function normalizeToRichValue(value: any): RichValue {
116
116
  const v = BigInt(value)
117
117
  return { bigintValue: toBigInteger(v) }
118
118
  case 'number':
119
+ if (isNaN(value) || !isFinite(value)) {
120
+ throw new Error("can't submit NaN or Infinity value")
121
+ }
119
122
  if (Number.isInteger(value)) {
120
123
  return { intValue: value }
121
124
  }
@@ -138,6 +141,9 @@ function normalizeToRichValue(value: any): RichValue {
138
141
  }
139
142
  if (BN.isBN(value)) {
140
143
  const value1 = new BigDecimal(value.toString())
144
+ if (value1.isNaN() || !value1.isFinite()) {
145
+ throw new Error("can't submit NaN or Infinity value")
146
+ }
141
147
  return { bigdecimalValue: toBigDecimal(value1) }
142
148
  }
143
149
  if (Array.isArray(value)) {
@@ -152,13 +158,16 @@ function normalizeToRichValue(value: any): RichValue {
152
158
  return { nullValue: RichValue_NullValue.UNRECOGNIZED }
153
159
  }
154
160
  if (typeof value === 'object') {
161
+ const tokenAmount = toTokenAmount(value)
162
+ if (tokenAmount) {
163
+ return { tokenValue: tokenAmount }
164
+ }
165
+
155
166
  return {
156
167
  structValue: normalizeToRichStruct(value)
157
168
  }
158
169
  }
159
170
 
160
- // todo: support token value
161
-
162
171
  console.warn('Cannot submit unsupported type ' + typeof value)
163
172
  return { nullValue: RichValue_NullValue.UNRECOGNIZED }
164
173
  }
@@ -170,8 +179,64 @@ export function normalizeToRichStruct(...objs: any[]): RichStruct {
170
179
  }
171
180
  for (const obj of objs) {
172
181
  for (const [key, value] of Object.entries(obj)) {
173
- ret.fields[key] = normalizeToRichValue(value)
182
+ try {
183
+ ret.fields[key] = normalizeToRichValue(value)
184
+ } catch (e) {
185
+ throw new Error("error when converting data for key '" + key + "': " + e.message)
186
+ }
187
+ }
188
+ }
189
+ return ret
190
+ }
191
+
192
+ function toTokenAmount(value: any): TokenAmount | undefined {
193
+ const ret = TokenAmount.create()
194
+
195
+ for (const key of Object.getOwnPropertyNames(value)) {
196
+ switch (key) {
197
+ case 'token':
198
+ const token = toCoinID(value.token)
199
+ if (!token) {
200
+ return undefined
201
+ }
202
+ ret.token = token
203
+ break
204
+ case 'amount':
205
+ if (value.amount instanceof BigDecimal) {
206
+ ret.amount = toBigDecimal(value)
207
+ } else if (typeof value.amount == 'string' || typeof value.amount == 'number') {
208
+ ret.amount = toBigDecimal(new BigDecimal(value.amount))
209
+ } else {
210
+ return undefined
211
+ }
212
+ break
213
+ case 'specifiedAt':
214
+ if (value.specifiedAt instanceof Date) {
215
+ ret.specifiedAt = value.specifiedAt
216
+ } else {
217
+ return undefined
218
+ }
219
+ break
220
+ default:
221
+ return undefined
174
222
  }
175
223
  }
224
+
225
+ return ret.amount && ret.token ? ret : undefined
226
+ }
227
+
228
+ function toCoinID(coin: any): CoinID | undefined {
229
+ const ret = CoinID.create()
230
+ if (typeof coin.symbol === 'string') {
231
+ return (ret.symbol = coin.symbol)
232
+ } else if (coin.hasOwnProperty('address')) {
233
+ ret.address = {
234
+ address: coin.address.address,
235
+ chain: coin.address.chain
236
+ }
237
+ } else {
238
+ return undefined
239
+ }
240
+
176
241
  return ret
177
242
  }
@@ -0,0 +1,85 @@
1
+ import { Interface, LogDescription, LogParams, ParamType, Result } from 'ethers'
2
+ import { Piscina } from 'piscina'
3
+ import { ServerError, Status } from 'nice-grpc'
4
+
5
+ export interface IResult {
6
+ array?: any[]
7
+ keys: string[]
8
+ }
9
+
10
+ export function decodeTraceInline(contractViewInterface: any, inputs: readonly ParamType[], traceData: string): Result {
11
+ return contractViewInterface.getAbiCoder().decode(inputs, traceData, true)
12
+ }
13
+
14
+ export function decodeTrace({ inputs, traceData }: { inputs: ParamType[]; traceData: string }): IResult | null {
15
+ const fragments = Piscina['workerData']
16
+ const contractViewInterface = new Interface(fragments)
17
+ const result = decodeTraceInline(contractViewInterface, inputs, traceData)
18
+
19
+ const argsObj = result?.args.toObject(true)
20
+ const argsArray: any[] = []
21
+ const keys: string[] = []
22
+ for (const [key, value] of Object.entries(argsObj)) {
23
+ keys.push(key)
24
+ argsArray.push(value)
25
+ }
26
+
27
+ return {
28
+ array: argsArray,
29
+ keys: keys
30
+ }
31
+ }
32
+
33
+ export interface ILogDescription {
34
+ topic: string
35
+ args: {
36
+ array?: any[]
37
+ keys: string[]
38
+ } | null
39
+ }
40
+
41
+ export function parseLogInline(contractViewInterface: any, log: LogParams): LogDescription | null {
42
+ if (!log) {
43
+ throw new ServerError(Status.INVALID_ARGUMENT, 'Log is empty')
44
+ }
45
+ const logParam = log as any as { topics: Array<string>; data: string }
46
+ return contractViewInterface.parseLog(logParam)
47
+ }
48
+
49
+ export function parseLog({ log }: { log: LogParams }): ILogDescription | null {
50
+ const fragments = Piscina['workerData']
51
+ const contractViewInterface = new Interface(fragments)
52
+ const result = parseLogInline(contractViewInterface, log)
53
+ if (!result) {
54
+ return null
55
+ }
56
+
57
+ // can't serialize LogDescription, so return args and topics only
58
+ if (result?.args == null) {
59
+ return {
60
+ args: null,
61
+ topic: result.topic
62
+ }
63
+ }
64
+
65
+ const argsObj = result?.args.toObject(true)
66
+ const argsArray: any[] = []
67
+ const keys: string[] = []
68
+ for (const [key, value] of Object.entries(argsObj)) {
69
+ keys.push(key)
70
+ argsArray.push(value)
71
+ }
72
+
73
+ return {
74
+ args: {
75
+ array: argsArray,
76
+ keys: keys
77
+ },
78
+ topic: result.topic
79
+ }
80
+ }
81
+
82
+ export default {
83
+ parseLog,
84
+ decodeTrace
85
+ }
@@ -0,0 +1,133 @@
1
+ import { LogDescription, LogParams, Result, ParamType } from 'ethers'
2
+ import { GLOBAL_CONFIG, processMetrics } from '@sentio/runtime'
3
+ import { Piscina } from 'piscina'
4
+
5
+ import { decodeTraceInline, parseLogInline, IResult } from './decode-worker.js'
6
+
7
+ function createOptions() {
8
+ const options: any = {
9
+ filename: findWorkFile(),
10
+ recordTiming: true
11
+ }
12
+ if (GLOBAL_CONFIG.execution.ethAbiDecoderConfig?.workerCount) {
13
+ try {
14
+ const workerNum = GLOBAL_CONFIG.execution.ethAbiDecoderConfig?.workerCount
15
+ options.maxThreads = workerNum
16
+ options.minThreads = workerNum
17
+ } catch (e) {}
18
+ }
19
+ return options
20
+ }
21
+
22
+ function findWorkFile() {
23
+ let baseUrl = import.meta.url
24
+ // find the base from @sentio/sdk
25
+ const index = baseUrl.indexOf('/@sentio/sdk/')
26
+ if (index > 0) {
27
+ baseUrl = baseUrl.substring(0, index + 13)
28
+ } else {
29
+ // dev environment, path is .../packages/sdk/src/eth/abi-decoder/parse-log-worker.ts
30
+ const index = baseUrl.indexOf('packages/sdk/')
31
+ if (index > 0) {
32
+ baseUrl = baseUrl.substring(0, index + 13)
33
+ }
34
+ }
35
+ return new URL('./lib/eth/abi-decoder/decode-worker.js', baseUrl).href
36
+ }
37
+
38
+ export async function parseLog(processor: any, log: LogParams) {
39
+ if (GLOBAL_CONFIG.execution.ethAbiDecoderConfig?.enabled) {
40
+ let workerPool = processor._logWorkerPool as Piscina
41
+ const contractView = processor.CreateBoundContractView()
42
+ const contractViewInterface = contractView.rawContract.interface
43
+ if (!workerPool) {
44
+ const fragments = contractViewInterface.fragments
45
+ const options = createOptions()
46
+ options.workerData = fragments
47
+
48
+ workerPool = new Piscina(options)
49
+ processor._logWorkerPool = workerPool
50
+ }
51
+ try {
52
+ const result = (await workerPool.run({ log }, { name: 'parseLog' })) as any
53
+ if (result) {
54
+ const fragment = contractViewInterface.getEvent(result.topic)
55
+
56
+ if (!fragment || fragment.anonymous) {
57
+ return null
58
+ }
59
+ return new LogDescription(fragment, result.topic, Result.fromItems(result.args?.array ?? [], result.args?.keys))
60
+ }
61
+ } catch (e) {
62
+ const skipWhenDecodeFailed = GLOBAL_CONFIG.execution.ethAbiDecoderConfig?.skipWhenDecodeFailed
63
+ console.error(`parseLog worker failed, skip: ${!!skipWhenDecodeFailed}, the error is:`, e)
64
+ if (!skipWhenDecodeFailed) {
65
+ throw e
66
+ }
67
+ } finally {
68
+ if (workerPool.waitTime && workerPool.runTime) {
69
+ const labels = {
70
+ chain_id: processor.config?.network,
71
+ processor: processor.config?.name,
72
+ workerPool: 'parseLog'
73
+ }
74
+ processMetrics.processor_worker_wait_time.record(workerPool.waitTime.average, labels)
75
+ processMetrics.processor_worker_run_time.record(workerPool.runTime?.average, labels)
76
+ processMetrics.processor_worker_utilization.record(workerPool.utilization, labels)
77
+ processMetrics.processor_worker_queue_size.record(workerPool.queueSize, labels)
78
+ processMetrics.processor_worker_completed.record(workerPool.completed, labels)
79
+ }
80
+ }
81
+ return null
82
+ } else {
83
+ const contractView = processor.CreateBoundContractView()
84
+ const contractViewInterface = contractView.rawContract.interface
85
+ return parseLogInline(contractViewInterface, log)
86
+ }
87
+ }
88
+
89
+ export async function decodeTrace(processor: any, inputs: readonly ParamType[], traceData: string) {
90
+ if (GLOBAL_CONFIG.execution.ethAbiDecoderConfig?.enabled) {
91
+ let workerPool = processor._traceWorkerPool
92
+ if (!workerPool) {
93
+ const contractView = processor.CreateBoundContractView()
94
+ const contractViewInterface = contractView.rawContract.interface
95
+ const fragments = contractViewInterface.fragments
96
+ const options = createOptions()
97
+ options.workerData = fragments
98
+
99
+ workerPool = new Piscina(options)
100
+ processor._traceWorkerPool = workerPool
101
+ }
102
+ try {
103
+ const result = (await workerPool.run({ inputs, traceData }, { name: 'decodeTrace' })) as IResult
104
+ if (result) {
105
+ return Result.fromItems(result.array ?? [], result.keys)
106
+ }
107
+ } catch (e) {
108
+ const skipWhenDecodeFailed = GLOBAL_CONFIG.execution.ethAbiDecoderConfig?.skipWhenDecodeFailed
109
+ console.error(`decode trace worker failed, skip: ${!!skipWhenDecodeFailed}, the error is:`, e)
110
+ if (!skipWhenDecodeFailed) {
111
+ throw e
112
+ }
113
+ } finally {
114
+ if (workerPool.waitTime && workerPool.runTime) {
115
+ const labels = {
116
+ chain_id: processor.config?.network,
117
+ processor: processor.config?.name,
118
+ workerPool: 'parseLog'
119
+ }
120
+ processMetrics.processor_worker_wait_time.record(workerPool.waitTime.average, labels)
121
+ processMetrics.processor_worker_run_time.record(workerPool.runTime?.average, labels)
122
+ processMetrics.processor_worker_utilization.record(workerPool.utilization, labels)
123
+ processMetrics.processor_worker_queue_size.record(workerPool.queueSize, labels)
124
+ processMetrics.processor_worker_completed.record(workerPool.completed, labels)
125
+ }
126
+ }
127
+ return null
128
+ } else {
129
+ const contractView = processor.CreateBoundContractView()
130
+ const contractViewInterface = contractView.rawContract.interface
131
+ return decodeTraceInline(contractViewInterface, inputs, traceData)
132
+ }
133
+ }
@@ -22,6 +22,7 @@ import { ListStateStorage } from '@sentio/runtime'
22
22
  import { EthChainId } from '@sentio/chain'
23
23
  import { getHandlerName, proxyHandlers, proxyProcessor } from '../utils/metrics.js'
24
24
  import { ALL_ADDRESS } from '../core/index.js'
25
+ import { parseLog, decodeTrace } from './abi-decoder/index.js'
25
26
 
26
27
  export interface AddressOrTypeEventFilter extends DeferredTopicFilter {
27
28
  addressType?: AddressType
@@ -463,24 +464,9 @@ export abstract class BaseProcessor<
463
464
  contractView.address = log.address
464
465
  }
465
466
 
466
- const ctx = new ContractContext<TContract, TBoundContractView>(
467
- contractName,
468
- contractView,
469
- chainId,
470
- data.timestamp,
471
- block,
472
- log,
473
- undefined,
474
- transaction,
475
- transactionReceipt,
476
- processor.config.baseLabels,
477
- preparedData
478
- )
479
- const logParam = log as any as { topics: Array<string>; data: string }
480
-
481
467
  let parsed: LogDescription | null = null
482
468
  try {
483
- parsed = contractView.rawContract.interface.parseLog(logParam)
469
+ parsed = await parseLog(processor, log)
484
470
  } catch (e) {
485
471
  // RangeError data out-of-bounds
486
472
  if (e instanceof Error) {
@@ -492,6 +478,19 @@ export abstract class BaseProcessor<
492
478
  throw e
493
479
  }
494
480
  if (parsed) {
481
+ const ctx = new ContractContext<TContract, TBoundContractView>(
482
+ contractName,
483
+ contractView,
484
+ chainId,
485
+ data.timestamp,
486
+ block,
487
+ log,
488
+ undefined,
489
+ transaction,
490
+ transactionReceipt,
491
+ processor.config.baseLabels,
492
+ preparedData
493
+ )
495
494
  const event: TypedEvent = { ...log, name: parsed.name, args: fixEmptyKey(parsed) }
496
495
  await handler(event, ctx)
497
496
  return ctx.stopAndGetResult()
@@ -529,11 +528,10 @@ export abstract class BaseProcessor<
529
528
  transactionReceipt,
530
529
  processor.config.baseLabels
531
530
  )
532
- const logParam = log as any as { topics: Array<string>; data: string }
533
531
 
534
532
  let parsed: LogDescription | null = null
535
533
  try {
536
- parsed = contractView.rawContract.interface.parseLog(logParam)
534
+ parsed = await parseLog(processor, log)
537
535
  } catch (e) {
538
536
  // RangeError data out-of-bounds
539
537
  if (e instanceof Error) {
@@ -714,7 +712,8 @@ export abstract class BaseProcessor<
714
712
  }
715
713
  const traceData = '0x' + trace.action.input.slice(10)
716
714
  try {
717
- typedTrace.args = contractInterface.getAbiCoder().decode(fragment.inputs, traceData, true)
715
+ typedTrace.args = await decodeTrace(processor, fragment.inputs, traceData)
716
+ // typedTrace.args = contractInterface.getAbiCoder().decode(fragment.inputs, traceData, true)
718
717
  } catch (e) {
719
718
  if (!trace.error) {
720
719
  throw e
@@ -759,7 +758,7 @@ export abstract class BaseProcessor<
759
758
  }
760
759
  const traceData = '0x' + trace.action.input.slice(10)
761
760
  try {
762
- typedTrace.args = contractInterface.getAbiCoder().decode(fragment.inputs, traceData, true)
761
+ typedTrace.args = await decodeTrace(processor, fragment.inputs, traceData)
763
762
  } catch (e) {
764
763
  if (!trace.error) {
765
764
  throw e
@@ -11,6 +11,7 @@ import {
11
11
  export interface EventFilter {
12
12
  type: string
13
13
  account?: string
14
+ eventAccount?: string
14
15
  }
15
16
 
16
17
  export interface FunctionNameAndCallFilter extends CallFilter {
@@ -113,8 +113,8 @@ export abstract class SharedNetworkCodegen<NetworkType, ModuleTypes, StructType>
113
113
  const source = `
114
114
  onEvent${struct.name}(func: (event: ${moduleName}.${normalizeToJSName(struct.name)}Instance, ctx: ${
115
115
  this.PREFIX
116
- }Context) => void, fetchConfig?: Partial<MoveFetchConfig>): ${moduleName} {
117
- this.onMoveEvent(func, { type: '${module.name}::${struct.name}' }, fetchConfig)
116
+ }Context) => void, fetchConfig?: Partial<MoveFetchConfig>, eventFilter?: Omit<EventFilter, "type"|"account">): ${moduleName} {
117
+ this.onMoveEvent(func, {...eventFilter ?? {}, type: '${module.name}::${struct.name}' }, fetchConfig)
118
118
  return this
119
119
  }`
120
120
  return source
@@ -122,7 +122,7 @@ onEvent${struct.name}(func: (event: ${moduleName}.${normalizeToJSName(struct.nam
122
122
 
123
123
  generateImports() {
124
124
  return `
125
- import { CallFilter, MoveFetchConfig } from "@sentio/sdk/move"
125
+ import { CallFilter, MoveFetchConfig, EventFilter } from "@sentio/sdk/move"
126
126
  import {
127
127
  ${this.PREFIX}BindOptions, ${this.PREFIX}BaseProcessor,
128
128
  ${this.PREFIX}Network, TypedFunctionPayload,
@@ -106,7 +106,7 @@ async function codegenInternal(schema: GraphQLSchema, source: string, target: st
106
106
  const imports: Import[] = [
107
107
  {
108
108
  module: '@sentio/sdk/store',
109
- types: ['String', 'Int', 'BigInt', 'Float', 'ID', 'Bytes', 'Timestamp', 'Boolean'],
109
+ types: ['String', 'Int', 'BigInt', 'Float', 'ID', 'Bytes', 'Timestamp', 'Boolean', 'Int8'],
110
110
  importType: true
111
111
  },
112
112
  {
@@ -134,6 +134,22 @@ export const IntConverter: ValueConverter<Int | undefined> = {
134
134
  }
135
135
  }
136
136
 
137
+ export const Int8Converter: ValueConverter<bigint | undefined> = {
138
+ from: (value?: bigint) => {
139
+ if (value == null) {
140
+ return {
141
+ nullValue: RichValue_NullValue.NULL_VALUE
142
+ }
143
+ }
144
+ return {
145
+ int64Value: BigInt(value)
146
+ }
147
+ },
148
+ to(v) {
149
+ return v.int64Value
150
+ }
151
+ }
152
+
137
153
  export const FloatConverter: ValueConverter<Float | undefined> = {
138
154
  from: (value?: Float) => {
139
155
  if (value == null) {
@@ -291,6 +307,7 @@ export const TypeConverters: Record<string, ValueConverter<any>> = {
291
307
  ID: IDConverter,
292
308
  Bytes: BytesConverter,
293
309
  Int: IntConverter,
310
+ Int8: Int8Converter,
294
311
  Float: FloatConverter,
295
312
  Timestamp: TimestampConverter
296
313
  }
@@ -7,6 +7,7 @@ import {
7
7
  BytesConverter,
8
8
  FloatConverter,
9
9
  IDConverter,
10
+ Int8Converter,
10
11
  IntConverter,
11
12
  objectId_,
12
13
  required_,
@@ -161,6 +162,7 @@ export function column(type?: ValueConverter<any>) {
161
162
 
162
163
  export const IDColumn = column(IDConverter)
163
164
  export const IntColumn = column(IntConverter)
165
+ export const Int8Column = column(Int8Converter)
164
166
  export const FloatColumn = column(FloatConverter)
165
167
  export const BigDecimalColumn = column(BigDecimalConverter)
166
168
  export const BigIntColumn = column(BigIntConverter)
@@ -2,7 +2,7 @@ import { buildASTSchema, DocumentNode, extendSchema, GraphQLSchema, parse, valid
2
2
  import * as fs from 'node:fs'
3
3
  import { GraphQLObjectType, GraphQLOutputType, isListType, isNonNullType } from 'graphql'
4
4
 
5
- const customScalars = ['BigInt', 'BigDecimal', 'Timestamp', 'JSON', 'Bytes', 'ID']
5
+ const customScalars = ['BigInt', 'BigDecimal', 'Timestamp', 'JSON', 'Bytes', 'ID', 'Int8']
6
6
 
7
7
  const baseSchema = buildASTSchema(
8
8
  parse(`