@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.
- package/CHANGELOG.md +47 -0
- package/README.md +129 -9
- package/dist/accountReader.d.ts +57 -0
- package/dist/accountReader.d.ts.map +1 -0
- package/dist/accountReader.js +149 -0
- package/dist/accountReader.js.map +1 -0
- package/dist/address.d.ts +9 -0
- package/dist/address.d.ts.map +1 -1
- package/dist/address.js +36 -6
- package/dist/address.js.map +1 -1
- package/dist/approvals.d.ts +5 -3
- package/dist/approvals.d.ts.map +1 -1
- package/dist/approvals.js +25 -36
- package/dist/approvals.js.map +1 -1
- package/dist/balances.d.ts +178 -0
- package/dist/balances.d.ts.map +1 -0
- package/dist/balances.js +524 -0
- package/dist/balances.js.map +1 -0
- package/dist/batchPlan.d.ts +52 -0
- package/dist/batchPlan.d.ts.map +1 -0
- package/dist/batchPlan.js +64 -0
- package/dist/batchPlan.js.map +1 -0
- package/dist/bytes.d.ts +31 -0
- package/dist/bytes.d.ts.map +1 -0
- package/dist/bytes.js +74 -0
- package/dist/bytes.js.map +1 -0
- package/dist/claim.d.ts +163 -0
- package/dist/claim.d.ts.map +1 -0
- package/dist/claim.js +197 -0
- package/dist/claim.js.map +1 -0
- package/dist/client.d.ts +26 -41
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +41 -986
- package/dist/client.js.map +1 -1
- package/dist/clientConfig.d.ts +11 -0
- package/dist/clientConfig.d.ts.map +1 -0
- package/dist/clientConfig.js +3 -0
- package/dist/clientConfig.js.map +1 -0
- package/dist/decode.d.ts +22 -0
- package/dist/decode.d.ts.map +1 -0
- package/dist/decode.js +160 -0
- package/dist/decode.js.map +1 -0
- package/dist/describe.d.ts +26 -0
- package/dist/describe.d.ts.map +1 -0
- package/dist/describe.js +58 -0
- package/dist/describe.js.map +1 -0
- package/dist/fees.d.ts.map +1 -1
- package/dist/fees.js +2 -12
- package/dist/fees.js.map +1 -1
- package/dist/history.d.ts +125 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +220 -0
- package/dist/history.js.map +1 -0
- package/dist/historyHelius.d.ts +52 -0
- package/dist/historyHelius.d.ts.map +1 -0
- package/dist/historyHelius.js +125 -0
- package/dist/historyHelius.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +21 -0
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +50 -69
- package/dist/layout.js.map +1 -1
- package/dist/liquidity/common.js +2 -2
- package/dist/liquidity/common.js.map +1 -1
- package/dist/liquidity/orca.d.ts +6 -0
- package/dist/liquidity/orca.d.ts.map +1 -1
- package/dist/liquidity/orca.js +14 -3
- package/dist/liquidity/orca.js.map +1 -1
- package/dist/liquidity/raydiumClmm.d.ts +6 -0
- package/dist/liquidity/raydiumClmm.d.ts.map +1 -1
- package/dist/liquidity/raydiumClmm.js +12 -5
- package/dist/liquidity/raydiumClmm.js.map +1 -1
- package/dist/lp.d.ts +55 -12
- package/dist/lp.d.ts.map +1 -1
- package/dist/lp.js +158 -70
- package/dist/lp.js.map +1 -1
- package/dist/lpMath.d.ts +22 -0
- package/dist/lpMath.d.ts.map +1 -1
- package/dist/lpMath.js +21 -0
- package/dist/lpMath.js.map +1 -1
- package/dist/portfolio.d.ts.map +1 -1
- package/dist/portfolio.js +3 -8
- package/dist/portfolio.js.map +1 -1
- package/dist/programs.d.ts +19 -0
- package/dist/programs.d.ts.map +1 -0
- package/dist/programs.js +175 -0
- package/dist/programs.js.map +1 -0
- package/dist/reclaim.d.ts +192 -0
- package/dist/reclaim.d.ts.map +1 -0
- package/dist/reclaim.js +399 -0
- package/dist/reclaim.js.map +1 -0
- package/dist/risk.js +2 -2
- package/dist/risk.js.map +1 -1
- package/dist/rpc.d.ts +30 -7
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +404 -111
- package/dist/rpc.js.map +1 -1
- package/dist/simulate.d.ts +106 -0
- package/dist/simulate.d.ts.map +1 -0
- package/dist/simulate.js +395 -0
- package/dist/simulate.js.map +1 -0
- package/dist/source.d.ts +8 -4
- package/dist/source.d.ts.map +1 -1
- package/dist/source.js +11 -4
- package/dist/source.js.map +1 -1
- package/dist/subpaths/approvals.d.ts +3 -3
- package/dist/subpaths/approvals.d.ts.map +1 -1
- package/dist/subpaths/approvals.js.map +1 -1
- package/dist/subpaths/claim.d.ts +31 -0
- package/dist/subpaths/claim.d.ts.map +1 -0
- package/dist/subpaths/claim.js +31 -0
- package/dist/subpaths/claim.js.map +1 -0
- package/dist/subpaths/history.d.ts +21 -0
- package/dist/subpaths/history.d.ts.map +1 -0
- package/dist/subpaths/history.js +22 -0
- package/dist/subpaths/history.js.map +1 -0
- package/dist/subpaths/lp.d.ts +2 -2
- package/dist/subpaths/lp.d.ts.map +1 -1
- package/dist/subpaths/lp.js +2 -2
- package/dist/subpaths/lp.js.map +1 -1
- package/dist/subpaths/reclaim.d.ts +34 -0
- package/dist/subpaths/reclaim.d.ts.map +1 -0
- package/dist/subpaths/reclaim.js +34 -0
- package/dist/subpaths/reclaim.js.map +1 -0
- package/dist/subpaths/simulate.d.ts +22 -0
- package/dist/subpaths/simulate.d.ts.map +1 -0
- package/dist/subpaths/simulate.js +23 -0
- package/dist/subpaths/simulate.js.map +1 -0
- package/dist/swap/index.js +3 -3
- package/dist/swap/index.js.map +1 -1
- package/dist/tokenDetails.d.ts +12 -0
- package/dist/tokenDetails.d.ts.map +1 -0
- package/dist/tokenDetails.js +196 -0
- package/dist/tokenDetails.js.map +1 -0
- package/dist/tokenMeta.d.ts +63 -0
- package/dist/tokenMeta.d.ts.map +1 -0
- package/dist/tokenMeta.js +226 -0
- package/dist/tokenMeta.js.map +1 -0
- package/dist/tradeCheck.js +3 -3
- package/dist/tradeCheck.js.map +1 -1
- package/dist/util.d.ts +22 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +107 -0
- package/dist/util.js.map +1 -0
- package/dist/write/chain.d.ts +51 -0
- package/dist/write/chain.d.ts.map +1 -0
- package/dist/write/chain.js +184 -0
- package/dist/write/chain.js.map +1 -0
- package/dist/write/collect.js +2 -2
- package/dist/write/collect.js.map +1 -1
- package/dist/write/errors.d.ts +10 -0
- package/dist/write/errors.d.ts.map +1 -0
- package/dist/write/errors.js +77 -0
- package/dist/write/errors.js.map +1 -0
- package/dist/write/instructions.d.ts +2 -0
- package/dist/write/instructions.d.ts.map +1 -1
- package/dist/write/instructions.js +16 -0
- package/dist/write/instructions.js.map +1 -1
- package/dist/write/pack.d.ts +28 -0
- package/dist/write/pack.d.ts.map +1 -0
- package/dist/write/pack.js +125 -0
- package/dist/write/pack.js.map +1 -0
- package/dist/write/send.d.ts +23 -9
- package/dist/write/send.d.ts.map +1 -1
- package/dist/write/send.js +53 -351
- package/dist/write/send.js.map +1 -1
- package/dist/write/tracker.d.ts +24 -0
- package/dist/write/tracker.d.ts.map +1 -0
- package/dist/write/tracker.js +129 -0
- package/dist/write/tracker.js.map +1 -0
- package/package.json +21 -1
- package/src/accountReader.ts +187 -0
- package/src/address.ts +41 -6
- package/src/approvals.ts +36 -44
- package/src/balances.ts +678 -0
- package/src/batchPlan.ts +117 -0
- package/src/bytes.ts +89 -0
- package/src/claim.ts +327 -0
- package/src/client.ts +59 -1239
- package/src/clientConfig.ts +12 -0
- package/src/decode.ts +176 -0
- package/src/describe.ts +77 -0
- package/src/fees.ts +2 -9
- package/src/history.ts +325 -0
- package/src/historyHelius.ts +136 -0
- package/src/index.ts +13 -1
- package/src/layout.ts +63 -82
- package/src/liquidity/common.ts +2 -2
- package/src/liquidity/orca.ts +15 -5
- package/src/liquidity/raydiumClmm.ts +13 -5
- package/src/lp.ts +226 -75
- package/src/lpMath.ts +38 -0
- package/src/portfolio.ts +8 -11
- package/src/programs.ts +216 -0
- package/src/reclaim.ts +550 -0
- package/src/risk.ts +2 -2
- package/src/rpc.ts +476 -118
- package/src/simulate.ts +517 -0
- package/src/source.ts +14 -5
- package/src/subpaths/approvals.ts +3 -2
- package/src/subpaths/claim.ts +54 -0
- package/src/subpaths/history.ts +38 -0
- package/src/subpaths/lp.ts +5 -1
- package/src/subpaths/reclaim.ts +58 -0
- package/src/subpaths/simulate.ts +37 -0
- package/src/swap/index.ts +3 -3
- package/src/tokenDetails.ts +240 -0
- package/src/tokenMeta.ts +270 -0
- package/src/tradeCheck.ts +3 -3
- package/src/util.ts +110 -0
- package/src/write/chain.ts +218 -0
- package/src/write/collect.ts +2 -2
- package/src/write/errors.ts +82 -0
- package/src/write/instructions.ts +17 -0
- package/src/write/pack.ts +142 -0
- package/src/write/send.ts +74 -407
- 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 {
|
|
11
|
-
import {
|
|
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
|
|
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
|
-
/**
|
|
93
|
+
/** 解析代币账户(基础布局用 layout 的 parseTokenAccountState)及关闭相关的 Token-2022 扩展;不是已初始化的代币账户时为 null */
|
|
92
94
|
export function parseTokenAccountState(data: Uint8Array): ParsedAccount | null {
|
|
93
|
-
|
|
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:
|
|
111
|
-
owner:
|
|
112
|
-
amount:
|
|
113
|
-
delegate:
|
|
114
|
-
frozen:
|
|
115
|
-
native:
|
|
116
|
-
delegatedAmount:
|
|
117
|
-
closeAuthority:
|
|
118
|
-
withheldAmount: withheld && withheld.length >= 8 ? new
|
|
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,
|
|
140
|
+
export async function approvals(client: SolanaClient, owner: string, options: ApprovalsOptions = {}): Promise<TokenAccountApproval[]> {
|
|
146
141
|
if (!isAddress(owner)) {
|
|
147
|
-
throw new
|
|
142
|
+
throw new InvalidAddressError(`Invalid owner address: ${owner}`, owner)
|
|
148
143
|
}
|
|
149
|
-
const { signal } =
|
|
150
|
-
const found =
|
|
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
|
|
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
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|