@w3lib/solana-batch-call 0.6.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 (165) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +16 -8
  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 +2 -2
  20. package/dist/batchPlan.d.ts.map +1 -1
  21. package/dist/batchPlan.js +5 -26
  22. package/dist/batchPlan.js.map +1 -1
  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 +5 -3
  28. package/dist/claim.d.ts.map +1 -1
  29. package/dist/claim.js +10 -10
  30. package/dist/claim.js.map +1 -1
  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.map +1 -1
  40. package/dist/decode.js +2 -29
  41. package/dist/decode.js.map +1 -1
  42. package/dist/fees.d.ts.map +1 -1
  43. package/dist/fees.js +2 -12
  44. package/dist/fees.js.map +1 -1
  45. package/dist/history.d.ts.map +1 -1
  46. package/dist/history.js +4 -15
  47. package/dist/history.js.map +1 -1
  48. package/dist/index.d.ts +3 -3
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +1 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/layout.d.ts +21 -0
  53. package/dist/layout.d.ts.map +1 -1
  54. package/dist/layout.js +50 -69
  55. package/dist/layout.js.map +1 -1
  56. package/dist/liquidity/common.js +2 -2
  57. package/dist/liquidity/common.js.map +1 -1
  58. package/dist/lp.d.ts +9 -13
  59. package/dist/lp.d.ts.map +1 -1
  60. package/dist/lp.js +67 -55
  61. package/dist/lp.js.map +1 -1
  62. package/dist/portfolio.d.ts.map +1 -1
  63. package/dist/portfolio.js +3 -8
  64. package/dist/portfolio.js.map +1 -1
  65. package/dist/reclaim.d.ts +4 -2
  66. package/dist/reclaim.d.ts.map +1 -1
  67. package/dist/reclaim.js +16 -16
  68. package/dist/reclaim.js.map +1 -1
  69. package/dist/risk.js +2 -2
  70. package/dist/risk.js.map +1 -1
  71. package/dist/rpc.d.ts +30 -7
  72. package/dist/rpc.d.ts.map +1 -1
  73. package/dist/rpc.js +400 -109
  74. package/dist/rpc.js.map +1 -1
  75. package/dist/simulate.d.ts.map +1 -1
  76. package/dist/simulate.js +3 -26
  77. package/dist/simulate.js.map +1 -1
  78. package/dist/source.d.ts +8 -4
  79. package/dist/source.d.ts.map +1 -1
  80. package/dist/source.js +11 -4
  81. package/dist/source.js.map +1 -1
  82. package/dist/subpaths/approvals.d.ts +3 -3
  83. package/dist/subpaths/approvals.d.ts.map +1 -1
  84. package/dist/subpaths/approvals.js.map +1 -1
  85. package/dist/subpaths/claim.d.ts +3 -3
  86. package/dist/subpaths/claim.d.ts.map +1 -1
  87. package/dist/subpaths/claim.js.map +1 -1
  88. package/dist/subpaths/reclaim.d.ts +3 -3
  89. package/dist/subpaths/reclaim.d.ts.map +1 -1
  90. package/dist/subpaths/reclaim.js.map +1 -1
  91. package/dist/swap/index.js +3 -3
  92. package/dist/swap/index.js.map +1 -1
  93. package/dist/tokenDetails.d.ts +12 -0
  94. package/dist/tokenDetails.d.ts.map +1 -0
  95. package/dist/tokenDetails.js +196 -0
  96. package/dist/tokenDetails.js.map +1 -0
  97. package/dist/tokenMeta.d.ts +63 -0
  98. package/dist/tokenMeta.d.ts.map +1 -0
  99. package/dist/tokenMeta.js +226 -0
  100. package/dist/tokenMeta.js.map +1 -0
  101. package/dist/tradeCheck.js +3 -3
  102. package/dist/tradeCheck.js.map +1 -1
  103. package/dist/util.d.ts +22 -0
  104. package/dist/util.d.ts.map +1 -0
  105. package/dist/util.js +107 -0
  106. package/dist/util.js.map +1 -0
  107. package/dist/write/chain.d.ts +51 -0
  108. package/dist/write/chain.d.ts.map +1 -0
  109. package/dist/write/chain.js +184 -0
  110. package/dist/write/chain.js.map +1 -0
  111. package/dist/write/collect.js +2 -2
  112. package/dist/write/collect.js.map +1 -1
  113. package/dist/write/errors.d.ts +10 -0
  114. package/dist/write/errors.d.ts.map +1 -0
  115. package/dist/write/errors.js +77 -0
  116. package/dist/write/errors.js.map +1 -0
  117. package/dist/write/pack.d.ts +28 -0
  118. package/dist/write/pack.d.ts.map +1 -0
  119. package/dist/write/pack.js +125 -0
  120. package/dist/write/pack.js.map +1 -0
  121. package/dist/write/send.d.ts +23 -9
  122. package/dist/write/send.d.ts.map +1 -1
  123. package/dist/write/send.js +53 -351
  124. package/dist/write/send.js.map +1 -1
  125. package/dist/write/tracker.d.ts +24 -0
  126. package/dist/write/tracker.d.ts.map +1 -0
  127. package/dist/write/tracker.js +129 -0
  128. package/dist/write/tracker.js.map +1 -0
  129. package/package.json +1 -1
  130. package/src/accountReader.ts +187 -0
  131. package/src/address.ts +41 -6
  132. package/src/approvals.ts +36 -44
  133. package/src/balances.ts +678 -0
  134. package/src/batchPlan.ts +6 -26
  135. package/src/bytes.ts +89 -0
  136. package/src/claim.ts +15 -11
  137. package/src/client.ts +59 -1239
  138. package/src/clientConfig.ts +12 -0
  139. package/src/decode.ts +4 -30
  140. package/src/fees.ts +2 -9
  141. package/src/history.ts +4 -15
  142. package/src/index.ts +13 -1
  143. package/src/layout.ts +63 -82
  144. package/src/liquidity/common.ts +2 -2
  145. package/src/lp.ts +86 -60
  146. package/src/portfolio.ts +8 -11
  147. package/src/reclaim.ts +20 -17
  148. package/src/risk.ts +2 -2
  149. package/src/rpc.ts +472 -116
  150. package/src/simulate.ts +3 -21
  151. package/src/source.ts +14 -5
  152. package/src/subpaths/approvals.ts +3 -2
  153. package/src/subpaths/claim.ts +3 -2
  154. package/src/subpaths/reclaim.ts +3 -2
  155. package/src/swap/index.ts +3 -3
  156. package/src/tokenDetails.ts +240 -0
  157. package/src/tokenMeta.ts +270 -0
  158. package/src/tradeCheck.ts +3 -3
  159. package/src/util.ts +110 -0
  160. package/src/write/chain.ts +218 -0
  161. package/src/write/collect.ts +2 -2
  162. package/src/write/errors.ts +82 -0
  163. package/src/write/pack.ts +142 -0
  164. package/src/write/send.ts +74 -407
  165. package/src/write/tracker.ts +152 -0
package/src/reclaim.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * - Wrapped SOL 账户:关闭 = 解包,余额和租金一起退回
8
8
  * - 已清空的集中流动性仓位(Orca Whirlpool、Raydium CLMM:流动性、手续费、奖励都是 0):关闭仓位账户并销毁 NFT。还有没领的手续费 / 奖励时列在 blocked,先用 /claim 领取
9
9
  */
10
- import { decodeAddress, findProgramAddress, isAddress } from './address.js'
10
+ import { decodeAddress, findProgramAddress, InvalidAddressError, isAddress } from './address.js'
11
11
  import type { RequestOptions, SolanaClient } from './client.js'
12
12
  import { TOKEN_2022_PROGRAM_ID } from './constants.js'
13
13
  import { approvals, parseTokenAccountState, type TokenAccountApproval } from './approvals.js'
@@ -90,7 +90,7 @@ export interface JunkContext {
90
90
  risk: SolanaTokenRisk | null
91
91
  }
92
92
 
93
- export interface ReclaimQuery extends RequestOptions {
93
+ export interface ReclaimableOptions extends RequestOptions {
94
94
  /** 只看这些 mint 的关联代币账户(免费公共节点也能用);不传时列出全部代币账户(getTokenAccountsByOwner,需要支持它的节点) */
95
95
  mints?: readonly string[]
96
96
  /** 找垃圾币(有余额的代币),默认 true;false 只找空账户、Wrapped SOL 和空仓位 */
@@ -111,6 +111,9 @@ export interface ReclaimQuery extends RequestOptions {
111
111
  fetch?: typeof fetch
112
112
  }
113
113
 
114
+ /** @deprecated 改名为 ReclaimableOptions(与其他查询的 options 命名统一),旧名保留 */
115
+ export type ReclaimQuery = ReclaimableOptions
116
+
114
117
  /** 垃圾特征里足以自动勾选的风险标记(只有这些:legit 的 RWA / 稳定币常有 permanent-delegate、transfer-hook,不能据此判断) */
115
118
  const JUNK_RISK_FLAGS = ['non-transferable', 'high-transfer-fee', 'paused']
116
119
  /** 垃圾币常见的名字:链接 / 域名、领奖广告。只作提示(reasons 里的 spam-name),不会让代币被自动勾选 */
@@ -160,16 +163,16 @@ function tokenItem(a: TokenAccountApproval, kind: ReclaimKind, extra: { selected
160
163
  * r.items.filter((i) => i.selected) // 建议勾选的
161
164
  * ```
162
165
  */
163
- export async function reclaimable(client: SolanaClient, owner: string, query: ReclaimQuery = {}): Promise<Reclaimable> {
166
+ export async function reclaimable(client: SolanaClient, owner: string, options: ReclaimableOptions = {}): Promise<Reclaimable> {
164
167
  if (!isAddress(owner)) {
165
- throw new Error(`Invalid owner address: ${owner}`)
168
+ throw new InvalidAddressError(`Invalid owner address: ${owner}`, owner)
166
169
  }
167
- const { signal } = query
168
- const maxJunkUsd = query.maxJunkUsd ?? 0.01
170
+ const { signal } = options
171
+ const maxJunkUsd = options.maxJunkUsd ?? 0.01
169
172
  if (!(maxJunkUsd >= 0)) {
170
173
  throw new RangeError(`maxJunkUsd must be >= 0: ${maxJunkUsd}`)
171
174
  }
172
- const accounts = (await approvals(client, owner, { mints: query.mints, all: true, signal })).filter((a) => ownedBy(a, owner))
175
+ const accounts = (await approvals(client, owner, { mints: options.mints, all: true, signal })).filter((a) => ownedBy(a, owner))
173
176
  const items: ReclaimItem[] = []
174
177
  const blocked: ReclaimItem[] = []
175
178
  const warnings: string[] = []
@@ -190,11 +193,11 @@ export async function reclaimable(client: SolanaClient, owner: string, query: Re
190
193
  }
191
194
  }
192
195
 
193
- if (query.positions ?? true) {
196
+ if (options.positions ?? true) {
194
197
  await scanPositions(client, accounts.filter(nft), push, signal)
195
198
  }
196
- if ((query.junk ?? true) && rest.length) {
197
- await scanJunk(client, rest, query, maxJunkUsd, push, warnings)
199
+ if ((options.junk ?? true) && rest.length) {
200
+ await scanJunk(client, rest, options, maxJunkUsd, push, warnings)
198
201
  }
199
202
 
200
203
  const byKind: Reclaimable['byKind'] = {}
@@ -245,20 +248,20 @@ async function scanPositions(client: SolanaClient, nfts: readonly TokenAccountAp
245
248
  async function scanJunk(
246
249
  client: SolanaClient,
247
250
  list: readonly TokenAccountApproval[],
248
- query: ReclaimQuery,
251
+ options: ReclaimableOptions,
249
252
  maxJunkUsd: number,
250
253
  push: (item: ReclaimItem, blocker?: ReclaimBlocker) => void,
251
254
  warnings: string[],
252
255
  ): Promise<void> {
253
- const { signal } = query
256
+ const { signal } = options
254
257
  const mints = [...new Set(list.map((a) => a.mint))]
255
- const source = query.prices === false ? null : query.prices && query.prices !== true ? query.prices : defillamaPrices()
258
+ const source = options.prices === false ? null : options.prices && options.prices !== true ? options.prices : defillamaPrices()
256
259
  // 价格没查到(关闭 / 服务出错)时不知道哪些值钱:不自动勾选任何垃圾币
257
260
  let pricesOk = source !== null
258
261
  let priceMap = new Map<string, number>()
259
262
  if (source) {
260
263
  try {
261
- const fetchFn = query.fetch ?? ((...args: Parameters<typeof fetch>) => fetch(...args))
264
+ const fetchFn = options.fetch ?? ((...args: Parameters<typeof fetch>) => fetch(...args))
262
265
  priceMap = await source.prices({ mints, fetch: fetchFn, signal, client })
263
266
  } catch (err) {
264
267
  if (signal?.aborted) throw err
@@ -269,7 +272,7 @@ async function scanJunk(
269
272
  warnings.push('Prices are off: junk tokens are not auto-selected')
270
273
  }
271
274
  const risks = new Map<string, SolanaTokenRisk>()
272
- if (query.risk ?? true) {
275
+ if (options.risk ?? true) {
273
276
  try {
274
277
  const found = await tokenRisks(client, mints, { signal })
275
278
  found.forEach((r, i) => risks.set(mints[i] as string, r))
@@ -282,7 +285,7 @@ async function scanJunk(
282
285
  const price = priceMap.get(a.mint) ?? null
283
286
  const usd = price !== null && a.formatted !== null ? Number(a.formatted) * price : null
284
287
  const risk = risks.get(a.mint) ?? null
285
- const custom = query.isJunk?.({ account: a, price, usd, risk })
288
+ const custom = options.isJunk?.({ account: a, price, usd, risk })
286
289
  const valuable = usd !== null && usd > maxJunkUsd
287
290
  if (custom === false || (valuable && custom !== true)) continue
288
291
  const reasons: string[] = []
@@ -354,7 +357,7 @@ export interface ReclaimPlan {
354
357
  */
355
358
  export async function buildReclaim(client: SolanaClient, owner: string, items: readonly ReclaimItem[], options: BuildReclaimOptions = {}): Promise<ReclaimPlan> {
356
359
  if (!isAddress(owner)) {
357
- throw new Error(`Invalid owner address: ${owner}`)
360
+ throw new InvalidAddressError(`Invalid owner address: ${owner}`, owner)
358
361
  }
359
362
  const destination = options.destination ?? owner
360
363
  if (!isAddress(destination)) {
package/src/risk.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * 影响持有人的设置(转账手续费、永久授权、转账 hook、不可转让、新账户默认冻结、可暂停、保密转账、mint 可关闭等),一次 getMultipleAccounts 读完。
4
4
  * 可选:持币集中度(getTokenLargestAccounts,免费公共节点大多不支持);能不能买、能不能卖用 tradeChecks(在主网模拟“买入 → 卖出”)
5
5
  */
6
- import { isAddress } from './address.js'
6
+ import { InvalidAddressError, isAddress } from './address.js'
7
7
  import type { RequestOptions, SolanaClient } from './client.js'
8
8
  import { NATIVE_MINT, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from './constants.js'
9
9
  import { findExtension, parseMint, parseTransferFeeConfig, type AccountInfo } from './layout.js'
@@ -89,7 +89,7 @@ export interface TokenRisksOptions extends RequestOptions {
89
89
  export async function tokenRisks(client: SolanaClient, mints: readonly string[], options: TokenRisksOptions = {}): Promise<SolanaTokenRisk[]> {
90
90
  const keys = mints.map((m) => (client.isNativeMint(m) ? NATIVE_MINT : m))
91
91
  for (const m of keys) {
92
- if (!isAddress(m)) throw new Error(`Invalid mint address: ${m}`)
92
+ if (!isAddress(m)) throw new InvalidAddressError(`Invalid mint address: ${m}`, m)
93
93
  }
94
94
  const unique = [...new Set(keys)]
95
95
  const accounts = await client.accounts([CLOCK_SYSVAR_ID, ...unique], { signal: options.signal })