@w3lib/solana-batch-call 0.4.0 → 0.6.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 (223) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +343 -3
  3. package/dist/approvals.d.ts +129 -0
  4. package/dist/approvals.d.ts.map +1 -0
  5. package/dist/approvals.js +221 -0
  6. package/dist/approvals.js.map +1 -0
  7. package/dist/batchPlan.d.ts +52 -0
  8. package/dist/batchPlan.d.ts.map +1 -0
  9. package/dist/batchPlan.js +85 -0
  10. package/dist/batchPlan.js.map +1 -0
  11. package/dist/claim.d.ts +161 -0
  12. package/dist/claim.d.ts.map +1 -0
  13. package/dist/claim.js +197 -0
  14. package/dist/claim.js.map +1 -0
  15. package/dist/decode.d.ts +22 -0
  16. package/dist/decode.d.ts.map +1 -0
  17. package/dist/decode.js +187 -0
  18. package/dist/decode.js.map +1 -0
  19. package/dist/describe.d.ts +26 -0
  20. package/dist/describe.d.ts.map +1 -0
  21. package/dist/describe.js +58 -0
  22. package/dist/describe.js.map +1 -0
  23. package/dist/fees.d.ts +89 -0
  24. package/dist/fees.d.ts.map +1 -0
  25. package/dist/fees.js +166 -0
  26. package/dist/fees.js.map +1 -0
  27. package/dist/history.d.ts +125 -0
  28. package/dist/history.d.ts.map +1 -0
  29. package/dist/history.js +231 -0
  30. package/dist/history.js.map +1 -0
  31. package/dist/historyHelius.d.ts +52 -0
  32. package/dist/historyHelius.d.ts.map +1 -0
  33. package/dist/historyHelius.js +125 -0
  34. package/dist/historyHelius.js.map +1 -0
  35. package/dist/layout.d.ts +2 -0
  36. package/dist/layout.d.ts.map +1 -1
  37. package/dist/layout.js +2 -2
  38. package/dist/layout.js.map +1 -1
  39. package/dist/liquidity/orca.d.ts +6 -0
  40. package/dist/liquidity/orca.d.ts.map +1 -1
  41. package/dist/liquidity/orca.js +14 -3
  42. package/dist/liquidity/orca.js.map +1 -1
  43. package/dist/liquidity/raydiumClmm.d.ts +6 -0
  44. package/dist/liquidity/raydiumClmm.d.ts.map +1 -1
  45. package/dist/liquidity/raydiumClmm.js +12 -5
  46. package/dist/liquidity/raydiumClmm.js.map +1 -1
  47. package/dist/lp.d.ts +55 -15
  48. package/dist/lp.d.ts.map +1 -1
  49. package/dist/lp.js +98 -46
  50. package/dist/lp.js.map +1 -1
  51. package/dist/lpMath.d.ts +22 -0
  52. package/dist/lpMath.d.ts.map +1 -1
  53. package/dist/lpMath.js +21 -0
  54. package/dist/lpMath.js.map +1 -1
  55. package/dist/names.d.ts +68 -0
  56. package/dist/names.d.ts.map +1 -0
  57. package/dist/names.js +257 -0
  58. package/dist/names.js.map +1 -0
  59. package/dist/pools.d.ts +9 -0
  60. package/dist/pools.d.ts.map +1 -0
  61. package/dist/pools.js +45 -0
  62. package/dist/pools.js.map +1 -0
  63. package/dist/portfolio.d.ts +64 -0
  64. package/dist/portfolio.d.ts.map +1 -0
  65. package/dist/portfolio.js +57 -0
  66. package/dist/portfolio.js.map +1 -0
  67. package/dist/price.d.ts +90 -0
  68. package/dist/price.d.ts.map +1 -0
  69. package/dist/price.js +287 -0
  70. package/dist/price.js.map +1 -0
  71. package/dist/programs.d.ts +19 -0
  72. package/dist/programs.d.ts.map +1 -0
  73. package/dist/programs.js +175 -0
  74. package/dist/programs.js.map +1 -0
  75. package/dist/reclaim.d.ts +190 -0
  76. package/dist/reclaim.d.ts.map +1 -0
  77. package/dist/reclaim.js +399 -0
  78. package/dist/reclaim.js.map +1 -0
  79. package/dist/risk.d.ts +84 -0
  80. package/dist/risk.d.ts.map +1 -0
  81. package/dist/risk.js +211 -0
  82. package/dist/risk.js.map +1 -0
  83. package/dist/rpc.d.ts +2 -0
  84. package/dist/rpc.d.ts.map +1 -1
  85. package/dist/rpc.js +36 -10
  86. package/dist/rpc.js.map +1 -1
  87. package/dist/simulate.d.ts +106 -0
  88. package/dist/simulate.d.ts.map +1 -0
  89. package/dist/simulate.js +418 -0
  90. package/dist/simulate.js.map +1 -0
  91. package/dist/subpaths/approvals.d.ts +29 -0
  92. package/dist/subpaths/approvals.d.ts.map +1 -0
  93. package/dist/subpaths/approvals.js +30 -0
  94. package/dist/subpaths/approvals.js.map +1 -0
  95. package/dist/subpaths/claim.d.ts +31 -0
  96. package/dist/subpaths/claim.d.ts.map +1 -0
  97. package/dist/subpaths/claim.js +31 -0
  98. package/dist/subpaths/claim.js.map +1 -0
  99. package/dist/subpaths/fees.d.ts +23 -0
  100. package/dist/subpaths/fees.d.ts.map +1 -0
  101. package/dist/subpaths/fees.js +25 -0
  102. package/dist/subpaths/fees.js.map +1 -0
  103. package/dist/subpaths/history.d.ts +21 -0
  104. package/dist/subpaths/history.d.ts.map +1 -0
  105. package/dist/subpaths/history.js +22 -0
  106. package/dist/subpaths/history.js.map +1 -0
  107. package/dist/subpaths/lp.d.ts +2 -2
  108. package/dist/subpaths/lp.d.ts.map +1 -1
  109. package/dist/subpaths/lp.js +2 -2
  110. package/dist/subpaths/lp.js.map +1 -1
  111. package/dist/subpaths/names.d.ts +37 -0
  112. package/dist/subpaths/names.d.ts.map +1 -0
  113. package/dist/subpaths/names.js +27 -0
  114. package/dist/subpaths/names.js.map +1 -0
  115. package/dist/subpaths/price.d.ts +40 -0
  116. package/dist/subpaths/price.d.ts.map +1 -0
  117. package/dist/subpaths/price.js +43 -0
  118. package/dist/subpaths/price.js.map +1 -0
  119. package/dist/subpaths/reclaim.d.ts +34 -0
  120. package/dist/subpaths/reclaim.d.ts.map +1 -0
  121. package/dist/subpaths/reclaim.js +34 -0
  122. package/dist/subpaths/reclaim.js.map +1 -0
  123. package/dist/subpaths/risk.d.ts +28 -0
  124. package/dist/subpaths/risk.d.ts.map +1 -0
  125. package/dist/subpaths/risk.js +30 -0
  126. package/dist/subpaths/risk.js.map +1 -0
  127. package/dist/subpaths/simulate.d.ts +22 -0
  128. package/dist/subpaths/simulate.d.ts.map +1 -0
  129. package/dist/subpaths/simulate.js +23 -0
  130. package/dist/subpaths/simulate.js.map +1 -0
  131. package/dist/subpaths/swap.d.ts +22 -0
  132. package/dist/subpaths/swap.d.ts.map +1 -0
  133. package/dist/subpaths/swap.js +21 -0
  134. package/dist/subpaths/swap.js.map +1 -0
  135. package/dist/subpaths/write.d.ts +1 -1
  136. package/dist/subpaths/write.d.ts.map +1 -1
  137. package/dist/subpaths/write.js +1 -1
  138. package/dist/subpaths/write.js.map +1 -1
  139. package/dist/swap/amm.d.ts +20 -0
  140. package/dist/swap/amm.d.ts.map +1 -0
  141. package/dist/swap/amm.js +77 -0
  142. package/dist/swap/amm.js.map +1 -0
  143. package/dist/swap/clmmMath.d.ts +24 -0
  144. package/dist/swap/clmmMath.d.ts.map +1 -0
  145. package/dist/swap/clmmMath.js +82 -0
  146. package/dist/swap/clmmMath.js.map +1 -0
  147. package/dist/swap/common.d.ts +68 -0
  148. package/dist/swap/common.d.ts.map +1 -0
  149. package/dist/swap/common.js +65 -0
  150. package/dist/swap/common.js.map +1 -0
  151. package/dist/swap/cpmm.d.ts +28 -0
  152. package/dist/swap/cpmm.d.ts.map +1 -0
  153. package/dist/swap/cpmm.js +113 -0
  154. package/dist/swap/cpmm.js.map +1 -0
  155. package/dist/swap/index.d.ts +145 -0
  156. package/dist/swap/index.d.ts.map +1 -0
  157. package/dist/swap/index.js +349 -0
  158. package/dist/swap/index.js.map +1 -0
  159. package/dist/swap/orca.d.ts +50 -0
  160. package/dist/swap/orca.d.ts.map +1 -0
  161. package/dist/swap/orca.js +382 -0
  162. package/dist/swap/orca.js.map +1 -0
  163. package/dist/swap/raydiumClmm.d.ts +62 -0
  164. package/dist/swap/raydiumClmm.d.ts.map +1 -0
  165. package/dist/swap/raydiumClmm.js +447 -0
  166. package/dist/swap/raydiumClmm.js.map +1 -0
  167. package/dist/tradeCheck.d.ts +45 -0
  168. package/dist/tradeCheck.d.ts.map +1 -0
  169. package/dist/tradeCheck.js +131 -0
  170. package/dist/tradeCheck.js.map +1 -0
  171. package/dist/write/instructions.d.ts +9 -0
  172. package/dist/write/instructions.d.ts.map +1 -1
  173. package/dist/write/instructions.js +40 -1
  174. package/dist/write/instructions.js.map +1 -1
  175. package/dist/write/transaction.d.ts +23 -0
  176. package/dist/write/transaction.d.ts.map +1 -1
  177. package/dist/write/transaction.js +50 -0
  178. package/dist/write/transaction.js.map +1 -1
  179. package/package.json +66 -14
  180. package/src/approvals.ts +358 -0
  181. package/src/batchPlan.ts +137 -0
  182. package/src/claim.ts +323 -0
  183. package/src/decode.ts +202 -0
  184. package/src/describe.ts +77 -0
  185. package/src/fees.ts +259 -0
  186. package/src/history.ts +336 -0
  187. package/src/historyHelius.ts +136 -0
  188. package/src/layout.ts +2 -2
  189. package/src/liquidity/orca.ts +15 -5
  190. package/src/liquidity/raydiumClmm.ts +13 -5
  191. package/src/lp.ts +148 -59
  192. package/src/lpMath.ts +38 -0
  193. package/src/names.ts +329 -0
  194. package/src/pools.ts +43 -0
  195. package/src/portfolio.ts +124 -0
  196. package/src/price.ts +366 -0
  197. package/src/programs.ts +216 -0
  198. package/src/reclaim.ts +547 -0
  199. package/src/risk.ts +243 -0
  200. package/src/rpc.ts +39 -10
  201. package/src/simulate.ts +535 -0
  202. package/src/subpaths/approvals.ts +47 -0
  203. package/src/subpaths/claim.ts +53 -0
  204. package/src/subpaths/fees.ts +41 -0
  205. package/src/subpaths/history.ts +38 -0
  206. package/src/subpaths/lp.ts +5 -1
  207. package/src/subpaths/names.ts +45 -0
  208. package/src/subpaths/price.ts +62 -0
  209. package/src/subpaths/reclaim.ts +57 -0
  210. package/src/subpaths/risk.ts +36 -0
  211. package/src/subpaths/simulate.ts +37 -0
  212. package/src/subpaths/swap.ts +41 -0
  213. package/src/subpaths/write.ts +2 -0
  214. package/src/swap/amm.ts +88 -0
  215. package/src/swap/clmmMath.ts +96 -0
  216. package/src/swap/common.ts +113 -0
  217. package/src/swap/cpmm.ts +132 -0
  218. package/src/swap/index.ts +467 -0
  219. package/src/swap/orca.ts +397 -0
  220. package/src/swap/raydiumClmm.ts +464 -0
  221. package/src/tradeCheck.ts +166 -0
  222. package/src/write/instructions.ts +43 -1
  223. package/src/write/transaction.ts +62 -0
@@ -0,0 +1,221 @@
1
+ /**
2
+ * 授权管理(子路径 `@w3lib/solana-batch-call/approvals`):Solana 上的“授权”是代币账户的 delegate(Approve 设置,可以转走 delegatedAmount 以内的代币)。
3
+ * 批量查一个地址的代币账户给出的授权、可以关闭回收租金的空账户;批量撤销(Revoke)、关闭(CloseAccount,租金退回)
4
+ */
5
+ import { base64 } from '@scure/base';
6
+ import { encodeAddress, getAssociatedTokenAddress, getMetadataAddress, isAddress } from './address.js';
7
+ import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from './constants.js';
8
+ import { findExtension, formatUnits, parseMetaplexMetadata, parseMint } from './layout.js';
9
+ import { methodUnavailable } from './lp.js';
10
+ import { closeAccount, harvestWithheldTokensToMint, revoke } from './write/instructions.js';
11
+ const ACCOUNT_SIZE = 165;
12
+ const ACCOUNT_TYPE_ACCOUNT = 2;
13
+ const EXT_TRANSFER_FEE_AMOUNT = 2;
14
+ const EXT_CONFIDENTIAL_TRANSFER_ACCOUNT = 5;
15
+ const EXT_PERMANENT_DELEGATE = 12;
16
+ const EXT_CONFIDENTIAL_TRANSFER_FEE_AMOUNT = 17;
17
+ const ZERO_PUBKEY = '11111111111111111111111111111111';
18
+ /** 解析代币账户;不是已初始化的代币账户时为 null */
19
+ export function parseTokenAccountState(data) {
20
+ if (data.length !== ACCOUNT_SIZE && !(data.length > ACCOUNT_SIZE && data[ACCOUNT_SIZE] === ACCOUNT_TYPE_ACCOUNT)) {
21
+ return null;
22
+ }
23
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
24
+ const pubkey = (offset) => encodeAddress(data.slice(offset, offset + 32));
25
+ // COption:u32 标记(1 有、0 没有)+ 值
26
+ const option = (offset) => view.getUint32(offset, true) === 1;
27
+ const state = data[108];
28
+ if (state === 0) {
29
+ return null; // 未初始化
30
+ }
31
+ const withheld = findExtension(data, EXT_TRANSFER_FEE_AMOUNT);
32
+ // 机密转账:待入账(lo / hi)和可用余额的密文全为 0 才能关闭;手续费扩展同理(Token-2022 的 closable 检查)
33
+ const confidential = findExtension(data, EXT_CONFIDENTIAL_TRANSFER_ACCOUNT);
34
+ const confidentialFee = findExtension(data, EXT_CONFIDENTIAL_TRANSFER_FEE_AMOUNT);
35
+ const nonZero = (bytes, from, to) => !!bytes && bytes.slice(from, to).some((b) => b !== 0);
36
+ return {
37
+ mint: pubkey(0),
38
+ owner: pubkey(32),
39
+ amount: view.getBigUint64(64, true),
40
+ delegate: option(72) ? pubkey(76) : null,
41
+ frozen: state === 2,
42
+ native: option(109),
43
+ delegatedAmount: view.getBigUint64(121, true),
44
+ closeAuthority: option(129) ? pubkey(133) : null,
45
+ withheldAmount: withheld && withheld.length >= 8 ? new DataView(withheld.buffer, withheld.byteOffset).getBigUint64(0, true) : 0n,
46
+ confidentialBalance: nonZero(confidential, 33, 225) || nonZero(confidentialFee, 0, 64),
47
+ };
48
+ }
49
+ /**
50
+ * 查一个地址的代币账户给出的授权,和可以关闭回收租金的空账户(结果按账户,同一账户的授权和关闭状态在一起)。
51
+ * 传 mints 时读这些代币的 ATA(一次 getMultipleAccounts,免费公共节点也能用);不传时列出全部代币账户(需要支持 getTokenAccountsByOwner 的节点)
52
+ *
53
+ * ```ts
54
+ * await approvals(client, owner, { mints: [USDC, BONK] })
55
+ * // [{ account: '…', mint: USDC, delegate: 'JUP…', delegatedAmount: '1000000', revocable: true, closable: false, closeBlocker: 'balance', … }]
56
+ * await approvals(new SolanaClient('https://my-rpc…'), owner) // 全部代币账户
57
+ * ```
58
+ */
59
+ export async function approvals(client, owner, query = {}) {
60
+ if (!isAddress(owner)) {
61
+ throw new Error(`Invalid owner address: ${owner}`);
62
+ }
63
+ const { signal } = query;
64
+ const found = query.mints ? await ataAccounts(client, owner, query.mints, signal) : await listAccounts(client, owner, signal);
65
+ // 只看 owner 自己的账户(ATA 的 owner 可能被改过:SPL Token 的 ATA 能 SetAuthority 换 owner)
66
+ const mine = found.filter((f) => f.parsed.owner === owner);
67
+ const mints = [...new Set(mine.map((f) => f.parsed.mint))];
68
+ const metaAddresses = mints.flatMap((m) => [m, getMetadataAddress(m)]);
69
+ const metaAccounts = metaAddresses.length ? await client.accounts(metaAddresses, { signal }) : [];
70
+ const meta = new Map(mints.map((mint, i) => [mint, mintMeta(metaAccounts[2 * i] ?? null, metaAccounts[2 * i + 1] ?? null)]));
71
+ const list = mine.map((f) => {
72
+ const p = f.parsed;
73
+ const m = meta.get(p.mint) ?? { decimals: null, symbol: null, permanentDelegate: null };
74
+ const format = (v) => (m.decimals === null ? null : formatUnits(v, m.decimals));
75
+ const closeBlocker = p.closeAuthority !== null && p.closeAuthority !== owner ? 'close-authority' : !p.native && p.amount > 0n ? 'balance' : p.confidentialBalance ? 'confidential-balance' : null;
76
+ return {
77
+ account: f.address,
78
+ mint: p.mint,
79
+ owner: p.owner,
80
+ tokenProgram: f.program,
81
+ ata: getAssociatedTokenAddress(owner, p.mint, f.program) === f.address,
82
+ native: p.native,
83
+ symbol: m.symbol,
84
+ decimals: m.decimals,
85
+ amount: p.amount.toString(),
86
+ formatted: format(p.amount),
87
+ delegate: p.delegate,
88
+ delegatedAmount: p.delegatedAmount.toString(),
89
+ delegatedFormatted: format(p.delegatedAmount),
90
+ closeAuthority: p.closeAuthority,
91
+ permanentDelegate: m.permanentDelegate,
92
+ frozen: p.frozen,
93
+ lamports: f.lamports.toString(),
94
+ withheldAmount: p.withheldAmount.toString(),
95
+ revocable: p.delegate !== null && !p.frozen,
96
+ closable: closeBlocker === null,
97
+ closeBlocker,
98
+ };
99
+ });
100
+ return query.all ? list : list.filter((a) => a.delegate !== null || a.closeBlocker === 'close-authority' || BigInt(a.amount) === 0n);
101
+ }
102
+ /** 指定 mints:两个程序的 ATA 都读(mint 所属程序未知时只有一个存在) */
103
+ async function ataAccounts(client, owner, mints, signal) {
104
+ const targets = [...new Set(mints.filter((m) => isAddress(m)))].flatMap((mint) => [TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID].map((program) => ({ program, address: getAssociatedTokenAddress(owner, mint, program) })));
105
+ const accounts = targets.length ? await client.accounts(targets.map((t) => t.address), { signal }) : [];
106
+ return targets.flatMap((t, i) => {
107
+ const account = accounts[i];
108
+ const parsed = account && account.owner === t.program ? parseTokenAccountState(account.data) : null;
109
+ return parsed && account ? [{ address: t.address, program: t.program, lamports: account.lamports, parsed }] : [];
110
+ });
111
+ }
112
+ /** 不传 mints:用 getTokenAccountsByOwner 列出两个程序的全部代币账户(base64,自己解析扩展) */
113
+ async function listAccounts(client, owner, signal) {
114
+ const lists = await Promise.all([TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID].map((programId) => client.request('getTokenAccountsByOwner', [owner, { programId }, { encoding: 'base64', commitment: client.commitment }], { signal }).then((res) => ({ programId, value: res.value ?? [] })))).catch((err) => {
115
+ if (signal?.aborted || !methodUnavailable(err)) {
116
+ throw err; // 取消、限频、超时等原样抛出(保留错误类型)
117
+ }
118
+ throw new Error(`Listing the token accounts of ${owner} failed (${err instanceof Error ? err.message : String(err)}). ` +
119
+ 'Listing needs getTokenAccountsByOwner (most free public nodes do not support it): pass the mints in `mints`, or use a node that supports it', { cause: err });
120
+ });
121
+ return lists.flatMap(({ programId, value }) => value.flatMap((entry) => {
122
+ const parsed = entry.account.owner === programId ? parseTokenAccountState(base64.decode(entry.account.data[0])) : null;
123
+ return parsed ? [{ address: entry.pubkey, program: programId, lamports: BigInt(entry.account.lamports), parsed }] : [];
124
+ }));
125
+ }
126
+ /** mint 的精度、symbol(Token-2022 TokenMetadata 扩展或 Metaplex 元数据)、永久授权 */
127
+ function mintMeta(mint, metadata) {
128
+ if (!mint) {
129
+ return { decimals: null, symbol: null, permanentDelegate: null };
130
+ }
131
+ let decimals = null;
132
+ let symbol = null;
133
+ try {
134
+ const info = parseMint(mint.data);
135
+ decimals = info.decimals;
136
+ symbol = info.metadata?.symbol || null;
137
+ }
138
+ catch {
139
+ // 不是 mint
140
+ }
141
+ if (!symbol && metadata) {
142
+ try {
143
+ symbol = parseMetaplexMetadata(metadata.data).symbol || null;
144
+ }
145
+ catch {
146
+ // 元数据格式不对
147
+ }
148
+ }
149
+ const ext = findExtension(mint.data, EXT_PERMANENT_DELEGATE);
150
+ const delegate = ext && ext.length >= 32 ? encodeAddress(ext.slice(0, 32)) : null;
151
+ return { decimals, symbol, permanentDelegate: delegate && delegate !== ZERO_PUBKEY ? delegate : null };
152
+ }
153
+ /** 撤销授权的指令:每个有 delegate、没有冻结的账户一条 Revoke;其他的跳过 */
154
+ export function buildRevokes(list) {
155
+ return list
156
+ .filter((a) => a.revocable)
157
+ .map((a) => ({ kind: 'revoke', account: a.account, owner: a.owner, instructions: [revoke(a.account, a.owner, a.tokenProgram)], approval: a }));
158
+ }
159
+ /**
160
+ * 关闭账户的指令:每个 closable 的账户一条 CloseAccount(关闭同时去掉授权);Token-2022 账户里有暂存的转账手续费时,
161
+ * 先加一条 HarvestWithheldTokensToMint(不需要签名)。关不掉的跳过。
162
+ * 注意 Wrapped SOL 账户有余额时也能关闭(余额作为 SOL 退回 destination):只想回收空账户时先按 amount 过滤
163
+ */
164
+ export function buildCloses(list, options = {}) {
165
+ if (options.destination !== undefined && !isAddress(options.destination)) {
166
+ throw new Error(`Invalid destination: ${options.destination}`);
167
+ }
168
+ return list
169
+ .filter((a) => a.closable)
170
+ .map((a) => ({
171
+ kind: 'close',
172
+ account: a.account,
173
+ owner: a.owner,
174
+ instructions: [
175
+ ...(a.tokenProgram === TOKEN_2022_PROGRAM_ID && BigInt(a.withheldAmount) > 0n ? [harvestWithheldTokensToMint(a.mint, [a.account])] : []),
176
+ closeAccount(a.account, options.destination ?? a.owner, a.owner, a.tokenProgram),
177
+ ],
178
+ approval: a,
179
+ }));
180
+ }
181
+ /**
182
+ * 撤销授权:构建(同 buildRevokes)后用 owner 签名发送,钱包和选项同 batchCall(多个账户打包进同一笔交易,feePayer 可以替 owner 付手续费)。
183
+ * 默认一个失败不影响后面的(continueOnError: true);结果与构建出的调用一一对应
184
+ *
185
+ * ```ts
186
+ * const list = await approvals(client, owner, { mints })
187
+ * await revokeApprovals(client, key, list)
188
+ * ```
189
+ */
190
+ export function revokeApprovals(client, from, list, options = {}) {
191
+ return send(client, from, buildRevokes(list), options);
192
+ }
193
+ /**
194
+ * 关闭代币账户回收租金(同 buildCloses),发送同 revokeApprovals。
195
+ *
196
+ * ```ts
197
+ * const empty = (await approvals(client, owner, { mints })).filter((a) => a.amount === '0')
198
+ * await closeTokenAccounts(client, key, empty) // 租金退回 owner
199
+ * ```
200
+ */
201
+ export function closeTokenAccounts(client, from, list, options = {}) {
202
+ const { destination, ...rest } = options;
203
+ return send(client, from, buildCloses(list, { destination }), rest);
204
+ }
205
+ async function send(client, from, calls, options) {
206
+ if (!calls.length)
207
+ return [];
208
+ // 发送的代码按需加载:只查授权时打包不会带上
209
+ const [{ batchCall }, { resolveSigner }] = await Promise.all([import('./write/batch.js'), import('./write/signer.js')]);
210
+ const { address } = await resolveSigner(from);
211
+ const other = calls.find((c) => c.owner !== address);
212
+ if (other) {
213
+ throw new Error(`Token account ${other.account} belongs to ${other.owner}, not the signer ${address}`);
214
+ }
215
+ const results = await batchCall(client, calls.map((c) => ({ from, instructions: c.instructions })), { continueOnError: true, ...options });
216
+ return results.map((r, i) => {
217
+ const call = calls[i];
218
+ return { ...r, kind: call.kind, account: call.account, approval: call.approval };
219
+ });
220
+ }
221
+ //# sourceMappingURL=approvals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvals.js","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * 批量计划的公共部分(/reclaim、/claim 用):一组“调用”(每个调用的指令原子执行)按交易大小打包、先模拟再发送。
3
+ * 打包规则同 batchCall(相邻的调用放进同一笔交易,不超过 1232 字节和 64 个账户)
4
+ */
5
+ import type { SolanaClient } from './client.js';
6
+ import type { SimulationResult } from './simulate.js';
7
+ import type { BatchCallOptions } from './write/batch.js';
8
+ import type { WriteResult } from './write/send.js';
9
+ import type { SignerInput } from './write/signer.js';
10
+ import { type Instruction } from './write/transaction.js';
11
+ /** 一个调用:要签名的地址(代币账户 / 仓位的 owner)和原子执行的指令 */
12
+ export interface PlannedCall {
13
+ owner: string;
14
+ instructions: Instruction[];
15
+ }
16
+ /** 把调用按顺序打包成交易,返回每笔交易包含的调用下标。单个调用放不进一笔交易时自己成一笔(发送时会报“transaction too large”) */
17
+ export declare function packCalls(payer: string, calls: readonly PlannedCall[], batchSize?: number): number[][];
18
+ export interface PlanSimulationOptions {
19
+ /** 手续费支付者,默认第一个调用的 owner */
20
+ feePayer?: string;
21
+ /** 每笔交易最多几个调用,默认不限(只受交易大小限制) */
22
+ batchSize?: number;
23
+ /** 额外要看的地址(如收款地址) */
24
+ watch?: readonly string[];
25
+ signal?: AbortSignal;
26
+ /** 算美元价值(/simulate 的 prices) */
27
+ prices?: boolean;
28
+ fetch?: typeof fetch;
29
+ }
30
+ export interface PlanSimulation {
31
+ /** 所有交易都模拟通过 */
32
+ success: boolean;
33
+ /** 打包后的每笔交易:包含的调用下标和 /simulate 的结果 */
34
+ transactions: Array<{
35
+ calls: number[];
36
+ simulation: SimulationResult;
37
+ }>;
38
+ /** 模拟失败的调用(整笔失败时逐个重新模拟找出来):下标和原因 */
39
+ failed: Array<{
40
+ index: number;
41
+ error: string;
42
+ }>;
43
+ /** 各笔交易手续费之和(lamports,十进制字符串) */
44
+ fee: string;
45
+ /** 手续费支付者的 SOL 变化之和(lamports,带符号,不含手续费:/simulate 的 SOL 余额变化已经把手续费加回) */
46
+ payerNativeDelta: string;
47
+ }
48
+ /** 打包后逐笔用 /simulate 模拟(不签名、不发送);失败的交易逐个调用重新模拟,找出是哪些调用失败 */
49
+ export declare function simulatePlan(client: SolanaClient, calls: readonly PlannedCall[], options?: PlanSimulationOptions): Promise<PlanSimulation>;
50
+ /** 用 from 签名发送:调用的 owner 都必须是签名者本人;一个调用失败不影响后面的(continueOnError),feePayer 可以替 owner 付手续费 */
51
+ export declare function sendCalls(client: SolanaClient, from: SignerInput, calls: readonly PlannedCall[], options?: BatchCallOptions): Promise<WriteResult[]>;
52
+ //# sourceMappingURL=batchPlan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batchPlan.d.ts","sourceRoot":"","sources":["../src/batchPlan.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAwE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAE/H,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,WAAW,EAAE,CAAA;CAC5B;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,WAAW,EAAE,EAAE,SAAS,SAA2B,GAAG,MAAM,EAAE,EAAE,CAsBxH;AAED,MAAM,WAAW,qBAAqB;IACpC,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qBAAqB;IACrB,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,gCAAgC;IAChC,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,gBAAgB;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,sCAAsC;IACtC,YAAY,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAA;IACtE,oCAAoC;IACpC,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC/C,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,2DAA2D;AAC3D,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,WAAW,EAAE,EAAE,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,cAAc,CAAC,CA8CpJ;AAED,4FAA4F;AAC5F,wBAAsB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,WAAW,EAAE,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAgB9J"}
@@ -0,0 +1,85 @@
1
+ import { isAddress } from './address.js';
2
+ import { MAX_COMPUTE_UNITS, setComputeUnitLimit, setComputeUnitPrice } from './write/instructions.js';
3
+ import { MAX_ACCOUNT_LOCKS, PACKET_DATA_SIZE, compileMessage, transactionSize } from './write/transaction.js';
4
+ /** 把调用按顺序打包成交易,返回每笔交易包含的调用下标。单个调用放不进一笔交易时自己成一笔(发送时会报“transaction too large”) */
5
+ export function packCalls(payer, calls, batchSize = Number.POSITIVE_INFINITY) {
6
+ const packs = [];
7
+ let current = [];
8
+ let instructions = [];
9
+ const fits = (list) => {
10
+ const probe = compileMessage(payer, [setComputeUnitLimit(MAX_COMPUTE_UNITS), setComputeUnitPrice(1n), ...list], '11111111111111111111111111111111');
11
+ return transactionSize(probe) <= PACKET_DATA_SIZE && probe.accountKeys.length <= MAX_ACCOUNT_LOCKS;
12
+ };
13
+ calls.forEach((call, i) => {
14
+ const next = [...instructions, ...call.instructions];
15
+ if (current.length && (current.length >= batchSize || !fits(next))) {
16
+ packs.push(current);
17
+ current = [];
18
+ instructions = [];
19
+ }
20
+ current.push(i);
21
+ instructions.push(...call.instructions);
22
+ });
23
+ if (current.length) {
24
+ packs.push(current);
25
+ }
26
+ return packs;
27
+ }
28
+ /** 打包后逐笔用 /simulate 模拟(不签名、不发送);失败的交易逐个调用重新模拟,找出是哪些调用失败 */
29
+ export async function simulatePlan(client, calls, options = {}) {
30
+ const first = calls[0];
31
+ if (!first) {
32
+ return { success: true, transactions: [], failed: [], fee: '0', payerNativeDelta: '0' };
33
+ }
34
+ const payer = options.feePayer ?? first.owner;
35
+ if (!isAddress(payer)) {
36
+ throw new Error(`Invalid fee payer: ${payer}`);
37
+ }
38
+ const { simulate } = await import('./simulate.js');
39
+ const run = (list) => simulate(client, { feePayer: payer, instructions: list.flatMap((c) => c.instructions) }, { signers: [...new Set(list.map((c) => c.owner))], watch: options.watch, signal: options.signal, prices: options.prices, fetch: options.fetch });
40
+ const packs = packCalls(payer, calls, options.batchSize);
41
+ const transactions = [];
42
+ const failed = [];
43
+ for (const pack of packs) {
44
+ const simulation = await run(pack.map((i) => calls[i]));
45
+ transactions.push({ calls: pack, simulation });
46
+ if (!simulation.success) {
47
+ if (pack.length === 1) {
48
+ failed.push({ index: pack[0], error: simulation.error ?? 'simulation failed' });
49
+ continue;
50
+ }
51
+ for (const i of pack) {
52
+ const single = await run([calls[i]]);
53
+ if (!single.success) {
54
+ failed.push({ index: i, error: single.error ?? 'simulation failed' });
55
+ }
56
+ }
57
+ }
58
+ }
59
+ let fee = 0n;
60
+ let delta = 0n;
61
+ for (const { simulation } of transactions) {
62
+ fee += BigInt(simulation.fee ?? '0');
63
+ for (const change of simulation.balanceChanges) {
64
+ if (change.address === payer && change.asset === 'native') {
65
+ delta += BigInt(change.delta);
66
+ }
67
+ }
68
+ }
69
+ return { success: transactions.every((t) => t.simulation.success), transactions, failed, fee: fee.toString(), payerNativeDelta: delta.toString() };
70
+ }
71
+ /** 用 from 签名发送:调用的 owner 都必须是签名者本人;一个调用失败不影响后面的(continueOnError),feePayer 可以替 owner 付手续费 */
72
+ export async function sendCalls(client, from, calls, options = {}) {
73
+ if (!calls.length) {
74
+ return [];
75
+ }
76
+ // 发送的代码按需加载:只查询、模拟时打包不会带上
77
+ const [{ batchCall }, { resolveSigner }] = await Promise.all([import('./write/batch.js'), import('./write/signer.js')]);
78
+ const { address } = await resolveSigner(from);
79
+ const other = calls.find((c) => c.owner !== address);
80
+ if (other) {
81
+ throw new Error(`The account belongs to ${other.owner}, not the signer ${address}`);
82
+ }
83
+ return batchCall(client, calls.map((c) => ({ from, instructions: c.instructions })), { continueOnError: true, ...options });
84
+ }
85
+ //# sourceMappingURL=batchPlan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batchPlan.js","sourceRoot":"","sources":["../src/batchPlan.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAGxC,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAGrG,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAoB,MAAM,wBAAwB,CAAA;AAQ/H,gFAAgF;AAChF,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,KAA6B,EAAE,SAAS,GAAG,MAAM,CAAC,iBAAiB;IAC1G,MAAM,KAAK,GAAe,EAAE,CAAA;IAC5B,IAAI,OAAO,GAAa,EAAE,CAAA;IAC1B,IAAI,YAAY,GAAkB,EAAE,CAAA;IACpC,MAAM,IAAI,GAAG,CAAC,IAA4B,EAAE,EAAE;QAC5C,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,EAAE,mBAAmB,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,kCAAkC,CAAC,CAAA;QACnJ,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,gBAAgB,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,IAAI,iBAAiB,CAAA;IACpG,CAAC,CAAA;IACD,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACxB,MAAM,IAAI,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,CAAA;QACpD,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACnE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACnB,OAAO,GAAG,EAAE,CAAA;YACZ,YAAY,GAAG,EAAE,CAAA;QACnB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACf,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IACF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACrB,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AA4BD,2DAA2D;AAC3D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAoB,EAAE,KAA6B,EAAE,UAAiC,EAAE;IACzH,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IACtB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAA;IACzF,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAA;IAC7C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAA;IAChD,CAAC;IACD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;IAClD,MAAM,GAAG,GAAG,CAAC,IAA4B,EAAE,EAAE,CAC3C,QAAQ,CACN,MAAM,EACN,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,EACtE,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAChJ,CAAA;IACH,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;IACxD,MAAM,YAAY,GAAmC,EAAE,CAAA;IACvD,MAAM,MAAM,GAA6B,EAAE,CAAA;IAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAgB,CAAC,CAAC,CAAA;QACtE,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAA;QAC9C,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAW,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,mBAAmB,EAAE,CAAC,CAAA;gBACzF,SAAQ;YACV,CAAC;YACD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACrB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAgB,CAAC,CAAC,CAAA;gBACnD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBACpB,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,mBAAmB,EAAE,CAAC,CAAA;gBACvE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,IAAI,KAAK,GAAG,EAAE,CAAA;IACd,KAAK,MAAM,EAAE,UAAU,EAAE,IAAI,YAAY,EAAE,CAAC;QAC1C,GAAG,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,CAAA;QACpC,KAAK,MAAM,MAAM,IAAI,UAAU,CAAC,cAAc,EAAE,CAAC;YAC/C,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC1D,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,gBAAgB,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAA;AACpJ,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAoB,EAAE,IAAiB,EAAE,KAA6B,EAAE,UAA4B,EAAE;IACpI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,EAAE,CAAA;IACX,CAAC;IACD,0BAA0B;IAC1B,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAA;IACvH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CAAA;IACpD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,CAAC,KAAK,oBAAoB,OAAO,EAAE,CAAC,CAAA;IACrF,CAAC;IACD,OAAO,SAAS,CACd,MAAM,EACN,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,EAC1D,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CACtC,CAAA;AACH,CAAC"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * 批量领取(子路径 `@w3lib/solana-batch-call/claim`):Orca Whirlpool、Raydium CLMM 仓位的未领取手续费和挖矿奖励(Orca 的奖励 slot、Raydium 的农场奖励)。
3
+ * 先只读预览(每个仓位能领多少、美元价值),再把全部(或选中的)仓位的领取指令打包成交易,发送前用 /simulate 模拟。
4
+ * 领取的指令就是 /liquidity 的 collectFees(手续费 + 全部奖励,SOL 自动解包、缺少的代币账户自动创建),这里只做批量和打包
5
+ */
6
+ import type { RequestOptions, SolanaClient } from './client.js';
7
+ import type { SolanaLiquidityPlan } from './liquidity/types.js';
8
+ import { type SolanaLpProtocol, type SolanaLpToken } from './lp.js';
9
+ import { type SolanaPriceSource } from './price.js';
10
+ import { type PlanSimulation, type PlanSimulationOptions, type PlannedCall } from './batchPlan.js';
11
+ import type { BatchCallOptions } from './write/batch.js';
12
+ import { type WriteResult } from './write/send.js';
13
+ import type { SignerInput } from './write/signer.js';
14
+ export type ClaimProtocol = Extract<SolanaLpProtocol, 'orca-whirlpool' | 'raydium-clmm'>;
15
+ /** 一项能领取的东西:手续费或挖矿奖励 */
16
+ export interface ClaimableAmount {
17
+ mint: string;
18
+ symbol: string | null;
19
+ decimals: number | null;
20
+ /** 数量(最小单位);读不到两端的 tick 数据时为 null */
21
+ amount: string | null;
22
+ formatted: string | null;
23
+ /** 美元价值(查到价格时;没有价格为 null;数量为 0 时为 0) */
24
+ usd: number | null;
25
+ /** 只在按代币汇总(`Claimable.tokens`)里:true 表示有仓位的数量读不到,`amount` 只是已读到部分的合计(偏低),`usd` 为 null */
26
+ incomplete?: true;
27
+ }
28
+ export interface ClaimablePosition {
29
+ protocol: ClaimProtocol;
30
+ protocolName: string;
31
+ /** 仓位 NFT 的 mint 和仓位账户 */
32
+ positionMint: string;
33
+ position: string;
34
+ pool: string;
35
+ token0: SolanaLpToken;
36
+ token1: SolanaLpToken;
37
+ liquidity: string;
38
+ inRange: boolean;
39
+ /** token0 / token1 的未领取手续费 */
40
+ fees: [ClaimableAmount, ClaimableAmount];
41
+ /** 池子里已初始化的挖矿奖励(Orca 的奖励 slot / Raydium 的 reward_infos),数量按程序的方式结算到当前时间 */
42
+ rewards: Array<ClaimableAmount & {
43
+ index: number;
44
+ }>;
45
+ feesUsd: number | null;
46
+ rewardsUsd: number | null;
47
+ /** 手续费 + 奖励的美元价值:有数量的项缺价格或读不到时为 null */
48
+ totalUsd: number | null;
49
+ }
50
+ export interface Claimable {
51
+ owner: string;
52
+ /** 有手续费或奖励可领的仓位(没有流动性也没有可领的不在内),按美元价值从大到小 */
53
+ positions: ClaimablePosition[];
54
+ /** 按代币汇总:手续费 + 奖励,所有仓位合计 */
55
+ tokens: ClaimableAmount[];
56
+ /** true:有仓位的数量读不到(tick 数据读不到),`tokens` 的数量和各项合计都可能偏低 */
57
+ incomplete: boolean;
58
+ feesUsd: number | null;
59
+ rewardsUsd: number | null;
60
+ totalUsd: number | null;
61
+ warnings: string[];
62
+ }
63
+ export interface ClaimQuery extends RequestOptions {
64
+ /** 只看这些仓位 NFT 的 mint(读 ATA,免费公共节点也能用);不传时列出全部代币账户(getTokenAccountsByOwner,需要支持它的节点) */
65
+ mints?: readonly string[];
66
+ /** 协议,默认两个都查 */
67
+ protocols?: readonly ClaimProtocol[];
68
+ /** 价格:true(默认)用 DefiLlama;false 不查;也可以传自己的价格源(如 combinePrices([defillamaPrices(), onchainPrices()])) */
69
+ prices?: boolean | SolanaPriceSource;
70
+ /** 奖励结算到哪个时刻(unix 秒),默认当前时间 */
71
+ now?: number;
72
+ fetch?: typeof fetch;
73
+ }
74
+ /**
75
+ * 预览能领取的手续费和挖矿奖励(只读取,不构建交易):每个仓位的两种手续费、每个奖励的数量和美元价值,以及按代币汇总。
76
+ * 奖励照搬程序的结算:池子的奖励增长按时间摊给当前流动性,再按仓位区间内的增长计算
77
+ *
78
+ * ```ts
79
+ * const c = await claimable(client, owner)
80
+ * c.totalUsd // 全部能领的美元价值
81
+ * c.positions[0].rewards // [{ index: 0, symbol: 'RAY', formatted: '0.042698', usd: 0.083 }]
82
+ * ```
83
+ */
84
+ export declare function claimable(client: SolanaClient, owner: string, query?: ClaimQuery): Promise<Claimable>;
85
+ /** 要领取的仓位:claimable 的结果,或只给协议 + 仓位 NFT 的 mint(getLpPositions 的结果也可以) */
86
+ export type ClaimTarget = Pick<ClaimablePosition, 'protocol' | 'positionMint'> & {
87
+ pool?: string;
88
+ };
89
+ export interface BuildClaimOptions extends RequestOptions {
90
+ /** wSOL(池子的一边或奖励)原来没有账户时用完关闭、换回 SOL,默认 true(同 /liquidity) */
91
+ native?: boolean;
92
+ /** 同时构建几个仓位(每个要读几次账户),默认 4 */
93
+ concurrency?: number;
94
+ }
95
+ export interface ClaimCall extends PlannedCall {
96
+ protocol: ClaimProtocol;
97
+ positionMint: string;
98
+ /** /liquidity 的领取计划(预计的手续费、奖励的代币、步骤) */
99
+ plan: SolanaLiquidityPlan;
100
+ }
101
+ export interface ClaimPlan {
102
+ owner: string;
103
+ /** 每个仓位一个调用(创建缺少的代币账户 + 领取手续费 + 领取每个奖励,原子执行) */
104
+ calls: ClaimCall[];
105
+ /** 构建失败的仓位:仓位不在 owner 名下、不支持的代币(带转账手续费的 Token-2022 池子)等 */
106
+ failed: Array<{
107
+ position: ClaimTarget;
108
+ error: string;
109
+ }>;
110
+ }
111
+ /**
112
+ * 构建批量领取(只读取、不签名):每个仓位一个调用,指令来自 /liquidity 的 buildCollectFees,构建时重新读取仓位。
113
+ * 打包成交易由 simulateClaim / claimAll(batchCall)完成
114
+ *
115
+ * ```ts
116
+ * const c = await claimable(client, owner)
117
+ * const plan = await buildClaimAll(client, owner, c.positions)
118
+ * ```
119
+ */
120
+ export declare function buildClaimAll(client: SolanaClient, owner: string, positions: readonly ClaimTarget[], options?: BuildClaimOptions): Promise<ClaimPlan>;
121
+ export interface ClaimSimulation extends PlanSimulation {
122
+ /** 模拟里收到的代币合计(手续费支付者 / owner 的余额变化,按资产汇总;SOL 为 'native') */
123
+ received: Array<{
124
+ asset: string;
125
+ symbol: string;
126
+ decimals: number;
127
+ delta: string;
128
+ formatted: string;
129
+ usd?: number | null;
130
+ }>;
131
+ }
132
+ /** 用 /simulate 模拟构建好的批量领取(不签名、不发送):逐笔交易的结果、哪些仓位会失败、收到的代币合计 */
133
+ export declare function simulateClaim(client: SolanaClient, plan: ClaimPlan, options?: Omit<PlanSimulationOptions, 'watch'>): Promise<ClaimSimulation>;
134
+ export interface ClaimOptions extends BatchCallOptions, BuildClaimOptions {
135
+ /** 发送前先用 /simulate 模拟,模拟失败的仓位不发送,默认 true */
136
+ simulate?: boolean;
137
+ /** 只领取预计价值不低于它的仓位(美元);没有价格的仓位照常领取。默认 0 */
138
+ minUsd?: number;
139
+ }
140
+ export interface ClaimCallResult extends WriteResult {
141
+ protocol: ClaimProtocol;
142
+ positionMint: string;
143
+ }
144
+ export interface ClaimResult {
145
+ plan: ClaimPlan;
146
+ /** 发送前的模拟(simulate: false 时为 null) */
147
+ simulation: ClaimSimulation | null;
148
+ /** 与 plan.calls 一一对应;dryRun 时 status 为 'simulated' / 'failed',没有签名 */
149
+ results: ClaimCallResult[];
150
+ }
151
+ /**
152
+ * 批量领取:构建 → 模拟 → 用 from 签名发送(钱包同 /write 的 batchCall,多个仓位打包进同一笔交易,feePayer 可以替 owner 付手续费)。
153
+ * positions 不传时先预览、领取全部有东西可领的仓位;一个仓位失败不影响其他的。dryRun: true 只构建和模拟(不签名,from 只用来取地址)
154
+ *
155
+ * ```ts
156
+ * await claimAll(client, key) // 全部
157
+ * await claimAll(client, key, c.positions.slice(0, 5), { dryRun: true })
158
+ * ```
159
+ */
160
+ export declare function claimAll(client: SolanaClient, from: SignerInput, positions?: readonly (ClaimTarget & Partial<Pick<ClaimablePosition, 'totalUsd'>>)[], options?: ClaimOptions): Promise<ClaimResult>;
161
+ //# sourceMappingURL=claim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim.d.ts","sourceRoot":"","sources":["../src/claim.ts"],"names":[],"mappings":"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"}