@sentio/sdk 2.0.0-rc.13 → 2.0.0-rc.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.
Files changed (240) hide show
  1. package/lib/aptos/api.d.ts +5 -0
  2. package/lib/aptos/api.js +21 -0
  3. package/lib/aptos/api.js.map +1 -0
  4. package/lib/aptos/aptos-plugin.d.ts +14 -0
  5. package/lib/aptos/aptos-plugin.js +146 -0
  6. package/lib/aptos/aptos-plugin.js.map +1 -0
  7. package/lib/aptos/aptos-processor.d.ts +72 -0
  8. package/lib/aptos/aptos-processor.js +201 -0
  9. package/lib/aptos/aptos-processor.js.map +1 -0
  10. package/lib/aptos/builtin/0x1.d.ts +2140 -0
  11. package/lib/aptos/builtin/0x1.js +2727 -0
  12. package/lib/aptos/builtin/0x1.js.map +1 -0
  13. package/lib/aptos/builtin/0x3.d.ts +573 -0
  14. package/lib/aptos/builtin/0x3.js +496 -0
  15. package/lib/aptos/builtin/0x3.js.map +1 -0
  16. package/lib/aptos/builtin/index.d.ts +2 -0
  17. package/lib/aptos/builtin/index.js +6 -0
  18. package/lib/aptos/builtin/index.js.map +1 -0
  19. package/lib/aptos/codegen/codegen.d.ts +23 -0
  20. package/lib/aptos/codegen/codegen.js +388 -0
  21. package/lib/aptos/codegen/codegen.js.map +1 -0
  22. package/lib/aptos/codegen/index.d.ts +1 -0
  23. package/lib/aptos/codegen/index.js +2 -0
  24. package/lib/aptos/codegen/index.js.map +1 -0
  25. package/lib/aptos/codegen/typegen.d.ts +18 -0
  26. package/lib/aptos/codegen/typegen.js +145 -0
  27. package/lib/aptos/codegen/typegen.js.map +1 -0
  28. package/lib/aptos/codegen/typegen.test.d.ts +1 -0
  29. package/lib/aptos/codegen/typegen.test.js.map +1 -0
  30. package/lib/aptos/context.d.ts +21 -0
  31. package/lib/aptos/context.js +59 -0
  32. package/lib/aptos/context.js.map +1 -0
  33. package/lib/aptos/index.d.ts +9 -0
  34. package/lib/aptos/index.js +8 -0
  35. package/lib/aptos/index.js.map +1 -0
  36. package/lib/aptos/models.d.ts +37 -0
  37. package/lib/aptos/models.js +2 -0
  38. package/lib/aptos/models.js.map +1 -0
  39. package/lib/aptos/move-coder.d.ts +22 -0
  40. package/lib/aptos/move-coder.js +164 -0
  41. package/lib/aptos/move-coder.js.map +1 -0
  42. package/lib/aptos/move-types.d.ts +10 -0
  43. package/lib/aptos/move-types.js +2 -0
  44. package/lib/aptos/move-types.js.map +1 -0
  45. package/lib/aptos/network.d.ts +11 -0
  46. package/lib/aptos/network.js +27 -0
  47. package/lib/aptos/network.js.map +1 -0
  48. package/lib/aptos/run-codegen.d.ts +1 -0
  49. package/lib/aptos/run-codegen.js +12 -0
  50. package/lib/aptos/run-codegen.js.map +1 -0
  51. package/lib/aptos/tests/aptos.test.d.ts +1 -0
  52. package/lib/aptos/tests/aptos.test.js.map +1 -0
  53. package/lib/aptos/tests/souffl3.d.ts +1 -0
  54. package/lib/aptos/tests/souffl3.js +44 -0
  55. package/lib/aptos/tests/souffl3.js.map +1 -0
  56. package/lib/aptos/tests/types/index.d.ts +3 -0
  57. package/lib/aptos/tests/types/index.js +7 -0
  58. package/lib/aptos/tests/types/index.js.map +1 -0
  59. package/lib/aptos/tests/types/reserved.d.ts +445 -0
  60. package/lib/aptos/tests/types/reserved.js +301 -0
  61. package/lib/aptos/tests/types/reserved.js.map +1 -0
  62. package/lib/aptos/tests/types/soffl3.d.ts +1065 -0
  63. package/lib/aptos/tests/types/soffl3.js +548 -0
  64. package/lib/aptos/tests/types/soffl3.js.map +1 -0
  65. package/lib/aptos/tests/types/souffle.d.ts +440 -0
  66. package/lib/aptos/tests/types/souffle.js +295 -0
  67. package/lib/aptos/tests/types/souffle.js.map +1 -0
  68. package/lib/aptos/types.d.ts +9 -0
  69. package/lib/aptos/types.js +130 -0
  70. package/lib/aptos/types.js.map +1 -0
  71. package/lib/aptos/types.test.d.ts +1 -0
  72. package/lib/aptos/types.test.js.map +1 -0
  73. package/lib/aptos/utils.d.ts +7 -0
  74. package/lib/aptos/utils.js +20 -0
  75. package/lib/aptos/utils.js.map +1 -0
  76. package/lib/builtin/internal/eacaggregatorproxy_processor.js +90 -180
  77. package/lib/builtin/internal/eacaggregatorproxy_processor.js.map +1 -1
  78. package/lib/builtin/internal/erc1155_processor.js +25 -50
  79. package/lib/builtin/internal/erc1155_processor.js.map +1 -1
  80. package/lib/builtin/internal/erc20_processor.js +40 -80
  81. package/lib/builtin/internal/erc20_processor.js.map +1 -1
  82. package/lib/builtin/internal/erc20bytes_processor.js +30 -60
  83. package/lib/builtin/internal/erc20bytes_processor.js.map +1 -1
  84. package/lib/builtin/internal/erc721_processor.js +45 -90
  85. package/lib/builtin/internal/erc721_processor.js.map +1 -1
  86. package/lib/builtin/internal/weth9_processor.js +30 -60
  87. package/lib/builtin/internal/weth9_processor.js.map +1 -1
  88. package/lib/{utils/chain.d.ts → chain.d.ts} +0 -0
  89. package/lib/{utils/chain.js → chain.js} +0 -0
  90. package/lib/chain.js.map +1 -0
  91. package/lib/core/context.js +1 -1
  92. package/lib/core/context.js.map +1 -1
  93. package/lib/core/sui-plugin.js +1 -1
  94. package/lib/core/sui-plugin.js.map +1 -1
  95. package/lib/error.d.ts +1 -1
  96. package/lib/error.js +10 -12
  97. package/lib/error.js.map +1 -1
  98. package/lib/eth/base-processor-template.d.ts +3 -3
  99. package/lib/eth/base-processor-template.js.map +1 -1
  100. package/lib/eth/base-processor.d.ts +3 -3
  101. package/lib/eth/base-processor.js.map +1 -1
  102. package/lib/eth/{eth-event.d.ts → eth.d.ts} +1 -1
  103. package/lib/eth/eth.js +2 -0
  104. package/lib/eth/eth.js.map +1 -0
  105. package/lib/eth/index.d.ts +1 -0
  106. package/lib/eth/index.js +1 -0
  107. package/lib/eth/index.js.map +1 -1
  108. package/lib/index.d.ts +2 -2
  109. package/lib/index.js +2 -2
  110. package/lib/index.js.map +1 -1
  111. package/lib/solana/builtin/index.d.ts +1 -0
  112. package/lib/solana/builtin/index.js +2 -0
  113. package/lib/solana/builtin/index.js.map +1 -0
  114. package/lib/solana/builtin/spl-token-processor.d.ts +39 -0
  115. package/lib/solana/builtin/spl-token-processor.js +254 -0
  116. package/lib/solana/builtin/spl-token-processor.js.map +1 -0
  117. package/lib/solana/builtin/types.d.ts +427 -0
  118. package/lib/solana/builtin/types.js +200 -0
  119. package/lib/solana/builtin/types.js.map +1 -0
  120. package/lib/solana/codegen/codegen.d.ts +1 -0
  121. package/lib/solana/codegen/codegen.js +122 -0
  122. package/lib/solana/codegen/codegen.js.map +1 -0
  123. package/lib/solana/codegen/index.d.ts +1 -0
  124. package/lib/solana/codegen/index.js +2 -0
  125. package/lib/solana/codegen/index.js.map +1 -0
  126. package/lib/solana/index.d.ts +4 -0
  127. package/lib/solana/index.js +5 -0
  128. package/lib/solana/index.js.map +1 -0
  129. package/lib/solana/run-codegen.d.ts +2 -0
  130. package/lib/solana/run-codegen.js +12 -0
  131. package/lib/solana/run-codegen.js.map +1 -0
  132. package/lib/solana/solana-context.d.ts +9 -0
  133. package/lib/solana/solana-context.js +28 -0
  134. package/lib/solana/solana-context.js.map +1 -0
  135. package/lib/solana/solana-options.d.ts +10 -0
  136. package/lib/solana/solana-options.js +10 -0
  137. package/lib/solana/solana-options.js.map +1 -0
  138. package/lib/solana/solana-plugin.d.ts +9 -0
  139. package/lib/solana/solana-plugin.js +87 -0
  140. package/lib/solana/solana-plugin.js.map +1 -0
  141. package/lib/solana/solana-processor.d.ts +43 -0
  142. package/lib/solana/solana-processor.js +72 -0
  143. package/lib/solana/solana-processor.js.map +1 -0
  144. package/lib/solana/tests/solana.test.d.ts +1 -0
  145. package/lib/solana/tests/solana.test.js.map +1 -0
  146. package/lib/solana/tests/types/basic_1.d.ts +26 -0
  147. package/lib/solana/tests/types/basic_1.js +63 -0
  148. package/lib/solana/tests/types/basic_1.js.map +1 -0
  149. package/lib/solana/tests/types/basic_1_processor.d.ts +21 -0
  150. package/lib/solana/tests/types/basic_1_processor.js +35 -0
  151. package/lib/solana/tests/types/basic_1_processor.js.map +1 -0
  152. package/lib/solana/tests/types/token_bridge.d.ts +29 -0
  153. package/lib/solana/tests/types/token_bridge.js +938 -0
  154. package/lib/solana/tests/types/token_bridge.js.map +1 -0
  155. package/lib/solana/tests/types/token_bridge_processor.d.ts +212 -0
  156. package/lib/solana/tests/types/token_bridge_processor.js +134 -0
  157. package/lib/solana/tests/types/token_bridge_processor.js.map +1 -0
  158. package/lib/solana/tests/wormhole-token-bridge.d.ts +15 -0
  159. package/lib/solana/tests/wormhole-token-bridge.js +79 -0
  160. package/lib/solana/tests/wormhole-token-bridge.js.map +1 -0
  161. package/lib/target-ethers-sentio/view-function.cjs +4 -9
  162. package/lib/target-ethers-sentio/view-function.cjs.map +1 -1
  163. package/lib/testing/test-processor-server.js +1 -1
  164. package/lib/testing/test-processor-server.js.map +1 -1
  165. package/lib/testing/test-provider.js +1 -1
  166. package/lib/testing/test-provider.js.map +1 -1
  167. package/lib/utils/index.d.ts +0 -1
  168. package/lib/utils/index.js +0 -1
  169. package/lib/utils/index.js.map +1 -1
  170. package/package.json +34 -11
  171. package/src/aptos/abis/0x1.json +9205 -0
  172. package/src/aptos/abis/0x3.json +1515 -0
  173. package/src/aptos/api.ts +23 -0
  174. package/src/aptos/aptos-plugin.ts +183 -0
  175. package/src/aptos/aptos-processor.ts +331 -0
  176. package/src/aptos/builtin/0x1.ts +4911 -0
  177. package/src/aptos/builtin/0x3.ts +1092 -0
  178. package/src/aptos/builtin/index.ts +5 -0
  179. package/src/aptos/codegen/codegen.ts +470 -0
  180. package/src/aptos/codegen/index.ts +1 -0
  181. package/src/aptos/codegen/tsconfig.json +8 -0
  182. package/src/aptos/codegen/typegen.ts +165 -0
  183. package/src/aptos/context.ts +72 -0
  184. package/src/aptos/index.ts +10 -0
  185. package/src/aptos/models.ts +47 -0
  186. package/src/aptos/move-coder.ts +201 -0
  187. package/src/aptos/move-types.ts +11 -0
  188. package/src/aptos/network.ts +29 -0
  189. package/src/aptos/run-codegen.ts +13 -0
  190. package/src/aptos/tests/abis/reserved.json +402 -0
  191. package/src/aptos/tests/abis/soffl3.json +1411 -0
  192. package/src/aptos/tests/abis/souffle.json +389 -0
  193. package/src/aptos/tests/souffl3.ts +57 -0
  194. package/src/aptos/tests/types/index.ts +6 -0
  195. package/src/aptos/tests/types/reserved.ts +881 -0
  196. package/src/aptos/tests/types/soffl3.ts +1820 -0
  197. package/src/aptos/tests/types/souffle.ts +880 -0
  198. package/src/aptos/types.ts +149 -0
  199. package/src/aptos/utils.ts +26 -0
  200. package/src/builtin/internal/eacaggregatorproxy_processor.ts +90 -162
  201. package/src/builtin/internal/erc1155_processor.ts +25 -49
  202. package/src/builtin/internal/erc20_processor.ts +40 -72
  203. package/src/builtin/internal/erc20bytes_processor.ts +30 -54
  204. package/src/builtin/internal/erc721_processor.ts +45 -81
  205. package/src/builtin/internal/weth9_processor.ts +30 -54
  206. package/src/{utils/chain.ts → chain.ts} +0 -0
  207. package/src/core/context.ts +1 -1
  208. package/src/core/sui-plugin.ts +1 -1
  209. package/src/error.ts +12 -14
  210. package/src/eth/base-processor-template.ts +3 -3
  211. package/src/eth/base-processor.ts +4 -4
  212. package/src/eth/{eth-event.ts → eth.ts} +1 -1
  213. package/src/eth/index.ts +2 -0
  214. package/src/index.ts +2 -2
  215. package/src/solana/builtin/index.ts +1 -0
  216. package/src/solana/builtin/spl-token-processor.ts +298 -0
  217. package/src/solana/builtin/types.ts +279 -0
  218. package/src/solana/codegen/codegen.ts +140 -0
  219. package/src/solana/codegen/index.ts +1 -0
  220. package/src/solana/codegen/tsconfig.json +8 -0
  221. package/src/solana/index.ts +4 -0
  222. package/src/solana/run-codegen.ts +13 -0
  223. package/src/solana/solana-context.ts +30 -0
  224. package/src/solana/solana-options.ts +11 -0
  225. package/src/solana/solana-plugin.ts +103 -0
  226. package/src/solana/solana-processor.ts +102 -0
  227. package/src/solana/tests/abis/basic_1.json +62 -0
  228. package/src/solana/tests/abis/token_bridge.json +937 -0
  229. package/src/solana/tests/types/basic_1.ts +62 -0
  230. package/src/solana/tests/types/basic_1_processor.ts +42 -0
  231. package/src/solana/tests/types/token_bridge.ts +937 -0
  232. package/src/solana/tests/types/token_bridge_processor.ts +150 -0
  233. package/src/solana/tests/wormhole-token-bridge.ts +96 -0
  234. package/src/target-ethers-sentio/view-function.cts +4 -11
  235. package/src/testing/test-processor-server.ts +1 -1
  236. package/src/testing/test-provider.ts +1 -1
  237. package/src/utils/index.ts +0 -1
  238. package/lib/eth/eth-event.js +0 -2
  239. package/lib/eth/eth-event.js.map +0 -1
  240. package/lib/utils/chain.js.map +0 -1
@@ -0,0 +1,140 @@
1
+ import path from 'path'
2
+ import fs from 'fs'
3
+ import chalk from 'chalk'
4
+ import { Idl } from '@project-serum/anchor'
5
+ import { IdlAccountItem, IdlField, IdlInstruction, IdlType } from '@project-serum/anchor/dist/cjs/idl.js'
6
+
7
+ export function codeGenSolanaProcessor(abisDir: string, targetPath = path.join('src', 'types', 'solana')) {
8
+ if (!fs.existsSync(abisDir)) {
9
+ return
10
+ }
11
+
12
+ const abisFiles = fs.readdirSync(abisDir)
13
+
14
+ if (abisFiles.length > 0) {
15
+ console.log(chalk.green('Generated Types for Solana'))
16
+ }
17
+
18
+ for (const file of abisFiles) {
19
+ if (path.extname(file) === '.json') {
20
+ if (!fs.existsSync(targetPath)) {
21
+ fs.mkdirSync(targetPath, { recursive: true })
22
+ }
23
+ const idlContent = fs.readFileSync(path.join(abisDir, file), 'utf-8')
24
+ const idlObj = JSON.parse(idlContent)
25
+ const idlName = idlObj.name
26
+ const idlFile = path.join(targetPath, idlName + '.ts')
27
+ fs.writeFileSync(idlFile, `export const ${idlName}_idl = ${idlContent}`)
28
+ fs.writeFileSync(path.join(targetPath, `${idlName}_processor.ts`), codeGenSolanaIdlProcessor(idlObj))
29
+ }
30
+ }
31
+ }
32
+
33
+ function codeGenSolanaIdlProcessor(idlObj: Idl): string {
34
+ const idlName = idlObj.name
35
+ const idlNamePascalCase = toPascalCase(idlName)
36
+ const instructions: any[] = idlObj.instructions
37
+ return `import { BorshInstructionCoder, Instruction, Idl } from '@project-serum/anchor'
38
+ import { SolanaBaseProcessor, SolanaContext, SolanaBindOptions } from "@sentio/sdk/solana"
39
+ import { ${idlName}_idl } from "./${idlName}.js"
40
+ import { PublicKey } from '@solana/web3.js'
41
+
42
+ export class ${idlNamePascalCase}Processor extends SolanaBaseProcessor {
43
+ static DEFAULT_OPTIONS = {
44
+ name: '${idlNamePascalCase}',
45
+ instructionCoder: new BorshInstructionCoder(${idlName}_idl as Idl)
46
+ }
47
+
48
+ static bind(options: SolanaBindOptions): ${idlNamePascalCase}Processor {
49
+ return new ${idlNamePascalCase}Processor( { ...${idlNamePascalCase}Processor.DEFAULT_OPTIONS, ...options })
50
+ }
51
+
52
+ ${instructions.map((ins) => codeGenSolanaInstruction(idlNamePascalCase, ins)).join('')}
53
+ }
54
+ `
55
+ }
56
+
57
+ function codeGenSolanaInstruction(idlName: string, ins: IdlInstruction): string {
58
+ const instructionName = ins.name
59
+
60
+ const argsType = codeGenInstructionArgsType(ins.args)
61
+ const accountType = codeGenAccountType(ins.accounts)
62
+
63
+ return `
64
+ on${
65
+ instructionName.charAt(0).toUpperCase() + instructionName.slice(1)
66
+ }(handler: (args: ${argsType}, accounts: ${accountType}, ctx: SolanaContext) => void): ${idlName}Processor {
67
+ this.onInstruction('${instructionName}', (ins: Instruction, ctx, accounts: string[]) => {
68
+ const origin = ins.data as any
69
+ if (origin) {
70
+ const data = ${codeGenInstructionArgs(ins.args)}
71
+ const accountData = ${codeGenAccountTypeArgs(ins.accounts)}
72
+ handler(data, accountData, ctx)
73
+ }
74
+ })
75
+ return this
76
+ }
77
+ `
78
+ }
79
+
80
+ function codeGenInstructionArgs(args: IdlField[]): string {
81
+ return `{ ${args.map((arg) => codeGenInstructionArg(arg.name, arg.type)).join(', ')} }`
82
+ }
83
+
84
+ function codeGenInstructionArg(name: string, type: IdlType): string {
85
+ const mType = mapType(type)
86
+ if (mType === 'bigint') {
87
+ return `${name}: BigInt(origin.${name}.toString())`
88
+ }
89
+ return `${name}: origin.${name} as ${mType}`
90
+ }
91
+
92
+ function codeGenInstructionArgsType(args: IdlField[]): string {
93
+ return `{ ${args.map((arg) => arg.name + ': ' + mapType(arg.type)).join(', ')} }`
94
+ }
95
+
96
+ function codeGenAccountType(args: IdlAccountItem[]): string {
97
+ return `{ ${args.map((arg) => arg.name + ': string').join(', ')} }`
98
+ }
99
+
100
+ function codeGenAccountTypeArgs(args: IdlAccountItem[]): string {
101
+ return `{ ${args.map((arg, idx) => `${arg.name}: accounts[${idx}]`).join(', ')} }`
102
+ }
103
+
104
+ // Reference: https://github.com/coral-xyz/anchor/blob/93332766f13e86efbe77c9986722731742317ede/ts/src/program/namespace/types.ts#L104
105
+ function mapType(tpe: IdlType): string {
106
+ // TODO handle complex type
107
+ switch (tpe) {
108
+ case 'publicKey':
109
+ return 'PublicKey'
110
+ case 'bool':
111
+ return 'boolean'
112
+ case 'string':
113
+ return 'string'
114
+ case 'u8':
115
+ case 'i8':
116
+ case 'u16':
117
+ case 'i16':
118
+ case 'u32':
119
+ case 'i32':
120
+ case 'f32':
121
+ case 'f64':
122
+ return 'number'
123
+ case 'u64':
124
+ case 'i64':
125
+ case 'u128':
126
+ case 'i128':
127
+ return 'bigint'
128
+ default:
129
+ return 'any'
130
+ }
131
+ }
132
+
133
+ function toPascalCase(str: string) {
134
+ return `${str}`
135
+ .toLowerCase()
136
+ .replace(new RegExp(/[-_]+/, 'g'), ' ')
137
+ .replace(new RegExp(/[^\w\s]/, 'g'), '')
138
+ .replace(new RegExp(/\s+(.)(\w*)/, 'g'), ($1, $2, $3) => `${$2.toUpperCase() + $3}`)
139
+ .replace(new RegExp(/\w/), (s) => s.toUpperCase())
140
+ }
@@ -0,0 +1 @@
1
+ export * from './codegen.js'
@@ -0,0 +1,8 @@
1
+ {
2
+ "compilerOptions": {
3
+ "rootDir": "..",
4
+ "outDir": "../../../lib"
5
+ },
6
+ "extends": "@sentio/sdk-solana/tsconfig.json",
7
+ "include": ["./"]
8
+ }
@@ -0,0 +1,4 @@
1
+ export * from './solana-plugin.js'
2
+ export * from './solana-context.js'
3
+ export * from './solana-processor.js'
4
+ export * from './solana-options.js'
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+
3
+ import path from 'path'
4
+ import { codeGenSolanaProcessor } from './codegen/codegen.js'
5
+
6
+ if (process.argv.length > 3) {
7
+ const abisDir = process.argv[2]
8
+ const targetDir = process.argv[3]
9
+ codeGenSolanaProcessor(abisDir, targetDir)
10
+ } else {
11
+ console.error('Not enough argument')
12
+ process.exit(1)
13
+ }
@@ -0,0 +1,30 @@
1
+ import { normalizeLabels, Labels, BaseContext, RecordMetaData, CHAIN_IDS } from '@sentio/sdk'
2
+
3
+ export class SolanaContext extends BaseContext {
4
+ network: string
5
+ address: string
6
+ programName: string
7
+ blockNumber: bigint
8
+
9
+ constructor(programName: string, network: string, address: string, slot: bigint) {
10
+ super()
11
+ this.network = network || CHAIN_IDS.SOLANA_MAINNET
12
+ this.programName = programName
13
+ this.address = address
14
+ this.blockNumber = slot
15
+ }
16
+
17
+ getMetaData(name: string, labels: Labels): RecordMetaData {
18
+ return {
19
+ address: this.address,
20
+ contractName: this.programName,
21
+ blockNumber: this.blockNumber,
22
+ transactionIndex: 0,
23
+ transactionHash: '', // TODO add
24
+ logIndex: 0,
25
+ chainId: this.network,
26
+ name: name,
27
+ labels: normalizeLabels(labels),
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,11 @@
1
+ import { InstructionCoder } from './solana-processor.js'
2
+
3
+ export class SolanaBindOptions {
4
+ address: string
5
+ network?: string
6
+ name?: string
7
+ startBlock?: bigint | number
8
+ endBlock?: bigint | number
9
+ processInnerInstruction?: boolean
10
+ instructionCoder?: InstructionCoder
11
+ }
@@ -0,0 +1,103 @@
1
+ import { errorString, mergeProcessResults, Plugin, PluginManager, USER_PROCESSOR } from '@sentio/runtime'
2
+ import { ContractConfig, DataBinding, HandlerType, ProcessConfigResponse, ProcessResult } from '@sentio/protos'
3
+
4
+ import { ServerError, Status } from 'nice-grpc'
5
+
6
+ import { SolanaProcessorState } from './solana-processor.js'
7
+ import { Instruction as SolInstruction } from '@project-serum/anchor'
8
+
9
+ export class SolanaPlugin extends Plugin {
10
+ name: string = 'SolanaPlugin'
11
+
12
+ async configure(config: ProcessConfigResponse) {
13
+ // Part 2, prepare solana constractors
14
+ for (const solanaProcessor of SolanaProcessorState.INSTANCE.getValues()) {
15
+ const contractConfig: ContractConfig = {
16
+ transactionConfig: [],
17
+ processorType: USER_PROCESSOR,
18
+ contract: {
19
+ name: solanaProcessor.contractName,
20
+ chainId: solanaProcessor.network,
21
+ address: solanaProcessor.address,
22
+ abi: '',
23
+ },
24
+ logConfigs: [],
25
+ traceConfigs: [],
26
+ intervalConfigs: [],
27
+ startBlock: solanaProcessor.config.startSlot,
28
+ endBlock: 0n,
29
+ instructionConfig: {
30
+ innerInstruction: solanaProcessor.processInnerInstruction,
31
+ parsedInstruction: solanaProcessor.fromParsedInstruction !== null,
32
+ rawDataInstruction: solanaProcessor.decodeInstruction !== null,
33
+ },
34
+ aptosEventConfigs: [],
35
+ aptosCallConfigs: [],
36
+ }
37
+ config.contractConfigs.push(contractConfig)
38
+ }
39
+ }
40
+
41
+ supportedHandlers = [HandlerType.SOL_INSTRUCTION]
42
+
43
+ processBinding(request: DataBinding): Promise<ProcessResult> {
44
+ switch (request.handlerType) {
45
+ case HandlerType.SOL_INSTRUCTION:
46
+ return this.processSolInstruction(request)
47
+ default:
48
+ throw new ServerError(Status.INVALID_ARGUMENT, 'No handle type registered ' + request.handlerType)
49
+ }
50
+ }
51
+
52
+ async processSolInstruction(request: DataBinding): Promise<ProcessResult> {
53
+ if (!request.data) {
54
+ throw new ServerError(Status.INVALID_ARGUMENT, 'instruction data cannot be empty')
55
+ }
56
+ if (!request.data.solInstruction) {
57
+ throw new ServerError(Status.INVALID_ARGUMENT, 'instruction data cannot be empty')
58
+ }
59
+
60
+ const instruction = request.data.solInstruction
61
+ const promises: Promise<ProcessResult>[] = []
62
+
63
+ // Only have instruction handlers for solana processors
64
+ for (const processor of SolanaProcessorState.INSTANCE.getValues()) {
65
+ if (processor.address === instruction.programAccountId) {
66
+ let parsedInstruction: SolInstruction | null = null
67
+
68
+ try {
69
+ if (instruction.parsed) {
70
+ parsedInstruction = processor.getParsedInstruction(instruction.parsed as { type: string; info: any })
71
+ } else if (instruction.instructionData) {
72
+ parsedInstruction = processor.getParsedInstruction(instruction.instructionData)
73
+ }
74
+ } catch (e) {
75
+ throw new ServerError(
76
+ Status.INTERNAL,
77
+ 'Failed to decode instruction: ' + JSON.stringify(instruction) + errorString(e)
78
+ )
79
+ }
80
+ if (parsedInstruction == null) {
81
+ continue
82
+ }
83
+ const insHandler = processor.getInstructionHandler(parsedInstruction)
84
+ if (insHandler == null) {
85
+ continue
86
+ }
87
+ const res = processor
88
+ .handleInstruction(parsedInstruction, instruction.accounts, insHandler, instruction.slot)
89
+ .catch((e) => {
90
+ throw new ServerError(
91
+ Status.INTERNAL,
92
+ 'Error processing instruction: ' + JSON.stringify(instruction) + '\n' + errorString(e)
93
+ )
94
+ })
95
+
96
+ promises.push(res)
97
+ }
98
+ }
99
+ return mergeProcessResults(await Promise.all(promises))
100
+ }
101
+ }
102
+
103
+ PluginManager.INSTANCE.register(new SolanaPlugin())
@@ -0,0 +1,102 @@
1
+ import { ProcessResult } from '@sentio/protos'
2
+ import { SolanaContext } from './solana-context.js'
3
+ import { Instruction } from '@project-serum/anchor'
4
+ import { SolanaBindOptions } from './solana-options.js'
5
+ import { ListStateStorage } from '@sentio/runtime'
6
+ import { CHAIN_IDS } from '@sentio/sdk'
7
+
8
+ type IndexConfigure = {
9
+ startSlot: bigint
10
+ endSlot?: bigint
11
+ }
12
+
13
+ export interface InstructionCoder {
14
+ decode(ix: Buffer | string, encoding?: 'hex' | 'base58'): Instruction | null
15
+ }
16
+
17
+ export type SolanaInstructionHandler = (instruction: Instruction, ctx: SolanaContext, accounts?: string[]) => void
18
+
19
+ export class SolanaProcessorState extends ListStateStorage<SolanaBaseProcessor> {
20
+ static INSTANCE: SolanaProcessorState = new SolanaProcessorState()
21
+ }
22
+
23
+ export class SolanaBaseProcessor {
24
+ public instructionHandlerMap: Map<string, SolanaInstructionHandler> = new Map()
25
+ address: string
26
+ endpoint: string
27
+ contractName: string
28
+ network: string
29
+ processInnerInstruction: boolean
30
+ config: IndexConfigure = { startSlot: 0n }
31
+ instructionCoder: InstructionCoder
32
+
33
+ decodeInstruction(rawInstruction: string): Instruction | null {
34
+ if (this.instructionCoder) {
35
+ return this.instructionCoder.decode(rawInstruction, 'base58')
36
+ }
37
+ return null
38
+ }
39
+
40
+ fromParsedInstruction: (instruction: { type: string; info: any }) => Instruction | null
41
+
42
+ constructor(options: SolanaBindOptions) {
43
+ this.address = options.address
44
+ this.contractName = options.name || ''
45
+ this.processInnerInstruction = options.processInnerInstruction || false
46
+ this.network = options.network || CHAIN_IDS.SOLANA_MAINNET
47
+ if (options.instructionCoder) {
48
+ this.instructionCoder = options.instructionCoder
49
+ }
50
+ if (options.startBlock) {
51
+ this.startSlot(options.startBlock)
52
+ }
53
+ if (options.endBlock) {
54
+ this.endBlock(options.endBlock)
55
+ }
56
+ this.endpoint = options.network || 'https://api.mainnet-beta.solana.com'
57
+
58
+ SolanaProcessorState.INSTANCE.addValue(this)
59
+ }
60
+
61
+ public onInstruction(instructionName: string, handler: SolanaInstructionHandler) {
62
+ this.instructionHandlerMap.set(instructionName, handler)
63
+ return this
64
+ }
65
+
66
+ public getParsedInstruction(ins: string | { type: string; info: any }): Instruction | null {
67
+ if (ins) {
68
+ if ((ins as { type: string; info: any }).info) {
69
+ return this.fromParsedInstruction ? this.fromParsedInstruction(ins as { type: string; info: any }) : null
70
+ }
71
+ if (this.decodeInstruction != null) {
72
+ return this.decodeInstruction(ins as string)
73
+ }
74
+ }
75
+ return null
76
+ }
77
+
78
+ public getInstructionHandler(parsedInstruction: Instruction): SolanaInstructionHandler | undefined {
79
+ return this.instructionHandlerMap.get(parsedInstruction.name)
80
+ }
81
+
82
+ public async handleInstruction(
83
+ parsedInstruction: Instruction,
84
+ accounts: string[],
85
+ handler: SolanaInstructionHandler,
86
+ slot: bigint
87
+ ): Promise<ProcessResult> {
88
+ const ctx = new SolanaContext(this.contractName, this.network, this.address, slot)
89
+ await handler(parsedInstruction, ctx, accounts)
90
+ return ctx.getProcessResult()
91
+ }
92
+
93
+ public startSlot(startSlot: bigint | number) {
94
+ this.config.startSlot = BigInt(startSlot)
95
+ return this
96
+ }
97
+
98
+ public endBlock(endBlock: bigint | number) {
99
+ this.config.endSlot = BigInt(endBlock)
100
+ return this
101
+ }
102
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "accounts": [
3
+ {
4
+ "name": "MyAccount",
5
+ "type": {
6
+ "kind": "struct",
7
+ "fields": [
8
+ {
9
+ "name": "data",
10
+ "type": "u64"
11
+ }
12
+ ]
13
+ }
14
+ }
15
+ ],
16
+ "instructions": [
17
+ {
18
+ "name": "initialize",
19
+ "accounts": [
20
+ {
21
+ "name": "myAccount",
22
+ "isMut": true,
23
+ "isSigner": true
24
+ },
25
+ {
26
+ "name": "user",
27
+ "isMut": true,
28
+ "isSigner": true
29
+ },
30
+ {
31
+ "name": "systemProgram",
32
+ "isMut": false,
33
+ "isSigner": false
34
+ }
35
+ ],
36
+ "args": [
37
+ {
38
+ "name": "data",
39
+ "type": "u64"
40
+ }
41
+ ]
42
+ },
43
+ {
44
+ "name": "update",
45
+ "accounts": [
46
+ {
47
+ "name": "myAccount",
48
+ "isMut": true,
49
+ "isSigner": false
50
+ }
51
+ ],
52
+ "args": [
53
+ {
54
+ "name": "data",
55
+ "type": "u64"
56
+ }
57
+ ]
58
+ }
59
+ ],
60
+ "name": "basic_1",
61
+ "version": "0.1.0"
62
+ }