@w3lib/solana-batch-call 0.1.0 → 0.2.1

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.
package/src/index.ts CHANGED
@@ -1,21 +1,43 @@
1
- export { SolanaClient, type BalancesOptions, type ClientConfig, type OwnerTokensOptions, type TokensOptions } from './client.js'
1
+ export {
2
+ SolanaClient,
3
+ exportTokenMetaCache,
4
+ importTokenMetaCache,
5
+ persistTokenMetaCache,
6
+ type AccountsOptions,
7
+ type BalanceQuery,
8
+ type BalancesOptions,
9
+ type ClientConfig,
10
+ type OwnerTokensOptions,
11
+ type PersistTokenMetaOptions,
12
+ type RequestOptions,
13
+ type SlotOptions,
14
+ type SolBalancesOptions,
15
+ type TokenMetaSnapshot,
16
+ type TokensOptions,
17
+ } from './client.js'
2
18
  export {
3
19
  getBalances,
20
+ getMultiBalances,
4
21
  getNftOwners,
5
22
  getNfts,
6
23
  getOwnerNfts,
7
24
  getOwnerTokens,
8
25
  getSolBalances,
9
26
  getTokens,
27
+ watchBalances,
10
28
  type GetBalancesOptions,
29
+ type GetNftsOptions,
11
30
  type GetOwnerTokensOptions,
31
+ type GetSolBalancesOptions,
12
32
  type GetTokensOptions,
33
+ type WatchBalancesOptions,
13
34
  type ShortcutOptions,
14
35
  } from './shortcuts.js'
15
36
  export {
16
37
  DEFAULT_TOKEN_FIELDS,
17
38
  type Commitment,
18
39
  type DefaultTokenField,
40
+ type FailureReason,
19
41
  type NftDetails,
20
42
  type NftOwner,
21
43
  type OwnedToken,
@@ -23,7 +45,11 @@ export {
23
45
  type TokenBalance,
24
46
  type TokenDetails,
25
47
  type TokenField,
48
+ type TokenProgramName,
49
+ type TokenProgramOption,
26
50
  type TokenStandard,
51
+ type TransferFee,
52
+ type TransferFeeConfig,
27
53
  } from './types.js'
28
54
  export {
29
55
  ASSOCIATED_TOKEN_PROGRAM_ID,
@@ -38,17 +64,35 @@ export {
38
64
  clusterOfGenesis,
39
65
  type Cluster,
40
66
  } from './constants.js'
41
- export { decodeAddress, encodeAddress, findProgramAddress, getAssociatedTokenAddress, getMetadataAddress, isAddress } from './address.js'
67
+ export { decodeAddress, encodeAddress, findProgramAddress, getAssociatedTokenAddress, getMetadataAddress, isAddress, isOnCurve } from './address.js'
42
68
  export {
43
69
  formatAmount,
70
+ formatUnits,
44
71
  parseMetaplexMetadata,
45
72
  parseMint,
46
73
  parseTokenAccount,
74
+ parseTransferFeeConfig,
47
75
  type AccountInfo,
48
76
  type MetaplexMetadata,
49
77
  type MintInfo,
50
78
  type TokenAccountInfo,
51
79
  type TokenMetadata,
80
+ type TransferFeeConfigInfo,
81
+ type TransferFeeInfo,
52
82
  } from './layout.js'
53
- export { FallbackRpc, HttpError, HttpRpc, RpcError, isNodeFault, type FallbackOptions, type HttpRpcOptions, type RpcTransport } from './rpc.js'
83
+ export {
84
+ AllNodesFailedError,
85
+ FallbackRpc,
86
+ HttpError,
87
+ HttpRpc,
88
+ MIN_CONTEXT_SLOT_NOT_REACHED,
89
+ RpcError,
90
+ isNodeFault,
91
+ nodeLabel,
92
+ onRequest,
93
+ type FallbackOptions,
94
+ type HttpRpcOptions,
95
+ type RequestEvent,
96
+ type RpcTransport,
97
+ } from './rpc.js'
54
98
  export { NetworkCheckedRpc, NetworkMismatchError, type RpcSource, type SourceOptions } from './source.js'
package/src/layout.ts CHANGED
@@ -107,6 +107,7 @@ const ACCOUNT_TYPE_OFFSET = 165
107
107
  const EXTENSIONS_OFFSET = 166
108
108
  const ACCOUNT_TYPE_MINT = 1
109
109
  const ACCOUNT_TYPE_ACCOUNT = 2
110
+ const EXTENSION_TRANSFER_FEE_CONFIG = 1
110
111
  const EXTENSION_TOKEN_METADATA = 19
111
112
 
112
113
  /** 解析 Mint 账户(SPL Token / Token-2022 通用,Token-2022 额外解析 TokenMetadata 扩展) */
@@ -133,7 +134,11 @@ export function parseMint(data: Uint8Array): MintInfo {
133
134
  }
134
135
  }
135
136
 
136
- function parseTokenMetadataExtension(data: Uint8Array): TokenMetadata | null {
137
+ /** 在 Token-2022 账户的扩展(TLV:u16 类型 + u16 长度 + 数据)里找指定类型,返回其数据;没有或数据不完整时为 null */
138
+ function findExtension(data: Uint8Array, extensionType: number): Uint8Array | null {
139
+ if (data.length <= EXTENSIONS_OFFSET) {
140
+ return null
141
+ }
137
142
  try {
138
143
  const r = new Reader(data, EXTENSIONS_OFFSET)
139
144
  while (r.offset + 4 <= data.length) {
@@ -142,11 +147,11 @@ function parseTokenMetadataExtension(data: Uint8Array): TokenMetadata | null {
142
147
  if (type === 0 && length === 0) {
143
148
  return null // 未初始化的填充
144
149
  }
145
- if (type === EXTENSION_TOKEN_METADATA) {
146
- const m = new Reader(data.slice(r.offset, r.offset + length))
147
- m.pubkey() // updateAuthority
148
- m.pubkey() // mint
149
- return { name: m.string(), symbol: m.string(), uri: m.string() }
150
+ if (type === extensionType) {
151
+ if (r.offset + length > data.length) {
152
+ return null
153
+ }
154
+ return data.slice(r.offset, r.offset + length)
150
155
  }
151
156
  r.skip(length)
152
157
  }
@@ -156,6 +161,77 @@ function parseTokenMetadataExtension(data: Uint8Array): TokenMetadata | null {
156
161
  return null
157
162
  }
158
163
 
164
+ function parseTokenMetadataExtension(data: Uint8Array): TokenMetadata | null {
165
+ const ext = findExtension(data, EXTENSION_TOKEN_METADATA)
166
+ if (!ext) {
167
+ return null
168
+ }
169
+ try {
170
+ const m = new Reader(ext)
171
+ m.pubkey() // updateAuthority
172
+ m.pubkey() // mint
173
+ return { name: m.string(), symbol: m.string(), uri: m.string() }
174
+ } catch {
175
+ return null
176
+ }
177
+ }
178
+
179
+ /** Token-2022 转账手续费的一套配置:从 epoch 开始生效,费率 basisPoints(万分比),单笔最多 maximumFee(最小单位) */
180
+ export interface TransferFeeInfo {
181
+ epoch: bigint
182
+ maximumFee: bigint
183
+ basisPoints: number
184
+ }
185
+
186
+ /** Token-2022 TransferFeeConfig 扩展 */
187
+ export interface TransferFeeConfigInfo {
188
+ /** 可以修改手续费的地址;null 表示不能再改 */
189
+ transferFeeConfigAuthority: string | null
190
+ withdrawWithheldAuthority: string | null
191
+ /** mint 上暂存的、已收取未提取的手续费 */
192
+ withheldAmount: bigint
193
+ /** 旧配置:当前 epoch < newer.epoch 时生效 */
194
+ older: TransferFeeInfo
195
+ /** 新配置:从 newer.epoch 起生效 */
196
+ newer: TransferFeeInfo
197
+ }
198
+
199
+ const ZERO_PUBKEY = '11111111111111111111111111111111'
200
+
201
+ /**
202
+ * 解析 mint 账户里的 Token-2022 TransferFeeConfig 扩展(类型 1,108 字节);
203
+ * SPL Token、没有这个扩展或数据不完整时为 null。
204
+ * 当前生效的是 `epoch >= newer.epoch ? newer : older`
205
+ */
206
+ export function parseTransferFeeConfig(data: Uint8Array): TransferFeeConfigInfo | null {
207
+ if (!(data.length > ACCOUNT_TYPE_OFFSET && data[ACCOUNT_TYPE_OFFSET] === ACCOUNT_TYPE_MINT)) {
208
+ return null
209
+ }
210
+ const ext = findExtension(data, EXTENSION_TRANSFER_FEE_CONFIG)
211
+ if (!ext) {
212
+ return null
213
+ }
214
+ try {
215
+ const r = new Reader(ext)
216
+ // OptionalNonZeroPubkey:全 0 表示没有
217
+ const configAuthority = r.pubkey()
218
+ const withdrawAuthority = r.pubkey()
219
+ const withheldAmount = r.u64()
220
+ const fee = (): TransferFeeInfo => ({ epoch: r.u64(), maximumFee: r.u64(), basisPoints: r.u16() })
221
+ const older = fee()
222
+ const newer = fee()
223
+ return {
224
+ transferFeeConfigAuthority: configAuthority === ZERO_PUBKEY ? null : configAuthority,
225
+ withdrawWithheldAuthority: withdrawAuthority === ZERO_PUBKEY ? null : withdrawAuthority,
226
+ withheldAmount,
227
+ older,
228
+ newer,
229
+ }
230
+ } catch {
231
+ return null
232
+ }
233
+ }
234
+
159
235
  export interface TokenAccountInfo {
160
236
  mint: string
161
237
  owner: string
@@ -228,11 +304,17 @@ export function parseMetaplexMetadata(data: Uint8Array): MetaplexMetadata {
228
304
  return result
229
305
  }
230
306
 
231
- /** 按精度格式化:formatAmount(1_500_000_000n, 9) === '1.5' */
232
- export function formatAmount(value: bigint, decimals: number): string {
307
+ /** 按精度格式化(与 ethers 的 formatUnits 同名同义):formatUnits(1_500_000_000n, 9) === '1.5';不四舍五入,整数不带小数点 */
308
+ export function formatUnits(value: bigint, decimals: number): string {
233
309
  const negative = value < 0n
234
310
  const digits = (negative ? -value : value).toString().padStart(decimals + 1, '0')
235
311
  const whole = digits.slice(0, digits.length - decimals)
236
312
  const fraction = digits.slice(digits.length - decimals).replace(/0+$/, '')
237
313
  return `${negative ? '-' : ''}${whole}${fraction ? `.${fraction}` : ''}`
238
314
  }
315
+
316
+ /**
317
+ * 同 formatUnits。
318
+ * @deprecated 改用 formatUnits:formatAmount 这个名字容易和项目里的数字展示函数撞名
319
+ */
320
+ export const formatAmount = formatUnits