@w3lib/solana-batch-call 0.5.0 → 0.7.0

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 (220) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +129 -9
  3. package/dist/accountReader.d.ts +57 -0
  4. package/dist/accountReader.d.ts.map +1 -0
  5. package/dist/accountReader.js +149 -0
  6. package/dist/accountReader.js.map +1 -0
  7. package/dist/address.d.ts +9 -0
  8. package/dist/address.d.ts.map +1 -1
  9. package/dist/address.js +36 -6
  10. package/dist/address.js.map +1 -1
  11. package/dist/approvals.d.ts +5 -3
  12. package/dist/approvals.d.ts.map +1 -1
  13. package/dist/approvals.js +25 -36
  14. package/dist/approvals.js.map +1 -1
  15. package/dist/balances.d.ts +178 -0
  16. package/dist/balances.d.ts.map +1 -0
  17. package/dist/balances.js +524 -0
  18. package/dist/balances.js.map +1 -0
  19. package/dist/batchPlan.d.ts +52 -0
  20. package/dist/batchPlan.d.ts.map +1 -0
  21. package/dist/batchPlan.js +64 -0
  22. package/dist/batchPlan.js.map +1 -0
  23. package/dist/bytes.d.ts +31 -0
  24. package/dist/bytes.d.ts.map +1 -0
  25. package/dist/bytes.js +74 -0
  26. package/dist/bytes.js.map +1 -0
  27. package/dist/claim.d.ts +163 -0
  28. package/dist/claim.d.ts.map +1 -0
  29. package/dist/claim.js +197 -0
  30. package/dist/claim.js.map +1 -0
  31. package/dist/client.d.ts +26 -41
  32. package/dist/client.d.ts.map +1 -1
  33. package/dist/client.js +41 -986
  34. package/dist/client.js.map +1 -1
  35. package/dist/clientConfig.d.ts +11 -0
  36. package/dist/clientConfig.d.ts.map +1 -0
  37. package/dist/clientConfig.js +3 -0
  38. package/dist/clientConfig.js.map +1 -0
  39. package/dist/decode.d.ts +22 -0
  40. package/dist/decode.d.ts.map +1 -0
  41. package/dist/decode.js +160 -0
  42. package/dist/decode.js.map +1 -0
  43. package/dist/describe.d.ts +26 -0
  44. package/dist/describe.d.ts.map +1 -0
  45. package/dist/describe.js +58 -0
  46. package/dist/describe.js.map +1 -0
  47. package/dist/fees.d.ts.map +1 -1
  48. package/dist/fees.js +2 -12
  49. package/dist/fees.js.map +1 -1
  50. package/dist/history.d.ts +125 -0
  51. package/dist/history.d.ts.map +1 -0
  52. package/dist/history.js +220 -0
  53. package/dist/history.js.map +1 -0
  54. package/dist/historyHelius.d.ts +52 -0
  55. package/dist/historyHelius.d.ts.map +1 -0
  56. package/dist/historyHelius.js +125 -0
  57. package/dist/historyHelius.js.map +1 -0
  58. package/dist/index.d.ts +3 -3
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +1 -1
  61. package/dist/index.js.map +1 -1
  62. package/dist/layout.d.ts +21 -0
  63. package/dist/layout.d.ts.map +1 -1
  64. package/dist/layout.js +50 -69
  65. package/dist/layout.js.map +1 -1
  66. package/dist/liquidity/common.js +2 -2
  67. package/dist/liquidity/common.js.map +1 -1
  68. package/dist/liquidity/orca.d.ts +6 -0
  69. package/dist/liquidity/orca.d.ts.map +1 -1
  70. package/dist/liquidity/orca.js +14 -3
  71. package/dist/liquidity/orca.js.map +1 -1
  72. package/dist/liquidity/raydiumClmm.d.ts +6 -0
  73. package/dist/liquidity/raydiumClmm.d.ts.map +1 -1
  74. package/dist/liquidity/raydiumClmm.js +12 -5
  75. package/dist/liquidity/raydiumClmm.js.map +1 -1
  76. package/dist/lp.d.ts +55 -12
  77. package/dist/lp.d.ts.map +1 -1
  78. package/dist/lp.js +158 -70
  79. package/dist/lp.js.map +1 -1
  80. package/dist/lpMath.d.ts +22 -0
  81. package/dist/lpMath.d.ts.map +1 -1
  82. package/dist/lpMath.js +21 -0
  83. package/dist/lpMath.js.map +1 -1
  84. package/dist/portfolio.d.ts.map +1 -1
  85. package/dist/portfolio.js +3 -8
  86. package/dist/portfolio.js.map +1 -1
  87. package/dist/programs.d.ts +19 -0
  88. package/dist/programs.d.ts.map +1 -0
  89. package/dist/programs.js +175 -0
  90. package/dist/programs.js.map +1 -0
  91. package/dist/reclaim.d.ts +192 -0
  92. package/dist/reclaim.d.ts.map +1 -0
  93. package/dist/reclaim.js +399 -0
  94. package/dist/reclaim.js.map +1 -0
  95. package/dist/risk.js +2 -2
  96. package/dist/risk.js.map +1 -1
  97. package/dist/rpc.d.ts +30 -7
  98. package/dist/rpc.d.ts.map +1 -1
  99. package/dist/rpc.js +404 -111
  100. package/dist/rpc.js.map +1 -1
  101. package/dist/simulate.d.ts +106 -0
  102. package/dist/simulate.d.ts.map +1 -0
  103. package/dist/simulate.js +395 -0
  104. package/dist/simulate.js.map +1 -0
  105. package/dist/source.d.ts +8 -4
  106. package/dist/source.d.ts.map +1 -1
  107. package/dist/source.js +11 -4
  108. package/dist/source.js.map +1 -1
  109. package/dist/subpaths/approvals.d.ts +3 -3
  110. package/dist/subpaths/approvals.d.ts.map +1 -1
  111. package/dist/subpaths/approvals.js.map +1 -1
  112. package/dist/subpaths/claim.d.ts +31 -0
  113. package/dist/subpaths/claim.d.ts.map +1 -0
  114. package/dist/subpaths/claim.js +31 -0
  115. package/dist/subpaths/claim.js.map +1 -0
  116. package/dist/subpaths/history.d.ts +21 -0
  117. package/dist/subpaths/history.d.ts.map +1 -0
  118. package/dist/subpaths/history.js +22 -0
  119. package/dist/subpaths/history.js.map +1 -0
  120. package/dist/subpaths/lp.d.ts +2 -2
  121. package/dist/subpaths/lp.d.ts.map +1 -1
  122. package/dist/subpaths/lp.js +2 -2
  123. package/dist/subpaths/lp.js.map +1 -1
  124. package/dist/subpaths/reclaim.d.ts +34 -0
  125. package/dist/subpaths/reclaim.d.ts.map +1 -0
  126. package/dist/subpaths/reclaim.js +34 -0
  127. package/dist/subpaths/reclaim.js.map +1 -0
  128. package/dist/subpaths/simulate.d.ts +22 -0
  129. package/dist/subpaths/simulate.d.ts.map +1 -0
  130. package/dist/subpaths/simulate.js +23 -0
  131. package/dist/subpaths/simulate.js.map +1 -0
  132. package/dist/swap/index.js +3 -3
  133. package/dist/swap/index.js.map +1 -1
  134. package/dist/tokenDetails.d.ts +12 -0
  135. package/dist/tokenDetails.d.ts.map +1 -0
  136. package/dist/tokenDetails.js +196 -0
  137. package/dist/tokenDetails.js.map +1 -0
  138. package/dist/tokenMeta.d.ts +63 -0
  139. package/dist/tokenMeta.d.ts.map +1 -0
  140. package/dist/tokenMeta.js +226 -0
  141. package/dist/tokenMeta.js.map +1 -0
  142. package/dist/tradeCheck.js +3 -3
  143. package/dist/tradeCheck.js.map +1 -1
  144. package/dist/util.d.ts +22 -0
  145. package/dist/util.d.ts.map +1 -0
  146. package/dist/util.js +107 -0
  147. package/dist/util.js.map +1 -0
  148. package/dist/write/chain.d.ts +51 -0
  149. package/dist/write/chain.d.ts.map +1 -0
  150. package/dist/write/chain.js +184 -0
  151. package/dist/write/chain.js.map +1 -0
  152. package/dist/write/collect.js +2 -2
  153. package/dist/write/collect.js.map +1 -1
  154. package/dist/write/errors.d.ts +10 -0
  155. package/dist/write/errors.d.ts.map +1 -0
  156. package/dist/write/errors.js +77 -0
  157. package/dist/write/errors.js.map +1 -0
  158. package/dist/write/instructions.d.ts +2 -0
  159. package/dist/write/instructions.d.ts.map +1 -1
  160. package/dist/write/instructions.js +16 -0
  161. package/dist/write/instructions.js.map +1 -1
  162. package/dist/write/pack.d.ts +28 -0
  163. package/dist/write/pack.d.ts.map +1 -0
  164. package/dist/write/pack.js +125 -0
  165. package/dist/write/pack.js.map +1 -0
  166. package/dist/write/send.d.ts +23 -9
  167. package/dist/write/send.d.ts.map +1 -1
  168. package/dist/write/send.js +53 -351
  169. package/dist/write/send.js.map +1 -1
  170. package/dist/write/tracker.d.ts +24 -0
  171. package/dist/write/tracker.d.ts.map +1 -0
  172. package/dist/write/tracker.js +129 -0
  173. package/dist/write/tracker.js.map +1 -0
  174. package/package.json +21 -1
  175. package/src/accountReader.ts +187 -0
  176. package/src/address.ts +41 -6
  177. package/src/approvals.ts +36 -44
  178. package/src/balances.ts +678 -0
  179. package/src/batchPlan.ts +117 -0
  180. package/src/bytes.ts +89 -0
  181. package/src/claim.ts +327 -0
  182. package/src/client.ts +59 -1239
  183. package/src/clientConfig.ts +12 -0
  184. package/src/decode.ts +176 -0
  185. package/src/describe.ts +77 -0
  186. package/src/fees.ts +2 -9
  187. package/src/history.ts +325 -0
  188. package/src/historyHelius.ts +136 -0
  189. package/src/index.ts +13 -1
  190. package/src/layout.ts +63 -82
  191. package/src/liquidity/common.ts +2 -2
  192. package/src/liquidity/orca.ts +15 -5
  193. package/src/liquidity/raydiumClmm.ts +13 -5
  194. package/src/lp.ts +226 -75
  195. package/src/lpMath.ts +38 -0
  196. package/src/portfolio.ts +8 -11
  197. package/src/programs.ts +216 -0
  198. package/src/reclaim.ts +550 -0
  199. package/src/risk.ts +2 -2
  200. package/src/rpc.ts +476 -118
  201. package/src/simulate.ts +517 -0
  202. package/src/source.ts +14 -5
  203. package/src/subpaths/approvals.ts +3 -2
  204. package/src/subpaths/claim.ts +54 -0
  205. package/src/subpaths/history.ts +38 -0
  206. package/src/subpaths/lp.ts +5 -1
  207. package/src/subpaths/reclaim.ts +58 -0
  208. package/src/subpaths/simulate.ts +37 -0
  209. package/src/swap/index.ts +3 -3
  210. package/src/tokenDetails.ts +240 -0
  211. package/src/tokenMeta.ts +270 -0
  212. package/src/tradeCheck.ts +3 -3
  213. package/src/util.ts +110 -0
  214. package/src/write/chain.ts +218 -0
  215. package/src/write/collect.ts +2 -2
  216. package/src/write/errors.ts +82 -0
  217. package/src/write/instructions.ts +17 -0
  218. package/src/write/pack.ts +142 -0
  219. package/src/write/send.ts +74 -407
  220. package/src/write/tracker.ts +152 -0
@@ -0,0 +1,216 @@
1
+ /**
2
+ * 常见程序的名字、指令名(Anchor 程序按 sha256("global:<name>") 的前 8 字节识别)和自定义错误码,
3
+ * 给 /simulate 和 /history 说明交易在做什么。只收录认得准的,其他程序只显示地址
4
+ */
5
+ import { sha256 } from '@noble/hashes/sha2.js'
6
+
7
+ import {
8
+ ASSOCIATED_TOKEN_PROGRAM_ID,
9
+ SYSTEM_PROGRAM_ID,
10
+ TOKEN_2022_PROGRAM_ID,
11
+ TOKEN_PROGRAM_ID,
12
+ } from './constants.js'
13
+
14
+ // 与 lp.ts 里的同名常量相同;这里不 import 它,避免 /simulate、/history 把整个 LP 模块打进来
15
+ const RAYDIUM_CLMM_PROGRAM_ID = 'CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK'
16
+ const ORCA_WHIRLPOOL_PROGRAM_ID = 'whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc'
17
+ const RAYDIUM_AMM_PROGRAM_ID = '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8'
18
+ const RAYDIUM_CPMM_PROGRAM_ID = 'CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C'
19
+
20
+ export const COMPUTE_BUDGET = 'ComputeBudget111111111111111111111111111111'
21
+ export const MEMO_V2 = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'
22
+ export const MEMO_V1 = 'Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo'
23
+ export const BPF_LOADER_UPGRADEABLE = 'BPFLoaderUpgradeab1e11111111111111111111111'
24
+
25
+ /** 指令的大类:交易的类型由它们和余额变化一起决定 */
26
+ export type IxType = 'transfer' | 'swap' | 'approve' | 'liquidity' | 'mint' | 'burn' | 'close' | 'setup' | 'budget' | 'memo' | 'contract' | 'unknown'
27
+
28
+ export interface ProgramInfo {
29
+ name: string
30
+ /** 内置程序(系统、代币、ATA、计算预算、备忘录等):不算“不认识的程序” */
31
+ builtin?: boolean
32
+ /** 协议名(DEX / 借贷等),内置程序没有 */
33
+ protocol?: string
34
+ }
35
+
36
+ const p = (name: string, protocol = name): ProgramInfo => ({ name, protocol })
37
+ const b = (name: string): ProgramInfo => ({ name, builtin: true })
38
+
39
+ export const PROGRAMS: Readonly<Record<string, ProgramInfo>> = {
40
+ [SYSTEM_PROGRAM_ID]: b('System Program'),
41
+ [TOKEN_PROGRAM_ID]: b('SPL Token'),
42
+ [TOKEN_2022_PROGRAM_ID]: b('Token-2022'),
43
+ [ASSOCIATED_TOKEN_PROGRAM_ID]: b('Associated Token Account'),
44
+ [COMPUTE_BUDGET]: b('Compute Budget'),
45
+ [MEMO_V2]: b('Memo'),
46
+ [MEMO_V1]: b('Memo'),
47
+ [BPF_LOADER_UPGRADEABLE]: b('BPF Loader Upgradeable'),
48
+ AddressLookupTab1e1111111111111111111111111: b('Address Lookup Table'),
49
+ Stake11111111111111111111111111111111111111: b('Stake Program'),
50
+ Vote111111111111111111111111111111111111111: b('Vote Program'),
51
+ Ed25519SigVerify111111111111111111111111111: b('Ed25519 Program'),
52
+ KeccakSecp256k11111111111111111111111111111: b('Secp256k1 Program'),
53
+ metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s: b('Metaplex Token Metadata'),
54
+ JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4: p('Jupiter Aggregator v6', 'Jupiter'),
55
+ JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB: p('Jupiter Aggregator v4', 'Jupiter'),
56
+ DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M: p('Jupiter DCA', 'Jupiter'),
57
+ j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X: p('Jupiter Limit Order', 'Jupiter'),
58
+ jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu: p('Jupiter Limit Order v2', 'Jupiter'),
59
+ PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu: p('Jupiter Perpetuals', 'Jupiter'),
60
+ [RAYDIUM_AMM_PROGRAM_ID]: p('Raydium AMM v4', 'Raydium'),
61
+ [RAYDIUM_CLMM_PROGRAM_ID]: p('Raydium CLMM', 'Raydium'),
62
+ [RAYDIUM_CPMM_PROGRAM_ID]: p('Raydium CPMM', 'Raydium'),
63
+ routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS: p('Raydium Route', 'Raydium'),
64
+ [ORCA_WHIRLPOOL_PROGRAM_ID]: p('Orca Whirlpool', 'Orca'),
65
+ '9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP': p('Orca v2', 'Orca'),
66
+ LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo: p('Meteora DLMM', 'Meteora'),
67
+ Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB: p('Meteora Pools', 'Meteora'),
68
+ cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG: p('Meteora DAMM v2', 'Meteora'),
69
+ dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN: p('Meteora Dynamic Bonding Curve', 'Meteora'),
70
+ '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P': p('Pump.fun', 'Pump.fun'),
71
+ pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA: p('PumpSwap', 'Pump.fun'),
72
+ PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY: p('Phoenix'),
73
+ srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX: p('OpenBook v1', 'OpenBook'),
74
+ opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb: p('OpenBook v2', 'OpenBook'),
75
+ LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj: p('Lifinity v2', 'Lifinity'),
76
+ MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD: p('Marinade'),
77
+ MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA: p('marginfi v2', 'marginfi'),
78
+ KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD: p('Kamino Lending', 'Kamino'),
79
+ dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH: p('Drift v2', 'Drift'),
80
+ So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo: p('Solend'),
81
+ SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf: p('Squads v4', 'Squads'),
82
+ wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb: p('Wormhole Token Bridge', 'Wormhole'),
83
+ CndyV3LdqHUfDLmE5naZjVN8rBZz4tqhdefbAnjHG3JR: p('Candy Machine v3', 'Metaplex'),
84
+ Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g: p('Candy Guard', 'Metaplex'),
85
+ CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d: p('Metaplex Core', 'Metaplex'),
86
+ TSWAPaqyCSx2KABk68Shruf4rp7CxcNi8hAsbdwmHbN: p('Tensor Swap', 'Tensor'),
87
+ M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K: p('Magic Eden v2', 'Magic Eden'),
88
+ }
89
+
90
+ /** 按指令名(snake_case)识别的 Anchor 程序:指令名 → 大类 */
91
+ const JUPITER_METHODS: Record<string, IxType> = {
92
+ ...Object.fromEntries(['route', 'route_with_token_ledger', 'shared_accounts_route', 'shared_accounts_route_with_token_ledger', 'exact_out_route', 'shared_accounts_exact_out_route'].map((n) => [n, 'swap'])),
93
+ set_token_ledger: 'setup',
94
+ }
95
+
96
+ const ANCHOR: Record<string, Record<string, IxType>> = {
97
+ JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4: JUPITER_METHODS,
98
+ JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB: JUPITER_METHODS,
99
+ dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN: { swap: 'swap', swap2: 'swap' },
100
+ CndyV3LdqHUfDLmE5naZjVN8rBZz4tqhdefbAnjHG3JR: { mint: 'mint', mint_v2: 'mint' },
101
+ Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g: { mint: 'mint', mint_v2: 'mint' },
102
+ [ORCA_WHIRLPOOL_PROGRAM_ID]: {
103
+ ...Object.fromEntries(['swap', 'swap_v2', 'two_hop_swap', 'two_hop_swap_v2'].map((n) => [n, 'swap'])),
104
+ ...Object.fromEntries(
105
+ [
106
+ 'increase_liquidity', 'increase_liquidity_v2', 'decrease_liquidity', 'decrease_liquidity_v2', 'open_position', 'open_position_with_metadata',
107
+ 'open_position_with_token_extensions', 'close_position', 'close_position_with_token_extensions', 'collect_fees', 'collect_fees_v2', 'collect_reward',
108
+ 'collect_reward_v2', 'open_bundled_position', 'close_bundled_position', 'increase_liquidity_by_token_amounts_v2',
109
+ ].map((n) => [n, 'liquidity']),
110
+ ),
111
+ initialize_tick_array: 'setup',
112
+ initialize_dynamic_tick_array: 'setup',
113
+ },
114
+ [RAYDIUM_CLMM_PROGRAM_ID]: {
115
+ ...Object.fromEntries(['swap', 'swap_v2', 'swap_router_base_in'].map((n) => [n, 'swap'])),
116
+ ...Object.fromEntries(
117
+ ['open_position', 'open_position_v2', 'open_position_with_token22_nft', 'increase_liquidity', 'increase_liquidity_v2', 'decrease_liquidity', 'decrease_liquidity_v2', 'close_position', 'collect_fund_fee'].map((n) => [n, 'liquidity']),
118
+ ),
119
+ },
120
+ [RAYDIUM_CPMM_PROGRAM_ID]: { swap_base_input: 'swap', swap_base_output: 'swap', deposit: 'liquidity', withdraw: 'liquidity' },
121
+ LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo: {
122
+ ...Object.fromEntries(['swap', 'swap_exact_out', 'swap_with_price_impact'].map((n) => [n, 'swap'])),
123
+ ...Object.fromEntries(
124
+ [
125
+ 'add_liquidity', 'add_liquidity_by_weight', 'add_liquidity_by_strategy', 'add_liquidity_by_strategy_one_side', 'add_liquidity_one_side', 'remove_liquidity',
126
+ 'remove_liquidity_by_range', 'remove_all_liquidity', 'claim_fee', 'claim_reward', 'close_position', 'initialize_position',
127
+ ].map((n) => [n, 'liquidity']),
128
+ ),
129
+ },
130
+ Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB: {
131
+ swap: 'swap',
132
+ add_balance_liquidity: 'liquidity',
133
+ add_imbalance_liquidity: 'liquidity',
134
+ remove_balance_liquidity: 'liquidity',
135
+ remove_liquidity_single_side: 'liquidity',
136
+ },
137
+ cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG: {
138
+ swap: 'swap',
139
+ swap2: 'swap',
140
+ add_liquidity: 'liquidity',
141
+ remove_liquidity: 'liquidity',
142
+ remove_all_liquidity: 'liquidity',
143
+ claim_position_fee: 'liquidity',
144
+ create_position: 'liquidity',
145
+ close_position: 'liquidity',
146
+ },
147
+ '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P': { buy: 'swap', sell: 'swap', create: 'mint', create_v2: 'mint' },
148
+ pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA: { buy: 'swap', sell: 'swap', deposit: 'liquidity', withdraw: 'liquidity', create_pool: 'liquidity' },
149
+ }
150
+
151
+ /** Raydium AMM v4:第一个字节是指令编号 */
152
+ const AMM_V4: Record<number, [string, IxType]> = {
153
+ 3: ['deposit', 'liquidity'],
154
+ 4: ['withdraw', 'liquidity'],
155
+ 9: ['swapBaseIn', 'swap'],
156
+ 11: ['swapBaseOut', 'swap'],
157
+ 16: ['swapBaseInV2', 'swap'],
158
+ 17: ['swapBaseOutV2', 'swap'],
159
+ }
160
+
161
+ let discriminators: Map<string, Map<string, [string, IxType]>> | undefined
162
+
163
+ const hex = (bytes: Uint8Array) => Array.from(bytes, (x) => x.toString(16).padStart(2, '0')).join('')
164
+
165
+ /** 认得的程序指令:返回指令名和大类;不认识的指令(程序认得)返回 null */
166
+ export function knownMethod(programId: string, data: Uint8Array): [method: string, type: IxType] | null {
167
+ if (programId === RAYDIUM_AMM_PROGRAM_ID) return AMM_V4[data[0] as number] ?? null
168
+ const methods = ANCHOR[programId]
169
+ if (!methods || data.length < 8) return null
170
+ if (!discriminators) {
171
+ discriminators = new Map(
172
+ Object.entries(ANCHOR).map(([program, list]) => [
173
+ program,
174
+ new Map(Object.entries(list).map(([name, type]) => [hex(sha256(new TextEncoder().encode(`global:${name}`)).slice(0, 8)), [name, type] as [string, IxType]])),
175
+ ]),
176
+ )
177
+ }
178
+ return discriminators.get(programId)?.get(hex(data.slice(0, 8))) ?? null
179
+ }
180
+
181
+ // ---------------------------------------------------------------------------
182
+ // 自定义错误码
183
+ // ---------------------------------------------------------------------------
184
+
185
+ const list = (names: string): Record<number, string> => Object.fromEntries(names.split(',').map((n, i) => [i, n]))
186
+
187
+ const SYSTEM_ERRORS = list('AccountAlreadyInUse,ResultWithNegativeLamports,InvalidProgramId,InvalidAccountDataLength,MaxSeedLengthExceeded,AddressWithSeedMismatch,NonceNoRecentBlockhashes,NonceBlockhashNotExpired,NonceUnexpectedBlockhashValue')
188
+ const TOKEN_ERRORS = list(
189
+ 'NotRentExempt,InsufficientFunds,InvalidMint,MintMismatch,OwnerMismatch,FixedSupply,AlreadyInUse,InvalidNumberOfProvidedSigners,InvalidNumberOfRequiredSigners,UninitializedState,NativeNotSupported,NonNativeHasBalance,InvalidInstruction,InvalidState,Overflow,AuthorityTypeNotSupported,MintCannotFreeze,AccountFrozen,MintDecimalsMismatch,NonNativeNotSupported',
190
+ )
191
+ const JUPITER_ERRORS: Record<number, string> = Object.fromEntries(
192
+ 'EmptyRoute,SlippageToleranceExceeded,InvalidCalculation,MissingPlatformFeeAccount,InvalidSlippage,NotEnoughPercent,InvalidInputIndex,InvalidOutputIndex,NotEnoughAccountKeys,NonZeroMinimumOutAmountNotSupported,InvalidRoutePlan,InvalidReferralAuthority,LedgerTokenAccountDoesNotMatch,InvalidTokenLedger,IncorrectTokenProgramID,TokenProgramNotProvided,SwapNotSupported,ExactOutAmountNotMatched,SourceAndDestinationMintCannotBeTheSame'
193
+ .split(',')
194
+ .map((n, i) => [6000 + i, n]),
195
+ )
196
+ const RAYDIUM_AMM_ERRORS: Record<number, string> = { 22: 'InvalidStatus', 23: 'InvalidInstruction', 30: 'ExceededSlippage', 40: 'InsufficientFunds' }
197
+ /** Anchor 框架自带的错误码(2000 起是账户约束) */
198
+ const ANCHOR_ERRORS: Record<number, string> = {
199
+ 100: 'InstructionMissing', 101: 'InstructionFallbackNotFound', 102: 'InstructionDidNotDeserialize', 2000: 'ConstraintMut', 2001: 'ConstraintHasOne',
200
+ 2002: 'ConstraintSigner', 2003: 'ConstraintRaw', 2004: 'ConstraintOwner', 2006: 'ConstraintSeeds', 2012: 'ConstraintAddress', 2014: 'ConstraintTokenMint',
201
+ 2015: 'ConstraintTokenOwner', 3001: 'AccountDiscriminatorNotFound', 3002: 'AccountDiscriminatorMismatch', 3003: 'AccountDidNotDeserialize',
202
+ 3007: 'AccountOwnedByWrongProgram', 3010: 'AccountNotSigner', 3012: 'AccountNotInitialized',
203
+ }
204
+
205
+ const PROGRAM_ERRORS: Record<string, Record<number, string>> = {
206
+ [SYSTEM_PROGRAM_ID]: SYSTEM_ERRORS,
207
+ [TOKEN_PROGRAM_ID]: TOKEN_ERRORS,
208
+ [TOKEN_2022_PROGRAM_ID]: TOKEN_ERRORS,
209
+ JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4: JUPITER_ERRORS,
210
+ [RAYDIUM_AMM_PROGRAM_ID]: RAYDIUM_AMM_ERRORS,
211
+ }
212
+
213
+ /** 自定义错误码的名字:先看这个程序自己的表,再看 Anchor 框架的;认不出时返回 undefined */
214
+ export function programErrorName(programId: string | undefined, code: number): string | undefined {
215
+ return (programId ? PROGRAM_ERRORS[programId]?.[code] : undefined) ?? ANCHOR_ERRORS[code]
216
+ }