@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
package/src/approvals.ts CHANGED
@@ -4,18 +4,19 @@
4
4
  */
5
5
  import { base64 } from '@scure/base'
6
6
 
7
- import { encodeAddress, getAssociatedTokenAddress, getMetadataAddress, isAddress } from './address.js'
7
+ import { encodeAddress, getAssociatedTokenAddress, getMetadataAddress, InvalidAddressError, isAddress } from './address.js'
8
8
  import type { RequestOptions, SolanaClient } from './client.js'
9
9
  import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from './constants.js'
10
- import { findExtension, formatUnits, parseMetaplexMetadata, parseMint, type AccountInfo } from './layout.js'
11
- import { methodUnavailable } from './lp.js'
10
+ import { Bytes } from './bytes.js'
11
+ import { findExtension, formatUnits, parseMetaplexMetadata, parseMint, parseTokenAccountState as parseTokenAccountBase, type AccountInfo } from './layout.js'
12
+ import { withMethodHint } from './lp.js'
12
13
  import { closeAccount, harvestWithheldTokensToMint, revoke } from './write/instructions.js'
13
14
  import type { BatchCallOptions } from './write/batch.js'
14
15
  import type { WriteResult } from './write/send.js'
15
16
  import type { SignerInput } from './write/signer.js'
16
17
  import type { Instruction } from './write/transaction.js'
17
18
 
18
- export interface ApprovalsQuery extends RequestOptions {
19
+ export interface ApprovalsOptions extends RequestOptions {
19
20
  /**
20
21
  * 要检查的代币 mint:读这些代币的关联代币账户(ATA,SPL Token 和 Token-2022 都看),免费公共节点也能用;非 ATA 的代币账户查不到。
21
22
  * 不传时列出地址的全部代币账户(getTokenAccountsByOwner),需要支持它的节点
@@ -25,6 +26,9 @@ export interface ApprovalsQuery extends RequestOptions {
25
26
  all?: boolean
26
27
  }
27
28
 
29
+ /** @deprecated 改名为 ApprovalsOptions(与其他查询的 options 命名统一),旧名保留 */
30
+ export type ApprovalsQuery = ApprovalsOptions
31
+
28
32
  /** 关不掉的原因:balance 有余额(Wrapped SOL 除外);close-authority 关闭权限是别的地址;confidential-balance Token-2022 机密余额不为 0 */
29
33
  export type CloseBlocker = 'balance' | 'close-authority' | 'confidential-balance'
30
34
 
@@ -66,8 +70,6 @@ export interface TokenAccountApproval {
66
70
  closeBlocker: CloseBlocker | null
67
71
  }
68
72
 
69
- const ACCOUNT_SIZE = 165
70
- const ACCOUNT_TYPE_ACCOUNT = 2
71
73
  const EXT_TRANSFER_FEE_AMOUNT = 2
72
74
  const EXT_CONFIDENTIAL_TRANSFER_ACCOUNT = 5
73
75
  const EXT_PERMANENT_DELEGATE = 12
@@ -88,34 +90,27 @@ interface ParsedAccount {
88
90
  confidentialBalance: boolean
89
91
  }
90
92
 
91
- /** 解析代币账户;不是已初始化的代币账户时为 null */
93
+ /** 解析代币账户(基础布局用 layout 的 parseTokenAccountState)及关闭相关的 Token-2022 扩展;不是已初始化的代币账户时为 null */
92
94
  export function parseTokenAccountState(data: Uint8Array): ParsedAccount | null {
93
- if (data.length !== ACCOUNT_SIZE && !(data.length > ACCOUNT_SIZE && data[ACCOUNT_SIZE] === ACCOUNT_TYPE_ACCOUNT)) {
95
+ const base = parseTokenAccountBase(data)
96
+ if (!base) {
94
97
  return null
95
98
  }
96
- const view = new DataView(data.buffer, data.byteOffset, data.byteLength)
97
- const pubkey = (offset: number) => encodeAddress(data.slice(offset, offset + 32))
98
- // COption:u32 标记(1 有、0 没有)+ 值
99
- const option = (offset: number) => view.getUint32(offset, true) === 1
100
- const state = data[108] as number
101
- if (state === 0) {
102
- return null // 未初始化
103
- }
104
99
  const withheld = findExtension(data, EXT_TRANSFER_FEE_AMOUNT)
105
100
  // 机密转账:待入账(lo / hi)和可用余额的密文全为 0 才能关闭;手续费扩展同理(Token-2022 的 closable 检查)
106
101
  const confidential = findExtension(data, EXT_CONFIDENTIAL_TRANSFER_ACCOUNT)
107
102
  const confidentialFee = findExtension(data, EXT_CONFIDENTIAL_TRANSFER_FEE_AMOUNT)
108
103
  const nonZero = (bytes: Uint8Array | null, from: number, to: number) => !!bytes && bytes.slice(from, to).some((b) => b !== 0)
109
104
  return {
110
- mint: pubkey(0),
111
- owner: pubkey(32),
112
- amount: view.getBigUint64(64, true),
113
- delegate: option(72) ? pubkey(76) : null,
114
- frozen: state === 2,
115
- native: option(109),
116
- delegatedAmount: view.getBigUint64(121, true),
117
- closeAuthority: option(129) ? pubkey(133) : null,
118
- withheldAmount: withheld && withheld.length >= 8 ? new DataView(withheld.buffer, withheld.byteOffset).getBigUint64(0, true) : 0n,
105
+ mint: base.mint,
106
+ owner: base.owner,
107
+ amount: base.amount,
108
+ delegate: base.delegate,
109
+ frozen: base.frozen,
110
+ native: base.native,
111
+ delegatedAmount: base.delegatedAmount,
112
+ closeAuthority: base.closeAuthority,
113
+ withheldAmount: withheld && withheld.length >= 8 ? new Bytes(withheld).u64(0) : 0n,
119
114
  confidentialBalance: nonZero(confidential, 33, 225) || nonZero(confidentialFee, 0, 64),
120
115
  }
121
116
  }
@@ -142,12 +137,12 @@ interface Found {
142
137
  * await approvals(new SolanaClient('https://my-rpc…'), owner) // 全部代币账户
143
138
  * ```
144
139
  */
145
- export async function approvals(client: SolanaClient, owner: string, query: ApprovalsQuery = {}): Promise<TokenAccountApproval[]> {
140
+ export async function approvals(client: SolanaClient, owner: string, options: ApprovalsOptions = {}): Promise<TokenAccountApproval[]> {
146
141
  if (!isAddress(owner)) {
147
- throw new Error(`Invalid owner address: ${owner}`)
142
+ throw new InvalidAddressError(`Invalid owner address: ${owner}`, owner)
148
143
  }
149
- const { signal } = query
150
- const found = query.mints ? await ataAccounts(client, owner, query.mints, signal) : await listAccounts(client, owner, signal)
144
+ const { signal } = options
145
+ const found = options.mints ? await ataAccounts(client, owner, options.mints, signal) : await listAccounts(client, owner, signal)
151
146
  // 只看 owner 自己的账户(ATA 的 owner 可能被改过:SPL Token 的 ATA 能 SetAuthority 换 owner)
152
147
  const mine = found.filter((f) => f.parsed.owner === owner)
153
148
  const mints = [...new Set(mine.map((f) => f.parsed.mint))]
@@ -185,7 +180,7 @@ export async function approvals(client: SolanaClient, owner: string, query: Appr
185
180
  closeBlocker,
186
181
  }
187
182
  })
188
- return query.all ? list : list.filter((a) => a.delegate !== null || a.closeBlocker === 'close-authority' || BigInt(a.amount) === 0n)
183
+ return options.all ? list : list.filter((a) => a.delegate !== null || a.closeBlocker === 'close-authority' || BigInt(a.amount) === 0n)
189
184
  }
190
185
 
191
186
  /** 指定 mints:两个程序的 ATA 都读(mint 所属程序未知时只有一个存在) */
@@ -203,22 +198,19 @@ async function ataAccounts(client: SolanaClient, owner: string, mints: readonly
203
198
 
204
199
  /** 不传 mints:用 getTokenAccountsByOwner 列出两个程序的全部代币账户(base64,自己解析扩展) */
205
200
  async function listAccounts(client: SolanaClient, owner: string, signal: AbortSignal | undefined): Promise<Found[]> {
206
- const lists = await Promise.all(
207
- [TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID].map((programId) =>
208
- client.request<{ value: RawTokenAccount[] }>('getTokenAccountsByOwner', [owner, { programId }, { encoding: 'base64', commitment: client.commitment }], { signal }).then(
209
- (res) => ({ programId, value: res.value ?? [] }),
201
+ const lists = await withMethodHint(
202
+ Promise.all(
203
+ [TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID].map((programId) =>
204
+ client
205
+ .request<{ value: RawTokenAccount[] }>('getTokenAccountsByOwner', [owner, { programId }, { encoding: 'base64', commitment: client.commitment }], { signal })
206
+ .then((res) => ({ programId, value: res.value ?? [] })),
210
207
  ),
211
208
  ),
212
- ).catch((err: unknown) => {
213
- if (signal?.aborted || !methodUnavailable(err)) {
214
- throw err // 取消、限频、超时等原样抛出(保留错误类型)
215
- }
216
- throw new Error(
217
- `Listing the token accounts of ${owner} failed (${err instanceof Error ? err.message : String(err)}). ` +
218
- 'Listing needs getTokenAccountsByOwner (most free public nodes do not support it): pass the mints in `mints`, or use a node that supports it',
219
- { cause: err },
220
- )
221
- })
209
+ signal,
210
+ (detail) =>
211
+ `Listing the token accounts of ${owner} failed (${detail}). ` +
212
+ 'Listing needs getTokenAccountsByOwner (most free public nodes do not support it): pass the mints in `mints`, or use a node that supports it',
213
+ )
222
214
  return lists.flatMap(({ programId, value }) =>
223
215
  value.flatMap((entry) => {
224
216
  const parsed = entry.account.owner === programId ? parseTokenAccountState(base64.decode(entry.account.data[0])) : null