@sentio/sdk 4.0.0-rc.2 → 4.0.0-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.
- package/lib/eth/context.d.ts.map +1 -1
- package/lib/eth/context.js +5 -1
- package/lib/eth/context.js.map +1 -1
- package/lib/eth/eth.d.ts.map +1 -1
- package/lib/eth/eth.js +17 -12
- package/lib/eth/eth.js.map +1 -1
- package/lib/testing/memory-database.d.ts +11 -3
- package/lib/testing/memory-database.d.ts.map +1 -1
- package/lib/testing/memory-database.js +9 -6
- package/lib/testing/memory-database.js.map +1 -1
- package/lib/testing/test-processor-server.d.ts +1446 -15
- package/lib/testing/test-processor-server.d.ts.map +1 -1
- package/lib/testing/test-processor-server.js +94 -33
- package/lib/testing/test-processor-server.js.map +1 -1
- package/package.json +3 -3
- package/src/eth/context.ts +11 -2
- package/src/eth/eth.ts +17 -12
- package/src/testing/memory-database.ts +25 -11
- package/src/testing/test-processor-server.ts +125 -41
|
@@ -2,30 +2,34 @@ import {
|
|
|
2
2
|
type AccountConfig,
|
|
3
3
|
type ContractConfig,
|
|
4
4
|
type DataBinding,
|
|
5
|
+
type DBResponse,
|
|
5
6
|
type Empty,
|
|
6
7
|
EmptySchema,
|
|
7
|
-
type PreprocessStreamRequest,
|
|
8
8
|
type ProcessBindingResponse,
|
|
9
9
|
ProcessBindingResponseSchema,
|
|
10
10
|
ProcessBindingsRequestSchema,
|
|
11
11
|
ProcessConfigRequestSchema,
|
|
12
12
|
type ProcessConfigResponse,
|
|
13
|
+
type ProcessResult,
|
|
13
14
|
type ProcessStreamRequest,
|
|
14
|
-
|
|
15
|
+
ProcessStreamRequestSchema,
|
|
16
|
+
ProcessStreamResponseV3Schema,
|
|
15
17
|
StartRequestSchema,
|
|
16
18
|
type TemplateInstance,
|
|
19
|
+
TemplateInstanceSchema,
|
|
17
20
|
type TimeseriesResult,
|
|
18
21
|
UpdateTemplatesRequestSchema
|
|
19
22
|
} from '@sentio/protos'
|
|
20
23
|
import { create, type MessageInitShape } from '@bufbuild/protobuf'
|
|
21
24
|
import { type HandlerContext } from '@connectrpc/connect'
|
|
22
25
|
import {
|
|
26
|
+
DataBindingContext,
|
|
23
27
|
Endpoints,
|
|
24
28
|
IDataBindingContext,
|
|
29
|
+
mergeProcessResults,
|
|
25
30
|
PluginManager,
|
|
26
|
-
ProcessorServiceImpl,
|
|
27
31
|
State,
|
|
28
|
-
|
|
32
|
+
ProcessorServiceImplV3
|
|
29
33
|
} from '@sentio/runtime'
|
|
30
34
|
|
|
31
35
|
import { AptosFacet } from './aptos-facet.js'
|
|
@@ -40,7 +44,7 @@ import { DatabaseSchemaState } from '../core/database-schema.js'
|
|
|
40
44
|
import { IotaFacet } from './iota-facet.js'
|
|
41
45
|
import { ChainInfo } from '@sentio/chain'
|
|
42
46
|
|
|
43
|
-
type
|
|
47
|
+
type ProcessStreamResponseV3Init = MessageInitShape<typeof ProcessStreamResponseV3Schema>
|
|
44
48
|
|
|
45
49
|
export const TEST_CONTEXT = {} as HandlerContext
|
|
46
50
|
|
|
@@ -52,10 +56,11 @@ export function cleanTest() {
|
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
export class TestProcessorServer {
|
|
55
|
-
service:
|
|
59
|
+
service: ProcessorServiceImplV3
|
|
56
60
|
contractConfigs: ContractConfig[]
|
|
57
61
|
accountConfigs: AccountConfig[]
|
|
58
62
|
storeContext: TestStoreContext
|
|
63
|
+
private nextProcessId = 1
|
|
59
64
|
|
|
60
65
|
aptos: AptosFacet
|
|
61
66
|
eth: EthFacet
|
|
@@ -69,7 +74,7 @@ export class TestProcessorServer {
|
|
|
69
74
|
constructor(loader: () => Promise<any>, httpEndpoints: Record<string, string> = {}) {
|
|
70
75
|
cleanTest()
|
|
71
76
|
|
|
72
|
-
this.service = new
|
|
77
|
+
this.service = new ProcessorServiceImplV3(loader)
|
|
73
78
|
this.aptos = new AptosFacet(this)
|
|
74
79
|
this.solana = new SolanaFacet(this)
|
|
75
80
|
this.eth = new EthFacet(this)
|
|
@@ -84,8 +89,8 @@ export class TestProcessorServer {
|
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
// start a memory database for testing
|
|
87
|
-
const subject = new Subject<
|
|
88
|
-
this.storeContext = new TestStoreContext(subject, 1)
|
|
92
|
+
const subject = new Subject<ProcessStreamResponseV3Init>()
|
|
93
|
+
this.storeContext = new TestStoreContext(subject, 1, this.service)
|
|
89
94
|
this._db = new MemoryDatabase(this.storeContext)
|
|
90
95
|
}
|
|
91
96
|
|
|
@@ -104,7 +109,8 @@ export class TestProcessorServer {
|
|
|
104
109
|
}
|
|
105
110
|
|
|
106
111
|
stop(request: Empty = create(EmptySchema), context = TEST_CONTEXT) {
|
|
107
|
-
|
|
112
|
+
this._db.stop()
|
|
113
|
+
return request
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
async getConfig(
|
|
@@ -121,43 +127,96 @@ export class TestProcessorServer {
|
|
|
121
127
|
context: HandlerContext = TEST_CONTEXT
|
|
122
128
|
): Promise<ProcessBindingResponse> {
|
|
123
129
|
const req = create(ProcessBindingsRequestSchema, request)
|
|
124
|
-
return
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
return this.processBindingList(req.bindings, context)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async processBinding(request: DataBinding, context: HandlerContext = TEST_CONTEXT): Promise<ProcessBindingResponse> {
|
|
134
|
+
return this.processBindingList([request], context)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private async processBindingList(
|
|
138
|
+
bindings: DataBinding[],
|
|
139
|
+
context: HandlerContext = TEST_CONTEXT
|
|
140
|
+
): Promise<ProcessBindingResponse> {
|
|
141
|
+
const results: ProcessResult[] = []
|
|
142
|
+
for (const binding of bindings) {
|
|
143
|
+
const result = await this.processBindingV3(binding, context)
|
|
144
|
+
results.push(result)
|
|
145
|
+
|
|
146
|
+
if (result.states?.configUpdated) {
|
|
128
147
|
await PluginManager.INSTANCE.updateTemplates(
|
|
129
148
|
create(UpdateTemplatesRequestSchema, {
|
|
130
|
-
chainId:
|
|
149
|
+
chainId: binding.chainId,
|
|
131
150
|
templateInstances: this.storeContext.templateInstances
|
|
132
151
|
})
|
|
133
152
|
)
|
|
134
153
|
}
|
|
135
|
-
|
|
154
|
+
}
|
|
155
|
+
return create(ProcessBindingResponseSchema, {
|
|
156
|
+
result: mergeProcessResults(results)
|
|
136
157
|
})
|
|
137
158
|
}
|
|
138
159
|
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
})
|
|
143
|
-
if (ret.result?.states?.configUpdated) {
|
|
144
|
-
// template may changed
|
|
145
|
-
await PluginManager.INSTANCE.updateTemplates(
|
|
146
|
-
create(UpdateTemplatesRequestSchema, {
|
|
147
|
-
chainId: request.chainId,
|
|
148
|
-
templateInstances: this.storeContext.templateInstances
|
|
149
|
-
})
|
|
150
|
-
)
|
|
151
|
-
}
|
|
152
|
-
return create(ProcessBindingResponseSchema, ret)
|
|
153
|
-
}
|
|
160
|
+
private processBindingV3(request: DataBinding, context: HandlerContext): Promise<ProcessResult> {
|
|
161
|
+
const processId = this.nextProcessId++
|
|
162
|
+
const subject = this.storeContext.subject
|
|
154
163
|
|
|
155
|
-
|
|
156
|
-
|
|
164
|
+
return new Promise((resolve, reject) => {
|
|
165
|
+
const subscription = subject.subscribe({
|
|
166
|
+
next: (response) => {
|
|
167
|
+
if (response.processId !== processId) {
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
if (response.value?.case === 'tplRequest') {
|
|
171
|
+
this.storeContext.applyTemplateRequest(
|
|
172
|
+
(response.value.value.templates ?? []).map((template) => create(TemplateInstanceSchema, template)),
|
|
173
|
+
response.value.value.remove ?? false
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
if (response.value?.case === 'result') {
|
|
177
|
+
subscription.unsubscribe()
|
|
178
|
+
// The service always emits a fully-formed ProcessResult message here; use it directly.
|
|
179
|
+
// Do NOT re-`create(ProcessResultSchema, ...)` — that re-validates every field and throws
|
|
180
|
+
// on results carrying loosely-typed values (e.g. a hex string in an int32 field), which
|
|
181
|
+
// the old unary processBindings path passed through untouched.
|
|
182
|
+
const result = response.value.value as ProcessResult
|
|
183
|
+
// The V3 service reports handler failures as a result with `states.error` set (via
|
|
184
|
+
// DataBindingContext.error) rather than erroring the stream. Surface it as a thrown
|
|
185
|
+
// error so tests observe the same behavior as the old unary processBindings path.
|
|
186
|
+
if (result.states?.error) {
|
|
187
|
+
reject(new Error(result.states.error))
|
|
188
|
+
} else {
|
|
189
|
+
resolve(result)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
error: (e) => {
|
|
194
|
+
subscription.unsubscribe()
|
|
195
|
+
reject(e)
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
this.service
|
|
200
|
+
.handleRequest(
|
|
201
|
+
create(ProcessStreamRequestSchema, {
|
|
202
|
+
processId,
|
|
203
|
+
value: {
|
|
204
|
+
case: 'binding',
|
|
205
|
+
value: request
|
|
206
|
+
}
|
|
207
|
+
}),
|
|
208
|
+
undefined,
|
|
209
|
+
subject
|
|
210
|
+
)
|
|
211
|
+
.catch((e) => {
|
|
212
|
+
subscription.unsubscribe()
|
|
213
|
+
reject(e)
|
|
214
|
+
})
|
|
215
|
+
})
|
|
157
216
|
}
|
|
158
217
|
|
|
159
|
-
|
|
160
|
-
|
|
218
|
+
processBindingsStream(requests: AsyncIterable<ProcessStreamRequest>, context: HandlerContext) {
|
|
219
|
+
return this.service.processBindingsStream(requests, context)
|
|
161
220
|
}
|
|
162
221
|
|
|
163
222
|
// processBindingsStream(request: AsyncIterable<ProcessStreamRequest>, context: HandlerContext) {
|
|
@@ -172,17 +231,37 @@ export class TestProcessorServer {
|
|
|
172
231
|
}
|
|
173
232
|
}
|
|
174
233
|
|
|
175
|
-
class TestStoreContext extends
|
|
234
|
+
class TestStoreContext extends DataBindingContext implements IDataBindingContext {
|
|
176
235
|
constructor(
|
|
177
|
-
|
|
178
|
-
processId: number
|
|
236
|
+
subject: Subject<ProcessStreamResponseV3Init>,
|
|
237
|
+
processId: number,
|
|
238
|
+
private readonly service: ProcessorServiceImplV3
|
|
179
239
|
) {
|
|
180
|
-
super(
|
|
240
|
+
super(processId, subject)
|
|
181
241
|
}
|
|
182
242
|
|
|
183
243
|
templateInstances: TemplateInstance[] = []
|
|
184
244
|
|
|
185
|
-
|
|
245
|
+
result(dbResult: DBResponse, processId = this.processId): void {
|
|
246
|
+
// Resolve a request issued directly from this context (e.g. `service.store.get(...)` in a test,
|
|
247
|
+
// which goes through the TestStoreContext rather than a per-binding context). opIds are globally
|
|
248
|
+
// unique, so this is a no-op when the request originated from the service's per-binding context.
|
|
249
|
+
super.result(dbResult)
|
|
250
|
+
// Forward to the service's per-binding context for requests issued while processing a binding.
|
|
251
|
+
void this.service.handleRequest(
|
|
252
|
+
create(ProcessStreamRequestSchema, {
|
|
253
|
+
processId,
|
|
254
|
+
value: {
|
|
255
|
+
case: 'dbResult',
|
|
256
|
+
value: dbResult
|
|
257
|
+
}
|
|
258
|
+
}),
|
|
259
|
+
undefined,
|
|
260
|
+
this.subject
|
|
261
|
+
)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
applyTemplateRequest(templates: Array<TemplateInstance>, remove: boolean): void {
|
|
186
265
|
if (remove) {
|
|
187
266
|
this.templateInstances = this.templateInstances.filter(
|
|
188
267
|
(i) => !templates.find((t) => t.templateId === i.templateId && t.contract?.address === i.contract?.address)
|
|
@@ -191,7 +270,12 @@ class TestStoreContext extends StoreContext implements IDataBindingContext {
|
|
|
191
270
|
this.templateInstances.push(...templates)
|
|
192
271
|
}
|
|
193
272
|
}
|
|
273
|
+
|
|
274
|
+
sendTemplateRequest(templates: Array<TemplateInstance>, remove: boolean): void {
|
|
275
|
+
this.applyTemplateRequest(templates, remove)
|
|
276
|
+
}
|
|
277
|
+
|
|
194
278
|
sendTimeseriesRequest(timeseries: Array<TimeseriesResult>): void {
|
|
195
|
-
|
|
279
|
+
// Test helpers currently expose metric/event/export results through ProcessResult.
|
|
196
280
|
}
|
|
197
281
|
}
|