@sentio/sdk 1.7.12 → 1.7.15
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/{base-processor-template.d.ts → lib/base-processor-template.d.ts} +0 -0
- package/{base-processor-template.js → lib/base-processor-template.js} +0 -0
- package/lib/base-processor-template.js.map +1 -0
- package/{base-processor.d.ts → lib/base-processor.d.ts} +0 -0
- package/{base-processor.js → lib/base-processor.js} +0 -0
- package/lib/base-processor.js.map +1 -0
- package/{bind-options.d.ts → lib/bind-options.d.ts} +0 -0
- package/{bind-options.js → lib/bind-options.js} +0 -0
- package/lib/bind-options.js.map +1 -0
- package/{binds.d.ts → lib/binds.d.ts} +0 -0
- package/{binds.js → lib/binds.js} +0 -0
- package/lib/binds.js.map +1 -0
- package/{builtin → lib/builtin}/erc20/index.d.ts +0 -0
- package/{builtin → lib/builtin}/erc20/index.js +0 -0
- package/lib/builtin/erc20/index.js.map +1 -0
- package/{builtin → lib/builtin}/erc20/test-utils.d.ts +0 -0
- package/{builtin → lib/builtin}/erc20/test-utils.js +0 -0
- package/lib/builtin/erc20/test-utils.js.map +1 -0
- package/{builtin → lib/builtin}/internal/Erc20.d.ts +0 -0
- package/{builtin → lib/builtin}/internal/Erc20.js +0 -0
- package/lib/builtin/internal/Erc20.js.map +1 -0
- package/{builtin → lib/builtin}/internal/common.d.ts +0 -0
- package/{builtin → lib/builtin}/internal/common.js +0 -0
- package/lib/builtin/internal/common.js.map +1 -0
- package/{builtin → lib/builtin}/internal/erc20_processor.d.ts +0 -0
- package/{builtin → lib/builtin}/internal/erc20_processor.js +0 -0
- package/lib/builtin/internal/erc20_processor.js.map +1 -0
- package/{builtin → lib/builtin}/internal/factories/Erc20__factory.d.ts +0 -0
- package/{builtin → lib/builtin}/internal/factories/Erc20__factory.js +0 -0
- package/lib/builtin/internal/factories/Erc20__factory.js.map +1 -0
- package/{builtin → lib/builtin}/internal/factories/index.d.ts +0 -0
- package/{builtin → lib/builtin}/internal/factories/index.js +0 -0
- package/{builtin → lib/builtin}/internal/factories/index.js.map +1 -1
- package/{builtin → lib/builtin}/internal/index.d.ts +0 -0
- package/{builtin → lib/builtin}/internal/index.js +0 -0
- package/lib/builtin/internal/index.js.map +1 -0
- package/{chain-config.d.ts → lib/chain-config.d.ts} +0 -0
- package/{chain-config.js → lib/chain-config.js} +0 -0
- package/lib/chain-config.js.map +1 -0
- package/{cli → lib/cli}/build.d.ts +0 -0
- package/{cli → lib/cli}/build.js +0 -0
- package/lib/cli/build.js.map +1 -0
- package/{cli → lib/cli}/cli.d.ts +0 -0
- package/{cli → lib/cli}/cli.js +0 -0
- package/lib/cli/cli.js.map +1 -0
- package/{cli → lib/cli}/config.d.ts +0 -0
- package/{cli → lib/cli}/config.js +0 -0
- package/lib/cli/config.js.map +1 -0
- package/{cli → lib/cli}/key.d.ts +0 -0
- package/{cli → lib/cli}/key.js +0 -0
- package/{cli → lib/cli}/key.js.map +1 -1
- package/{cli → lib/cli}/solana-code-gen.d.ts +0 -0
- package/{cli → lib/cli}/solana-code-gen.js +0 -0
- package/{cli → lib/cli}/solana-code-gen.js.map +1 -1
- package/{cli → lib/cli}/upload.d.ts +0 -0
- package/{cli → lib/cli}/upload.js +0 -0
- package/{cli → lib/cli}/upload.js.map +1 -1
- package/{cli → lib/cli}/webpack.config.js +0 -0
- package/{context.d.ts → lib/context.d.ts} +0 -0
- package/{context.js → lib/context.js} +0 -0
- package/lib/context.js.map +1 -0
- package/{contract-namer.d.ts → lib/contract-namer.d.ts} +0 -0
- package/{contract-namer.js → lib/contract-namer.js} +0 -0
- package/{contract-namer.js.map → lib/contract-namer.js.map} +1 -1
- package/{error.d.ts → lib/error.d.ts} +0 -0
- package/{error.js → lib/error.js} +0 -0
- package/lib/error.js.map +1 -0
- package/{gen → lib/gen}/builtin.d.ts +0 -0
- package/{gen → lib/gen}/builtin.js +0 -0
- package/lib/gen/builtin.js.map +1 -0
- package/{gen → lib/gen}/google/protobuf/empty.d.ts +0 -0
- package/{gen → lib/gen}/google/protobuf/empty.js +0 -0
- package/lib/gen/google/protobuf/empty.js.map +1 -0
- package/{gen → lib/gen}/processor/protos/processor.d.ts +0 -0
- package/{gen → lib/gen}/processor/protos/processor.js +0 -0
- package/lib/gen/processor/protos/processor.js.map +1 -0
- package/{generic-processor.d.ts → lib/generic-processor.d.ts} +0 -0
- package/{generic-processor.js → lib/generic-processor.js} +0 -0
- package/lib/generic-processor.js.map +1 -0
- package/{index.d.ts → lib/index.d.ts} +0 -0
- package/{index.js → lib/index.js} +0 -0
- package/lib/index.js.map +1 -0
- package/{meter.d.ts → lib/meter.d.ts} +0 -0
- package/{meter.js → lib/meter.js} +0 -0
- package/lib/meter.js.map +1 -0
- package/{numberish.d.ts → lib/numberish.d.ts} +0 -0
- package/{numberish.js → lib/numberish.js} +0 -0
- package/lib/numberish.js.map +1 -0
- package/{numberish.test.d.ts → lib/numberish.test.d.ts} +0 -0
- package/{numberish.test.js → lib/numberish.test.js} +0 -0
- package/{numberish.test.js.map → lib/numberish.test.js.map} +1 -1
- package/{processor-runner.d.ts → lib/processor-runner.d.ts} +0 -0
- package/{processor-runner.js → lib/processor-runner.js} +0 -0
- package/lib/processor-runner.js.map +1 -0
- package/{processor-state.d.ts → lib/processor-state.d.ts} +0 -0
- package/{processor-state.js → lib/processor-state.js} +0 -0
- package/lib/processor-state.js.map +1 -0
- package/{promise-or-void.d.ts → lib/promise-or-void.d.ts} +0 -0
- package/{promise-or-void.js → lib/promise-or-void.js} +0 -0
- package/lib/promise-or-void.js.map +1 -0
- package/{provider.d.ts → lib/provider.d.ts} +0 -0
- package/{provider.js → lib/provider.js} +1 -1
- package/lib/provider.js.map +1 -0
- package/{release.config.js → lib/release.config.js} +0 -0
- package/{service.d.ts → lib/service.d.ts} +0 -0
- package/{service.js → lib/service.js} +0 -0
- package/lib/service.js.map +1 -0
- package/{solana → lib/solana}/builtin/index.d.ts +0 -0
- package/{solana → lib/solana}/builtin/index.js +0 -0
- package/lib/solana/builtin/index.js.map +1 -0
- package/{solana → lib/solana}/builtin/spl-token-processor.d.ts +0 -0
- package/{solana → lib/solana}/builtin/spl-token-processor.js +0 -0
- package/lib/solana/builtin/spl-token-processor.js.map +1 -0
- package/{solana → lib/solana}/builtin/types.d.ts +0 -0
- package/{solana → lib/solana}/builtin/types.js +0 -0
- package/lib/solana/builtin/types.js.map +1 -0
- package/{solana → lib/solana}/builtin/wormhole-processor.d.ts +0 -0
- package/{solana → lib/solana}/builtin/wormhole-processor.js +0 -0
- package/lib/solana/builtin/wormhole-processor.js.map +1 -0
- package/{solana-processor.d.ts → lib/solana-processor.d.ts} +0 -0
- package/{solana-processor.js → lib/solana-processor.js} +0 -0
- package/lib/solana-processor.js.map +1 -0
- package/{target-ethers-sentio → lib/target-ethers-sentio}/codegen.d.ts +0 -0
- package/{target-ethers-sentio → lib/target-ethers-sentio}/codegen.js +0 -0
- package/{target-ethers-sentio → lib/target-ethers-sentio}/codegen.js.map +0 -0
- package/{target-ethers-sentio → lib/target-ethers-sentio}/index.d.ts +0 -0
- package/{target-ethers-sentio → lib/target-ethers-sentio}/index.js +0 -0
- package/{target-ethers-sentio → lib/target-ethers-sentio}/index.js.map +0 -0
- package/{test → lib/test}/codegen.test.d.ts +0 -0
- package/{test → lib/test}/codegen.test.js +4 -8
- package/lib/test/codegen.test.js.map +1 -0
- package/{test → lib/test}/erc20-template.d.ts +0 -0
- package/{test → lib/test}/erc20-template.js +0 -0
- package/lib/test/erc20-template.js.map +1 -0
- package/{test → lib/test}/erc20-template.test.d.ts +0 -0
- package/{test → lib/test}/erc20-template.test.js +0 -0
- package/{test → lib/test}/erc20-template.test.js.map +1 -1
- package/{test → lib/test}/erc20.d.ts +0 -0
- package/{test → lib/test}/erc20.js +0 -0
- package/lib/test/erc20.js.map +1 -0
- package/{test → lib/test}/erc20.test.d.ts +0 -0
- package/{test → lib/test}/erc20.test.js +0 -0
- package/{test → lib/test}/erc20.test.js.map +1 -1
- package/{test → lib/test}/generic-processor.test.d.ts +0 -0
- package/{test → lib/test}/generic-processor.test.js +11 -1
- package/lib/test/generic-processor.test.js.map +1 -0
- package/{test → lib/test}/index.d.ts +0 -0
- package/{test → lib/test}/index.js +0 -0
- package/{test → lib/test}/index.js.map +1 -1
- package/{test → lib/test}/metric-utils.d.ts +0 -0
- package/{test → lib/test}/metric-utils.js +0 -0
- package/lib/test/metric-utils.js.map +1 -0
- package/{test → lib/test}/mirrorworld.d.ts +0 -0
- package/{test → lib/test}/mirrorworld.js +0 -0
- package/{test → lib/test}/mirrorworld.js.map +1 -1
- package/{test → lib/test}/solana.test.d.ts +0 -0
- package/{test → lib/test}/solana.test.js +0 -0
- package/lib/test/solana.test.js.map +1 -0
- package/{test → lib/test}/test-processor-server.d.ts +0 -0
- package/{test → lib/test}/test-processor-server.js +0 -0
- package/lib/test/test-processor-server.js.map +1 -0
- package/{test → lib/test}/types/game_wallet.d.ts +0 -0
- package/{test → lib/test}/types/game_wallet.js +0 -0
- package/lib/test/types/game_wallet.js.map +1 -0
- package/{test → lib/test}/types/game_wallet_processor.d.ts +0 -0
- package/{test → lib/test}/types/game_wallet_processor.js +0 -0
- package/lib/test/types/game_wallet_processor.js.map +1 -0
- package/{test → lib/test}/wormhole-token-bridge.d.ts +0 -0
- package/{test → lib/test}/wormhole-token-bridge.js +0 -0
- package/lib/test/wormhole-token-bridge.js.map +1 -0
- package/{utils → lib/utils}/chainmap.d.ts +0 -0
- package/{utils → lib/utils}/chainmap.js +0 -0
- package/lib/utils/chainmap.js.map +1 -0
- package/{utils → lib/utils}/convert.d.ts +0 -0
- package/{utils → lib/utils}/convert.js +0 -0
- package/lib/utils/convert.js.map +1 -0
- package/{utils → lib/utils}/index.d.ts +0 -0
- package/{utils → lib/utils}/index.js +0 -0
- package/lib/utils/index.js.map +1 -0
- package/package.json +47 -6
- package/src/abis/erc20.json +198 -0
- package/src/base-processor-template.ts +92 -0
- package/src/base-processor.ts +128 -0
- package/src/bind-options.ts +41 -0
- package/src/binds.ts +73 -0
- package/src/builtin/erc20/index.ts +6 -0
- package/src/builtin/erc20/test-utils.ts +49 -0
- package/src/builtin/internal/Erc20.ts +356 -0
- package/src/builtin/internal/common.ts +46 -0
- package/src/builtin/internal/erc20_processor.ts +295 -0
- package/src/builtin/internal/factories/Erc20__factory.ts +216 -0
- package/src/builtin/internal/factories/index.ts +4 -0
- package/src/builtin/internal/index.ts +6 -0
- package/src/chain-config.ts +6 -0
- package/src/cli/build.ts +180 -0
- package/src/cli/cli.ts +217 -0
- package/src/cli/config.ts +43 -0
- package/src/cli/key.ts +43 -0
- package/src/cli/solana-code-gen.ts +16 -0
- package/src/cli/upload.ts +86 -0
- package/src/cli/webpack.config.js +42 -0
- package/src/context.ts +93 -0
- package/src/contract-namer.ts +17 -0
- package/src/error.ts +43 -0
- package/src/gen/builtin.ts +22 -0
- package/src/gen/google/protobuf/empty.ts +70 -0
- package/src/gen/processor/protos/processor.ts +3071 -0
- package/src/generic-processor.ts +38 -0
- package/src/index.ts +19 -0
- package/src/meter.ts +122 -0
- package/src/numberish.test.ts +82 -0
- package/src/numberish.ts +99 -0
- package/src/processor-runner.ts +75 -0
- package/src/processor-state.ts +24 -0
- package/src/promise-or-void.ts +1 -0
- package/src/provider.ts +74 -0
- package/src/service.ts +434 -0
- package/src/solana/builtin/index.ts +2 -0
- package/src/solana/builtin/spl-token-processor.ts +164 -0
- package/src/solana/builtin/types.ts +268 -0
- package/src/solana/builtin/wormhole-processor.ts +178 -0
- package/src/solana-processor.ts +105 -0
- package/src/target-ethers-sentio/codegen.ts +289 -0
- package/src/target-ethers-sentio/index.ts +50 -0
- package/src/target-ethers-sentio/tsconfig.json +9 -0
- package/src/test/abis/evm/anyswapRouter.json +490 -0
- package/src/test/abis/solana/mirrorworld.json +1392 -0
- package/src/test/codegen.test.ts +26 -0
- package/src/test/erc20-template.test.ts +39 -0
- package/src/test/erc20-template.ts +25 -0
- package/src/test/erc20.test.ts +92 -0
- package/src/test/erc20.ts +48 -0
- package/src/test/generic-processor.test.ts +72 -0
- package/src/test/index.ts +1 -0
- package/src/test/metric-utils.ts +49 -0
- package/src/test/mirrorworld.ts +40 -0
- package/src/test/sentio.yaml +4 -0
- package/src/test/solana.test.ts +93 -0
- package/src/test/test-processor-server.ts +210 -0
- package/src/test/types/game_wallet.ts +1392 -0
- package/src/test/types/game_wallet_processor.ts +113 -0
- package/src/test/wormhole-token-bridge.ts +21 -0
- package/src/types/global.d.ts +17 -0
- package/src/utils/chainmap.ts +95 -0
- package/src/utils/convert.ts +6 -0
- package/src/utils/index.ts +2 -0
- package/base-processor-template.js.map +0 -1
- package/base-processor.js.map +0 -1
- package/bind-options.js.map +0 -1
- package/binds.js.map +0 -1
- package/builtin/erc20/index.js.map +0 -1
- package/builtin/erc20/test-utils.js.map +0 -1
- package/builtin/internal/Erc20.js.map +0 -1
- package/builtin/internal/common.js.map +0 -1
- package/builtin/internal/erc20_processor.js.map +0 -1
- package/builtin/internal/factories/Erc20__factory.js.map +0 -1
- package/builtin/internal/index.js.map +0 -1
- package/chain-config.js.map +0 -1
- package/cli/build.js.map +0 -1
- package/cli/cli.js.map +0 -1
- package/cli/config.js.map +0 -1
- package/context.js.map +0 -1
- package/error.js.map +0 -1
- package/gen/builtin.js.map +0 -1
- package/gen/google/protobuf/empty.js.map +0 -1
- package/gen/processor/protos/processor.js.map +0 -1
- package/generic-processor.js.map +0 -1
- package/index.js.map +0 -1
- package/meter.js.map +0 -1
- package/numberish.js.map +0 -1
- package/processor-runner.js.map +0 -1
- package/processor-state.js.map +0 -1
- package/promise-or-void.js.map +0 -1
- package/provider.js.map +0 -1
- package/service.js.map +0 -1
- package/solana/builtin/index.js.map +0 -1
- package/solana/builtin/spl-token-processor.js.map +0 -1
- package/solana/builtin/types.js.map +0 -1
- package/solana/builtin/wormhole-processor.js.map +0 -1
- package/solana-processor.js.map +0 -1
- package/test/codegen.test.js.map +0 -1
- package/test/erc20-template.js.map +0 -1
- package/test/erc20.js.map +0 -1
- package/test/generic-processor.test.js.map +0 -1
- package/test/metric-utils.js.map +0 -1
- package/test/solana.test.js.map +0 -1
- package/test/test-processor-server.js.map +0 -1
- package/test/types/game_wallet.js.map +0 -1
- package/test/types/game_wallet_processor.js.map +0 -1
- package/test/wormhole-token-bridge.js.map +0 -1
- package/utils/chainmap.js.map +0 -1
- package/utils/convert.js.map +0 -1
- package/utils/index.js.map +0 -1
package/src/service.ts
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import { Block, Log } from '@ethersproject/abstract-provider'
|
|
2
|
+
import { CallContext, ServerError, Status } from 'nice-grpc'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
BlockBinding,
|
|
6
|
+
ContractConfig,
|
|
7
|
+
HandlerType,
|
|
8
|
+
LogFilter,
|
|
9
|
+
LogHandlerConfig,
|
|
10
|
+
O11yResult,
|
|
11
|
+
ProcessBlocksRequest,
|
|
12
|
+
ProcessBlocksResponse,
|
|
13
|
+
ProcessConfigRequest,
|
|
14
|
+
ProcessConfigResponse,
|
|
15
|
+
ProcessInstructionsRequest,
|
|
16
|
+
ProcessInstructionsResponse,
|
|
17
|
+
ProcessLogsRequest,
|
|
18
|
+
ProcessLogsResponse,
|
|
19
|
+
ProcessorServiceImplementation,
|
|
20
|
+
ProcessTransactionsRequest,
|
|
21
|
+
ProcessTransactionsResponse,
|
|
22
|
+
StartRequest,
|
|
23
|
+
TemplateInstance,
|
|
24
|
+
} from './gen/processor/protos/processor'
|
|
25
|
+
|
|
26
|
+
import { Empty } from './gen/google/protobuf/empty'
|
|
27
|
+
import Long from 'long'
|
|
28
|
+
import { TextDecoder } from 'util'
|
|
29
|
+
|
|
30
|
+
const DEFAULT_MAX_BLOCK = Long.ZERO
|
|
31
|
+
|
|
32
|
+
export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
33
|
+
private eventHandlers: ((event: Log) => Promise<O11yResult>)[] = []
|
|
34
|
+
private blockHandlers: ((block: Block) => Promise<O11yResult>)[] = []
|
|
35
|
+
|
|
36
|
+
// map from chain id to list of processors
|
|
37
|
+
// private blockHandlers = new Map<string, ((block: Block) => Promise<O11yResult>)[]>()
|
|
38
|
+
// private processorsByChainId = new Map<string, BaseProcessor<BaseContract, BoundContractView<BaseContract, any>>>()
|
|
39
|
+
|
|
40
|
+
private started = false
|
|
41
|
+
private contractConfigs: ContractConfig[]
|
|
42
|
+
private templateInstances: TemplateInstance[]
|
|
43
|
+
|
|
44
|
+
private readonly shutdownHandler?: () => void
|
|
45
|
+
|
|
46
|
+
constructor(shutdownHandler?: () => void) {
|
|
47
|
+
this.shutdownHandler = shutdownHandler
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async getConfig(request: ProcessConfigRequest, context: CallContext): Promise<ProcessConfigResponse> {
|
|
51
|
+
if (!this.started) {
|
|
52
|
+
throw new ServerError(Status.UNAVAILABLE, 'Service Not started.')
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
// TODO project setting
|
|
56
|
+
config: undefined,
|
|
57
|
+
contractConfigs: this.contractConfigs,
|
|
58
|
+
templateInstances: this.templateInstances,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async configure() {
|
|
63
|
+
this.eventHandlers = []
|
|
64
|
+
this.templateInstances = []
|
|
65
|
+
// this.processorsByChainId.clear()
|
|
66
|
+
this.contractConfigs = []
|
|
67
|
+
|
|
68
|
+
this.templateInstances = [...global.PROCESSOR_STATE.templatesInstances]
|
|
69
|
+
|
|
70
|
+
// Part 1, prepare EVM processors
|
|
71
|
+
for (const processor of global.PROCESSOR_STATE.processors) {
|
|
72
|
+
// If server favor incremental update this need to change
|
|
73
|
+
// Start basic config for contract
|
|
74
|
+
const chainId = processor.getChainId()
|
|
75
|
+
// this.processorsByChainId.set(chainId, processor)
|
|
76
|
+
|
|
77
|
+
const contractConfig: ContractConfig = {
|
|
78
|
+
processorType: 'user_processor',
|
|
79
|
+
contract: {
|
|
80
|
+
name: processor.config.name,
|
|
81
|
+
chainId: chainId.toString(),
|
|
82
|
+
address: processor.config.address,
|
|
83
|
+
abi: '',
|
|
84
|
+
},
|
|
85
|
+
blockConfigs: [],
|
|
86
|
+
logConfigs: [],
|
|
87
|
+
startBlock: processor.config.startBlock,
|
|
88
|
+
endBlock: DEFAULT_MAX_BLOCK,
|
|
89
|
+
instructionConfig: undefined,
|
|
90
|
+
}
|
|
91
|
+
if (processor.config.endBlock) {
|
|
92
|
+
contractConfig.endBlock = processor.config.endBlock
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Step 1. Prepare all the block handlers
|
|
96
|
+
for (const blockHandler of processor.blockHandlers) {
|
|
97
|
+
const handlerId = this.blockHandlers.push(blockHandler) - 1
|
|
98
|
+
contractConfig.blockConfigs.push({
|
|
99
|
+
handlerId: handlerId,
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Step 2. Prepare all the event handlers
|
|
104
|
+
for (const eventsHandler of processor.eventHandlers) {
|
|
105
|
+
// associate id with filter
|
|
106
|
+
const handlerId = this.eventHandlers.push(eventsHandler.handler) - 1
|
|
107
|
+
const logConfig: LogHandlerConfig = {
|
|
108
|
+
handlerId: handlerId,
|
|
109
|
+
filters: [],
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
for (const filter of eventsHandler.filters) {
|
|
113
|
+
if (!filter.topics) {
|
|
114
|
+
throw new ServerError(Status.INVALID_ARGUMENT, 'Topic should not be null')
|
|
115
|
+
}
|
|
116
|
+
const logFilter: LogFilter = {
|
|
117
|
+
topics: [],
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
for (const ts of filter.topics) {
|
|
121
|
+
let hashes: string[] = []
|
|
122
|
+
if (Array.isArray(ts)) {
|
|
123
|
+
hashes = hashes.concat(ts)
|
|
124
|
+
} else if (ts) {
|
|
125
|
+
hashes.push(ts)
|
|
126
|
+
}
|
|
127
|
+
logFilter.topics.push({ hashes: hashes })
|
|
128
|
+
}
|
|
129
|
+
logConfig.filters.push(logFilter)
|
|
130
|
+
}
|
|
131
|
+
contractConfig.logConfigs.push(logConfig)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Finish up a contract
|
|
135
|
+
this.contractConfigs.push(contractConfig)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Part 2, prepare solana constractors
|
|
139
|
+
for (const solanaProcessor of global.PROCESSOR_STATE.solanaProcessors) {
|
|
140
|
+
const contractConfig: ContractConfig = {
|
|
141
|
+
processorType: 'user_processor',
|
|
142
|
+
contract: {
|
|
143
|
+
name: solanaProcessor.contractName,
|
|
144
|
+
chainId: 'SOL:mainnet', // TODO set in processor
|
|
145
|
+
address: solanaProcessor.address,
|
|
146
|
+
abi: '',
|
|
147
|
+
},
|
|
148
|
+
blockConfigs: [],
|
|
149
|
+
logConfigs: [],
|
|
150
|
+
startBlock: solanaProcessor.config.startSlot,
|
|
151
|
+
endBlock: DEFAULT_MAX_BLOCK,
|
|
152
|
+
instructionConfig: {
|
|
153
|
+
innerInstruction: solanaProcessor.processInnerInstruction,
|
|
154
|
+
parsedInstruction: solanaProcessor.fromParsedInstruction != null ? true : false,
|
|
155
|
+
rawDataInstruction: solanaProcessor.decodeInstruction != null ? true : false,
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
this.contractConfigs.push(contractConfig)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async start(request: StartRequest, context: CallContext): Promise<Empty> {
|
|
163
|
+
if (this.started) {
|
|
164
|
+
return {}
|
|
165
|
+
}
|
|
166
|
+
for (const instance of request.templateInstances) {
|
|
167
|
+
const template = global.PROCESSOR_STATE.templates[instance.templateId]
|
|
168
|
+
if (!template) {
|
|
169
|
+
throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid template contract:' + instance)
|
|
170
|
+
}
|
|
171
|
+
if (!instance.contract) {
|
|
172
|
+
throw new ServerError(Status.INVALID_ARGUMENT, 'Contract Empty from:' + instance)
|
|
173
|
+
}
|
|
174
|
+
template.bind({
|
|
175
|
+
name: instance.contract.name,
|
|
176
|
+
address: instance.contract.address,
|
|
177
|
+
network: Number(instance.contract.chainId),
|
|
178
|
+
startBlock: instance.startBlock,
|
|
179
|
+
endBlock: instance.endBlock,
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
await this.configure()
|
|
183
|
+
this.started = true
|
|
184
|
+
return {}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async stop(request: Empty, context: CallContext): Promise<Empty> {
|
|
188
|
+
console.log('Server Shutting down in 5 seconds')
|
|
189
|
+
if (this.shutdownHandler) {
|
|
190
|
+
setTimeout(this.shutdownHandler, 5000)
|
|
191
|
+
}
|
|
192
|
+
return {}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async processLogs(request: ProcessLogsRequest, context: CallContext): Promise<ProcessLogsResponse> {
|
|
196
|
+
if (!this.started) {
|
|
197
|
+
throw new ServerError(Status.UNAVAILABLE, 'Service Not started.')
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const resp: O11yResult = {
|
|
201
|
+
gauges: [],
|
|
202
|
+
counters: [],
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const promises: Promise<O11yResult>[] = []
|
|
206
|
+
for (const l of request.logBindings) {
|
|
207
|
+
if (!l.log) {
|
|
208
|
+
throw new ServerError(Status.INVALID_ARGUMENT, "Log can't be null")
|
|
209
|
+
}
|
|
210
|
+
// const jsonString = Buffer.from(l.log.raw.buffer).toString("utf-8")
|
|
211
|
+
// const jsonString = String.fromCharCode.apply(null, l.log.raw)
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
const jsonString = Utf8ArrayToStr(l.log.raw)
|
|
215
|
+
const log: Log = JSON.parse(jsonString)
|
|
216
|
+
const handler = this.eventHandlers[l.handlerId]
|
|
217
|
+
const promise = handler(log).catch((e) => {
|
|
218
|
+
throw new ServerError(Status.INTERNAL, 'error processing log: ' + jsonString + '\n' + e.toString())
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
promises.push(promise)
|
|
222
|
+
} catch (e) {
|
|
223
|
+
throw new ServerError(Status.INTERNAL, 'error parse log: ' + l)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const results = await Promise.all(promises)
|
|
228
|
+
for (const res of results) {
|
|
229
|
+
resp.counters = resp.counters.concat(res.counters)
|
|
230
|
+
resp.gauges = resp.gauges.concat(res.gauges)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
let updated = false
|
|
234
|
+
if (
|
|
235
|
+
global.PROCESSOR_STATE.templatesInstances &&
|
|
236
|
+
this.templateInstances.length != global.PROCESSOR_STATE.templatesInstances.length
|
|
237
|
+
) {
|
|
238
|
+
await this.configure()
|
|
239
|
+
updated = true
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
recordRuntimeInfo(resp, HandlerType.LOG)
|
|
243
|
+
return {
|
|
244
|
+
result: resp,
|
|
245
|
+
configUpdated: updated,
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async processTransactions(
|
|
250
|
+
request: ProcessTransactionsRequest,
|
|
251
|
+
context: CallContext
|
|
252
|
+
): Promise<ProcessTransactionsResponse> {
|
|
253
|
+
if (!this.started) {
|
|
254
|
+
throw new ServerError(Status.UNAVAILABLE, 'Service not started.')
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
throw new ServerError(Status.UNIMPLEMENTED, 'Processing transaction is not suppored.')
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async processInstructions(
|
|
261
|
+
request: ProcessInstructionsRequest,
|
|
262
|
+
context: CallContext
|
|
263
|
+
): Promise<ProcessInstructionsResponse> {
|
|
264
|
+
if (!this.started) {
|
|
265
|
+
throw new ServerError(Status.UNAVAILABLE, 'Service not started.')
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const result: O11yResult = {
|
|
269
|
+
gauges: [],
|
|
270
|
+
counters: [],
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Only have instruction handlers for solana processors
|
|
274
|
+
if (global.PROCESSOR_STATE.solanaProcessors) {
|
|
275
|
+
const processorPromises: Promise<void>[] = []
|
|
276
|
+
for (const instruction of request.instructions) {
|
|
277
|
+
if (!instruction) {
|
|
278
|
+
throw new ServerError(Status.INVALID_ARGUMENT, 'instruction cannot be null')
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
processorPromises.push(
|
|
282
|
+
new Promise((resolve, _) => {
|
|
283
|
+
for (const processor of global.PROCESSOR_STATE.solanaProcessors) {
|
|
284
|
+
if (processor.address === instruction.programAccountId) {
|
|
285
|
+
let res: O11yResult | null
|
|
286
|
+
if (instruction.parsed) {
|
|
287
|
+
res = processor.handleInstruction(JSON.parse(new TextDecoder().decode(instruction.parsed)))
|
|
288
|
+
} else if (instruction.instructionData) {
|
|
289
|
+
res = processor.handleInstruction(instruction.instructionData)
|
|
290
|
+
} else {
|
|
291
|
+
continue
|
|
292
|
+
}
|
|
293
|
+
if (res) {
|
|
294
|
+
try {
|
|
295
|
+
res.gauges.forEach((g) => {
|
|
296
|
+
if (g.metadata) {
|
|
297
|
+
g.metadata.blockNumber = instruction.slot
|
|
298
|
+
}
|
|
299
|
+
result.gauges.push(g)
|
|
300
|
+
})
|
|
301
|
+
res.counters.forEach((c) => {
|
|
302
|
+
if (c.metadata) {
|
|
303
|
+
c.metadata.blockNumber = instruction.slot
|
|
304
|
+
}
|
|
305
|
+
result.counters.push(c)
|
|
306
|
+
})
|
|
307
|
+
} catch (e) {
|
|
308
|
+
console.error('error processing instruction ' + e.toString())
|
|
309
|
+
}
|
|
310
|
+
} else {
|
|
311
|
+
console.warn(
|
|
312
|
+
`Failed to decode the instruction: ${instruction.instructionData} with slot: ${instruction.slot}`
|
|
313
|
+
)
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
resolve()
|
|
318
|
+
})
|
|
319
|
+
)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
await Promise.all(processorPromises)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
recordRuntimeInfo(result, HandlerType.INSTRUCTION)
|
|
326
|
+
return {
|
|
327
|
+
result,
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
async processBlocks(request: ProcessBlocksRequest, context: CallContext): Promise<ProcessBlocksResponse> {
|
|
332
|
+
if (!this.started) {
|
|
333
|
+
throw new ServerError(Status.UNAVAILABLE, 'Service Not started.')
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const promises = request.blockBindings.map((binding) => this.processBlock(binding))
|
|
337
|
+
const results = await Promise.all(promises)
|
|
338
|
+
|
|
339
|
+
const res = O11yResult.fromPartial({})
|
|
340
|
+
|
|
341
|
+
for (const r of results) {
|
|
342
|
+
res.counters = res.counters.concat(r.counters)
|
|
343
|
+
res.gauges = res.gauges.concat(r.gauges)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
recordRuntimeInfo(res, HandlerType.BLOCK)
|
|
347
|
+
return {
|
|
348
|
+
result: res,
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async processBlock(binding: BlockBinding): Promise<O11yResult> {
|
|
353
|
+
if (!binding.block) {
|
|
354
|
+
throw new ServerError(Status.INVALID_ARGUMENT, "Block can't be empty")
|
|
355
|
+
}
|
|
356
|
+
const jsonString = Utf8ArrayToStr(binding.block.raw)
|
|
357
|
+
|
|
358
|
+
const block: Block = JSON.parse(jsonString)
|
|
359
|
+
|
|
360
|
+
const resp: O11yResult = {
|
|
361
|
+
gauges: [],
|
|
362
|
+
counters: [],
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const promises: Promise<O11yResult>[] = []
|
|
366
|
+
for (const handlerId of binding.handlerIds) {
|
|
367
|
+
const promise = this.blockHandlers[handlerId](block).catch((e) => {
|
|
368
|
+
throw new ServerError(Status.INTERNAL, 'error processing block: ' + block.number + '\n' + e.toString())
|
|
369
|
+
})
|
|
370
|
+
promises.push(promise)
|
|
371
|
+
}
|
|
372
|
+
const allRes = await Promise.all(promises)
|
|
373
|
+
for (const res of allRes) {
|
|
374
|
+
resp.counters = resp.counters.concat(res.counters)
|
|
375
|
+
resp.gauges = resp.gauges.concat(res.gauges)
|
|
376
|
+
}
|
|
377
|
+
return resp
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// https://ourcodeworld.com/articles/read/164/how-to-convert-an-uint8array-to-string-in-javascript
|
|
382
|
+
/* eslint-disable */
|
|
383
|
+
function Utf8ArrayToStr(array: Uint8Array) {
|
|
384
|
+
let out, i, len, c
|
|
385
|
+
let char2, char3
|
|
386
|
+
|
|
387
|
+
out = ''
|
|
388
|
+
len = array.length
|
|
389
|
+
i = 0
|
|
390
|
+
while (i < len) {
|
|
391
|
+
c = array[i++]
|
|
392
|
+
switch (c >> 4) {
|
|
393
|
+
case 0:
|
|
394
|
+
case 1:
|
|
395
|
+
case 2:
|
|
396
|
+
case 3:
|
|
397
|
+
case 4:
|
|
398
|
+
case 5:
|
|
399
|
+
case 6:
|
|
400
|
+
case 7:
|
|
401
|
+
// 0xxxxxxx
|
|
402
|
+
out += String.fromCharCode(c)
|
|
403
|
+
break
|
|
404
|
+
case 12:
|
|
405
|
+
case 13:
|
|
406
|
+
// 110x xxxx 10xx xxxx
|
|
407
|
+
char2 = array[i++]
|
|
408
|
+
out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f))
|
|
409
|
+
break
|
|
410
|
+
case 14:
|
|
411
|
+
// 1110 xxxx 10xx xxxx 10xx xxxx
|
|
412
|
+
char2 = array[i++]
|
|
413
|
+
char3 = array[i++]
|
|
414
|
+
out += String.fromCharCode(((c & 0x0f) << 12) | ((char2 & 0x3f) << 6) | ((char3 & 0x3f) << 0))
|
|
415
|
+
break
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return out
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function recordRuntimeInfo(results: O11yResult, handlerType: HandlerType) {
|
|
423
|
+
results.gauges.forEach((e) => {
|
|
424
|
+
e.runtimeInfo = {
|
|
425
|
+
from: handlerType,
|
|
426
|
+
}
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
results.counters.forEach((e) => {
|
|
430
|
+
e.runtimeInfo = {
|
|
431
|
+
from: handlerType,
|
|
432
|
+
}
|
|
433
|
+
})
|
|
434
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { SolanaBaseProcessor } from '../../solana-processor'
|
|
2
|
+
import { SolanaContext } from '../../context'
|
|
3
|
+
import { Instruction } from '@project-serum/anchor'
|
|
4
|
+
import { Approve, Burn, CloseAccount, FreezeAccount, InitializeAccount, InitializeAccount2, InitializeAccount3, InitializeMint, InitializeMultisig, MintTo, Revoke, ThawAccount, Transfer } from './types';
|
|
5
|
+
import { SolanaBindOptions } from '../../bind-options';
|
|
6
|
+
|
|
7
|
+
export class SPLTokenProcessor extends SolanaBaseProcessor {
|
|
8
|
+
static bind(options: SolanaBindOptions): SPLTokenProcessor {
|
|
9
|
+
if (options && !options.name) {
|
|
10
|
+
options.name = 'SPL Token Program'
|
|
11
|
+
}
|
|
12
|
+
return new SPLTokenProcessor(options)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
fromParsedInstruction: (instruction: { type: string, info: any }) => Instruction | null = (instruction: { type: string, info: any }) => {
|
|
16
|
+
const instructionType = instruction.type
|
|
17
|
+
if (!instructionType) {
|
|
18
|
+
return null
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
name: instruction.type,
|
|
22
|
+
data: {
|
|
23
|
+
...instruction.info,
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public onInitializeMint(
|
|
29
|
+
handler: (data: InitializeMint, ctx: SolanaContext) => void
|
|
30
|
+
): SPLTokenProcessor {
|
|
31
|
+
this.onInstruction('initializeMint', (ins: Instruction, ctx) => {
|
|
32
|
+
if (ins) {
|
|
33
|
+
handler(ins.data as InitializeMint, ctx)
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
return this
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public onInitializeAccount(
|
|
40
|
+
hanlder: (data: InitializeAccount, ctx: SolanaContext) => void
|
|
41
|
+
): SPLTokenProcessor {
|
|
42
|
+
this.onInstruction('initializeAccount', (ins: Instruction, ctx) => {
|
|
43
|
+
if (ins) {
|
|
44
|
+
hanlder(ins.data as InitializeAccount, ctx)
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
return this
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public onInitializeAccount2(
|
|
51
|
+
hanlder: (data: InitializeAccount2, ctx: SolanaContext) => void
|
|
52
|
+
): SPLTokenProcessor {
|
|
53
|
+
this.onInstruction('initializeAccount2', (ins: Instruction, ctx) => {
|
|
54
|
+
if (ins) {
|
|
55
|
+
hanlder(ins.data as InitializeAccount2, ctx)
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
return this
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public onInitializeAccount3(
|
|
62
|
+
hanlder: (data: InitializeAccount3, ctx: SolanaContext) => void
|
|
63
|
+
): SPLTokenProcessor {
|
|
64
|
+
this.onInstruction('initializeAccount3', (ins: Instruction, ctx) => {
|
|
65
|
+
if (ins) {
|
|
66
|
+
hanlder(ins.data as InitializeAccount3, ctx)
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
return this
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public onInitializeMultisig(
|
|
73
|
+
handler: (data: InitializeMultisig, ctx: SolanaContext) => void
|
|
74
|
+
): SPLTokenProcessor {
|
|
75
|
+
this.onInstruction('initializeMultisig', (ins: Instruction, ctx) => {
|
|
76
|
+
if (ins) {
|
|
77
|
+
handler(ins.data as InitializeMultisig, ctx)
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
return this
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public onTransfer(handler: (data: Transfer, ctx: SolanaContext) => void): SPLTokenProcessor {
|
|
84
|
+
this.onInstruction('transfer', (ins: Instruction, ctx) => {
|
|
85
|
+
if (ins) {
|
|
86
|
+
handler(ins.data as Transfer, ctx)
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
return this
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public onApprovend(handler: (data: Approve, ctx: SolanaContext) => void): SPLTokenProcessor {
|
|
93
|
+
this.onInstruction('approve', (ins: Instruction, ctx) => {
|
|
94
|
+
if (ins) {
|
|
95
|
+
handler(ins.data as Approve, ctx)
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
return this
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public onRevoke(handler: (data: Revoke, ctx: SolanaContext) => void): SPLTokenProcessor {
|
|
102
|
+
this.onInstruction('revoke', (ins: Instruction, ctx) => {
|
|
103
|
+
if (ins) {
|
|
104
|
+
handler(ins.data as Revoke, ctx)
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
return this
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public onSetAuthority(handler: (data: any, ctx: SolanaContext) => void): SPLTokenProcessor {
|
|
111
|
+
this.onInstruction('setAuthority', (ins: Instruction, ctx) => {
|
|
112
|
+
if (ins) {
|
|
113
|
+
handler(ins.data as any, ctx)
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
return this
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public onMintTo(handler: (data: MintTo, ctx: SolanaContext) => void): SPLTokenProcessor {
|
|
120
|
+
this.onInstruction('mintTo', (ins: Instruction, ctx) => {
|
|
121
|
+
if (ins) {
|
|
122
|
+
handler(ins.data as MintTo, ctx)
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
return this
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public onBurn(handler: (data: Burn, ctx: SolanaContext) => void): SPLTokenProcessor {
|
|
129
|
+
this.onInstruction('burn', (ins: Instruction, ctx) => {
|
|
130
|
+
if (ins) {
|
|
131
|
+
handler(ins.data as Burn, ctx)
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
return this
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public onCloseAccount(handler: (data: CloseAccount, ctx: SolanaContext) => void): SPLTokenProcessor {
|
|
138
|
+
this.onInstruction('closeAccount', (ins: Instruction, ctx) => {
|
|
139
|
+
if (ins) {
|
|
140
|
+
handler(ins.data as CloseAccount, ctx)
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
return this
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
public onFreezeAccount(handler: (data: FreezeAccount, ctx: SolanaContext) => void): SPLTokenProcessor {
|
|
147
|
+
this.onInstruction('freezeAccount', (ins: Instruction, ctx) => {
|
|
148
|
+
if (ins) {
|
|
149
|
+
handler(ins.data as FreezeAccount, ctx)
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
return this
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public onThawAccount(handler: (data: ThawAccount, ctx: SolanaContext) => void): SPLTokenProcessor {
|
|
156
|
+
this.onInstruction('thawAccount', (ins: Instruction, ctx) => {
|
|
157
|
+
if (ins) {
|
|
158
|
+
handler(ins.data as ThawAccount, ctx)
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
return this
|
|
162
|
+
}
|
|
163
|
+
// Todo(pcxu): auto gen this file
|
|
164
|
+
}
|