@sentio/sdk 3.0.0-rc.8 → 3.0.0-rc.9

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 (74) hide show
  1. package/lib/aptos/aptos-plugin.js +1 -1
  2. package/lib/aptos/aptos-plugin.js.map +1 -1
  3. package/lib/aptos/aptos-resource-processor-template.d.ts +2 -1
  4. package/lib/aptos/aptos-resource-processor-template.d.ts.map +1 -1
  5. package/lib/aptos/aptos-resource-processor-template.js +28 -25
  6. package/lib/aptos/aptos-resource-processor-template.js.map +1 -1
  7. package/lib/core/base-context.d.ts +2 -1
  8. package/lib/core/base-context.d.ts.map +1 -1
  9. package/lib/core/base-context.js +6 -0
  10. package/lib/core/base-context.js.map +1 -1
  11. package/lib/core/core-plugin.d.ts.map +1 -1
  12. package/lib/core/core-plugin.js +0 -3
  13. package/lib/core/core-plugin.js.map +1 -1
  14. package/lib/cosmos/cosmos-plugin.d.ts +0 -1
  15. package/lib/cosmos/cosmos-plugin.d.ts.map +1 -1
  16. package/lib/cosmos/cosmos-plugin.js +0 -4
  17. package/lib/cosmos/cosmos-plugin.js.map +1 -1
  18. package/lib/eth/base-processor-template.d.ts +2 -1
  19. package/lib/eth/base-processor-template.d.ts.map +1 -1
  20. package/lib/eth/base-processor-template.js +26 -24
  21. package/lib/eth/base-processor-template.js.map +1 -1
  22. package/lib/eth/eth-plugin.d.ts +0 -1
  23. package/lib/eth/eth-plugin.d.ts.map +1 -1
  24. package/lib/eth/eth-plugin.js +1 -5
  25. package/lib/eth/eth-plugin.js.map +1 -1
  26. package/lib/fuel/fuel-plugin.d.ts +0 -1
  27. package/lib/fuel/fuel-plugin.d.ts.map +1 -1
  28. package/lib/fuel/fuel-plugin.js +0 -4
  29. package/lib/fuel/fuel-plugin.js.map +1 -1
  30. package/lib/fuel/fuel-processor-template.d.ts +2 -1
  31. package/lib/fuel/fuel-processor-template.d.ts.map +1 -1
  32. package/lib/fuel/fuel-processor-template.js +28 -23
  33. package/lib/fuel/fuel-processor-template.js.map +1 -1
  34. package/lib/iota/iota-object-processor-template.d.ts +2 -1
  35. package/lib/iota/iota-object-processor-template.d.ts.map +1 -1
  36. package/lib/iota/iota-object-processor-template.js +51 -39
  37. package/lib/iota/iota-object-processor-template.js.map +1 -1
  38. package/lib/iota/iota-plugin-part.js +1 -1
  39. package/lib/iota/iota-plugin-part.js.map +1 -1
  40. package/lib/stark/starknet-plugin.d.ts +0 -1
  41. package/lib/stark/starknet-plugin.d.ts.map +1 -1
  42. package/lib/stark/starknet-plugin.js +0 -4
  43. package/lib/stark/starknet-plugin.js.map +1 -1
  44. package/lib/sui/sui-object-processor-template.d.ts +2 -1
  45. package/lib/sui/sui-object-processor-template.d.ts.map +1 -1
  46. package/lib/sui/sui-object-processor-template.js +51 -39
  47. package/lib/sui/sui-object-processor-template.js.map +1 -1
  48. package/lib/sui/sui-plugin-part.js +1 -1
  49. package/lib/sui/sui-plugin-part.js.map +1 -1
  50. package/lib/testing/test-processor-server.d.ts +12 -3
  51. package/lib/testing/test-processor-server.d.ts.map +1 -1
  52. package/lib/testing/test-processor-server.js +47 -7
  53. package/lib/testing/test-processor-server.js.map +1 -1
  54. package/package.json +3 -3
  55. package/src/aptos/aptos-plugin.ts +1 -1
  56. package/src/aptos/aptos-resource-processor-template.ts +36 -30
  57. package/src/core/base-context.ts +8 -1
  58. package/src/core/core-plugin.ts +0 -4
  59. package/src/cosmos/cosmos-plugin.ts +0 -5
  60. package/src/eth/base-processor-template.ts +32 -27
  61. package/src/eth/eth-plugin.ts +1 -6
  62. package/src/fuel/fuel-plugin.ts +0 -5
  63. package/src/fuel/fuel-processor-template.ts +34 -26
  64. package/src/iota/iota-object-processor-template.ts +61 -46
  65. package/src/iota/iota-plugin-part.ts +1 -1
  66. package/src/stark/starknet-plugin.ts +0 -5
  67. package/src/sui/sui-object-processor-template.ts +63 -47
  68. package/src/sui/sui-plugin-part.ts +1 -1
  69. package/src/testing/test-processor-server.ts +64 -10
  70. package/lib/core/template.d.ts +0 -2
  71. package/lib/core/template.d.ts.map +0 -1
  72. package/lib/core/template.js +0 -2
  73. package/lib/core/template.js.map +0 -1
  74. package/src/core/template.ts +0 -1
@@ -8,7 +8,6 @@ import { ListStateStorage, processMetrics } from '@sentio/runtime'
8
8
  import { BlockParams } from 'ethers/providers'
9
9
  import { DeferredTopicFilter } from 'ethers/contract'
10
10
  import { TypedEvent, TypedCallTrace, validateAndNormalizeAddress } from './eth.js'
11
- import { TemplateInstanceState } from '../core/template.js'
12
11
  import { getHandlerName, proxyProcessor } from '../utils/metrics.js'
13
12
 
14
13
  export class ProcessorTemplateProcessorState extends ListStateStorage<
@@ -22,7 +21,6 @@ export abstract class BaseProcessorTemplate<
22
21
  TBoundContractView extends BoundContractView<TContract, ContractView<TContract>>
23
22
  > {
24
23
  id: number
25
- binds = new Set<string>()
26
24
  blockHandlers: {
27
25
  handlerName: string
28
26
  handler: (block: BlockParams, ctx: ContractContext<TContract, TBoundContractView>) => PromiseOrVoid
@@ -58,6 +56,8 @@ export abstract class BaseProcessorTemplate<
58
56
  fetchConfig?: EthFetchConfig
59
57
  }[] = []
60
58
 
59
+ instances = new Set<string>()
60
+
61
61
  constructor() {
62
62
  this.id = ProcessorTemplateProcessorState.INSTANCE.getValues().length
63
63
  ProcessorTemplateProcessorState.INSTANCE.addValue(this)
@@ -72,18 +72,43 @@ export abstract class BaseProcessorTemplate<
72
72
  public bind(options: Omit<BindOptions, 'network'>, ctx: EthContext): void {
73
73
  options = { ...options, address: validateAndNormalizeAddress(options.address) }
74
74
 
75
+ const instance: TemplateInstance = {
76
+ templateId: this.id,
77
+ contract: {
78
+ address: options.address,
79
+ name: options.name || '',
80
+ chainId: ctx.chainId,
81
+ abi: ''
82
+ },
83
+ startBlock: BigInt(options.startBlock || 0),
84
+ endBlock: BigInt(options.endBlock || 0),
85
+ baseLabels: options.baseLabels
86
+ }
87
+
88
+ ctx.sendTemplateInstance(instance)
89
+
90
+ ctx.update({
91
+ states: {
92
+ configUpdated: true
93
+ }
94
+ })
95
+
96
+ processMetrics.processor_template_instance_count.add(1, { chain_id: ctx.chainId, template: this.constructor.name })
97
+ }
98
+
99
+ public startInstance(options: Omit<BindOptions, 'network'>, ctx: EthContext) {
100
+ options = { ...options, address: validateAndNormalizeAddress(options.address) }
75
101
  const sig = getOptionsSignature({
76
102
  address: options.address,
77
103
  network: ctx.chainId
78
104
  })
79
- if (this.binds.has(sig)) {
80
- console.log(`Same address can be bind to one template only once, ignore duplicate bind: ${sig}`)
105
+
106
+ if (this.instances.has(sig)) {
107
+ console.debug(`Same address can be bind to one template only once, ignore duplicate bind: ${sig}`)
81
108
  return
82
109
  }
83
- this.binds.add(sig)
84
110
 
85
111
  const processor = this.bindInternal({ ...options, network: ctx.chainId })
86
-
87
112
  for (const eh of this.eventHandlers) {
88
113
  // @ts-ignore friendly
89
114
  processor.onEthEvent(eh.handler, eh.filter, eh.fetchConfig, eh.preprocessHandler, eh.handlerName)
@@ -102,27 +127,7 @@ export abstract class BaseProcessorTemplate<
102
127
  bh.handlerName
103
128
  )
104
129
  }
105
-
106
- const instance: TemplateInstance = {
107
- templateId: this.id,
108
- contract: {
109
- address: options.address,
110
- name: options.name || '',
111
- chainId: ctx.chainId,
112
- abi: ''
113
- },
114
- startBlock: BigInt(options.startBlock || 0),
115
- endBlock: BigInt(options.endBlock || 0),
116
- baseLabels: options.baseLabels
117
- }
118
- TemplateInstanceState.INSTANCE.addValue(instance)
119
- ctx.update({
120
- states: {
121
- configUpdated: true
122
- }
123
- })
124
-
125
- processMetrics.processor_template_instance_count.add(1, { chain_id: ctx.chainId, template: this.constructor.name })
130
+ this.instances.add(sig)
126
131
  }
127
132
 
128
133
  protected onEthEvent(
@@ -32,7 +32,6 @@ import { GlobalProcessorState } from './base-processor.js'
32
32
  import { validateAndNormalizeAddress } from './eth.js'
33
33
  import { EthChainId } from '@sentio/chain'
34
34
  import { EthContext } from './context.js'
35
- import { TemplateInstanceState } from '../core/template.js'
36
35
  import { timeOrBlockToBlockNumber } from '@sentio/sdk/utils'
37
36
  import { HandlerRegister } from '../core/handler-register.js'
38
37
 
@@ -399,7 +398,7 @@ export class EthPlugin extends Plugin {
399
398
  throw new ServerError(Status.INVALID_ARGUMENT, 'Contract Empty from:' + instance)
400
399
  }
401
400
  const ctx = new NoopContext(instance.contract.chainId as EthChainId)
402
- template.bind(
401
+ template.startInstance(
403
402
  {
404
403
  name: instance.contract.name,
405
404
  address: validateAndNormalizeAddress(instance.contract.address),
@@ -412,10 +411,6 @@ export class EthPlugin extends Plugin {
412
411
  }
413
412
  }
414
413
 
415
- stateDiff(config: ProcessConfigResponse): boolean {
416
- return TemplateInstanceState.INSTANCE.getValues().length !== config.templateInstances.length
417
- }
418
-
419
414
  async processLog(request: DataBinding, preparedData: PreparedData | undefined): Promise<ProcessResult> {
420
415
  if (!request.data?.ethLog?.log) {
421
416
  throw new ServerError(Status.INVALID_ARGUMENT, "Log can't be null")
@@ -13,7 +13,6 @@ import {
13
13
  } from '@sentio/protos'
14
14
 
15
15
  import { ServerError, Status } from 'nice-grpc'
16
- import { TemplateInstanceState } from '../core/template.js'
17
16
  import { FuelAssetProcessor } from './asset-processor.js'
18
17
  import { FuelProcessorState } from './types.js'
19
18
  import { FuelProcessor } from './fuel-processor.js'
@@ -191,10 +190,6 @@ export class FuelPlugin extends Plugin {
191
190
  }
192
191
  }
193
192
 
194
- stateDiff(config: ProcessConfigResponse): boolean {
195
- return TemplateInstanceState.INSTANCE.getValues().length !== config.templateInstances.length
196
- }
197
-
198
193
  async processReceipt(binding: DataBinding): Promise<ProcessResult> {
199
194
  const receipt = binding?.data?.fuelLog
200
195
 
@@ -1,8 +1,7 @@
1
1
  import { FuelContext, FuelContractContext } from './context.js'
2
2
  import { HandleInterval, TemplateInstance } from '@sentio/protos'
3
3
  import { PromiseOrVoid } from '../core/promises.js'
4
- import { ListStateStorage } from '@sentio/runtime'
5
- import { TemplateInstanceState } from '../core/template.js'
4
+ import { ListStateStorage, processMetrics } from '@sentio/runtime'
6
5
  import { Contract } from 'fuels'
7
6
  import { FuelBlock, FuelLog, FuelTransaction } from './types.js'
8
7
  import { DEFAULT_FUEL_FETCH_CONFIG, FuelFetchConfig } from './transaction.js'
@@ -16,7 +15,7 @@ export class FuelProcessorTemplateProcessorState extends ListStateStorage<FuelBa
16
15
 
17
16
  export abstract class FuelBaseProcessorTemplate<TContract extends Contract> {
18
17
  id: number
19
- binds = new Set<string>()
18
+ instances = new Set<string>()
20
19
  blockHandlers: {
21
20
  handlerName: string
22
21
  handler: (block: FuelBlock, ctx: FuelContractContext<TContract>) => PromiseOrVoid
@@ -52,28 +51,6 @@ export abstract class FuelBaseProcessorTemplate<TContract extends Contract> {
52
51
  * @param ctx
53
52
  */
54
53
  public bind(options: Omit<Omit<FuelProcessorConfig, 'chainId'>, 'abi'>, ctx: FuelContext): void {
55
- const sig = getOptionsSignature({
56
- address: options.address,
57
- chainId: ctx.chainId
58
- })
59
- if (this.binds.has(sig)) {
60
- console.log(`Same address can be bind to one template only once, ignore duplicate bind: ${sig}`)
61
- return
62
- }
63
- this.binds.add(sig)
64
-
65
- const processor = this.bindInternal({ ...options, chainId: ctx.chainId })
66
-
67
- for (const eh of this.logHandlers) {
68
- processor.onLog(eh.logIdFilter, eh.handler, eh.handlerOptions, eh.handlerName)
69
- }
70
- for (const bh of this.blockHandlers) {
71
- processor.onInterval(bh.handler, bh.timeIntervalInMinutes, bh.blockInterval, bh.handlerOptions, bh.handlerName)
72
- }
73
- for (const th of this.transactionHandlers) {
74
- processor.onTransaction(th.handler, th.handlerOptions, th.handlerName)
75
- }
76
-
77
54
  const instance: TemplateInstance = {
78
55
  templateId: this.id,
79
56
  contract: {
@@ -87,12 +64,43 @@ export abstract class FuelBaseProcessorTemplate<TContract extends Contract> {
87
64
  baseLabels: {}
88
65
  // baseLabels: options.baseLabels
89
66
  }
90
- TemplateInstanceState.INSTANCE.addValue(instance)
67
+
68
+ ctx.sendTemplateInstance(instance)
69
+
91
70
  ctx.update({
92
71
  states: {
93
72
  configUpdated: true
94
73
  }
95
74
  })
75
+
76
+ processMetrics.processor_template_instance_count.add(1, {
77
+ chain_id: ctx.chainId,
78
+ template: this.constructor.name
79
+ })
80
+ }
81
+
82
+ public startInstance(options: Omit<Omit<FuelProcessorConfig, 'chainId'>, 'abi'>, ctx: FuelContext): void {
83
+ const sig = getOptionsSignature({
84
+ address: options.address,
85
+ chainId: ctx.chainId
86
+ })
87
+ if (this.instances.has(sig)) {
88
+ console.debug(`Same address can be bind to one template only once, ignore duplicate bind: ${sig}`)
89
+ return
90
+ }
91
+ this.instances.add(sig)
92
+
93
+ const processor = this.bindInternal({ ...options, chainId: ctx.chainId })
94
+
95
+ for (const eh of this.logHandlers) {
96
+ processor.onLog(eh.logIdFilter, eh.handler, eh.handlerOptions, eh.handlerName)
97
+ }
98
+ for (const bh of this.blockHandlers) {
99
+ processor.onInterval(bh.handler, bh.timeIntervalInMinutes, bh.blockInterval, bh.handlerOptions, bh.handlerName)
100
+ }
101
+ for (const th of this.transactionHandlers) {
102
+ processor.onTransaction(th.handler, th.handlerOptions, th.handlerName)
103
+ }
96
104
  }
97
105
 
98
106
  protected onLog<T>(
@@ -1,5 +1,5 @@
1
- import { HandleInterval, MoveAccountFetchConfig, MoveFetchConfig } from '@sentio/protos'
2
- import { ListStateStorage } from '@sentio/runtime'
1
+ import { HandleInterval, MoveAccountFetchConfig, MoveFetchConfig, TemplateInstance } from '@sentio/protos'
2
+ import { ListStateStorage, processMetrics } from '@sentio/runtime'
3
3
  import { IotaAddressContext, IotaContext, IotaObjectContext } from './context.js'
4
4
  import { IotaMoveObject, IotaTransactionBlockResponse } from '@iota/iota-sdk/client'
5
5
  import { PromiseOrVoid } from '../core/index.js'
@@ -12,7 +12,6 @@ import {
12
12
  IotaObjectProcessor,
13
13
  IotaWrappedObjectProcessor
14
14
  } from './iota-object-processor.js'
15
- import { TemplateInstanceState } from '../core/template.js'
16
15
  import { IotaBindOptions } from './iota-processor.js'
17
16
  import { TransactionFilter, accountAddressString } from '../move/index.js'
18
17
  import { ServerError, Status } from 'nice-grpc'
@@ -40,7 +39,7 @@ export abstract class IotaObjectOrAddressProcessorTemplate<
40
39
  > {
41
40
  id: number
42
41
  objectHandlers: ObjectHandler<HandlerType>[] = []
43
- binds = new Set<string>()
42
+ instances = new Set<string>()
44
43
 
45
44
  constructor() {
46
45
  this.id = IotaAccountProcessorTemplateState.INSTANCE.getValues().length
@@ -60,12 +59,49 @@ export abstract class IotaObjectOrAddressProcessorTemplate<
60
59
  }
61
60
  id = accountAddressString(id)
62
61
 
62
+ const instance: TemplateInstance = {
63
+ templateId: this.id,
64
+ contract: {
65
+ name: '',
66
+ chainId: options.network,
67
+ address: id,
68
+ abi: ''
69
+ },
70
+ startBlock: options.startCheckpoint || 0n,
71
+ endBlock: options.endCheckpoint || 0n,
72
+ baseLabels: options.baseLabels
73
+ }
74
+
75
+ ctx.sendTemplateInstance(instance)
76
+
77
+ ctx.update({
78
+ states: {
79
+ configUpdated: true
80
+ }
81
+ })
82
+
83
+ processMetrics.processor_template_instance_count.add(1, {
84
+ chain_id: options.network,
85
+ template: this.constructor.name
86
+ })
87
+ }
88
+
89
+ startInstance(options: OptionType, ctx: IotaContext): void {
90
+ options.network = options.network || ctx.network
91
+ options.startCheckpoint = options.startCheckpoint || ctx.checkpoint
92
+ let id = (options as IotaObjectBindOptions).objectId || (options as IotaBindOptions).address
93
+
94
+ if (id === '*') {
95
+ throw new ServerError(Status.INVALID_ARGUMENT, "can't bind template instance with *")
96
+ }
97
+ id = accountAddressString(id)
98
+
63
99
  const sig = [options.network, id].join('_')
64
- if (this.binds.has(sig)) {
65
- console.log(`Same object id can be bind to one template only once, ignore duplicate bind: ${sig}`)
100
+ if (this.instances.has(sig)) {
101
+ console.debug(`Same object id can be bind to one template only once, ignore duplicate bind: ${sig}`)
66
102
  return
67
103
  }
68
- this.binds.add(sig)
104
+ this.instances.add(sig)
69
105
 
70
106
  const processor = this.createProcessor(options)
71
107
  for (const h of this.objectHandlers) {
@@ -78,25 +114,6 @@ export abstract class IotaObjectOrAddressProcessorTemplate<
78
114
  h.handlerName
79
115
  )
80
116
  }
81
- const config = processor.config
82
-
83
- ctx.update({
84
- states: {
85
- configUpdated: true
86
- }
87
- })
88
- TemplateInstanceState.INSTANCE.addValue({
89
- templateId: this.id,
90
- contract: {
91
- name: '',
92
- chainId: config.network,
93
- address: config.address,
94
- abi: ''
95
- },
96
- startBlock: config.startCheckpoint,
97
- endBlock: config.endCheckpoint || 0n,
98
- baseLabels: config.baseLabels
99
- })
100
117
  console.log(`successfully bind template ${sig}`)
101
118
  }
102
119
 
@@ -111,31 +128,14 @@ export abstract class IotaObjectOrAddressProcessorTemplate<
111
128
  id = accountAddressString(id)
112
129
 
113
130
  const sig = [options.network, id].join('_')
114
- if (!this.binds.has(sig)) {
131
+ if (!this.instances.has(sig)) {
115
132
  console.log(`the template instance ${sig} not existed or already unbind`)
116
133
  return
117
134
  }
118
- this.binds.delete(sig)
119
-
120
- let deleted = 0
121
- const oldTemplateInstances = TemplateInstanceState.INSTANCE.unregister()
122
- for (const templateInstance of oldTemplateInstances) {
123
- if (templateInstance.contract?.chainId === options.network && templateInstance.contract.address == id) {
124
- deleted++
125
- continue
126
- }
127
- TemplateInstanceState.INSTANCE.addValue(templateInstance)
128
- }
129
-
130
- if (deleted !== 1) {
131
- throw new ServerError(
132
- Status.INVALID_ARGUMENT,
133
- `Failed to delete template instance ${sig}, deleted ${deleted} times`
134
- )
135
- }
135
+ this.instances.delete(sig)
136
136
 
137
137
  const oldProcessors = IotaAccountProcessorState.INSTANCE.unregister()
138
- deleted = 0
138
+ let deleted = 0
139
139
  for (const processor of oldProcessors) {
140
140
  if (processor.templateId === this.id) {
141
141
  if (processor.config.network == options.network && processor.config.address === id) {
@@ -160,6 +160,21 @@ export abstract class IotaObjectOrAddressProcessorTemplate<
160
160
  configUpdated: true
161
161
  }
162
162
  })
163
+ ctx.sendTemplateInstance(
164
+ {
165
+ templateId: this.id,
166
+ contract: {
167
+ name: '',
168
+ chainId: options.network,
169
+ address: id,
170
+ abi: ''
171
+ },
172
+ startBlock: options.startCheckpoint || 0n,
173
+ endBlock: options.endCheckpoint || 0n,
174
+ baseLabels: options.baseLabels
175
+ },
176
+ true
177
+ )
163
178
  }
164
179
 
165
180
  protected onInterval(
@@ -45,7 +45,7 @@ export class IotaPluginPart {
45
45
  const template: IotaObjectOrAddressProcessorTemplate<any, any, any> =
46
46
  IotaAccountProcessorTemplateState.INSTANCE.getValues()[instance.templateId]
47
47
 
48
- template.bind(
48
+ template.startInstance(
49
49
  {
50
50
  address: instance.contract?.address || '',
51
51
  objectId: instance.contract?.address || '',
@@ -10,7 +10,6 @@ import {
10
10
  } from '@sentio/protos'
11
11
 
12
12
  import { ServerError, Status } from 'nice-grpc'
13
- import { TemplateInstanceState } from '../core/template.js'
14
13
  import { HandlerRegister } from '../core/handler-register.js'
15
14
  import { StarknetProcessorState } from './starknet-processor.js'
16
15
  import { hash } from 'starknet'
@@ -79,10 +78,6 @@ export class StarknetPlugin extends Plugin {
79
78
 
80
79
  async start(request: StartRequest) {}
81
80
 
82
- stateDiff(config: ProcessConfigResponse): boolean {
83
- return TemplateInstanceState.INSTANCE.getValues().length !== config.templateInstances.length
84
- }
85
-
86
81
  async processEvent(binding: DataBinding): Promise<ProcessResult> {
87
82
  if (!binding.data?.starknetEvents?.result) {
88
83
  throw new ServerError(Status.INVALID_ARGUMENT, "starknetEvents can't be null")
@@ -1,5 +1,5 @@
1
- import { HandleInterval, MoveAccountFetchConfig, MoveFetchConfig } from '@sentio/protos'
2
- import { ListStateStorage } from '@sentio/runtime'
1
+ import { HandleInterval, MoveAccountFetchConfig, MoveFetchConfig, TemplateInstance } from '@sentio/protos'
2
+ import { ListStateStorage, processMetrics } from '@sentio/runtime'
3
3
  import { SuiAddressContext, SuiContext, SuiObjectContext } from './context.js'
4
4
  import { SuiMoveObject, SuiTransactionBlockResponse } from '@mysten/sui/client'
5
5
  import { PromiseOrVoid } from '../core/index.js'
@@ -12,9 +12,8 @@ import {
12
12
  SuiObjectProcessor,
13
13
  SuiWrappedObjectProcessor
14
14
  } from './sui-object-processor.js'
15
- import { TemplateInstanceState } from '../core/template.js'
16
15
  import { SuiBindOptions } from './sui-processor.js'
17
- import { TransactionFilter, accountAddressString } from '../move/index.js'
16
+ import { accountAddressString, TransactionFilter } from '../move/index.js'
18
17
  import { ServerError, Status } from 'nice-grpc'
19
18
  import { getHandlerName, proxyProcessor } from '../utils/metrics.js'
20
19
 
@@ -40,7 +39,7 @@ export abstract class SuiObjectOrAddressProcessorTemplate<
40
39
  > {
41
40
  id: number
42
41
  objectHandlers: ObjectHandler<HandlerType>[] = []
43
- binds = new Set<string>()
42
+ instances = new Set<string>()
44
43
 
45
44
  constructor() {
46
45
  this.id = SuiAccountProcessorTemplateState.INSTANCE.getValues().length
@@ -60,12 +59,49 @@ export abstract class SuiObjectOrAddressProcessorTemplate<
60
59
  }
61
60
  id = accountAddressString(id)
62
61
 
62
+ const instance: TemplateInstance = {
63
+ templateId: this.id,
64
+ contract: {
65
+ name: '',
66
+ chainId: options.network,
67
+ address: id,
68
+ abi: ''
69
+ },
70
+ startBlock: options.startCheckpoint || 0n,
71
+ endBlock: options.endCheckpoint || 0n,
72
+ baseLabels: options.baseLabels
73
+ }
74
+
75
+ ctx.sendTemplateInstance(instance)
76
+
77
+ ctx.update({
78
+ states: {
79
+ configUpdated: true
80
+ }
81
+ })
82
+
83
+ processMetrics.processor_template_instance_count.add(1, {
84
+ chain_id: options.network,
85
+ template: this.constructor.name
86
+ })
87
+ }
88
+
89
+ startInstance(options: OptionType, ctx: SuiContext): void {
90
+ options.network = options.network || ctx.network
91
+ options.startCheckpoint = options.startCheckpoint || ctx.checkpoint
92
+ let id = (options as SuiObjectBindOptions).objectId || (options as SuiBindOptions).address
93
+
94
+ if (id === '*') {
95
+ throw new ServerError(Status.INVALID_ARGUMENT, "can't bind template instance with *")
96
+ }
97
+ id = accountAddressString(id)
98
+
63
99
  const sig = [options.network, id].join('_')
64
- if (this.binds.has(sig)) {
65
- console.log(`Same object id can be bind to one template only once, ignore duplicate bind: ${sig}`)
100
+ if (this.instances.has(sig)) {
101
+ console.debug(`Same object id can be bind to one template only once, ignore duplicate bind: ${sig}`)
66
102
  return
67
103
  }
68
- this.binds.add(sig)
104
+ this.instances.add(sig)
69
105
 
70
106
  const processor = this.createProcessor(options)
71
107
  for (const h of this.objectHandlers) {
@@ -78,25 +114,6 @@ export abstract class SuiObjectOrAddressProcessorTemplate<
78
114
  h.handlerName
79
115
  )
80
116
  }
81
- const config = processor.config
82
-
83
- ctx.update({
84
- states: {
85
- configUpdated: true
86
- }
87
- })
88
- TemplateInstanceState.INSTANCE.addValue({
89
- templateId: this.id,
90
- contract: {
91
- name: '',
92
- chainId: config.network,
93
- address: config.address,
94
- abi: ''
95
- },
96
- startBlock: config.startCheckpoint,
97
- endBlock: config.endCheckpoint || 0n,
98
- baseLabels: config.baseLabels
99
- })
100
117
  console.log(`successfully bind template ${sig}`)
101
118
  }
102
119
 
@@ -111,31 +128,14 @@ export abstract class SuiObjectOrAddressProcessorTemplate<
111
128
  id = accountAddressString(id)
112
129
 
113
130
  const sig = [options.network, id].join('_')
114
- if (!this.binds.has(sig)) {
131
+ if (!this.instances.has(sig)) {
115
132
  console.log(`the template instance ${sig} not existed or already unbind`)
116
133
  return
117
134
  }
118
- this.binds.delete(sig)
119
-
120
- let deleted = 0
121
- const oldTemplateInstances = TemplateInstanceState.INSTANCE.unregister()
122
- for (const templateInstance of oldTemplateInstances) {
123
- if (templateInstance.contract?.chainId === options.network && templateInstance.contract.address == id) {
124
- deleted++
125
- continue
126
- }
127
- TemplateInstanceState.INSTANCE.addValue(templateInstance)
128
- }
129
-
130
- if (deleted !== 1) {
131
- throw new ServerError(
132
- Status.INVALID_ARGUMENT,
133
- `Failed to delete template instance ${sig}, deleted ${deleted} times`
134
- )
135
- }
135
+ this.instances.delete(sig)
136
136
 
137
137
  const oldProcessors = SuiAccountProcessorState.INSTANCE.unregister()
138
- deleted = 0
138
+ let deleted = 0
139
139
  for (const processor of oldProcessors) {
140
140
  if (processor.templateId === this.id) {
141
141
  if (processor.config.network == options.network && processor.config.address === id) {
@@ -160,6 +160,22 @@ export abstract class SuiObjectOrAddressProcessorTemplate<
160
160
  configUpdated: true
161
161
  }
162
162
  })
163
+
164
+ ctx.sendTemplateInstance(
165
+ {
166
+ templateId: this.id,
167
+ contract: {
168
+ name: '',
169
+ chainId: options.network,
170
+ address: id,
171
+ abi: ''
172
+ },
173
+ startBlock: options.startCheckpoint || 0n,
174
+ endBlock: options.endCheckpoint || 0n,
175
+ baseLabels: options.baseLabels
176
+ },
177
+ true
178
+ )
163
179
  }
164
180
 
165
181
  protected onInterval(
@@ -45,7 +45,7 @@ export class SuiPluginPart {
45
45
  const template: SuiObjectOrAddressProcessorTemplate<any, any, any> =
46
46
  SuiAccountProcessorTemplateState.INSTANCE.getValues()[instance.templateId]
47
47
 
48
- template.bind(
48
+ template.startInstance(
49
49
  {
50
50
  address: instance.contract?.address || '',
51
51
  objectId: instance.contract?.address || '',