@w3lib/solana-batch-call 0.3.0 → 0.5.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 +43 -0
- package/README.md +304 -3
- package/dist/address.d.ts +2 -0
- package/dist/address.d.ts.map +1 -1
- package/dist/address.js +8 -0
- package/dist/address.js.map +1 -1
- package/dist/approvals.d.ts +129 -0
- package/dist/approvals.d.ts.map +1 -0
- package/dist/approvals.js +221 -0
- package/dist/approvals.js.map +1 -0
- package/dist/fees.d.ts +89 -0
- package/dist/fees.d.ts.map +1 -0
- package/dist/fees.js +166 -0
- package/dist/fees.js.map +1 -0
- package/dist/index.d.ts +1 -1
- 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 +2 -0
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +2 -2
- package/dist/layout.js.map +1 -1
- package/dist/liquidity/amm.d.ts +7 -0
- package/dist/liquidity/amm.d.ts.map +1 -0
- package/dist/liquidity/amm.js +307 -0
- package/dist/liquidity/amm.js.map +1 -0
- package/dist/liquidity/clmm.d.ts +18 -0
- package/dist/liquidity/clmm.d.ts.map +1 -0
- package/dist/liquidity/clmm.js +85 -0
- package/dist/liquidity/clmm.js.map +1 -0
- package/dist/liquidity/common.d.ts +94 -0
- package/dist/liquidity/common.d.ts.map +1 -0
- package/dist/liquidity/common.js +228 -0
- package/dist/liquidity/common.js.map +1 -0
- package/dist/liquidity/index.d.ts +34 -0
- package/dist/liquidity/index.d.ts.map +1 -0
- package/dist/liquidity/index.js +157 -0
- package/dist/liquidity/index.js.map +1 -0
- package/dist/liquidity/orca.d.ts +6 -0
- package/dist/liquidity/orca.d.ts.map +1 -0
- package/dist/liquidity/orca.js +303 -0
- package/dist/liquidity/orca.js.map +1 -0
- package/dist/liquidity/raydiumClmm.d.ts +6 -0
- package/dist/liquidity/raydiumClmm.d.ts.map +1 -0
- package/dist/liquidity/raydiumClmm.js +307 -0
- package/dist/liquidity/raydiumClmm.js.map +1 -0
- package/dist/liquidity/types.d.ts +150 -0
- package/dist/liquidity/types.d.ts.map +1 -0
- package/dist/liquidity/types.js +2 -0
- package/dist/liquidity/types.js.map +1 -0
- package/dist/lp.d.ts +53 -15
- package/dist/lp.d.ts.map +1 -1
- package/dist/lp.js +15 -38
- package/dist/lp.js.map +1 -1
- package/dist/lpMath.d.ts +45 -0
- package/dist/lpMath.d.ts.map +1 -1
- package/dist/lpMath.js +189 -0
- package/dist/lpMath.js.map +1 -1
- package/dist/names.d.ts +68 -0
- package/dist/names.d.ts.map +1 -0
- package/dist/names.js +257 -0
- package/dist/names.js.map +1 -0
- package/dist/pools.d.ts +9 -0
- package/dist/pools.d.ts.map +1 -0
- package/dist/pools.js +45 -0
- package/dist/pools.js.map +1 -0
- package/dist/portfolio.d.ts +64 -0
- package/dist/portfolio.d.ts.map +1 -0
- package/dist/portfolio.js +57 -0
- package/dist/portfolio.js.map +1 -0
- package/dist/price.d.ts +90 -0
- package/dist/price.d.ts.map +1 -0
- package/dist/price.js +287 -0
- package/dist/price.js.map +1 -0
- package/dist/risk.d.ts +84 -0
- package/dist/risk.d.ts.map +1 -0
- package/dist/risk.js +211 -0
- package/dist/risk.js.map +1 -0
- package/dist/rpc.d.ts +2 -0
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +33 -9
- package/dist/rpc.js.map +1 -1
- package/dist/subpaths/approvals.d.ts +29 -0
- package/dist/subpaths/approvals.d.ts.map +1 -0
- package/dist/subpaths/approvals.js +30 -0
- package/dist/subpaths/approvals.js.map +1 -0
- package/dist/subpaths/fees.d.ts +23 -0
- package/dist/subpaths/fees.d.ts.map +1 -0
- package/dist/subpaths/fees.js +25 -0
- package/dist/subpaths/fees.js.map +1 -0
- package/dist/subpaths/liquidity.d.ts +23 -0
- package/dist/subpaths/liquidity.d.ts.map +1 -0
- package/dist/subpaths/liquidity.js +19 -0
- package/dist/subpaths/liquidity.js.map +1 -0
- package/dist/subpaths/lp.d.ts +1 -1
- package/dist/subpaths/lp.d.ts.map +1 -1
- package/dist/subpaths/lp.js +1 -1
- package/dist/subpaths/lp.js.map +1 -1
- package/dist/subpaths/names.d.ts +37 -0
- package/dist/subpaths/names.d.ts.map +1 -0
- package/dist/subpaths/names.js +27 -0
- package/dist/subpaths/names.js.map +1 -0
- package/dist/subpaths/price.d.ts +40 -0
- package/dist/subpaths/price.d.ts.map +1 -0
- package/dist/subpaths/price.js +43 -0
- package/dist/subpaths/price.js.map +1 -0
- package/dist/subpaths/risk.d.ts +28 -0
- package/dist/subpaths/risk.d.ts.map +1 -0
- package/dist/subpaths/risk.js +30 -0
- package/dist/subpaths/risk.js.map +1 -0
- package/dist/subpaths/swap.d.ts +22 -0
- package/dist/subpaths/swap.d.ts.map +1 -0
- package/dist/subpaths/swap.js +21 -0
- package/dist/subpaths/swap.js.map +1 -0
- package/dist/subpaths/write.d.ts +1 -1
- package/dist/subpaths/write.d.ts.map +1 -1
- package/dist/subpaths/write.js +1 -1
- package/dist/subpaths/write.js.map +1 -1
- package/dist/swap/amm.d.ts +20 -0
- package/dist/swap/amm.d.ts.map +1 -0
- package/dist/swap/amm.js +77 -0
- package/dist/swap/amm.js.map +1 -0
- package/dist/swap/clmmMath.d.ts +24 -0
- package/dist/swap/clmmMath.d.ts.map +1 -0
- package/dist/swap/clmmMath.js +82 -0
- package/dist/swap/clmmMath.js.map +1 -0
- package/dist/swap/common.d.ts +68 -0
- package/dist/swap/common.d.ts.map +1 -0
- package/dist/swap/common.js +65 -0
- package/dist/swap/common.js.map +1 -0
- package/dist/swap/cpmm.d.ts +28 -0
- package/dist/swap/cpmm.d.ts.map +1 -0
- package/dist/swap/cpmm.js +113 -0
- package/dist/swap/cpmm.js.map +1 -0
- package/dist/swap/index.d.ts +145 -0
- package/dist/swap/index.d.ts.map +1 -0
- package/dist/swap/index.js +349 -0
- package/dist/swap/index.js.map +1 -0
- package/dist/swap/orca.d.ts +50 -0
- package/dist/swap/orca.d.ts.map +1 -0
- package/dist/swap/orca.js +382 -0
- package/dist/swap/orca.js.map +1 -0
- package/dist/swap/raydiumClmm.d.ts +62 -0
- package/dist/swap/raydiumClmm.d.ts.map +1 -0
- package/dist/swap/raydiumClmm.js +447 -0
- package/dist/swap/raydiumClmm.js.map +1 -0
- package/dist/tradeCheck.d.ts +45 -0
- package/dist/tradeCheck.d.ts.map +1 -0
- package/dist/tradeCheck.js +131 -0
- package/dist/tradeCheck.js.map +1 -0
- package/dist/write/instructions.d.ts +7 -0
- package/dist/write/instructions.d.ts.map +1 -1
- package/dist/write/instructions.js +24 -1
- package/dist/write/instructions.js.map +1 -1
- package/dist/write/transaction.d.ts +23 -0
- package/dist/write/transaction.d.ts.map +1 -1
- package/dist/write/transaction.js +50 -0
- package/dist/write/transaction.js.map +1 -1
- package/package.json +41 -2
- package/src/address.ts +9 -0
- package/src/approvals.ts +358 -0
- package/src/fees.ts +259 -0
- package/src/index.ts +1 -1
- package/src/layout.ts +2 -2
- package/src/liquidity/amm.ts +353 -0
- package/src/liquidity/clmm.ts +108 -0
- package/src/liquidity/common.ts +285 -0
- package/src/liquidity/index.ts +177 -0
- package/src/liquidity/orca.ts +344 -0
- package/src/liquidity/raydiumClmm.ts +348 -0
- package/src/liquidity/types.ts +158 -0
- package/src/lp.ts +17 -52
- package/src/lpMath.ts +215 -0
- package/src/names.ts +329 -0
- package/src/pools.ts +43 -0
- package/src/portfolio.ts +124 -0
- package/src/price.ts +366 -0
- package/src/risk.ts +243 -0
- package/src/rpc.ts +36 -9
- package/src/subpaths/approvals.ts +47 -0
- package/src/subpaths/fees.ts +41 -0
- package/src/subpaths/liquidity.ts +45 -0
- package/src/subpaths/lp.ts +9 -0
- package/src/subpaths/names.ts +45 -0
- package/src/subpaths/price.ts +62 -0
- package/src/subpaths/risk.ts +36 -0
- package/src/subpaths/swap.ts +41 -0
- package/src/subpaths/write.ts +2 -0
- package/src/swap/amm.ts +88 -0
- package/src/swap/clmmMath.ts +96 -0
- package/src/swap/common.ts +113 -0
- package/src/swap/cpmm.ts +132 -0
- package/src/swap/index.ts +467 -0
- package/src/swap/orca.ts +397 -0
- package/src/swap/raydiumClmm.ts +464 -0
- package/src/tradeCheck.ts +166 -0
- package/src/write/instructions.ts +26 -1
- package/src/write/transaction.ts +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"names.js","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":"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"}
|
package/dist/pools.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type PdaPoolProtocol = 'raydium-clmm' | 'orca-whirlpool' | 'raydium-cpmm';
|
|
2
|
+
/** Orca 默认的 WhirlpoolsConfig */
|
|
3
|
+
export declare const ORCA_WHIRLPOOLS_CONFIG = "2LecshUwdy9xi7meFgHtFJQNSKk4KdTrcpvaB56dP2NQ";
|
|
4
|
+
/** 两个 mint 在这些协议里可能的池子地址(三个程序都要求 mint0 < mint1,按字节比较);两个 mint 相同时为空 */
|
|
5
|
+
export declare function poolAddresses(mintA: string, mintB: string, protocols: ReadonlySet<PdaPoolProtocol>): Array<{
|
|
6
|
+
protocol: PdaPoolProtocol;
|
|
7
|
+
address: string;
|
|
8
|
+
}>;
|
|
9
|
+
//# sourceMappingURL=pools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pools.d.ts","sourceRoot":"","sources":["../src/pools.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,gBAAgB,GAAG,cAAc,CAAA;AAEhF,gCAAgC;AAChC,eAAO,MAAM,sBAAsB,iDAAiD,CAAA;AAkBpF,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC;IAAE,QAAQ,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAa1J"}
|
package/dist/pools.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 按两个 mint 推导池子地址(PDA,不需要 getProgramAccounts):Raydium CLMM / CPMM 的每个 AmmConfig、Orca 的每个费率档位。
|
|
3
|
+
* 链上价格(/price)和兑换(/swap)共用;Raydium AMM v4 的池子地址要用 OpenBook 市场推导,不在这里
|
|
4
|
+
*/
|
|
5
|
+
import { decodeAddress, findProgramAddress } from './address.js';
|
|
6
|
+
import { ORCA_WHIRLPOOL_PROGRAM_ID, RAYDIUM_CLMM_PROGRAM_ID, RAYDIUM_CPMM_PROGRAM_ID, utf8 } from './lp.js';
|
|
7
|
+
/** Orca 默认的 WhirlpoolsConfig */
|
|
8
|
+
export const ORCA_WHIRLPOOLS_CONFIG = '2LecshUwdy9xi7meFgHtFJQNSKk4KdTrcpvaB56dP2NQ';
|
|
9
|
+
/**
|
|
10
|
+
* 池子 PDA 用到的配置(2026-10 主网实测存在的全部):
|
|
11
|
+
* - Raydium CLMM / CPMM 的 AmmConfig:PDA ["amm_config", index(u16 大端)],index 0~20
|
|
12
|
+
* - Orca 的费率档位:普通档位的种子是 tick spacing(1、2、4、8、16、64、96、128、256,32896 为 Splash 池),动态费率档位是 1025~1036
|
|
13
|
+
* Raydium CLMM 用 seed_index 建的自定义池子不在推导范围内
|
|
14
|
+
*/
|
|
15
|
+
const RAYDIUM_CONFIG_COUNT = 21;
|
|
16
|
+
const ORCA_FEE_TIERS = [1, 2, 4, 8, 16, 64, 96, 128, 256, 32896, ...Array.from({ length: 12 }, (_, i) => 1025 + i)];
|
|
17
|
+
let configs;
|
|
18
|
+
function poolConfigs() {
|
|
19
|
+
const derive = (program) => Array.from({ length: RAYDIUM_CONFIG_COUNT }, (_, i) => decodeAddress(findProgramAddress([utf8('amm_config'), new Uint8Array([i >> 8, i & 0xff])], program)));
|
|
20
|
+
configs ??= { clmm: derive(RAYDIUM_CLMM_PROGRAM_ID), cpmm: derive(RAYDIUM_CPMM_PROGRAM_ID), orca: decodeAddress(ORCA_WHIRLPOOLS_CONFIG) };
|
|
21
|
+
return configs;
|
|
22
|
+
}
|
|
23
|
+
/** 两个 mint 在这些协议里可能的池子地址(三个程序都要求 mint0 < mint1,按字节比较);两个 mint 相同时为空 */
|
|
24
|
+
export function poolAddresses(mintA, mintB, protocols) {
|
|
25
|
+
const a = decodeAddress(mintA);
|
|
26
|
+
const b = decodeAddress(mintB);
|
|
27
|
+
const i = a.findIndex((byte, k) => byte !== b[k]);
|
|
28
|
+
if (i < 0)
|
|
29
|
+
return [];
|
|
30
|
+
const [m0, m1] = a[i] < b[i] ? [a, b] : [b, a];
|
|
31
|
+
const { clmm, cpmm, orca } = poolConfigs();
|
|
32
|
+
const out = [];
|
|
33
|
+
const add = (protocol, seeds, program) => out.push({ protocol, address: findProgramAddress(seeds, program) });
|
|
34
|
+
if (protocols.has('raydium-clmm'))
|
|
35
|
+
for (const c of clmm)
|
|
36
|
+
add('raydium-clmm', [utf8('pool'), c, m0, m1], RAYDIUM_CLMM_PROGRAM_ID);
|
|
37
|
+
if (protocols.has('raydium-cpmm'))
|
|
38
|
+
for (const c of cpmm)
|
|
39
|
+
add('raydium-cpmm', [utf8('pool'), c, m0, m1], RAYDIUM_CPMM_PROGRAM_ID);
|
|
40
|
+
if (protocols.has('orca-whirlpool'))
|
|
41
|
+
for (const t of ORCA_FEE_TIERS)
|
|
42
|
+
add('orca-whirlpool', [utf8('whirlpool'), orca, m0, m1, new Uint8Array([t & 0xff, t >> 8])], ORCA_WHIRLPOOL_PROGRAM_ID);
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=pools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pools.js","sourceRoot":"","sources":["../src/pools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 资产总值(子路径 `@w3lib/solana-batch-call/price`):代币余额 × 价格,可选加上 LP 仓位的价值
|
|
3
|
+
*/
|
|
4
|
+
import type { RequestOptions, SolanaClient } from './client.js';
|
|
5
|
+
import { type LpPositionsOptions, type SolanaLpPosition } from './lp.js';
|
|
6
|
+
import { type SolanaPriceSource } from './price.js';
|
|
7
|
+
export interface PortfolioOptions extends RequestOptions {
|
|
8
|
+
/**
|
|
9
|
+
* 要计入的代币(SOL 用 NATIVE_MINT),按关联代币账户(ATA)读余额,免费公共节点也能用。
|
|
10
|
+
* 不传时列出地址持有的全部代币(同 getOwnerTokens,含 SOL,不含 NFT),需要支持 getTokenAccountsByOwner 的节点
|
|
11
|
+
*/
|
|
12
|
+
tokens?: readonly string[];
|
|
13
|
+
/** 价格源,依次使用,默认 [defillamaPrices(), onchainPrices()] */
|
|
14
|
+
sources?: readonly SolanaPriceSource[];
|
|
15
|
+
/**
|
|
16
|
+
* 同时计入 LP 仓位(参数同 lpPositions,价格源用上面的 sources),默认不计入。
|
|
17
|
+
* 注意 lpPositions 不传 mints 时也要扫描代币账户:免费公共节点上传 { mints: [仓位 NFT / LP mint], pools: [AMM 池子] }
|
|
18
|
+
*/
|
|
19
|
+
lp?: boolean | Omit<LpPositionsOptions, 'prices' | 'onPriceError' | 'fetch' | 'signal'>;
|
|
20
|
+
/** 价值低于它的代币不列出(不影响合计),默认 0 */
|
|
21
|
+
minUsd?: number;
|
|
22
|
+
/** 某个价格源出错时调用;回调本身出错会被忽略 */
|
|
23
|
+
onPriceError?: (err: unknown) => void;
|
|
24
|
+
/** 查价格用的 fetch,默认全局 fetch */
|
|
25
|
+
fetch?: typeof fetch;
|
|
26
|
+
}
|
|
27
|
+
export interface PortfolioToken {
|
|
28
|
+
/** 代币的 mint;SOL 为 NATIVE_MINT(或传入的 nativeMints 里的地址) */
|
|
29
|
+
token: string;
|
|
30
|
+
/** 原生 SOL;Wrapped SOL 的代币账户单独列出(native: false),价格同 SOL */
|
|
31
|
+
native: boolean;
|
|
32
|
+
symbol: string | null;
|
|
33
|
+
balance: string;
|
|
34
|
+
decimals: number;
|
|
35
|
+
formatted: string;
|
|
36
|
+
price: number | null;
|
|
37
|
+
/** 美元价值;没有价格时为 null */
|
|
38
|
+
value: number | null;
|
|
39
|
+
/** 给出价格的价格源 */
|
|
40
|
+
priceSource: string | null;
|
|
41
|
+
}
|
|
42
|
+
export interface Portfolio {
|
|
43
|
+
/** 合计(代币 + LP;没有价格的不计入) */
|
|
44
|
+
totalUsd: number;
|
|
45
|
+
tokensUsd: number;
|
|
46
|
+
lpUsd: number;
|
|
47
|
+
/** 有余额的代币,按价值从高到低 */
|
|
48
|
+
tokens: PortfolioToken[];
|
|
49
|
+
/** LP 仓位(开启 lp 时) */
|
|
50
|
+
lp: SolanaLpPosition[];
|
|
51
|
+
/** 有余额但没有价格的代币数(LP 仓位里缺价格的也算) */
|
|
52
|
+
unpriced: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 一个地址的资产总值:代币余额 × 价格,可选加上 LP 仓位。
|
|
56
|
+
*
|
|
57
|
+
* ```ts
|
|
58
|
+
* const p = await portfolio(client, owner, { tokens: [NATIVE_MINT, USDC, JUP] }) // 指定代币:免费公共节点也能用
|
|
59
|
+
* const all = await portfolio(new SolanaClient('https://my-rpc…'), owner, { lp: true }) // 全部持仓 + LP:需要支持 getTokenAccountsByOwner 的节点
|
|
60
|
+
* p.totalUsd // 1234.5
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function portfolio(client: SolanaClient, owner: string, options?: PortfolioOptions): Promise<Portfolio>;
|
|
64
|
+
//# sourceMappingURL=portfolio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portfolio.d.ts","sourceRoot":"","sources":["../src/portfolio.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/D,OAAO,EAAkC,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAA;AACxG,OAAO,EAA8D,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAE/G,MAAM,WAAW,gBAAiB,SAAQ,cAAc;IACtD;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B,uDAAuD;IACvD,OAAO,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACtC;;;OAGG;IACH,EAAE,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC,CAAA;IACvF,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,4BAA4B;IAC5B,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,uBAAuB;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,eAAe;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,qBAAqB;IACrB,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,qBAAqB;IACrB,EAAE,EAAE,gBAAgB,EAAE,CAAA;IACtB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAWD;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CA6BvH"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { lpPositions, methodUnavailable } from './lp.js';
|
|
2
|
+
import { combinePrices, defillamaPrices, onchainPrices, tokenPrices } from './price.js';
|
|
3
|
+
/**
|
|
4
|
+
* 一个地址的资产总值:代币余额 × 价格,可选加上 LP 仓位。
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* const p = await portfolio(client, owner, { tokens: [NATIVE_MINT, USDC, JUP] }) // 指定代币:免费公共节点也能用
|
|
8
|
+
* const all = await portfolio(new SolanaClient('https://my-rpc…'), owner, { lp: true }) // 全部持仓 + LP:需要支持 getTokenAccountsByOwner 的节点
|
|
9
|
+
* p.totalUsd // 1234.5
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export async function portfolio(client, owner, options = {}) {
|
|
13
|
+
const { tokens, sources = [defillamaPrices(), onchainPrices()], lp, minUsd = 0, onPriceError, fetch: fetchFn, signal } = options;
|
|
14
|
+
// 回调本身出错由 combinePrices / lpPositions 忽略
|
|
15
|
+
const onError = onPriceError ? (_, err) => onPriceError(err) : undefined;
|
|
16
|
+
const [balances, positions] = await Promise.all([
|
|
17
|
+
holdings(client, owner, tokens, signal),
|
|
18
|
+
lp
|
|
19
|
+
? lpPositions(client, owner, { ...(lp === true ? {} : lp), prices: combinePrices(sources, { onError }), fetch: fetchFn, onPriceError, signal })
|
|
20
|
+
: Promise.resolve([]),
|
|
21
|
+
]);
|
|
22
|
+
// 列出全部持仓时,LP 代币已经按仓位计入,不再作为代币重复计算
|
|
23
|
+
const lpMints = new Set(positions.flatMap((p) => (p.type === 'amm' ? [p.lpMint] : [])));
|
|
24
|
+
const held = balances.filter((b) => BigInt(b.balance) > 0n && !(tokens === undefined && lpMints.has(b.token)));
|
|
25
|
+
const prices = held.length ? await tokenPrices(client, held.map((b) => b.token), { sources, onError, fetch: fetchFn, signal }) : [];
|
|
26
|
+
const list = held.map((b, i) => {
|
|
27
|
+
const p = prices[i];
|
|
28
|
+
const price = p?.price ?? null;
|
|
29
|
+
return { ...b, price, value: price === null ? null : Number(b.formatted) * price, priceSource: p?.source ?? null };
|
|
30
|
+
});
|
|
31
|
+
const tokensUsd = list.reduce((sum, t) => sum + (t.value ?? 0), 0);
|
|
32
|
+
const lpUsd = positions.reduce((sum, p) => sum + (p.valueUsd ?? 0), 0);
|
|
33
|
+
return {
|
|
34
|
+
totalUsd: tokensUsd + lpUsd,
|
|
35
|
+
tokensUsd,
|
|
36
|
+
lpUsd,
|
|
37
|
+
tokens: list.filter((t) => (t.value ?? 0) >= minUsd || (minUsd === 0 && t.value === null)).sort((a, b) => (b.value ?? -1) - (a.value ?? -1)),
|
|
38
|
+
lp: positions,
|
|
39
|
+
unpriced: list.filter((t) => t.price === null).length + positions.filter((p) => p.valueUsd === null).length,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** 余额:传 tokens 时读这些代币的 ATA,否则列出全部持仓 */
|
|
43
|
+
async function holdings(client, owner, tokens, signal) {
|
|
44
|
+
if (tokens) {
|
|
45
|
+
const balances = tokens.length ? await client.balances(owner, tokens, { symbol: true, signal }) : [];
|
|
46
|
+
return balances.filter((b) => b.success).map((b) => ({ token: b.token, native: b.native, symbol: b.symbol ?? null, balance: b.balance, decimals: b.decimals, formatted: b.formatted }));
|
|
47
|
+
}
|
|
48
|
+
const owned = await client.ownerTokens(owner, { signal }).catch((err) => {
|
|
49
|
+
if (signal?.aborted || !methodUnavailable(err)) {
|
|
50
|
+
throw err; // 取消、限频、超时等原样抛出(保留错误类型)
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`Listing the tokens of ${owner} failed (${err instanceof Error ? err.message : String(err)}). ` +
|
|
53
|
+
'Listing needs getTokenAccountsByOwner (most free public nodes do not support it): pass the mints in `tokens`, or use a node that supports it', { cause: err });
|
|
54
|
+
});
|
|
55
|
+
return owned.map((t) => ({ token: t.token, native: t.native, symbol: t.symbol ?? null, balance: t.balance, decimals: t.decimals, formatted: t.formatted }));
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=portfolio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portfolio.js","sourceRoot":"","sources":["../src/portfolio.ts"],"names":[],"mappings":"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"}
|
package/dist/price.d.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { RequestOptions, SolanaClient } from './client.js';
|
|
2
|
+
import { type PdaPoolProtocol } from './pools.js';
|
|
3
|
+
export interface SolanaPriceSourceContext {
|
|
4
|
+
/** 代币 mint(原生 SOL 用 NATIVE_MINT So111…112 查) */
|
|
5
|
+
mints: readonly string[];
|
|
6
|
+
fetch: typeof fetch;
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
/** 查询用的客户端(链上价格源 onchainPrices 用它读池子) */
|
|
9
|
+
client?: SolanaClient;
|
|
10
|
+
}
|
|
11
|
+
export interface SolanaPriceSource {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
/** 返回 mint → 美元价格;没有价格的不返回 */
|
|
14
|
+
prices(ctx: SolanaPriceSourceContext): Promise<Map<string, number>>;
|
|
15
|
+
}
|
|
16
|
+
export interface DefillamaPriceOptions {
|
|
17
|
+
/** 置信度下限(0~1),DefiLlama 给出的置信度低于它视为没有价格,默认 0.9 */
|
|
18
|
+
minConfidence?: number;
|
|
19
|
+
/** 历史价格:这个时间点(unix 秒或 Date)附近的价格;不传为当前价格 */
|
|
20
|
+
at?: number | Date;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* DefiLlama 价格(免费、不需要 Key,按 100 个一批查询)。
|
|
24
|
+
* 注意:流动性很差的代币价格可能虚高,展示总资产时建议配合 minUsd 或自己的价格源。
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* defillamaPrices() // 当前价格
|
|
28
|
+
* defillamaPrices({ at: new Date('2026-01-01') }) // 历史价格
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function defillamaPrices(options?: DefillamaPriceOptions): SolanaPriceSource;
|
|
32
|
+
/**
|
|
33
|
+
* 依次使用多个价格源:前面的源没给出价格的代币交给下一个源。某个源出错时跳过它(错误交给 onError;取消查询时照常 reject)。
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* combinePrices([defillamaPrices(), onchainPrices()])
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function combinePrices(sources: readonly SolanaPriceSource[], options?: {
|
|
40
|
+
onError?: (source: SolanaPriceSource, err: unknown) => void;
|
|
41
|
+
}): SolanaPriceSource;
|
|
42
|
+
/** 按 1 美元计的稳定币(链上价格的计价锚点之一;另一个是 Wrapped SOL):USDC、USDT */
|
|
43
|
+
export declare const STABLECOINS: readonly string[];
|
|
44
|
+
export type OnchainPriceProtocol = PdaPoolProtocol;
|
|
45
|
+
export interface OnchainPriceOptions {
|
|
46
|
+
/** 池子里计价币一侧的价值(美元)下限,低于它的池子不用(防止小池子的价格被操纵),默认 10000 */
|
|
47
|
+
minLiquidityUsd?: number;
|
|
48
|
+
/** 按 1 美元计的稳定币,默认 STABLECOINS(USDC、USDT) */
|
|
49
|
+
stablecoins?: readonly string[];
|
|
50
|
+
/** 用哪些协议的池子,默认全部:'raydium-clmm'、'orca-whirlpool'、'raydium-cpmm' */
|
|
51
|
+
protocols?: readonly OnchainPriceProtocol[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 链上价格:按 PDA 推导代币对 Wrapped SOL、稳定币的池子(Raydium CLMM 的每个 AmmConfig、Orca 的每个费率档位、Raydium CPMM 的每个 AmmConfig),
|
|
55
|
+
* 用计价币一侧最深的池子的价格。稳定币按 1 美元;Wrapped SOL(和原生 SOL)按它对稳定币最深的池子。
|
|
56
|
+
* 不需要 getProgramAccounts(免费公共节点大多不支持);每个代币约推导 190 个地址,读取用 getMultipleAccounts 合并(一共两轮:池子和 mint、金库)。
|
|
57
|
+
* 深度:CPMM 是金库余额;集中流动性取金库余额和当前活跃流动性折算的储备中较小的(流动性都在区间外的池子价格不可信,不会被选中)。
|
|
58
|
+
* 适合 DefiLlama 没有收录的新币;价格是池子当前的价格,可能被单个区块内的交易影响,只用于展示。
|
|
59
|
+
* Raydium AMM v4、Meteora、PumpSwap 等池子地址不能只靠两个 mint 推导,不在查找范围内
|
|
60
|
+
*/
|
|
61
|
+
export declare function onchainPrices(options?: OnchainPriceOptions): SolanaPriceSource;
|
|
62
|
+
export interface TokenPricesOptions extends RequestOptions {
|
|
63
|
+
/** 价格源,依次使用(前面没有价格的交给后面的),默认 [defillamaPrices(), onchainPrices()] */
|
|
64
|
+
sources?: readonly SolanaPriceSource[];
|
|
65
|
+
/** 某个价格源出错时调用(继续用下一个源);回调本身出错会被忽略 */
|
|
66
|
+
onError?: (source: SolanaPriceSource, err: unknown) => void;
|
|
67
|
+
/** 查价格用的 fetch(代理等场景),默认全局 fetch */
|
|
68
|
+
fetch?: typeof fetch;
|
|
69
|
+
}
|
|
70
|
+
export interface TokenPrice {
|
|
71
|
+
/** 传入的 mint(原样) */
|
|
72
|
+
token: string;
|
|
73
|
+
/** 按原生 SOL 处理(客户端的 nativeMints,默认 So111…112 和 11111…1),价格就是 SOL 的价格 */
|
|
74
|
+
native: boolean;
|
|
75
|
+
/** 美元价格;所有价格源都没有时为 null */
|
|
76
|
+
price: number | null;
|
|
77
|
+
/** 给出价格的价格源(如 'defillama'、'onchain') */
|
|
78
|
+
source: string | null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 查代币的美元价格(SOL 用 NATIVE_MINT)。默认先查 DefiLlama,没有收录的再从链上池子算。
|
|
82
|
+
*
|
|
83
|
+
* ```ts
|
|
84
|
+
* await tokenPrices(client, [NATIVE_MINT, USDC, newToken])
|
|
85
|
+
* // [{ token: 'So111…112', native: true, price: 187.4, source: 'defillama' }, …, { token: newToken, price: 0.0012, source: 'onchain' }]
|
|
86
|
+
* await tokenPrices(client, mints, { sources: [defillamaPrices({ at: new Date('2026-01-01') })] }) // 历史价格
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare function tokenPrices(client: SolanaClient, mints: readonly string[], options?: TokenPricesOptions): Promise<TokenPrice[]>;
|
|
90
|
+
//# sourceMappingURL=price.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../src/price.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAK/D,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAA;AAEhE,MAAM,WAAW,wBAAwB;IACvC,gDAAgD;IAChD,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,KAAK,EAAE,OAAO,KAAK,CAAA;IACnB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,yCAAyC;IACzC,MAAM,CAAC,EAAE,YAAY,CAAA;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,8BAA8B;IAC9B,MAAM,CAAC,GAAG,EAAE,wBAAwB,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACpE;AAED,MAAM,WAAW,qBAAqB;IACpC,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,4CAA4C;IAC5C,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,qBAA0B,GAAG,iBAAiB,CA6BtF;AAMD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,EAAE,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;CAAO,GAAG,iBAAiB,CAQrK;AAsCD,0DAA0D;AAC1D,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAAqG,CAAA;AAE9I,MAAM,MAAM,oBAAoB,GAAG,eAAe,CAAA;AAElD,MAAM,WAAW,mBAAmB;IAClC,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/B,mEAAmE;IACnE,SAAS,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAA;CAC5C;AAmDD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,mBAAwB,GAAG,iBAAiB,CA2ElF;AA+CD,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD,qEAAqE;IACrE,OAAO,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACtC,qCAAqC;IACrC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3D,oCAAoC;IACpC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,MAAM,EAAE,OAAO,CAAA;IACf,2BAA2B;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,wCAAwC;IACxC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAYzI"}
|
package/dist/price.js
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 价格(子路径 `@w3lib/solana-batch-call/price`):DefiLlama(当前 / 历史)、链上池子价格(Raydium CLMM / CPMM、Orca Whirlpool,按 PDA 推导池子地址,
|
|
3
|
+
* 不需要 getProgramAccounts)、组合多个价格源。价格只用于展示和估值,不要用来计算交易的最小数量
|
|
4
|
+
*/
|
|
5
|
+
import { isAddress } from './address.js';
|
|
6
|
+
import { NATIVE_MINT } from './constants.js';
|
|
7
|
+
import { formatUnits, parseMint, parseTokenAccount } from './layout.js';
|
|
8
|
+
import { Bytes, ORCA_WHIRLPOOL_PROGRAM_ID, RAYDIUM_CLMM_PROGRAM_ID, parseAmmPool } from './lp.js';
|
|
9
|
+
import { sqrtPriceToPrice } from './lpMath.js';
|
|
10
|
+
import { poolAddresses } from './pools.js';
|
|
11
|
+
/**
|
|
12
|
+
* DefiLlama 价格(免费、不需要 Key,按 100 个一批查询)。
|
|
13
|
+
* 注意:流动性很差的代币价格可能虚高,展示总资产时建议配合 minUsd 或自己的价格源。
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* defillamaPrices() // 当前价格
|
|
17
|
+
* defillamaPrices({ at: new Date('2026-01-01') }) // 历史价格
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function defillamaPrices(options = {}) {
|
|
21
|
+
const minConfidence = options.minConfidence ?? 0.9;
|
|
22
|
+
const at = options.at instanceof Date ? Math.floor(options.at.getTime() / 1000) : options.at === undefined ? undefined : Math.floor(options.at);
|
|
23
|
+
const endpoint = at === undefined ? 'https://coins.llama.fi/prices/current' : `https://coins.llama.fi/prices/historical/${at}`;
|
|
24
|
+
return {
|
|
25
|
+
name: at === undefined ? 'defillama' : `defillama@${at}`,
|
|
26
|
+
async prices({ mints, fetch: fetchFn, signal }) {
|
|
27
|
+
const result = new Map();
|
|
28
|
+
const batches = [];
|
|
29
|
+
for (let i = 0; i < mints.length; i += 100) {
|
|
30
|
+
batches.push(mints.slice(i, i + 100));
|
|
31
|
+
}
|
|
32
|
+
await Promise.all(batches.map(async (batch) => {
|
|
33
|
+
const res = await fetchFn(`${endpoint}/${batch.map((m) => `solana:${m}`).join(',')}`, { signal });
|
|
34
|
+
if (!res.ok) {
|
|
35
|
+
throw new Error(`DefiLlama prices: HTTP ${res.status}`);
|
|
36
|
+
}
|
|
37
|
+
const body = (await res.json());
|
|
38
|
+
for (const [key, coin] of Object.entries(body.coins ?? {})) {
|
|
39
|
+
if (typeof coin.price === 'number' && Number.isFinite(coin.price) && (coin.confidence === undefined || coin.confidence >= minConfidence)) {
|
|
40
|
+
result.set(key.slice(key.indexOf(':') + 1), coin.price);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}));
|
|
44
|
+
return result;
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// 组合
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
/**
|
|
52
|
+
* 依次使用多个价格源:前面的源没给出价格的代币交给下一个源。某个源出错时跳过它(错误交给 onError;取消查询时照常 reject)。
|
|
53
|
+
*
|
|
54
|
+
* ```ts
|
|
55
|
+
* combinePrices([defillamaPrices(), onchainPrices()])
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function combinePrices(sources, options = {}) {
|
|
59
|
+
return {
|
|
60
|
+
name: sources.map((s) => s.name).join('+'),
|
|
61
|
+
async prices(ctx) {
|
|
62
|
+
const found = await runSources(sources, ctx, options.onError);
|
|
63
|
+
return new Map([...found].map(([k, v]) => [k, v.price]));
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** 依次查询,记下每个价格来自哪个源 */
|
|
68
|
+
async function runSources(sources, ctx, onError) {
|
|
69
|
+
const result = new Map();
|
|
70
|
+
let mints = [...ctx.mints];
|
|
71
|
+
for (const source of sources) {
|
|
72
|
+
if (!mints.length)
|
|
73
|
+
break;
|
|
74
|
+
let found;
|
|
75
|
+
try {
|
|
76
|
+
found = await source.prices({ ...ctx, mints });
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (ctx.signal?.aborted) {
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
onError?.(source, err);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// 回调出错不影响查询结果
|
|
87
|
+
}
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
for (const [mint, price] of found) {
|
|
91
|
+
if (!result.has(mint) && Number.isFinite(price))
|
|
92
|
+
result.set(mint, { price, source: source.name });
|
|
93
|
+
}
|
|
94
|
+
mints = mints.filter((m) => !result.has(m));
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// 链上价格
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
/** 按 1 美元计的稳定币(链上价格的计价锚点之一;另一个是 Wrapped SOL):USDC、USDT */
|
|
102
|
+
export const STABLECOINS = ['EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'];
|
|
103
|
+
/** 账户至少要读到的长度(Raydium PoolState 1544 字节,Orca Whirlpool 653 字节) */
|
|
104
|
+
const RAYDIUM_POOL_SIZE = 1544;
|
|
105
|
+
const ORCA_POOL_SIZE = 653;
|
|
106
|
+
/** 两个 mint 在所有协议里可能的池子地址 */
|
|
107
|
+
function candidates(token, anchor, protocols) {
|
|
108
|
+
return poolAddresses(token, anchor, protocols).map((p) => ({ ...p, token, anchor }));
|
|
109
|
+
}
|
|
110
|
+
function readPool(c, account) {
|
|
111
|
+
const b = new Bytes(account.data);
|
|
112
|
+
if (c.protocol === 'raydium-clmm' && account.owner === RAYDIUM_CLMM_PROGRAM_ID && account.data.length >= RAYDIUM_POOL_SIZE) {
|
|
113
|
+
// PoolState:mint 73 / 105、vault 137 / 169、liquidity 237、sqrt_price 253
|
|
114
|
+
return { kind: 'clmm', mint0: b.key(73), mint1: b.key(105), vault0: b.key(137), vault1: b.key(169), liquidity: b.u128(237), sqrtPrice: b.u128(253) };
|
|
115
|
+
}
|
|
116
|
+
if (c.protocol === 'orca-whirlpool' && account.owner === ORCA_WHIRLPOOL_PROGRAM_ID && account.data.length >= ORCA_POOL_SIZE) {
|
|
117
|
+
// Whirlpool:liquidity 49、sqrt_price 65、mint_a 101、vault_a 133、mint_b 181、vault_b 213
|
|
118
|
+
return { kind: 'clmm', mint0: b.key(101), mint1: b.key(181), vault0: b.key(133), vault1: b.key(213), liquidity: b.u128(49), sqrtPrice: b.u128(65) };
|
|
119
|
+
}
|
|
120
|
+
if (c.protocol === 'raydium-cpmm') {
|
|
121
|
+
const pool = parseAmmPool(account);
|
|
122
|
+
return pool?.protocol === 'raydium-cpmm'
|
|
123
|
+
? { kind: 'cpmm', mint0: pool.mint0, mint1: pool.mint1, vault0: pool.vault0, vault1: pool.vault1, reserved0: pool.reserved0, reserved1: pool.reserved1 }
|
|
124
|
+
: null;
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 链上价格:按 PDA 推导代币对 Wrapped SOL、稳定币的池子(Raydium CLMM 的每个 AmmConfig、Orca 的每个费率档位、Raydium CPMM 的每个 AmmConfig),
|
|
130
|
+
* 用计价币一侧最深的池子的价格。稳定币按 1 美元;Wrapped SOL(和原生 SOL)按它对稳定币最深的池子。
|
|
131
|
+
* 不需要 getProgramAccounts(免费公共节点大多不支持);每个代币约推导 190 个地址,读取用 getMultipleAccounts 合并(一共两轮:池子和 mint、金库)。
|
|
132
|
+
* 深度:CPMM 是金库余额;集中流动性取金库余额和当前活跃流动性折算的储备中较小的(流动性都在区间外的池子价格不可信,不会被选中)。
|
|
133
|
+
* 适合 DefiLlama 没有收录的新币;价格是池子当前的价格,可能被单个区块内的交易影响,只用于展示。
|
|
134
|
+
* Raydium AMM v4、Meteora、PumpSwap 等池子地址不能只靠两个 mint 推导,不在查找范围内
|
|
135
|
+
*/
|
|
136
|
+
export function onchainPrices(options = {}) {
|
|
137
|
+
return {
|
|
138
|
+
name: 'onchain',
|
|
139
|
+
async prices({ mints, client, signal }) {
|
|
140
|
+
if (!client)
|
|
141
|
+
throw new Error('onchainPrices needs a SolanaClient (ctx.client)');
|
|
142
|
+
const stables = options.stablecoins ?? STABLECOINS;
|
|
143
|
+
const protocols = new Set(options.protocols ?? ['raydium-clmm', 'orca-whirlpool', 'raydium-cpmm']);
|
|
144
|
+
const minLiquidity = options.minLiquidityUsd ?? 10_000;
|
|
145
|
+
const result = new Map();
|
|
146
|
+
const stableSet = new Set(stables);
|
|
147
|
+
for (const m of mints)
|
|
148
|
+
if (stableSet.has(m))
|
|
149
|
+
result.set(m, 1);
|
|
150
|
+
const rest = [...new Set(mints)].filter((m) => !stableSet.has(m) && m !== NATIVE_MINT && isAddress(m));
|
|
151
|
+
const wantSol = mints.includes(NATIVE_MINT);
|
|
152
|
+
if (!stables.length || !protocols.size || (!rest.length && !wantSol))
|
|
153
|
+
return result;
|
|
154
|
+
// 1. 一次读:Wrapped SOL 对稳定币、其他代币对 Wrapped SOL 和稳定币的候选池子,以及这些代币的 mint(精度)
|
|
155
|
+
const list = [
|
|
156
|
+
...stables.flatMap((s) => candidates(NATIVE_MINT, s, protocols)),
|
|
157
|
+
...rest.flatMap((t) => [NATIVE_MINT, ...stables].flatMap((anchor) => candidates(t, anchor, protocols))),
|
|
158
|
+
];
|
|
159
|
+
const mintList = [...new Set([NATIVE_MINT, ...stables, ...rest])];
|
|
160
|
+
const first = await client.accounts([...list.map((c) => c.address), ...mintList], { signal });
|
|
161
|
+
const decimals = new Map();
|
|
162
|
+
mintList.forEach((m, i) => {
|
|
163
|
+
const account = first[list.length + i];
|
|
164
|
+
try {
|
|
165
|
+
if (account)
|
|
166
|
+
decimals.set(m, parseMint(account.data).decimals);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// 不是代币 mint
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
const pools = list.flatMap((c, i) => {
|
|
173
|
+
const account = first[i];
|
|
174
|
+
const pool = account ? readPool(c, account) : null;
|
|
175
|
+
// 池子里的两个 mint 要和推导时的一致(PDA 上可能是别的账户)
|
|
176
|
+
const ok = pool && ((pool.mint0 === c.token && pool.mint1 === c.anchor) || (pool.mint1 === c.token && pool.mint0 === c.anchor));
|
|
177
|
+
return ok ? [{ ...c, pool }] : [];
|
|
178
|
+
});
|
|
179
|
+
if (!pools.length)
|
|
180
|
+
return result;
|
|
181
|
+
// 2. 一次读:金库(集中流动性只读计价币一侧,CPMM 两侧都读)
|
|
182
|
+
const vaultsOf = (p) => {
|
|
183
|
+
const anchorIs0 = p.pool.mint0 === p.anchor;
|
|
184
|
+
return p.pool.kind === 'cpmm' ? [p.pool.vault0, p.pool.vault1] : [anchorIs0 ? p.pool.vault0 : p.pool.vault1];
|
|
185
|
+
};
|
|
186
|
+
const vaultAddresses = [...new Set(pools.flatMap(vaultsOf))];
|
|
187
|
+
const vaultAccounts = await client.accounts(vaultAddresses, { signal });
|
|
188
|
+
const balances = new Map();
|
|
189
|
+
vaultAddresses.forEach((address, i) => {
|
|
190
|
+
const account = vaultAccounts[i];
|
|
191
|
+
try {
|
|
192
|
+
if (account)
|
|
193
|
+
balances.set(address, parseTokenAccount(account.data).amount);
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
// 不是代币账户
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
const quotes = pools.flatMap((p) => {
|
|
200
|
+
const q = quote(p.pool, p.token, p.anchor, decimals, balances);
|
|
201
|
+
return q && Number.isFinite(q.price) && q.price > 0 && Number.isFinite(q.depth) ? [q] : [];
|
|
202
|
+
});
|
|
203
|
+
// 3. 先算 Wrapped SOL(对稳定币),再按 SOL 和稳定币的美元价格算其他代币
|
|
204
|
+
const anchorsUsd = new Map(stables.map((s) => [s, 1]));
|
|
205
|
+
const sol = best(quotes.filter((q) => q.token === NATIVE_MINT), anchorsUsd, minLiquidity);
|
|
206
|
+
if (sol !== null) {
|
|
207
|
+
anchorsUsd.set(NATIVE_MINT, sol);
|
|
208
|
+
if (wantSol)
|
|
209
|
+
result.set(NATIVE_MINT, sol);
|
|
210
|
+
}
|
|
211
|
+
for (const t of rest) {
|
|
212
|
+
const usd = best(quotes.filter((q) => q.token === t), anchorsUsd, minLiquidity);
|
|
213
|
+
if (usd !== null)
|
|
214
|
+
result.set(t, usd);
|
|
215
|
+
}
|
|
216
|
+
return result;
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/** 一个池子给出的价格(计价币 / 代币)和计价币一侧的深度;缺精度、金库时为 null */
|
|
221
|
+
function quote(pool, token, anchor, decimals, balances) {
|
|
222
|
+
const d0 = decimals.get(pool.mint0);
|
|
223
|
+
const d1 = decimals.get(pool.mint1);
|
|
224
|
+
if (d0 === undefined || d1 === undefined)
|
|
225
|
+
return null;
|
|
226
|
+
const tokenIs0 = pool.mint0 === token;
|
|
227
|
+
const da = tokenIs0 ? d1 : d0;
|
|
228
|
+
if (pool.kind === 'cpmm') {
|
|
229
|
+
const v0 = balances.get(pool.vault0);
|
|
230
|
+
const v1 = balances.get(pool.vault1);
|
|
231
|
+
if (v0 === undefined || v1 === undefined)
|
|
232
|
+
return null;
|
|
233
|
+
// 与程序一致:金库余额扣掉协议 / 基金 / 创建者手续费才是储备
|
|
234
|
+
const r0 = v0 > pool.reserved0 ? v0 - pool.reserved0 : 0n;
|
|
235
|
+
const r1 = v1 > pool.reserved1 ? v1 - pool.reserved1 : 0n;
|
|
236
|
+
if (r0 === 0n || r1 === 0n)
|
|
237
|
+
return null;
|
|
238
|
+
const [rt, ra, dt] = tokenIs0 ? [r0, r1, d0] : [r1, r0, d1];
|
|
239
|
+
const depth = Number(formatUnits(ra, da));
|
|
240
|
+
return { token, anchor, price: depth / Number(formatUnits(rt, dt)), depth };
|
|
241
|
+
}
|
|
242
|
+
const vault = balances.get(tokenIs0 ? pool.vault1 : pool.vault0);
|
|
243
|
+
if (vault === undefined || pool.sqrtPrice === 0n)
|
|
244
|
+
return null;
|
|
245
|
+
// price = token1 / token0(按精度换算)
|
|
246
|
+
const price1Per0 = sqrtPriceToPrice(pool.sqrtPrice, d0, d1);
|
|
247
|
+
// 当前活跃流动性折算的计价币储备(最小单位):token1 = L × √P,token0 = L / √P(√P = sqrtPrice / 2^64)
|
|
248
|
+
const sqrt = Number(pool.sqrtPrice) / 2 ** 64;
|
|
249
|
+
const virtual = (tokenIs0 ? Number(pool.liquidity) * sqrt : Number(pool.liquidity) / sqrt) / 10 ** da;
|
|
250
|
+
return { token, anchor, price: tokenIs0 ? price1Per0 : 1 / price1Per0, depth: Math.min(Number(formatUnits(vault, da)), virtual) };
|
|
251
|
+
}
|
|
252
|
+
/** 深度(美元)达到下限的池子里最深的一个给出的美元价格;没有时为 null */
|
|
253
|
+
function best(quotes, anchorsUsd, minLiquidityUsd) {
|
|
254
|
+
let found = null;
|
|
255
|
+
for (const q of quotes) {
|
|
256
|
+
const anchorUsd = anchorsUsd.get(q.anchor);
|
|
257
|
+
if (anchorUsd === undefined)
|
|
258
|
+
continue;
|
|
259
|
+
const depthUsd = q.depth * anchorUsd;
|
|
260
|
+
if (depthUsd >= minLiquidityUsd && (!found || depthUsd > found.depthUsd))
|
|
261
|
+
found = { usd: q.price * anchorUsd, depthUsd };
|
|
262
|
+
}
|
|
263
|
+
return found ? found.usd : null;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* 查代币的美元价格(SOL 用 NATIVE_MINT)。默认先查 DefiLlama,没有收录的再从链上池子算。
|
|
267
|
+
*
|
|
268
|
+
* ```ts
|
|
269
|
+
* await tokenPrices(client, [NATIVE_MINT, USDC, newToken])
|
|
270
|
+
* // [{ token: 'So111…112', native: true, price: 187.4, source: 'defillama' }, …, { token: newToken, price: 0.0012, source: 'onchain' }]
|
|
271
|
+
* await tokenPrices(client, mints, { sources: [defillamaPrices({ at: new Date('2026-01-01') })] }) // 历史价格
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
export async function tokenPrices(client, mints, options = {}) {
|
|
275
|
+
const { sources = [defillamaPrices(), onchainPrices()], onError, fetch: fetchOption, signal } = options;
|
|
276
|
+
const fetchFn = fetchOption ?? ((...args) => fetch(...args));
|
|
277
|
+
const native = mints.map((m) => client.isNativeMint(m));
|
|
278
|
+
// 原生 SOL 按 Wrapped SOL 的 mint 查;不是合法地址的不查
|
|
279
|
+
const keys = mints.map((m, i) => (native[i] ? NATIVE_MINT : m));
|
|
280
|
+
const query = [...new Set(keys.filter((k) => isAddress(k)))];
|
|
281
|
+
const found = await runSources(sources, { mints: query, fetch: fetchFn, signal, client }, onError);
|
|
282
|
+
return mints.map((token, i) => {
|
|
283
|
+
const hit = found.get(keys[i]);
|
|
284
|
+
return { token, native: native[i], price: hit?.price ?? null, source: hit?.source ?? null };
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=price.js.map
|