@sentio/sdk 1.36.3-rc.1 → 1.36.4-rc.1
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/LICENSE +55 -0
- package/lib/aptos/aptos-plugin.d.ts +14 -0
- package/lib/aptos/aptos-plugin.js +190 -0
- package/lib/aptos/aptos-plugin.js.map +1 -0
- package/lib/aptos/index.d.ts +1 -0
- package/lib/aptos/index.js +3 -1
- package/lib/aptos/index.js.map +1 -1
- package/lib/core/eth-plugin.d.ts +14 -0
- package/lib/core/eth-plugin.js +221 -0
- package/lib/core/eth-plugin.js.map +1 -0
- package/lib/core/index.d.ts +3 -0
- package/lib/core/index.js +7 -1
- package/lib/core/index.js.map +1 -1
- package/lib/core/solana-plugin.d.ts +9 -0
- package/lib/core/solana-plugin.js +79 -0
- package/lib/core/solana-plugin.js.map +1 -0
- package/lib/core/sui-plugin.d.ts +8 -0
- package/lib/core/sui-plugin.js +46 -0
- package/lib/core/sui-plugin.js.map +1 -0
- package/lib/gen/index.d.ts +2 -1
- package/lib/gen/index.js +2 -1
- package/lib/gen/index.js.map +1 -1
- package/lib/plugin.d.ts +15 -0
- package/lib/plugin.js +32 -0
- package/lib/plugin.js.map +1 -0
- package/lib/processor-runner.js +0 -0
- package/lib/service.d.ts +7 -19
- package/lib/service.js +36 -486
- package/lib/service.js.map +1 -1
- package/package.json +6 -12
- package/src/aptos/aptos-plugin.ts +217 -0
- package/src/aptos/index.ts +2 -0
- package/src/core/eth-plugin.ts +255 -0
- package/src/core/index.ts +4 -0
- package/src/core/solana-plugin.ts +97 -0
- package/src/core/sui-plugin.ts +54 -0
- package/src/gen/index.ts +3 -1
- package/src/plugin.ts +41 -0
- package/src/service.ts +32 -563
- package/src/target-ethers-sentio/tsconfig.json +1 -1
- package/src/types/global.d.ts +15 -0
- package/lib/release.config.js +0 -39
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { Plugin, PluginManager } from '../plugin'
|
|
2
|
+
import {
|
|
3
|
+
AccountConfig,
|
|
4
|
+
ContractConfig,
|
|
5
|
+
DataBinding,
|
|
6
|
+
HandlerType,
|
|
7
|
+
LogFilter,
|
|
8
|
+
LogHandlerConfig,
|
|
9
|
+
ProcessConfigResponse,
|
|
10
|
+
ProcessResult,
|
|
11
|
+
} from '../gen/processor/protos/processor'
|
|
12
|
+
import { DEFAULT_MAX_BLOCK, errorString, mergeProcessResults, USER_PROCESSOR, Utf8ArrayToStr } from '../service'
|
|
13
|
+
|
|
14
|
+
import { ServerError, Status } from 'nice-grpc'
|
|
15
|
+
import { Block, Log } from '@ethersproject/abstract-provider'
|
|
16
|
+
import { Trace } from '@sentio/sdk'
|
|
17
|
+
import { ProcessorState } from '../binds'
|
|
18
|
+
import { AccountProcessorState } from './account-processor'
|
|
19
|
+
import Long from 'long'
|
|
20
|
+
|
|
21
|
+
export class EthPlugin implements Plugin {
|
|
22
|
+
name: string = 'EthPlugin'
|
|
23
|
+
|
|
24
|
+
private eventHandlers: ((event: Log) => Promise<ProcessResult>)[] = []
|
|
25
|
+
private traceHandlers: ((trace: Trace) => Promise<ProcessResult>)[] = []
|
|
26
|
+
private blockHandlers: ((block: Block) => Promise<ProcessResult>)[] = []
|
|
27
|
+
|
|
28
|
+
configure(config: ProcessConfigResponse): void {
|
|
29
|
+
for (const processor of ProcessorState.INSTANCE.getValues()) {
|
|
30
|
+
// If server favor incremental update this need to change
|
|
31
|
+
// Start basic config for contract
|
|
32
|
+
const chainId = processor.getChainId()
|
|
33
|
+
// this.processorsByChainId.set(chainId, processor)
|
|
34
|
+
|
|
35
|
+
const contractConfig: ContractConfig = {
|
|
36
|
+
processorType: USER_PROCESSOR,
|
|
37
|
+
contract: {
|
|
38
|
+
name: processor.config.name,
|
|
39
|
+
chainId: chainId.toString(),
|
|
40
|
+
address: processor.config.address,
|
|
41
|
+
abi: '',
|
|
42
|
+
},
|
|
43
|
+
intervalConfigs: [],
|
|
44
|
+
logConfigs: [],
|
|
45
|
+
traceConfigs: [],
|
|
46
|
+
startBlock: processor.config.startBlock,
|
|
47
|
+
endBlock: DEFAULT_MAX_BLOCK,
|
|
48
|
+
instructionConfig: undefined,
|
|
49
|
+
aptosEventConfigs: [],
|
|
50
|
+
aptosCallConfigs: [],
|
|
51
|
+
}
|
|
52
|
+
if (processor.config.endBlock) {
|
|
53
|
+
contractConfig.endBlock = processor.config.endBlock
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Step 1. Prepare all the block handlers
|
|
57
|
+
for (const blockHandler of processor.blockHandlers) {
|
|
58
|
+
const handlerId = this.blockHandlers.push(blockHandler.handler) - 1
|
|
59
|
+
// TODO wrap the block handler into one
|
|
60
|
+
|
|
61
|
+
contractConfig.intervalConfigs.push({
|
|
62
|
+
slot: 0,
|
|
63
|
+
slotInterval: blockHandler.blockInterval,
|
|
64
|
+
minutes: 0,
|
|
65
|
+
minutesInterval: blockHandler.timeIntervalInMinutes,
|
|
66
|
+
handlerId: handlerId,
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Step 2. Prepare all trace handlers
|
|
71
|
+
for (const traceHandler of processor.traceHandlers) {
|
|
72
|
+
const handlerId = this.traceHandlers.push(traceHandler.handler) - 1
|
|
73
|
+
contractConfig.traceConfigs.push({
|
|
74
|
+
signature: traceHandler.signature,
|
|
75
|
+
handlerId: handlerId,
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Step 3. Prepare all the event handlers
|
|
80
|
+
for (const eventsHandler of processor.eventHandlers) {
|
|
81
|
+
// associate id with filter
|
|
82
|
+
const handlerId = this.eventHandlers.push(eventsHandler.handler) - 1
|
|
83
|
+
const logConfig: LogHandlerConfig = {
|
|
84
|
+
handlerId: handlerId,
|
|
85
|
+
filters: [],
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
for (const filter of eventsHandler.filters) {
|
|
89
|
+
if (!filter.topics) {
|
|
90
|
+
throw new ServerError(Status.INVALID_ARGUMENT, 'Topic should not be null')
|
|
91
|
+
}
|
|
92
|
+
const logFilter: LogFilter = {
|
|
93
|
+
addressType: undefined,
|
|
94
|
+
address: contractConfig.contract?.address,
|
|
95
|
+
topics: [],
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
for (const ts of filter.topics) {
|
|
99
|
+
let hashes: string[] = []
|
|
100
|
+
if (Array.isArray(ts)) {
|
|
101
|
+
hashes = hashes.concat(ts)
|
|
102
|
+
} else if (ts) {
|
|
103
|
+
hashes.push(ts)
|
|
104
|
+
}
|
|
105
|
+
logFilter.topics.push({ hashes: hashes })
|
|
106
|
+
}
|
|
107
|
+
logConfig.filters.push(logFilter)
|
|
108
|
+
}
|
|
109
|
+
contractConfig.logConfigs.push(logConfig)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Finish up a contract
|
|
113
|
+
config.contractConfigs.push(contractConfig)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// part 1.b prepare EVM account processors
|
|
117
|
+
for (const processor of AccountProcessorState.INSTANCE.getValues()) {
|
|
118
|
+
const accountConfig: AccountConfig = {
|
|
119
|
+
address: processor.config.address,
|
|
120
|
+
chainId: processor.getChainId().toString(),
|
|
121
|
+
startBlock: processor.config.startBlock ? Long.fromValue(processor.config.startBlock) : Long.ZERO,
|
|
122
|
+
aptosIntervalConfigs: [],
|
|
123
|
+
intervalConfigs: [],
|
|
124
|
+
logConfigs: [],
|
|
125
|
+
}
|
|
126
|
+
// TODO add interval
|
|
127
|
+
for (const eventsHandler of processor.eventHandlers) {
|
|
128
|
+
// associate id with filter
|
|
129
|
+
const handlerId = this.eventHandlers.push(eventsHandler.handler) - 1
|
|
130
|
+
const logConfig: LogHandlerConfig = {
|
|
131
|
+
handlerId: handlerId,
|
|
132
|
+
filters: [],
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
for (const filter of eventsHandler.filters) {
|
|
136
|
+
if (!filter.topics) {
|
|
137
|
+
throw new ServerError(Status.INVALID_ARGUMENT, 'Topic should not be null')
|
|
138
|
+
}
|
|
139
|
+
const logFilter: LogFilter = {
|
|
140
|
+
addressType: filter.addressType,
|
|
141
|
+
address: filter.address,
|
|
142
|
+
topics: [],
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
for (const ts of filter.topics) {
|
|
146
|
+
let hashes: string[] = []
|
|
147
|
+
if (Array.isArray(ts)) {
|
|
148
|
+
hashes = hashes.concat(ts)
|
|
149
|
+
} else if (ts) {
|
|
150
|
+
hashes.push(ts)
|
|
151
|
+
}
|
|
152
|
+
logFilter.topics.push({ hashes: hashes })
|
|
153
|
+
}
|
|
154
|
+
logConfig.filters.push(logFilter)
|
|
155
|
+
}
|
|
156
|
+
accountConfig.logConfigs.push(logConfig)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
config.accountConfigs.push(accountConfig)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
supportedHandlers = [HandlerType.ETH_LOG, HandlerType.ETH_BLOCK, HandlerType.ETH_TRACE]
|
|
164
|
+
|
|
165
|
+
processBinding(request: DataBinding): Promise<ProcessResult> {
|
|
166
|
+
// return Promise.resolve(undefined);
|
|
167
|
+
switch (request.handlerType) {
|
|
168
|
+
case HandlerType.ETH_LOG:
|
|
169
|
+
return this.processLog(request)
|
|
170
|
+
case HandlerType.ETH_TRACE:
|
|
171
|
+
return this.processTrace(request)
|
|
172
|
+
case HandlerType.ETH_BLOCK:
|
|
173
|
+
return this.processBlock(request)
|
|
174
|
+
default:
|
|
175
|
+
throw new ServerError(Status.INVALID_ARGUMENT, 'No handle type registered ' + request.handlerType)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async processLog(request: DataBinding): Promise<ProcessResult> {
|
|
180
|
+
if (!request.data) {
|
|
181
|
+
throw new ServerError(Status.INVALID_ARGUMENT, "Log can't be null")
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const promises: Promise<ProcessResult>[] = []
|
|
185
|
+
let log: Log
|
|
186
|
+
if (request.data.ethLog) {
|
|
187
|
+
log = request.data.ethLog.log as Log
|
|
188
|
+
} else {
|
|
189
|
+
const jsonString = Utf8ArrayToStr(request.data.raw)
|
|
190
|
+
log = JSON.parse(jsonString)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
for (const handlerId of request.handlerIds) {
|
|
194
|
+
const handler = this.eventHandlers[handlerId]
|
|
195
|
+
promises.push(
|
|
196
|
+
handler(log).catch((e) => {
|
|
197
|
+
throw new ServerError(Status.INTERNAL, 'error processing log: ' + JSON.stringify(log) + '\n' + errorString(e))
|
|
198
|
+
})
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
return mergeProcessResults(await Promise.all(promises))
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async processTrace(binding: DataBinding): Promise<ProcessResult> {
|
|
205
|
+
if (!binding.data) {
|
|
206
|
+
throw new ServerError(Status.INVALID_ARGUMENT, "Trace can't be empty")
|
|
207
|
+
}
|
|
208
|
+
let trace: Trace
|
|
209
|
+
if (binding.data.ethTrace?.trace) {
|
|
210
|
+
trace = binding.data.ethTrace.trace as Trace
|
|
211
|
+
} else {
|
|
212
|
+
const jsonString = Utf8ArrayToStr(binding.data.raw)
|
|
213
|
+
trace = JSON.parse(jsonString)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const promises: Promise<ProcessResult>[] = []
|
|
217
|
+
|
|
218
|
+
for (const handlerId of binding.handlerIds) {
|
|
219
|
+
promises.push(
|
|
220
|
+
this.traceHandlers[handlerId](trace).catch((e) => {
|
|
221
|
+
throw new ServerError(
|
|
222
|
+
Status.INTERNAL,
|
|
223
|
+
'error processing trace: ' + JSON.stringify(trace) + '\n' + errorString(e)
|
|
224
|
+
)
|
|
225
|
+
})
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
return mergeProcessResults(await Promise.all(promises))
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async processBlock(binding: DataBinding): Promise<ProcessResult> {
|
|
232
|
+
if (!binding.data) {
|
|
233
|
+
throw new ServerError(Status.INVALID_ARGUMENT, "Block can't be empty")
|
|
234
|
+
}
|
|
235
|
+
let block: Block
|
|
236
|
+
if (binding.data.ethBlock?.block) {
|
|
237
|
+
block = binding.data.ethBlock.block as Block
|
|
238
|
+
} else {
|
|
239
|
+
const jsonString = Utf8ArrayToStr(binding.data.raw)
|
|
240
|
+
block = JSON.parse(jsonString)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const promises: Promise<ProcessResult>[] = []
|
|
244
|
+
for (const handlerId of binding.handlerIds) {
|
|
245
|
+
promises.push(
|
|
246
|
+
this.blockHandlers[handlerId](block).catch((e) => {
|
|
247
|
+
throw new ServerError(Status.INTERNAL, 'error processing block: ' + block.number + '\n' + errorString(e))
|
|
248
|
+
})
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
return mergeProcessResults(await Promise.all(promises))
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
PluginManager.INSTANCE.register(new EthPlugin())
|
package/src/core/index.ts
CHANGED
|
@@ -16,3 +16,7 @@ export { SolanaBindOptions } from './solana-options'
|
|
|
16
16
|
export { SolanaBaseProcessor } from './solana-processor'
|
|
17
17
|
|
|
18
18
|
export type { TypedCallTrace, Trace } from './trace'
|
|
19
|
+
|
|
20
|
+
export { EthPlugin } from './eth-plugin'
|
|
21
|
+
export { SolanaPlugin } from './solana-plugin'
|
|
22
|
+
export { SuiPlugin } from './sui-plugin'
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Plugin, PluginManager } from '../plugin'
|
|
2
|
+
import {
|
|
3
|
+
ContractConfig,
|
|
4
|
+
Data_SolInstruction,
|
|
5
|
+
DataBinding,
|
|
6
|
+
HandlerType,
|
|
7
|
+
ProcessConfigResponse,
|
|
8
|
+
ProcessResult,
|
|
9
|
+
} from '../gen/processor/protos/processor'
|
|
10
|
+
import { DEFAULT_MAX_BLOCK, errorString, mergeProcessResults, USER_PROCESSOR, Utf8ArrayToStr } from '../service'
|
|
11
|
+
|
|
12
|
+
import { ServerError, Status } from 'nice-grpc'
|
|
13
|
+
|
|
14
|
+
import { SolanaProcessorState } from './solana-processor'
|
|
15
|
+
import { Instruction as SolInstruction } from '@project-serum/anchor/dist/cjs/coder/borsh/instruction'
|
|
16
|
+
|
|
17
|
+
export class SolanaPlugin implements Plugin {
|
|
18
|
+
name: string = 'SolanaPlugin'
|
|
19
|
+
|
|
20
|
+
configure(config: ProcessConfigResponse): void {
|
|
21
|
+
// Part 2, prepare solana constractors
|
|
22
|
+
for (const solanaProcessor of SolanaProcessorState.INSTANCE.getValues()) {
|
|
23
|
+
const contractConfig: ContractConfig = {
|
|
24
|
+
processorType: USER_PROCESSOR,
|
|
25
|
+
contract: {
|
|
26
|
+
name: solanaProcessor.contractName,
|
|
27
|
+
chainId: solanaProcessor.network,
|
|
28
|
+
address: solanaProcessor.address,
|
|
29
|
+
abi: '',
|
|
30
|
+
},
|
|
31
|
+
logConfigs: [],
|
|
32
|
+
traceConfigs: [],
|
|
33
|
+
intervalConfigs: [],
|
|
34
|
+
startBlock: solanaProcessor.config.startSlot,
|
|
35
|
+
endBlock: DEFAULT_MAX_BLOCK,
|
|
36
|
+
instructionConfig: {
|
|
37
|
+
innerInstruction: solanaProcessor.processInnerInstruction,
|
|
38
|
+
parsedInstruction: solanaProcessor.fromParsedInstruction !== null,
|
|
39
|
+
rawDataInstruction: solanaProcessor.decodeInstruction !== null,
|
|
40
|
+
},
|
|
41
|
+
aptosEventConfigs: [],
|
|
42
|
+
aptosCallConfigs: [],
|
|
43
|
+
}
|
|
44
|
+
config.contractConfigs.push(contractConfig)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
supportedHandlers = [HandlerType.SOL_INSTRUCTION]
|
|
49
|
+
|
|
50
|
+
processBinding(request: DataBinding): Promise<ProcessResult> {
|
|
51
|
+
switch (request.handlerType) {
|
|
52
|
+
case HandlerType.SOL_INSTRUCTION:
|
|
53
|
+
return this.processSolInstruction(request)
|
|
54
|
+
default:
|
|
55
|
+
throw new ServerError(Status.INVALID_ARGUMENT, 'No handle type registered ' + request.handlerType)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async processSolInstruction(request: DataBinding): Promise<ProcessResult> {
|
|
60
|
+
if (!request.data) {
|
|
61
|
+
throw new ServerError(Status.INVALID_ARGUMENT, 'instruction data cannot be empty')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const instruction = request.data.solInstruction || Data_SolInstruction.decode(request.data.raw) // JSON.parse(jsonString)
|
|
65
|
+
const promises: Promise<ProcessResult>[] = []
|
|
66
|
+
|
|
67
|
+
// Only have instruction handlers for solana processors
|
|
68
|
+
for (const processor of SolanaProcessorState.INSTANCE.getValues()) {
|
|
69
|
+
if (processor.address === instruction.programAccountId) {
|
|
70
|
+
let parsedInstruction: SolInstruction | null = null
|
|
71
|
+
if (instruction.parsed) {
|
|
72
|
+
parsedInstruction = processor.getParsedInstruction(instruction.parsed as { type: string; info: any })
|
|
73
|
+
} else if (instruction.instructionData) {
|
|
74
|
+
parsedInstruction = processor.getParsedInstruction(instruction.instructionData)
|
|
75
|
+
}
|
|
76
|
+
if (parsedInstruction == null) {
|
|
77
|
+
continue
|
|
78
|
+
}
|
|
79
|
+
const insHandler = processor.getInstructionHandler(parsedInstruction)
|
|
80
|
+
if (insHandler == null) {
|
|
81
|
+
continue
|
|
82
|
+
}
|
|
83
|
+
const res = await processor.handleInstruction(
|
|
84
|
+
parsedInstruction,
|
|
85
|
+
instruction.accounts,
|
|
86
|
+
insHandler,
|
|
87
|
+
instruction.slot
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
promises.push(Promise.resolve(res))
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return mergeProcessResults(await Promise.all(promises))
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
PluginManager.INSTANCE.register(new SolanaPlugin())
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Plugin, PluginManager } from '../plugin'
|
|
2
|
+
import {
|
|
3
|
+
ContractConfig,
|
|
4
|
+
DataBinding,
|
|
5
|
+
HandlerType,
|
|
6
|
+
ProcessConfigResponse,
|
|
7
|
+
ProcessResult,
|
|
8
|
+
} from '../gen/processor/protos/processor'
|
|
9
|
+
import { DEFAULT_MAX_BLOCK, USER_PROCESSOR } from '../service'
|
|
10
|
+
|
|
11
|
+
import { ServerError, Status } from 'nice-grpc'
|
|
12
|
+
|
|
13
|
+
import { CHAIN_IDS } from '../utils/chain'
|
|
14
|
+
import { SuiProcessorState } from './sui-processor'
|
|
15
|
+
|
|
16
|
+
export class SuiPlugin implements Plugin {
|
|
17
|
+
name: string = 'SolanaPlugin'
|
|
18
|
+
|
|
19
|
+
configure(config: ProcessConfigResponse): void {
|
|
20
|
+
for (const suiProcessor of SuiProcessorState.INSTANCE.getValues()) {
|
|
21
|
+
const contractConfig: ContractConfig = {
|
|
22
|
+
processorType: USER_PROCESSOR,
|
|
23
|
+
contract: {
|
|
24
|
+
name: 'sui contract',
|
|
25
|
+
chainId: CHAIN_IDS.SUI_DEVNET,
|
|
26
|
+
address: suiProcessor.address,
|
|
27
|
+
abi: '',
|
|
28
|
+
},
|
|
29
|
+
logConfigs: [],
|
|
30
|
+
intervalConfigs: [],
|
|
31
|
+
traceConfigs: [],
|
|
32
|
+
startBlock: suiProcessor.config.startSeqNumber,
|
|
33
|
+
endBlock: DEFAULT_MAX_BLOCK,
|
|
34
|
+
instructionConfig: undefined,
|
|
35
|
+
aptosEventConfigs: [],
|
|
36
|
+
aptosCallConfigs: [],
|
|
37
|
+
}
|
|
38
|
+
config.contractConfigs.push(contractConfig)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
supportedHandlers = [HandlerType.SUI_TRANSACTION]
|
|
43
|
+
|
|
44
|
+
processBinding(request: DataBinding): Promise<ProcessResult> {
|
|
45
|
+
switch (request.handlerType) {
|
|
46
|
+
case HandlerType.SUI_TRANSACTION:
|
|
47
|
+
// return this.processSolInstruction(request)
|
|
48
|
+
default:
|
|
49
|
+
throw new ServerError(Status.INVALID_ARGUMENT, 'No handle type registered ' + request.handlerType)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
PluginManager.INSTANCE.register(new SuiPlugin())
|
package/src/gen/index.ts
CHANGED
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { DataBinding, HandlerType, ProcessConfigResponse, ProcessResult } from './gen'
|
|
2
|
+
|
|
3
|
+
export interface Plugin {
|
|
4
|
+
name: string
|
|
5
|
+
supportedHandlers: HandlerType[]
|
|
6
|
+
|
|
7
|
+
configure(config: ProcessConfigResponse): void
|
|
8
|
+
processBinding(request: DataBinding): Promise<ProcessResult>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class PluginManager {
|
|
12
|
+
static INSTANCE = new PluginManager()
|
|
13
|
+
|
|
14
|
+
plugins: Plugin[] = []
|
|
15
|
+
typesToPlugin = new Map<HandlerType, Plugin>()
|
|
16
|
+
|
|
17
|
+
register(plugin: Plugin) {
|
|
18
|
+
this.plugins.push(plugin)
|
|
19
|
+
// for (const plugin of this.plugins) {
|
|
20
|
+
for (const handlerType of plugin.supportedHandlers) {
|
|
21
|
+
const exsited = this.typesToPlugin.get(handlerType)
|
|
22
|
+
if (exsited) {
|
|
23
|
+
throw new Error(`Duplicate plugin for ${handlerType}: ${exsited.name} and ${plugin.name}`)
|
|
24
|
+
}
|
|
25
|
+
this.typesToPlugin.set(handlerType, plugin)
|
|
26
|
+
}
|
|
27
|
+
// }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
configure(config: ProcessConfigResponse) {
|
|
31
|
+
this.plugins.forEach((plugin) => plugin.configure(config))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
processBinding(request: DataBinding): Promise<ProcessResult> {
|
|
35
|
+
const plugin = this.typesToPlugin.get(request.handlerType)
|
|
36
|
+
if (!plugin) {
|
|
37
|
+
throw new Error(`No plugin for ${request.handlerType}`)
|
|
38
|
+
}
|
|
39
|
+
return plugin.processBinding(request)
|
|
40
|
+
}
|
|
41
|
+
}
|