@sentio/sdk 2.35.0 → 2.36.0-rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. package/lib/aptos/aptos-plugin.d.ts.map +1 -1
  2. package/lib/aptos/aptos-plugin.js +30 -20
  3. package/lib/aptos/aptos-plugin.js.map +1 -1
  4. package/lib/eth/binds.d.ts +2 -2
  5. package/lib/eth/binds.d.ts.map +1 -1
  6. package/lib/eth/binds.js +4 -4
  7. package/lib/eth/binds.js.map +1 -1
  8. package/lib/eth/codegen/codegen.js +2 -0
  9. package/lib/eth/codegen/codegen.js.map +1 -1
  10. package/lib/eth/codegen/ethers-sentio.d.ts.map +1 -1
  11. package/lib/eth/codegen/ethers-sentio.js +2 -0
  12. package/lib/eth/codegen/ethers-sentio.js.map +1 -1
  13. package/lib/eth/eth-plugin.js +2 -2
  14. package/lib/eth/eth-plugin.js.map +1 -1
  15. package/lib/fuel/base-processor.d.ts +13 -0
  16. package/lib/fuel/base-processor.d.ts.map +1 -0
  17. package/lib/fuel/base-processor.js +26 -0
  18. package/lib/fuel/base-processor.js.map +1 -0
  19. package/lib/fuel/codegen/codegen.d.ts +2 -0
  20. package/lib/fuel/codegen/codegen.d.ts.map +1 -0
  21. package/lib/fuel/codegen/codegen.js +132 -0
  22. package/lib/fuel/codegen/codegen.js.map +1 -0
  23. package/lib/fuel/codegen/index.d.ts +2 -0
  24. package/lib/fuel/codegen/index.d.ts.map +1 -0
  25. package/lib/fuel/codegen/index.js +2 -0
  26. package/lib/fuel/codegen/index.js.map +1 -0
  27. package/lib/fuel/codegen/run.d.ts +2 -0
  28. package/lib/fuel/codegen/run.d.ts.map +1 -0
  29. package/lib/fuel/codegen/run.js +11 -0
  30. package/lib/fuel/codegen/run.js.map +1 -0
  31. package/lib/fuel/codegen/utils.d.ts +2 -0
  32. package/lib/fuel/codegen/utils.d.ts.map +1 -0
  33. package/lib/fuel/codegen/utils.js +4 -0
  34. package/lib/fuel/codegen/utils.js.map +1 -0
  35. package/lib/fuel/context.d.ts +14 -0
  36. package/lib/fuel/context.d.ts.map +1 -0
  37. package/lib/fuel/context.js +27 -0
  38. package/lib/fuel/context.js.map +1 -0
  39. package/lib/fuel/fuel-plugin.d.ts +17 -0
  40. package/lib/fuel/fuel-plugin.d.ts.map +1 -0
  41. package/lib/fuel/fuel-plugin.js +96 -0
  42. package/lib/fuel/fuel-plugin.js.map +1 -0
  43. package/lib/fuel/fuel-processor.d.ts +32 -0
  44. package/lib/fuel/fuel-processor.d.ts.map +1 -0
  45. package/lib/fuel/fuel-processor.js +94 -0
  46. package/lib/fuel/fuel-processor.js.map +1 -0
  47. package/lib/fuel/index.d.ts +7 -0
  48. package/lib/fuel/index.d.ts.map +1 -0
  49. package/lib/fuel/index.js +7 -0
  50. package/lib/fuel/index.js.map +1 -0
  51. package/lib/fuel/network.d.ts +8 -0
  52. package/lib/fuel/network.d.ts.map +1 -0
  53. package/lib/fuel/network.js +14 -0
  54. package/lib/fuel/network.js.map +1 -0
  55. package/lib/fuel/transaction.d.ts +8 -0
  56. package/lib/fuel/transaction.d.ts.map +1 -0
  57. package/lib/fuel/transaction.js +23 -0
  58. package/lib/fuel/transaction.js.map +1 -0
  59. package/lib/testing/fuel-facet.d.ts +9 -0
  60. package/lib/testing/fuel-facet.d.ts.map +1 -0
  61. package/lib/testing/fuel-facet.js +51 -0
  62. package/lib/testing/fuel-facet.js.map +1 -0
  63. package/lib/testing/test-processor-server.d.ts +2 -0
  64. package/lib/testing/test-processor-server.d.ts.map +1 -1
  65. package/lib/testing/test-processor-server.js +3 -0
  66. package/lib/testing/test-processor-server.js.map +1 -1
  67. package/package.json +12 -6
  68. package/src/aptos/aptos-plugin.ts +38 -32
  69. package/src/eth/binds.ts +4 -4
  70. package/src/eth/codegen/codegen.ts +2 -0
  71. package/src/eth/codegen/ethers-sentio.ts +4 -1
  72. package/src/eth/eth-plugin.ts +2 -2
  73. package/src/fuel/base-processor.ts +38 -0
  74. package/src/fuel/codegen/codegen.ts +149 -0
  75. package/src/fuel/codegen/index.ts +1 -0
  76. package/src/fuel/codegen/run.ts +10 -0
  77. package/src/fuel/codegen/utils.ts +6 -0
  78. package/src/fuel/context.ts +34 -0
  79. package/src/fuel/fuel-plugin.ts +128 -0
  80. package/src/fuel/fuel-processor.ts +125 -0
  81. package/src/fuel/index.ts +6 -0
  82. package/src/fuel/network.ts +16 -0
  83. package/src/fuel/transaction.ts +43 -0
  84. package/src/testing/fuel-facet.ts +58 -0
  85. package/src/testing/test-processor-server.ts +4 -1
@@ -0,0 +1,128 @@
1
+ import { errorString, GLOBAL_CONFIG, mergeProcessResults, Plugin, PluginManager, USER_PROCESSOR } from '@sentio/runtime'
2
+ import {
3
+ ContractConfig,
4
+ Data_FuelCall,
5
+ DataBinding,
6
+ HandlerType,
7
+ ProcessConfigResponse,
8
+ ProcessResult,
9
+ StartRequest
10
+ } from '@sentio/protos'
11
+
12
+ import { ServerError, Status } from 'nice-grpc'
13
+ import { GlobalProcessorState } from '../eth/base-processor.js'
14
+ import { TemplateInstanceState } from '../core/template.js'
15
+ import { FuelProcessorState } from './fuel-processor.js'
16
+
17
+ interface Handlers {
18
+ callHandlers: ((trace: Data_FuelCall) => Promise<ProcessResult>)[]
19
+ }
20
+
21
+ export class FuelPlugin extends Plugin {
22
+ name: string = 'FuelPlugin'
23
+ handlers: Handlers = {
24
+ callHandlers: []
25
+ }
26
+
27
+ async configure(config: ProcessConfigResponse) {
28
+ const handlers: Handlers = {
29
+ callHandlers: []
30
+ }
31
+
32
+ for (const processor of FuelProcessorState.INSTANCE.getValues()) {
33
+ await processor.configure()
34
+ const contractConfig = ContractConfig.fromPartial({
35
+ processorType: USER_PROCESSOR,
36
+ contract: {
37
+ name: processor.config.name,
38
+ chainId: processor.config.chainId.toString(),
39
+ address: processor.config.address,
40
+ abi: ''
41
+ },
42
+ startBlock: processor.config.startBlock,
43
+ endBlock: processor.config.endBlock
44
+ })
45
+
46
+ for (const callHandler of processor.callHandlers) {
47
+ const handlerId = handlers.callHandlers.push(callHandler.handler) - 1
48
+ const fetchConfig = {
49
+ handlerId,
50
+ filters: callHandler.fetchConfig.filters || []
51
+ }
52
+ contractConfig.fuelCallConfigs.push(fetchConfig)
53
+ }
54
+
55
+ // Finish up a contract
56
+ config.contractConfigs.push(contractConfig)
57
+ }
58
+
59
+ for (const processor of GlobalProcessorState.INSTANCE.getValues()) {
60
+ const chainId = processor.getChainId()
61
+
62
+ const contractConfig = ContractConfig.fromPartial({
63
+ processorType: USER_PROCESSOR,
64
+ contract: {
65
+ name: processor.config.name,
66
+ chainId: chainId.toString(),
67
+ address: processor.config.address, // can only be *
68
+ abi: ''
69
+ },
70
+ startBlock: processor.config.startBlock,
71
+ endBlock: processor.config.endBlock
72
+ })
73
+
74
+ config.contractConfigs.push(contractConfig)
75
+ }
76
+
77
+ this.handlers = handlers
78
+ }
79
+
80
+ supportedHandlers = [HandlerType.FUEL_CALL]
81
+
82
+ processBinding(request: DataBinding): Promise<ProcessResult> {
83
+ // return Promise.resolve(undefined);
84
+ switch (request.handlerType) {
85
+ // case HandlerType.FUEL_LOG:
86
+ // return this.processLog(request)
87
+ // case HandlerType.FUEL_TRACE:
88
+ // return this.processTrace(request)
89
+ // case HandlerType.FUEL_BLOCK:
90
+ // return this.processBlock(request)
91
+ case HandlerType.FUEL_CALL:
92
+ return this.processTransaction(request)
93
+ default:
94
+ throw new ServerError(Status.INVALID_ARGUMENT, 'No handle type registered ' + request.handlerType)
95
+ }
96
+ }
97
+
98
+ async start(request: StartRequest) {}
99
+
100
+ stateDiff(config: ProcessConfigResponse): boolean {
101
+ return TemplateInstanceState.INSTANCE.getValues().length !== config.templateInstances.length
102
+ }
103
+
104
+ async processTransaction(binding: DataBinding): Promise<ProcessResult> {
105
+ if (!binding.data?.fuelCall?.transaction) {
106
+ throw new ServerError(Status.INVALID_ARGUMENT, "transaction can't be null")
107
+ }
108
+ const fuelTransaction = binding.data.fuelCall
109
+
110
+ const promises: Promise<ProcessResult>[] = []
111
+
112
+ for (const handlerId of binding.handlerIds) {
113
+ const promise = this.handlers.callHandlers[handlerId](fuelTransaction).catch((e) => {
114
+ throw new ServerError(
115
+ Status.INTERNAL,
116
+ 'error processing transaction: ' + JSON.stringify(fuelTransaction.transaction) + '\n' + errorString(e)
117
+ )
118
+ })
119
+ if (GLOBAL_CONFIG.execution.sequential) {
120
+ await promise
121
+ }
122
+ promises.push(promise)
123
+ }
124
+ return mergeProcessResults(await Promise.all(promises))
125
+ }
126
+ }
127
+
128
+ PluginManager.INSTANCE.register(new FuelPlugin())
@@ -0,0 +1,125 @@
1
+ import { ListStateStorage } from '@sentio/runtime'
2
+ import { Data_FuelCall, FuelCallFilter, FuelCallHandlerConfig, ProcessResult } from '@sentio/protos'
3
+ import { FuelCall, FuelContext } from './context.js'
4
+ import { bn, Contract, Interface, InvocationCallResult, JsonAbi, Provider } from 'fuels'
5
+ import { FuelNetwork, getRpcEndpoint } from './network.js'
6
+ import { decodeFuelTransaction, DEFAULT_FUEL_FETCH_CONFIG, FuelFetchConfig, FuelTransaction } from './transaction.js'
7
+
8
+ export class FuelProcessorState extends ListStateStorage<FuelProcessor> {
9
+ static INSTANCE = new FuelProcessorState()
10
+ }
11
+
12
+ export class FuelProcessor {
13
+ callHandlers: CallHandler<Data_FuelCall>[] = []
14
+
15
+ private provider: Provider
16
+
17
+ static bind(config: FuelProcessorConfig): FuelProcessor {
18
+ const processor = new FuelProcessor(config)
19
+ FuelProcessorState.INSTANCE.addValue(processor)
20
+ return processor
21
+ }
22
+
23
+ constructor(readonly config: FuelProcessorConfig) {}
24
+
25
+ async configure() {
26
+ const url = getRpcEndpoint(this.config.chainId)
27
+ this.provider = await Provider.create(url)
28
+ }
29
+
30
+ public onTransaction(
31
+ handler: (transaction: FuelTransaction, ctx: FuelContext) => void | Promise<void>,
32
+ config: FuelFetchConfig = DEFAULT_FUEL_FETCH_CONFIG
33
+ ) {
34
+ const callHandler = {
35
+ handler: async (call: Data_FuelCall) => {
36
+ const abiMap = this.config.abi
37
+ ? {
38
+ [this.config.address]: this.config.abi
39
+ }
40
+ : {}
41
+ const tx = decodeFuelTransaction(call.transaction, abiMap, this.provider)
42
+
43
+ const ctx = new FuelContext(tx, this.config.chainId)
44
+ await handler(tx, ctx)
45
+ return ctx.stopAndGetResult()
46
+ },
47
+ fetchConfig: {
48
+ filters: [],
49
+ ...config
50
+ }
51
+ }
52
+ this.callHandlers.push(callHandler)
53
+ return this
54
+ }
55
+
56
+ public onCall(
57
+ nameFilter: string | string[],
58
+ handler: (call: FuelCall, ctx: FuelContext) => void | Promise<void>,
59
+ config: FuelFetchConfig = DEFAULT_FUEL_FETCH_CONFIG
60
+ ) {
61
+ const names = new Set(Array.isArray(nameFilter) ? nameFilter : [nameFilter])
62
+
63
+ if (!this.config.abi) {
64
+ throw new Error('ABI must be provided to use onCall')
65
+ }
66
+ const abi = this.config.abi
67
+
68
+ const filters: Record<string, FuelCallFilter> = {}
69
+ const abiInterface = new Interface(abi)
70
+ for (const name of names) {
71
+ try {
72
+ const func = abiInterface.functions[name]
73
+ const filter = bn(func.selector, 'hex').toString()
74
+ filters[func.name] = {
75
+ function: filter,
76
+ includeFailed: !!config.includeFailed
77
+ }
78
+ } catch (e) {
79
+ console.error(e)
80
+ }
81
+ }
82
+
83
+ const callHandler = {
84
+ handler: async (call: Data_FuelCall) => {
85
+ const contract = new Contract(this.config.address, abi, this.provider)
86
+ const gqlTransaction = call.transaction
87
+ const tx = decodeFuelTransaction(gqlTransaction, { [this.config.address]: abi }, this.provider)
88
+
89
+ const ctx = new FuelContext(tx, this.config.chainId)
90
+ for (const op of tx.operations) {
91
+ for (const call of op.calls || []) {
92
+ if (names.has(call.functionName)) {
93
+ const fn = contract.functions[call.functionName]
94
+ const args = Object.values(call.argumentsProvided || {})
95
+ const scope = fn(...args)
96
+ const invocationResult = await InvocationCallResult.build(scope, tx, false)
97
+ await handler(invocationResult, ctx)
98
+ }
99
+ }
100
+ }
101
+
102
+ return ctx.stopAndGetResult()
103
+ },
104
+ fetchConfig: {
105
+ filters: Object.values(filters)
106
+ }
107
+ }
108
+ this.callHandlers.push(callHandler)
109
+ return this
110
+ }
111
+ }
112
+
113
+ export type CallHandler<T> = {
114
+ handler: (call: T) => Promise<ProcessResult>
115
+ fetchConfig: Partial<FuelCallHandlerConfig>
116
+ }
117
+
118
+ export type FuelProcessorConfig = {
119
+ address: string
120
+ name?: string
121
+ chainId: FuelNetwork
122
+ startBlock?: bigint
123
+ endBlock?: bigint
124
+ abi?: JsonAbi
125
+ }
@@ -0,0 +1,6 @@
1
+ export { FuelPlugin } from './fuel-plugin.js'
2
+ export * from './context.js'
3
+ export * from './fuel-processor.js'
4
+ export * from './network.js'
5
+ export * from './transaction.js'
6
+ export * from './base-processor.js'
@@ -0,0 +1,16 @@
1
+ import { FuelChainId } from '@sentio/chain'
2
+ import { FUEL_BETA_5_NETWORK_URL, FUEL_NETWORK_URL } from 'fuels'
3
+
4
+ export type FuelNetwork = FuelChainId
5
+ export const FuelNetwork = <const>{
6
+ MAIN_NET: FuelChainId.FUEL_MAINNET,
7
+ TEST_NET: FuelChainId.FUEL_TESTNET_BETA_V5
8
+ }
9
+
10
+ export function getRpcEndpoint(network: FuelNetwork): string {
11
+ switch (network) {
12
+ case FuelNetwork.TEST_NET:
13
+ return FUEL_BETA_5_NETWORK_URL
14
+ }
15
+ return FUEL_NETWORK_URL
16
+ }
@@ -0,0 +1,43 @@
1
+ import {
2
+ AbiMap,
3
+ arrayify,
4
+ assembleTransactionSummary,
5
+ bn,
6
+ processGqlReceipt,
7
+ Provider,
8
+ TransactionCoder,
9
+ TransactionSummary
10
+ } from 'fuels'
11
+
12
+ export type FuelFetchConfig = {
13
+ includeFailed?: boolean
14
+ }
15
+
16
+ export const DEFAULT_FUEL_FETCH_CONFIG: FuelFetchConfig = {
17
+ includeFailed: false
18
+ }
19
+
20
+ export type FuelTransaction = TransactionSummary
21
+
22
+ export function decodeFuelTransaction(gqlTransaction: any, abiMap: AbiMap, provider: Provider): FuelTransaction {
23
+ const rawPayload = arrayify(gqlTransaction.rawPayload)
24
+
25
+ const [decodedTransaction] = new TransactionCoder().decode(rawPayload, 0)
26
+
27
+ const receipts = gqlTransaction.receipts?.map(processGqlReceipt) || []
28
+
29
+ const { gasPerByte, gasPriceFactor, maxInputs, gasCosts } = provider.getChain().consensusParameters
30
+
31
+ return assembleTransactionSummary({
32
+ id: gqlTransaction.id,
33
+ receipts,
34
+ transaction: decodedTransaction,
35
+ transactionBytes: rawPayload,
36
+ gqlTransactionStatus: gqlTransaction.status,
37
+ gasPerByte: bn(gasPerByte),
38
+ gasPriceFactor: bn(gasPriceFactor),
39
+ abiMap,
40
+ maxInputs,
41
+ gasCosts
42
+ })
43
+ }
@@ -0,0 +1,58 @@
1
+ import { TestProcessorServer } from './test-processor-server.js'
2
+ import { FuelChainId } from '@sentio/chain'
3
+ import { DataBinding, HandlerType } from '@sentio/protos'
4
+ import { FuelNetwork } from '../fuel/index.js'
5
+
6
+ export class FuelFacet {
7
+ server: TestProcessorServer
8
+
9
+ constructor(server: TestProcessorServer) {
10
+ this.server = server
11
+ }
12
+
13
+ testOnTransaction(transaction: any, network: FuelNetwork = FuelNetwork.TEST_NET) {
14
+ const bindings = this.buildBinding(transaction, network)
15
+ if (!bindings) {
16
+ throw Error('Invalid test transaction: ' + JSON.stringify(transaction))
17
+ }
18
+
19
+ return this.server.processBindings({
20
+ bindings
21
+ })
22
+ }
23
+
24
+ private buildBinding(transaction: any, network: FuelChainId): DataBinding[] {
25
+ const res: DataBinding[] = []
26
+ for (const config of this.server.contractConfigs) {
27
+ if (config.contract?.chainId !== network) {
28
+ continue
29
+ }
30
+ for (const callConfig of config.fuelCallConfigs) {
31
+ const binding = {
32
+ data: {
33
+ fuelCall: {
34
+ transaction,
35
+ timestamp: new Date()
36
+ }
37
+ },
38
+ handlerIds: [callConfig.handlerId],
39
+ handlerType: HandlerType.FUEL_CALL
40
+ }
41
+
42
+ const filter = callConfig.filters[0]?.function
43
+ if (filter) {
44
+ // filter out by tx receipt
45
+ for (const receipt of transaction.receipts || []) {
46
+ if (receipt.receiptType == 'CALL' && receipt.param1 == filter) {
47
+ res.push(binding)
48
+ }
49
+ }
50
+ } else {
51
+ res.push(binding)
52
+ }
53
+ }
54
+ }
55
+
56
+ return res
57
+ }
58
+ }
@@ -8,7 +8,7 @@ import {
8
8
  ProcessConfigRequest,
9
9
  ProcessConfigResponse,
10
10
  ProcessorServiceImplementation,
11
- StartRequest,
11
+ StartRequest
12
12
  } from '@sentio/protos'
13
13
  import { CallContext } from 'nice-grpc-common'
14
14
  import { Endpoints, ProcessorServiceImpl, State } from '@sentio/runtime'
@@ -18,6 +18,7 @@ import { AptosFacet } from './aptos-facet.js'
18
18
  import { SolanaFacet } from './solana-facet.js'
19
19
  import { EthFacet } from './eth-facet.js'
20
20
  import { SuiFacet } from './sui-facet.js'
21
+ import { FuelFacet } from './fuel-facet.js'
21
22
 
22
23
  export const TEST_CONTEXT: CallContext = <CallContext>{}
23
24
 
@@ -34,6 +35,7 @@ export class TestProcessorServer implements ProcessorServiceImplementation {
34
35
  eth: EthFacet
35
36
  solana: SolanaFacet
36
37
  sui: SuiFacet
38
+ fuel: FuelFacet
37
39
 
38
40
  constructor(loader: () => Promise<any>, httpEndpoints: Record<string, string> = {}) {
39
41
  cleanTest()
@@ -43,6 +45,7 @@ export class TestProcessorServer implements ProcessorServiceImplementation {
43
45
  this.solana = new SolanaFacet(this)
44
46
  this.eth = new EthFacet(this)
45
47
  this.sui = new SuiFacet(this)
48
+ this.fuel = new FuelFacet(this)
46
49
 
47
50
  for (const k in CHAIN_MAP) {
48
51
  const http = httpEndpoints[k] || ''