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 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
- getPriceAndStatus(tokenAddr: string): Promise<{
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
- async getPriceAndStatus(tokenAddr) {
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 price = await this.getAmmPrice(mint);
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
- const solOut = this.calcSell(oneToken, state);
432
- const price = Number(solOut) / 1e9;
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
- SOL_MINT.toBuffer(),
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
- return quoteInfo.value.uiAmount / baseInfo.value.uiAmount;
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
- remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
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
- remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
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 getPriceAndStatus(tokenAddr) {
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 price = await this.getAmmPrice(mint);
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
- const solOut = this.calcSell(oneToken, state);
506
- const price = Number(solOut) / 1e9;
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
- SOL_MINT.toBuffer(),
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
- return quoteInfo.value.uiAmount / baseInfo.value.uiAmount;
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
- remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
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 price = await this.getAmmPrice(mint);
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
- const solOut = this.calcSell(oneToken, state);
716
- const price = Number(solOut) / 1e9;
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
- SOL_MINT.toBuffer(),
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
- return quoteInfo.value.uiAmount! / baseInfo.value.uiAmount!;
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
- remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
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
- remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
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
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pump-trader",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "PumpFun 交易库 - 自动判断 Token Program 和内盘/外盘",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",