pump-trader 1.2.1 → 1.2.3
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/dist/index.d.ts +4 -2
- package/dist/index.js +95 -10
- package/index.js +76 -8
- package/index.ts +100 -8
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -126,11 +126,13 @@ export declare class PumpTrader {
|
|
|
126
126
|
calcSell(tokenIn: bigint, state: BondingCurveState): bigint;
|
|
127
127
|
calculateAmmBuyOutput(quoteIn: bigint, reserves: PoolReserves): bigint;
|
|
128
128
|
calculateAmmSellOutput(baseIn: bigint, reserves: PoolReserves): bigint;
|
|
129
|
-
|
|
129
|
+
private solPriceCache;
|
|
130
|
+
getSolPriceInUsdc(): Promise<number>;
|
|
131
|
+
getPriceAndStatus(tokenAddr: string, quoteMint?: PublicKey): Promise<{
|
|
130
132
|
price: number;
|
|
131
133
|
completed: boolean;
|
|
132
134
|
}>;
|
|
133
|
-
getAmmPrice(mint: PublicKey): Promise<number>;
|
|
135
|
+
getAmmPrice(mint: PublicKey, quoteMint?: PublicKey): Promise<number>;
|
|
134
136
|
/**
|
|
135
137
|
* 查询代币余额
|
|
136
138
|
* @param tokenAddr - 代币地址(可选),如果不传则返回所有代币
|
package/dist/index.js
CHANGED
|
@@ -153,6 +153,8 @@ function parsePoolKeys(data) {
|
|
|
153
153
|
/* ================= PumpTrader 类 ================= */
|
|
154
154
|
class PumpTrader {
|
|
155
155
|
constructor(rpc, wallet) {
|
|
156
|
+
/* ---------- 价格查询 ---------- */
|
|
157
|
+
this.solPriceCache = null;
|
|
156
158
|
this.connection = new web3_js_1.Connection(rpc, "confirmed");
|
|
157
159
|
this._wallet = wallet;
|
|
158
160
|
this.publicKey = wallet.publicKey;
|
|
@@ -419,20 +421,77 @@ class PumpTrader {
|
|
|
419
421
|
const denominator = reserves.baseAmount + baseInAfterFee;
|
|
420
422
|
return numerator / denominator;
|
|
421
423
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
+
async getSolPriceInUsdc() {
|
|
425
|
+
if (this.solPriceCache && Date.now() - this.solPriceCache.timestamp < 60000) {
|
|
426
|
+
return this.solPriceCache.price;
|
|
427
|
+
}
|
|
428
|
+
try {
|
|
429
|
+
// Use Orca USDC/SOL whirlpool (7qbRF6YsyGuLUVs6Y1q64bdVrfe4ZcUUz1JRdoVNUJnm)
|
|
430
|
+
// Read token vault balances directly to compute price
|
|
431
|
+
const poolAddr = new web3_js_1.PublicKey("7qbRF6YsyGuLUVs6Y1q64bdVrfe4ZcUUz1JRdoVNUJnm");
|
|
432
|
+
const acc = await this.connection.getAccountInfo(poolAddr);
|
|
433
|
+
if (!acc || acc.data.length < 304)
|
|
434
|
+
throw new Error("Invalid pool data");
|
|
435
|
+
// Whirlpool: tokenMintA at offset 40, tokenMintB at offset 72, vaultA at 104, vaultB at 136
|
|
436
|
+
const tokenMintA = new web3_js_1.PublicKey(acc.data.slice(40, 72));
|
|
437
|
+
const tokenVaultA = new web3_js_1.PublicKey(acc.data.slice(104, 136));
|
|
438
|
+
const tokenVaultB = new web3_js_1.PublicKey(acc.data.slice(136, 168));
|
|
439
|
+
const [balanceA, balanceB] = await Promise.all([
|
|
440
|
+
this.connection.getTokenAccountBalance(tokenVaultA),
|
|
441
|
+
this.connection.getTokenAccountBalance(tokenVaultB),
|
|
442
|
+
]);
|
|
443
|
+
// Determine which vault holds SOL by checking tokenMintA
|
|
444
|
+
const SOL_ADDR = "So11111111111111111111111111111111111111112";
|
|
445
|
+
const solBalance = tokenMintA.toBase58() === SOL_ADDR
|
|
446
|
+
? Number(balanceA.value.amount)
|
|
447
|
+
: Number(balanceB.value.amount);
|
|
448
|
+
const usdcBalance = tokenMintA.toBase58() === SOL_ADDR
|
|
449
|
+
? Number(balanceB.value.amount)
|
|
450
|
+
: Number(balanceA.value.amount);
|
|
451
|
+
if (solBalance === 0)
|
|
452
|
+
throw new Error("Zero balance");
|
|
453
|
+
const price = usdcBalance / solBalance;
|
|
454
|
+
this.solPriceCache = { price, timestamp: Date.now() };
|
|
455
|
+
return price;
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
return 175;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
async getPriceAndStatus(tokenAddr, quoteMint) {
|
|
424
462
|
const mint = new web3_js_1.PublicKey(tokenAddr);
|
|
425
463
|
const { state } = await this.loadBonding(mint);
|
|
426
464
|
if (state.complete) {
|
|
427
|
-
const
|
|
465
|
+
const qm = quoteMint || (state.quoteMint && !state.quoteMint.equals(SOL_MINT) ? state.quoteMint : SOL_MINT);
|
|
466
|
+
const price = await this.getAmmPrice(mint, qm);
|
|
428
467
|
return { price, completed: true };
|
|
429
468
|
}
|
|
469
|
+
const qm = quoteMint || state.quoteMint || SOL_MINT;
|
|
470
|
+
const isSolQuote = qm.equals(SOL_MINT);
|
|
430
471
|
const oneToken = BigInt(1_000_000);
|
|
431
|
-
|
|
432
|
-
|
|
472
|
+
if (isSolQuote) {
|
|
473
|
+
const solOut = this.calcSell(oneToken, state);
|
|
474
|
+
const price = Number(solOut) / 1e9;
|
|
475
|
+
return { price, completed: false };
|
|
476
|
+
}
|
|
477
|
+
// USDC-paired bonding curve: pump stores USDC raw amount (6 decimals) in the
|
|
478
|
+
// virtualSolReserves field. calcSell returns USDC raw, divide by 1e6 for USDC price.
|
|
479
|
+
// Then convert to SOL using Orca USDC/SOL pool.
|
|
480
|
+
let quotePrice;
|
|
481
|
+
if (state.virtualQuoteReserves !== undefined) {
|
|
482
|
+
const newVirtualToken = state.virtualTokenReserves + oneToken;
|
|
483
|
+
const quoteOut = state.virtualQuoteReserves - (state.virtualQuoteReserves * state.virtualTokenReserves) / newVirtualToken;
|
|
484
|
+
quotePrice = Number(quoteOut) / 1e6;
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
const rawOut = this.calcSell(oneToken, state);
|
|
488
|
+
quotePrice = Number(rawOut) / 1e6;
|
|
489
|
+
}
|
|
490
|
+
const solPrice = await this.getSolPriceInUsdc();
|
|
491
|
+
const price = quotePrice / solPrice;
|
|
433
492
|
return { price, completed: false };
|
|
434
493
|
}
|
|
435
|
-
async getAmmPrice(mint) {
|
|
494
|
+
async getAmmPrice(mint, quoteMint = SOL_MINT) {
|
|
436
495
|
const [poolCreator] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("pool-authority"), mint.toBuffer()], PROGRAM_IDS.PUMP);
|
|
437
496
|
const indexBuffer = new bn_js_1.default(0).toArrayLike(Buffer, "le", 2);
|
|
438
497
|
const [pool] = web3_js_1.PublicKey.findProgramAddressSync([
|
|
@@ -440,7 +499,7 @@ class PumpTrader {
|
|
|
440
499
|
indexBuffer,
|
|
441
500
|
poolCreator.toBuffer(),
|
|
442
501
|
mint.toBuffer(),
|
|
443
|
-
|
|
502
|
+
quoteMint.toBuffer(),
|
|
444
503
|
], PROGRAM_IDS.PUMP_AMM);
|
|
445
504
|
const acc = await this.connection.getAccountInfo(pool);
|
|
446
505
|
if (!acc)
|
|
@@ -450,7 +509,13 @@ class PumpTrader {
|
|
|
450
509
|
this.connection.getTokenAccountBalance(poolKeys.poolBaseTokenAccount),
|
|
451
510
|
this.connection.getTokenAccountBalance(poolKeys.poolQuoteTokenAccount),
|
|
452
511
|
]);
|
|
453
|
-
|
|
512
|
+
let price = quoteInfo.value.uiAmount / baseInfo.value.uiAmount;
|
|
513
|
+
// If pool is not SOL-quoted, convert to SOL price
|
|
514
|
+
if (!quoteMint.equals(SOL_MINT)) {
|
|
515
|
+
const solPrice = await this.getSolPriceInUsdc();
|
|
516
|
+
price = price / solPrice;
|
|
517
|
+
}
|
|
518
|
+
return price;
|
|
454
519
|
}
|
|
455
520
|
/* ---------- 余额查询 ---------- */
|
|
456
521
|
/**
|
|
@@ -994,7 +1059,17 @@ class PumpTrader {
|
|
|
994
1059
|
isWritable: true,
|
|
995
1060
|
});
|
|
996
1061
|
}
|
|
997
|
-
|
|
1062
|
+
const POOL_DEFAULT_COIN_CREATOR = new web3_js_1.PublicKey("11111111111111111111111111111111");
|
|
1063
|
+
if (poolKeys.coinCreator && !poolKeys.coinCreator.equals(POOL_DEFAULT_COIN_CREATOR)) {
|
|
1064
|
+
remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
|
|
1065
|
+
}
|
|
1066
|
+
else {
|
|
1067
|
+
remainingKeys.push({
|
|
1068
|
+
pubkey: PUMP_BUYBACK_FEE_RECIPIENTS[0],
|
|
1069
|
+
isSigner: false,
|
|
1070
|
+
isWritable: true,
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
998
1073
|
remainingKeys.push({ pubkey: newFeeRecipient, isSigner: false, isWritable: false }, {
|
|
999
1074
|
pubkey: newFeeRecipientTokenAccount,
|
|
1000
1075
|
isSigner: false,
|
|
@@ -1080,7 +1155,17 @@ class PumpTrader {
|
|
|
1080
1155
|
isWritable: true,
|
|
1081
1156
|
}, { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true });
|
|
1082
1157
|
}
|
|
1083
|
-
|
|
1158
|
+
const POOL_DEFAULT_COIN_CREATOR = new web3_js_1.PublicKey("11111111111111111111111111111111");
|
|
1159
|
+
if (poolKeys.coinCreator && !poolKeys.coinCreator.equals(POOL_DEFAULT_COIN_CREATOR)) {
|
|
1160
|
+
remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
|
|
1161
|
+
}
|
|
1162
|
+
else {
|
|
1163
|
+
remainingKeys.push({
|
|
1164
|
+
pubkey: PUMP_BUYBACK_FEE_RECIPIENTS[0],
|
|
1165
|
+
isSigner: false,
|
|
1166
|
+
isWritable: true,
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1084
1169
|
remainingKeys.push({ pubkey: newFeeRecipient, isSigner: false, isWritable: false }, {
|
|
1085
1170
|
pubkey: newFeeRecipientTokenAccount,
|
|
1086
1171
|
isSigner: false,
|
package/index.js
CHANGED
|
@@ -492,22 +492,74 @@ export class PumpTrader {
|
|
|
492
492
|
|
|
493
493
|
/* ---------- 价格查询 ---------- */
|
|
494
494
|
|
|
495
|
-
async
|
|
495
|
+
async getSolPriceInUsdc() {
|
|
496
|
+
if (this._solPriceCache && Date.now() - this._solPriceCache.timestamp < 60000) {
|
|
497
|
+
return this._solPriceCache.price;
|
|
498
|
+
}
|
|
499
|
+
try {
|
|
500
|
+
const poolAddr = new PublicKey("7qbRF6YsyGuLUVs6Y1q64bdVrfe4ZcUUz1JRdoVNUJnm");
|
|
501
|
+
const acc = await this.connection.getAccountInfo(poolAddr);
|
|
502
|
+
if (!acc || acc.data.length < 304) throw new Error("Invalid pool data");
|
|
503
|
+
const tokenMintA = new PublicKey(acc.data.slice(40, 72));
|
|
504
|
+
const tokenVaultA = new PublicKey(acc.data.slice(104, 136));
|
|
505
|
+
const tokenVaultB = new PublicKey(acc.data.slice(136, 168));
|
|
506
|
+
const [balanceA, balanceB] = await Promise.all([
|
|
507
|
+
this.connection.getTokenAccountBalance(tokenVaultA),
|
|
508
|
+
this.connection.getTokenAccountBalance(tokenVaultB),
|
|
509
|
+
]);
|
|
510
|
+
const SOL_ADDR = "So11111111111111111111111111111111111111112";
|
|
511
|
+
const solBalance = tokenMintA.toBase58() === SOL_ADDR
|
|
512
|
+
? Number(balanceA.value.amount)
|
|
513
|
+
: Number(balanceB.value.amount);
|
|
514
|
+
const usdcBalance = tokenMintA.toBase58() === SOL_ADDR
|
|
515
|
+
? Number(balanceB.value.amount)
|
|
516
|
+
: Number(balanceA.value.amount);
|
|
517
|
+
if (solBalance === 0) throw new Error("Zero balance");
|
|
518
|
+
const price = usdcBalance / solBalance;
|
|
519
|
+
this._solPriceCache = { price, timestamp: Date.now() };
|
|
520
|
+
return price;
|
|
521
|
+
} catch {
|
|
522
|
+
return 175;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
async getPriceAndStatus(tokenAddr, quoteMint = null) {
|
|
496
527
|
const mint = new PublicKey(tokenAddr);
|
|
497
528
|
const { state } = await this.loadBonding(mint);
|
|
498
529
|
|
|
499
530
|
if (state.complete) {
|
|
500
|
-
const
|
|
531
|
+
const qm = quoteMint || (state.quoteMint && !state.quoteMint.equals(SOL_MINT) ? state.quoteMint : SOL_MINT);
|
|
532
|
+
const price = await this.getAmmPrice(mint, qm);
|
|
501
533
|
return { price, completed: true };
|
|
502
534
|
}
|
|
503
535
|
|
|
536
|
+
const qm = quoteMint || state.quoteMint || SOL_MINT;
|
|
537
|
+
const isSolQuote = qm.equals(SOL_MINT);
|
|
538
|
+
|
|
504
539
|
const oneToken = BigInt(1_000_000);
|
|
505
|
-
|
|
506
|
-
|
|
540
|
+
|
|
541
|
+
if (isSolQuote) {
|
|
542
|
+
const solOut = this.calcSell(oneToken, state);
|
|
543
|
+
const price = Number(solOut) / 1e9;
|
|
544
|
+
return { price, completed: false };
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
let quotePrice;
|
|
548
|
+
if (state.virtualQuoteReserves !== undefined) {
|
|
549
|
+
const newVirtualToken = state.virtualTokenReserves + oneToken;
|
|
550
|
+
const quoteOut = state.virtualQuoteReserves - (state.virtualQuoteReserves * state.virtualTokenReserves) / newVirtualToken;
|
|
551
|
+
quotePrice = Number(quoteOut) / 1e6;
|
|
552
|
+
} else {
|
|
553
|
+
const rawOut = this.calcSell(oneToken, state);
|
|
554
|
+
quotePrice = Number(rawOut) / 1e6;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const solPrice = await this.getSolPriceInUsdc();
|
|
558
|
+
const price = quotePrice / solPrice;
|
|
507
559
|
return { price, completed: false };
|
|
508
560
|
}
|
|
509
561
|
|
|
510
|
-
async getAmmPrice(mint) {
|
|
562
|
+
async getAmmPrice(mint, quoteMint = SOL_MINT) {
|
|
511
563
|
const [poolCreator] = PublicKey.findProgramAddressSync(
|
|
512
564
|
[Buffer.from("pool-authority"), mint.toBuffer()],
|
|
513
565
|
PROGRAM_IDS.PUMP,
|
|
@@ -520,7 +572,7 @@ export class PumpTrader {
|
|
|
520
572
|
indexBuffer,
|
|
521
573
|
poolCreator.toBuffer(),
|
|
522
574
|
mint.toBuffer(),
|
|
523
|
-
|
|
575
|
+
quoteMint.toBuffer(),
|
|
524
576
|
],
|
|
525
577
|
PROGRAM_IDS.PUMP_AMM,
|
|
526
578
|
);
|
|
@@ -534,7 +586,14 @@ export class PumpTrader {
|
|
|
534
586
|
this.connection.getTokenAccountBalance(poolKeys.poolQuoteTokenAccount),
|
|
535
587
|
]);
|
|
536
588
|
|
|
537
|
-
|
|
589
|
+
let price = quoteInfo.value.uiAmount / baseInfo.value.uiAmount;
|
|
590
|
+
|
|
591
|
+
if (!quoteMint.equals(SOL_MINT)) {
|
|
592
|
+
const solPrice = await this.getSolPriceInUsdc();
|
|
593
|
+
price = price / solPrice;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
return price;
|
|
538
597
|
}
|
|
539
598
|
|
|
540
599
|
/* ---------- 余额查询 ---------- */
|
|
@@ -1417,7 +1476,16 @@ export class PumpTrader {
|
|
|
1417
1476
|
isWritable: true,
|
|
1418
1477
|
});
|
|
1419
1478
|
}
|
|
1420
|
-
|
|
1479
|
+
const POOL_DEFAULT_COIN_CREATOR = new PublicKey("11111111111111111111111111111111");
|
|
1480
|
+
if (poolKeys.coinCreator && !poolKeys.coinCreator.equals(POOL_DEFAULT_COIN_CREATOR)) {
|
|
1481
|
+
remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
|
|
1482
|
+
} else {
|
|
1483
|
+
remainingKeys.push({
|
|
1484
|
+
pubkey: PUMP_BUYBACK_FEE_RECIPIENTS[0],
|
|
1485
|
+
isSigner: false,
|
|
1486
|
+
isWritable: true,
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1421
1489
|
remainingKeys.push(
|
|
1422
1490
|
{ pubkey: newFeeRecipient, isSigner: false, isWritable: false },
|
|
1423
1491
|
{
|
package/index.ts
CHANGED
|
@@ -700,24 +700,90 @@ export class PumpTrader {
|
|
|
700
700
|
|
|
701
701
|
/* ---------- 价格查询 ---------- */
|
|
702
702
|
|
|
703
|
+
private solPriceCache: { price: number; timestamp: number } | null = null;
|
|
704
|
+
|
|
705
|
+
async getSolPriceInUsdc(): Promise<number> {
|
|
706
|
+
if (this.solPriceCache && Date.now() - this.solPriceCache.timestamp < 60000) {
|
|
707
|
+
return this.solPriceCache.price;
|
|
708
|
+
}
|
|
709
|
+
try {
|
|
710
|
+
// Use Orca USDC/SOL whirlpool (7qbRF6YsyGuLUVs6Y1q64bdVrfe4ZcUUz1JRdoVNUJnm)
|
|
711
|
+
// Read token vault balances directly to compute price
|
|
712
|
+
const poolAddr = new PublicKey("7qbRF6YsyGuLUVs6Y1q64bdVrfe4ZcUUz1JRdoVNUJnm");
|
|
713
|
+
const acc = await this.connection.getAccountInfo(poolAddr);
|
|
714
|
+
if (!acc || acc.data.length < 304) throw new Error("Invalid pool data");
|
|
715
|
+
|
|
716
|
+
// Whirlpool: tokenMintA at offset 40, tokenMintB at offset 72, vaultA at 104, vaultB at 136
|
|
717
|
+
const tokenMintA = new PublicKey(acc.data.slice(40, 72));
|
|
718
|
+
const tokenVaultA = new PublicKey(acc.data.slice(104, 136));
|
|
719
|
+
const tokenVaultB = new PublicKey(acc.data.slice(136, 168));
|
|
720
|
+
|
|
721
|
+
const [balanceA, balanceB] = await Promise.all([
|
|
722
|
+
this.connection.getTokenAccountBalance(tokenVaultA),
|
|
723
|
+
this.connection.getTokenAccountBalance(tokenVaultB),
|
|
724
|
+
]);
|
|
725
|
+
|
|
726
|
+
// Determine which vault holds SOL by checking tokenMintA
|
|
727
|
+
const SOL_ADDR = "So11111111111111111111111111111111111111112";
|
|
728
|
+
const solBalance = tokenMintA.toBase58() === SOL_ADDR
|
|
729
|
+
? Number(balanceA.value.amount)
|
|
730
|
+
: Number(balanceB.value.amount);
|
|
731
|
+
const usdcBalance = tokenMintA.toBase58() === SOL_ADDR
|
|
732
|
+
? Number(balanceB.value.amount)
|
|
733
|
+
: Number(balanceA.value.amount);
|
|
734
|
+
|
|
735
|
+
if (solBalance === 0) throw new Error("Zero balance");
|
|
736
|
+
const price = usdcBalance / solBalance;
|
|
737
|
+
this.solPriceCache = { price, timestamp: Date.now() };
|
|
738
|
+
return price;
|
|
739
|
+
} catch {
|
|
740
|
+
return 175;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
703
744
|
async getPriceAndStatus(
|
|
704
745
|
tokenAddr: string,
|
|
746
|
+
quoteMint?: PublicKey,
|
|
705
747
|
): Promise<{ price: number; completed: boolean }> {
|
|
706
748
|
const mint = new PublicKey(tokenAddr);
|
|
707
749
|
const { state } = await this.loadBonding(mint);
|
|
708
750
|
|
|
709
751
|
if (state.complete) {
|
|
710
|
-
const
|
|
752
|
+
const qm = quoteMint || (state.quoteMint && !state.quoteMint.equals(SOL_MINT) ? state.quoteMint : SOL_MINT);
|
|
753
|
+
const price = await this.getAmmPrice(mint, qm);
|
|
711
754
|
return { price, completed: true };
|
|
712
755
|
}
|
|
713
756
|
|
|
757
|
+
const qm = quoteMint || state.quoteMint || SOL_MINT;
|
|
758
|
+
const isSolQuote = qm.equals(SOL_MINT);
|
|
759
|
+
|
|
714
760
|
const oneToken = BigInt(1_000_000);
|
|
715
|
-
|
|
716
|
-
|
|
761
|
+
|
|
762
|
+
if (isSolQuote) {
|
|
763
|
+
const solOut = this.calcSell(oneToken, state);
|
|
764
|
+
const price = Number(solOut) / 1e9;
|
|
765
|
+
return { price, completed: false };
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// USDC-paired bonding curve: pump stores USDC raw amount (6 decimals) in the
|
|
769
|
+
// virtualSolReserves field. calcSell returns USDC raw, divide by 1e6 for USDC price.
|
|
770
|
+
// Then convert to SOL using Orca USDC/SOL pool.
|
|
771
|
+
let quotePrice: number;
|
|
772
|
+
if (state.virtualQuoteReserves !== undefined) {
|
|
773
|
+
const newVirtualToken = state.virtualTokenReserves + oneToken;
|
|
774
|
+
const quoteOut = state.virtualQuoteReserves - (state.virtualQuoteReserves * state.virtualTokenReserves) / newVirtualToken;
|
|
775
|
+
quotePrice = Number(quoteOut) / 1e6;
|
|
776
|
+
} else {
|
|
777
|
+
const rawOut = this.calcSell(oneToken, state);
|
|
778
|
+
quotePrice = Number(rawOut) / 1e6;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
const solPrice = await this.getSolPriceInUsdc();
|
|
782
|
+
const price = quotePrice / solPrice;
|
|
717
783
|
return { price, completed: false };
|
|
718
784
|
}
|
|
719
785
|
|
|
720
|
-
async getAmmPrice(mint: PublicKey): Promise<number> {
|
|
786
|
+
async getAmmPrice(mint: PublicKey, quoteMint: PublicKey = SOL_MINT): Promise<number> {
|
|
721
787
|
const [poolCreator] = PublicKey.findProgramAddressSync(
|
|
722
788
|
[Buffer.from("pool-authority"), mint.toBuffer()],
|
|
723
789
|
PROGRAM_IDS.PUMP,
|
|
@@ -730,7 +796,7 @@ export class PumpTrader {
|
|
|
730
796
|
indexBuffer,
|
|
731
797
|
poolCreator.toBuffer(),
|
|
732
798
|
mint.toBuffer(),
|
|
733
|
-
|
|
799
|
+
quoteMint.toBuffer(),
|
|
734
800
|
],
|
|
735
801
|
PROGRAM_IDS.PUMP_AMM,
|
|
736
802
|
);
|
|
@@ -744,7 +810,15 @@ export class PumpTrader {
|
|
|
744
810
|
this.connection.getTokenAccountBalance(poolKeys.poolQuoteTokenAccount),
|
|
745
811
|
]);
|
|
746
812
|
|
|
747
|
-
|
|
813
|
+
let price = quoteInfo.value.uiAmount! / baseInfo.value.uiAmount!;
|
|
814
|
+
|
|
815
|
+
// If pool is not SOL-quoted, convert to SOL price
|
|
816
|
+
if (!quoteMint.equals(SOL_MINT)) {
|
|
817
|
+
const solPrice = await this.getSolPriceInUsdc();
|
|
818
|
+
price = price / solPrice;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
return price;
|
|
748
822
|
}
|
|
749
823
|
|
|
750
824
|
/* ---------- 余额查询 ---------- */
|
|
@@ -1681,7 +1755,16 @@ export class PumpTrader {
|
|
|
1681
1755
|
isWritable: true,
|
|
1682
1756
|
});
|
|
1683
1757
|
}
|
|
1684
|
-
|
|
1758
|
+
const POOL_DEFAULT_COIN_CREATOR = new PublicKey("11111111111111111111111111111111");
|
|
1759
|
+
if (poolKeys.coinCreator && !poolKeys.coinCreator.equals(POOL_DEFAULT_COIN_CREATOR)) {
|
|
1760
|
+
remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
|
|
1761
|
+
} else {
|
|
1762
|
+
remainingKeys.push({
|
|
1763
|
+
pubkey: PUMP_BUYBACK_FEE_RECIPIENTS[0],
|
|
1764
|
+
isSigner: false,
|
|
1765
|
+
isWritable: true,
|
|
1766
|
+
});
|
|
1767
|
+
}
|
|
1685
1768
|
remainingKeys.push(
|
|
1686
1769
|
{ pubkey: newFeeRecipient, isSigner: false, isWritable: false },
|
|
1687
1770
|
{
|
|
@@ -1826,7 +1909,16 @@ export class PumpTrader {
|
|
|
1826
1909
|
{ pubkey: userVolumeAccumulator, isSigner: false, isWritable: true },
|
|
1827
1910
|
);
|
|
1828
1911
|
}
|
|
1829
|
-
|
|
1912
|
+
const POOL_DEFAULT_COIN_CREATOR = new PublicKey("11111111111111111111111111111111");
|
|
1913
|
+
if (poolKeys.coinCreator && !poolKeys.coinCreator.equals(POOL_DEFAULT_COIN_CREATOR)) {
|
|
1914
|
+
remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
|
|
1915
|
+
} else {
|
|
1916
|
+
remainingKeys.push({
|
|
1917
|
+
pubkey: PUMP_BUYBACK_FEE_RECIPIENTS[0],
|
|
1918
|
+
isSigner: false,
|
|
1919
|
+
isWritable: true,
|
|
1920
|
+
});
|
|
1921
|
+
}
|
|
1830
1922
|
remainingKeys.push(
|
|
1831
1923
|
{ pubkey: newFeeRecipient, isSigner: false, isWritable: false },
|
|
1832
1924
|
{
|