diff --git a/.changeset/marketdata.md b/.changeset/marketdata.md new file mode 100644 index 0000000..6c58c09 --- /dev/null +++ b/.changeset/marketdata.md @@ -0,0 +1,5 @@ +--- +'@degenfrends/solana-rugchecker': patch +--- + +## @degenfrends/solana-rugchecker: Initial version diff --git a/README.md b/README.md index 641db9b..aa690cb 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,9 @@ from https://api.raydium.io/v2/sdk/liquidity/mainnet.json and set the path of th ```typescript const rugCheckConfig = { solanaRpcEndpoint: 'https://api.devnet.solana.com' - poolFilePath: './mainnet.json' + poolFilePath: './mainnet.json' //optional + poolAddress: '12345pooladdress' //optional, can't be set with environment variable, since it most likely changes on every check + heliusApiKey: 'your-api-key' //optional }; const rugChecker = new SPLRugchecker(rugCheckConfig); ``` diff --git a/index.js b/index.js index 0a6c664..cfba393 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,7 @@ const WebsiteChecker = require('./dist/index.js').WebsiteChecker; async function main() { const rugCheckConfig = { solanaRpcEndpoint: 'https://solana-mainnet.rpc.extrnode.com/036e028d-7094-4f3d-876e-956d6e56f0ff', - heliusApiKey: '123456' + heliusApiKey: '123456-your-api-key' //poolFilePath: './all_pools.json' }; const rugChecker = new SPLRugchecker(rugCheckConfig); diff --git a/src/checker/holders-checker.ts b/src/checker/holders-checker.ts index ef1cd7d..ff97881 100644 --- a/src/checker/holders-checker.ts +++ b/src/checker/holders-checker.ts @@ -52,7 +52,7 @@ export default class HoldersChecker { holdersCheckResult.topHolders = topHolders; holdersCheckResult.topHoldersPercentage = topHoldersPercentage; holdersCheckResult.raydiumPercentage = raydiumPercentage; - + holdersCheckResult.address = tokenAddress; return holdersCheckResult; } } diff --git a/src/checker/liquidity-checker.ts b/src/checker/liquidity-checker.ts index 1baafe6..369ddaf 100644 --- a/src/checker/liquidity-checker.ts +++ b/src/checker/liquidity-checker.ts @@ -59,7 +59,7 @@ export default class LiquidityChecker { liquidityCheckResult.isLiquidityLocked = burnPct > 95; liquidityCheckResult.burnt = burnPct; liquidityCheckResult.liquidityPoolAddress = poolAddress; - + liquidityCheckResult.address = tokenAddress; return liquidityCheckResult; } diff --git a/src/checker/marketdata-checker.ts b/src/checker/marketdata-checker.ts new file mode 100644 index 0000000..5698af6 --- /dev/null +++ b/src/checker/marketdata-checker.ts @@ -0,0 +1,45 @@ +import { config } from 'dotenv'; +import axios from 'axios'; +import MarketdataCheckConfig from '../model/config/marketdata-check'; +import MarketdataCheckResult from '../model/result/marketdata-check'; + +config(); + +export default class MarketdataChecker { + constructor({}: MarketdataCheckConfig) {} + + async check(tokenAddress: string): Promise { + const marketdataResponse = await axios.get('https://api.dexscreener.com/latest/dex/tokens/' + tokenAddress, { + timeout: 300000, + responseType: 'json' + }); + let marketdataResult = this.createMarketdataCheckResult(marketdataResponse.data.pairs[0]); + marketdataResult.address = tokenAddress; + return marketdataResult; + } + + private createMarketdataCheckResult(marketdata: any): MarketdataCheckResult { + const metadataCheckResult = new MarketdataCheckResult(); + metadataCheckResult.priceSol = marketdata.priceNative; + metadataCheckResult.priceUsd = marketdata.priceUsd; + metadataCheckResult.liquidityUsd = marketdata.liquidity.usd; + metadataCheckResult.fdv = marketdata.fdv; + metadataCheckResult.volume24h = marketdata.volume.h24; + metadataCheckResult.volume6h = marketdata.volume.h6; + metadataCheckResult.volume1h = marketdata.volume.h1; + metadataCheckResult.volume5m = marketdata.volume.m5; + metadataCheckResult.priceChange24h = marketdata.priceChange.h24; + metadataCheckResult.priceChange6h = marketdata.priceChange.h6; + metadataCheckResult.priceChange1h = marketdata.priceChange.h1; + metadataCheckResult.priceChange5m = marketdata.priceChange.m5; + metadataCheckResult.buys24h = marketdata.txns.h24.buys; + metadataCheckResult.buys6h = marketdata.txns.h6.buys; + metadataCheckResult.buys1h = marketdata.txns.h1.buys; + metadataCheckResult.buys5m = marketdata.txns.m5.buys; + metadataCheckResult.sells24h = marketdata.txns.h24.sells; + metadataCheckResult.sells6h = marketdata.txns.h6.sells; + metadataCheckResult.sells1h = marketdata.txns.h1.sells; + metadataCheckResult.sells5m = marketdata.txns.m5.sells; + return metadataCheckResult; + } +} diff --git a/src/checker/metadata-checker.ts b/src/checker/metadata-checker.ts index 1026935..bf3783e 100644 --- a/src/checker/metadata-checker.ts +++ b/src/checker/metadata-checker.ts @@ -23,7 +23,7 @@ export default class MetadataChecker { } this.connection = connection; if (!metaplex) { - metaplex = Metaplex.make(connection); + metaplex = Metaplex.make(this.connection); } this.metaplex = metaplex; if (heliusApiKey) { @@ -45,6 +45,7 @@ export default class MetadataChecker { ) { metadataCheckResult = await this.getHeliusMetadata(tokenAddress, metadataCheckResult); } + metadataCheckResult.address = tokenAddress; return metadataCheckResult; } diff --git a/src/index.ts b/src/index.ts index fe590bf..f37672d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,10 +7,13 @@ import WebsiteChecker from './checker/website-checker'; import MetadataCheckConfig from './model/config/metadata-check'; import HoldersCheckConfig from './model/config/holders-check'; import LiquidityCheckConfig from './model/config/liquidity-check'; +import MarketdataChecker from './checker/marketdata-checker'; +import MarketdataCheckConfig from './model/config/marketdata-check'; export default class SPLRugchecker { private holdersChecker: HoldersChecker; private liquidityChecker: LiquidityChecker; private metadataChecker: MetadataChecker; + private marketdataChecker: MarketdataChecker; public constructor({ solanaRpcEndpoint, poolFilePath, poolAddress, heliusApiKey }: RugCheckConfig) { const metadataCheckConfig = { solanaRpcEndpoint: solanaRpcEndpoint, heliusApiKey: heliusApiKey }; @@ -19,20 +22,23 @@ export default class SPLRugchecker { this.holdersChecker = new HoldersChecker(holdersCheckConfig); const liquidityCheckConfig = { solanaRpcEndpoint: solanaRpcEndpoint, poolFilePath: poolFilePath, poolAddress: poolAddress }; this.liquidityChecker = new LiquidityChecker(liquidityCheckConfig); + const marketdataCheckConfig = {}; + this.marketdataChecker = new MarketdataChecker(marketdataCheckConfig); } async check(tokenAddress: string): Promise { - const [metadataCheckResult, holdersCheckResult, liquidityCheckResult] = await Promise.all([ + const [metadataCheckResult, holdersCheckResult, liquidityCheckResult, marketdataCheckResult] = await Promise.all([ this.metadataChecker.check(tokenAddress), this.holdersChecker.check(tokenAddress), - this.liquidityChecker.check(tokenAddress) + this.liquidityChecker.check(tokenAddress), + this.marketdataChecker.check(tokenAddress) ]); const rugCheckResult = new RugCheckResult(); rugCheckResult.metadata = metadataCheckResult; rugCheckResult.holders = holdersCheckResult; rugCheckResult.liquidity = liquidityCheckResult; - + rugCheckResult.marketdata = marketdataCheckResult; return rugCheckResult; } @@ -89,8 +95,10 @@ export { WebsiteChecker }; export { MetadataChecker }; export { HoldersChecker }; export { LiquidityChecker }; +export { MarketdataChecker }; export { RugCheckConfig }; export { MetadataCheckConfig }; export { LiquidityCheckConfig }; export { HoldersCheckConfig }; +export { MarketdataCheckConfig }; diff --git a/src/model/config/marketdata-check.ts b/src/model/config/marketdata-check.ts new file mode 100644 index 0000000..8343492 --- /dev/null +++ b/src/model/config/marketdata-check.ts @@ -0,0 +1 @@ +export default class MarketdataCheckConfig {} diff --git a/src/model/result/holders-check.ts b/src/model/result/holders-check.ts index e8c7d4b..ed64572 100644 --- a/src/model/result/holders-check.ts +++ b/src/model/result/holders-check.ts @@ -1,6 +1,7 @@ import HolderCheckResult from './holder-check'; export default class HoldersCheckResult { + address: string; topHolders: HolderCheckResult[]; topHoldersPercentage: number; raydiumPercentage: number; diff --git a/src/model/result/liquidity-check.ts b/src/model/result/liquidity-check.ts index 2ea6d3c..e100b0b 100644 --- a/src/model/result/liquidity-check.ts +++ b/src/model/result/liquidity-check.ts @@ -1,4 +1,5 @@ export default class LiquidityCheckResult { + address: string; isLiquidityLocked: boolean; burnt: number; liquidityPoolAddress: string; diff --git a/src/model/result/marketdata-check.ts b/src/model/result/marketdata-check.ts new file mode 100644 index 0000000..78b3fed --- /dev/null +++ b/src/model/result/marketdata-check.ts @@ -0,0 +1,23 @@ +export default class MarketdataCheckResult { + address: string; + priceSol: number; + priceUsd: number; + liquidityUsd: number; + fdv: number; + volume24h: number; + volume6h: number; + volume1h: number; + volume5m: number; + priceChange24h: number; + priceChange6h: number; + priceChange1h: number; + priceChange5m: number; + buys24h: number; + buys6h: number; + buys1h: number; + buys5m: number; + sells24h: number; + sells6h: number; + sells1h: number; + sells5m: number; +} diff --git a/src/model/result/rug-check.ts b/src/model/result/rug-check.ts index 882cac9..0176344 100644 --- a/src/model/result/rug-check.ts +++ b/src/model/result/rug-check.ts @@ -1,9 +1,12 @@ import HoldersCheckResult from './holders-check'; import LiquidityCheckResult from './liquidity-check'; +import MarketdataCheckResult from './marketdata-check'; import MetadataCheckResult from './metadata-check'; export default class RugCheckResult { + address: string; metadata: MetadataCheckResult; holders: HoldersCheckResult; liquidity: LiquidityCheckResult; + marketdata: MarketdataCheckResult; }