├── src ├── Token │ ├── query.js │ ├── revoke_authority.js │ └── burn.js ├── Pool │ ├── check_pool.js │ ├── create_pool.js │ ├── formatAmmKeysById.js │ ├── remove_pool.js │ ├── add_pool.js │ ├── query_pool.js │ └── swap.js ├── helpers │ ├── constant.js │ ├── .env.copy │ ├── config.js │ ├── check_balance.js │ └── util.js ├── Trading │ ├── dex │ │ ├── Serum │ │ │ └── index.js │ │ ├── jupiter │ │ │ ├── dca.js │ │ │ ├── swap.js │ │ │ ├── limit_order.js │ │ │ └── swap │ │ │ │ ├── buy-helper.js │ │ │ │ ├── sell-helper.js │ │ │ │ └── swap-helper.js │ │ ├── meteora │ │ │ └── index.js │ │ ├── raydium │ │ │ ├── sell_helper.js │ │ │ ├── buy_helper.js │ │ │ ├── buy.js │ │ │ └── sell.js │ │ └── orca │ │ │ └── index.js │ ├── memecoin_trading_strategies │ │ ├── stop-loss.js │ │ ├── take-profit.js │ │ └── copy_trading │ │ │ ├── bought-tokens.json │ │ │ ├── copy-trade.js │ │ │ ├── copy-sell.js │ │ │ └── copy-buy.js │ └── volume │ │ └── boost_volume.js ├── pumpfunsdk │ ├── pump-keypair │ │ └── yourtoken.json │ └── pumpdotfun-sdk │ │ ├── .npmignore │ │ ├── src │ │ ├── WalletKeypairs │ │ │ ├── sniperKeys.csv │ │ │ └── privateKeys.json │ │ ├── IDL │ │ │ └── index.js │ │ ├── index.js │ │ ├── buy.js │ │ ├── sell.js │ │ ├── events.js │ │ ├── pump-events-listener │ │ │ └── listeners.js │ │ ├── types.js │ │ ├── globalAccount.js │ │ ├── createAndBuy.js │ │ ├── amm.js │ │ ├── bondingCurveAccount.js │ │ ├── transactions │ │ │ └── jito-tx-executor.js │ │ ├── tools.js │ │ └── pumpfun.js │ │ ├── images │ │ ├── 999.jpg │ │ └── download.jpeg │ │ ├── example │ │ ├── basic │ │ │ ├── 999.jpg │ │ │ └── index.ts │ │ ├── events │ │ │ └── index.ts │ │ └── util.js │ │ └── .gitignore ├── Transactions │ ├── bloXroute_tips_tx_executor.js │ ├── simple_tx_executor.js │ └── jito_tips_tx_executor.js ├── .DS_Store └── zk-compression │ ├── connect-testnet.js │ └── compressed-token │ └── createAndMint.js ├── data ├── payer_keypair │ ├── mainnet │ │ ├── test1_wallet.json │ │ ├── test_wallet.json │ │ └── .DS_Store │ ├── .DS_Store │ └── devnet │ │ └── .DS_Store ├── .DS_Store ├── Image_file │ └── FTW.jpeg ├── token_keypair │ ├── .DS_Store │ └── devnet │ │ └── .DS_Store └── metadata_file │ └── metadata.json ├── examples ├── buy_token │ ├── buy_help.txt │ ├── expected_output1.0.jpeg │ ├── expected_output1.1.jpeg │ ├── expected_output2.0.jpeg │ ├── expected_output2.1.jpeg │ └── buy_doc.txt ├── burn_token │ ├── burn_help.txt │ ├── expected_output1.jpg │ ├── expected_output2.jpg │ ├── ._expected_output1.jpg │ └── burn_doc.txt ├── sell_token │ ├── sell_help.txt │ ├── expected_output1.0.jpeg │ ├── expected_output1.1.jpeg │ ├── expected_output2.0.jpeg │ ├── expected_output2.1.jpeg │ └── sell_doc.txt ├── create_token │ ├── create_help.txt │ ├── expected_output1.jpg │ ├── expected_output2.jpg │ ├── ._expected_output1.jpg │ ├── ._expected_output2.jpg │ └── create_doc.txt ├── add_liquidity │ ├── add_liq_help.txt │ ├── expected_output1.0.jpeg │ ├── expected_output1.1.jpeg │ ├── expected_output2.0.jpeg │ ├── expected_output2.1.jpeg │ └── add_liq_doc.txt ├── remove_liquidity │ ├── remove_liq_help.txt │ ├── expected_output1.0.jpeg │ ├── expected_output1.1.jpeg │ ├── expected_output2.0.jpeg │ ├── expected_output2.1.jpeg │ ├── expected_output2.2.jpeg │ └── remove_liq_doc.txt ├── boost_volume │ ├── help.txt │ └── doc.txt ├── pump_buy │ ├── help.txt │ ├── expected_output.png │ └── doc.txt ├── pump_sell │ ├── help.txt │ ├── expected_output.png │ └── doc.txt ├── pump_createAndInitialBuy │ ├── help.txt │ ├── expected_output.png │ └── doc.txt └── zk_compressed_token │ ├── expected-output.png │ ├── npm-install-cli.png │ ├── cargo-install-photon.png │ ├── run-local-zk-validator.png │ └── doc.txt ├── .DS_Store ├── _config.yml ├── help.js ├── .github └── FUNDING.yml ├── LICENSE ├── package.json ├── CLI_Doc.txt └── .gitignore /src/Token/query.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Pool/check_pool.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/helpers/constant.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Pool/create_pool.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/Trading/dex/Serum/index.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Trading/dex/jupiter/dca.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Trading/dex/jupiter/swap.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Trading/dex/meteora/index.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Trading/dex/jupiter/limit_order.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pump-keypair/yourtoken.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Transactions/bloXroute_tips_tx_executor.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/.npmignore: -------------------------------------------------------------------------------- 1 | example/ -------------------------------------------------------------------------------- /data/payer_keypair/mainnet/test1_wallet.json: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/Trading/memecoin_trading_strategies/stop-loss.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Trading/memecoin_trading_strategies/take-profit.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/payer_keypair/mainnet/test_wallet.json: -------------------------------------------------------------------------------- 1 | [1, 2, 3, 4, 5] 2 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/WalletKeypairs/sniperKeys.csv: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/buy_token/buy_help.txt: -------------------------------------------------------------------------------- 1 | run 2 | node buy -h 3 | or 4 | node buy --help -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/WalletKeypairs/privateKeys.json: -------------------------------------------------------------------------------- 1 | [ 2 | 3 | ] -------------------------------------------------------------------------------- /examples/burn_token/burn_help.txt: -------------------------------------------------------------------------------- 1 | run 2 | node burn -h 3 | or 4 | node burn --help -------------------------------------------------------------------------------- /examples/sell_token/sell_help.txt: -------------------------------------------------------------------------------- 1 | run 2 | node sell -h 3 | or 4 | node sell --help -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/.DS_Store -------------------------------------------------------------------------------- /examples/create_token/create_help.txt: -------------------------------------------------------------------------------- 1 | run 2 | node create -h 3 | or 4 | node create --help -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/src/.DS_Store -------------------------------------------------------------------------------- /data/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/data/.DS_Store -------------------------------------------------------------------------------- /examples/add_liquidity/add_liq_help.txt: -------------------------------------------------------------------------------- 1 | run 2 | node add_pool --help 3 | or 4 | node add_pool -h -------------------------------------------------------------------------------- /examples/remove_liquidity/remove_liq_help.txt: -------------------------------------------------------------------------------- 1 | run 2 | node remove_pool --help 3 | or 4 | node remove_pool -h -------------------------------------------------------------------------------- /data/Image_file/FTW.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/data/Image_file/FTW.jpeg -------------------------------------------------------------------------------- /data/payer_keypair/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/data/payer_keypair/.DS_Store -------------------------------------------------------------------------------- /data/token_keypair/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/data/token_keypair/.DS_Store -------------------------------------------------------------------------------- /examples/boost_volume/help.txt: -------------------------------------------------------------------------------- 1 | run 2 | node /Users/chiwangso/Desktop/solana-memecoin-cli/src/Trading/volume/boost_volume.js -h -------------------------------------------------------------------------------- /data/metadata_file/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FuCK The WorLd", 3 | "symbol": "FTW", 4 | "description": "you mfers." 5 | } 6 | -------------------------------------------------------------------------------- /examples/pump_buy/help.txt: -------------------------------------------------------------------------------- 1 | run 2 | node /Users/chiwangso/Desktop/solana-memecoin-cli/src/pumpfunsdk-js/pumpdotfun-sdk/src/buy.js -h -------------------------------------------------------------------------------- /examples/pump_sell/help.txt: -------------------------------------------------------------------------------- 1 | run 2 | node /Users/chiwangso/Desktop/solana-memecoin-cli/src/pumpfunsdk-js/pumpdotfun-sdk/src/sell.js -h -------------------------------------------------------------------------------- /src/Trading/memecoin_trading_strategies/copy_trading/bought-tokens.json: -------------------------------------------------------------------------------- 1 | [ 2 | "9UNqoPEXXxEnEphmyYsZYdL5dnmAUtdiKRUchpnUF5Ph" 3 | ] -------------------------------------------------------------------------------- /data/payer_keypair/devnet/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/data/payer_keypair/devnet/.DS_Store -------------------------------------------------------------------------------- /data/token_keypair/devnet/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/data/token_keypair/devnet/.DS_Store -------------------------------------------------------------------------------- /data/payer_keypair/mainnet/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/data/payer_keypair/mainnet/.DS_Store -------------------------------------------------------------------------------- /examples/pump_buy/expected_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/pump_buy/expected_output.png -------------------------------------------------------------------------------- /examples/pump_sell/expected_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/pump_sell/expected_output.png -------------------------------------------------------------------------------- /examples/burn_token/expected_output1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/burn_token/expected_output1.jpg -------------------------------------------------------------------------------- /examples/burn_token/expected_output2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/burn_token/expected_output2.jpg -------------------------------------------------------------------------------- /examples/burn_token/._expected_output1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/burn_token/._expected_output1.jpg -------------------------------------------------------------------------------- /examples/buy_token/expected_output1.0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/buy_token/expected_output1.0.jpeg -------------------------------------------------------------------------------- /examples/buy_token/expected_output1.1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/buy_token/expected_output1.1.jpeg -------------------------------------------------------------------------------- /examples/buy_token/expected_output2.0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/buy_token/expected_output2.0.jpeg -------------------------------------------------------------------------------- /examples/buy_token/expected_output2.1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/buy_token/expected_output2.1.jpeg -------------------------------------------------------------------------------- /examples/create_token/expected_output1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/create_token/expected_output1.jpg -------------------------------------------------------------------------------- /examples/create_token/expected_output2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/create_token/expected_output2.jpg -------------------------------------------------------------------------------- /examples/sell_token/expected_output1.0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/sell_token/expected_output1.0.jpeg -------------------------------------------------------------------------------- /examples/sell_token/expected_output1.1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/sell_token/expected_output1.1.jpeg -------------------------------------------------------------------------------- /examples/sell_token/expected_output2.0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/sell_token/expected_output2.0.jpeg -------------------------------------------------------------------------------- /examples/sell_token/expected_output2.1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/sell_token/expected_output2.1.jpeg -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | remote_theme: pages-themes/cayman@v0.2.0 2 | plugins: 3 | - jekyll-remote-theme # add this line to the plugins list if you already have one 4 | -------------------------------------------------------------------------------- /examples/create_token/._expected_output1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/create_token/._expected_output1.jpg -------------------------------------------------------------------------------- /examples/create_token/._expected_output2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/create_token/._expected_output2.jpg -------------------------------------------------------------------------------- /examples/pump_createAndInitialBuy/help.txt: -------------------------------------------------------------------------------- 1 | run 2 | node /Users/chiwangso/Desktop/solana-memecoin-cli/src/pumpfunsdk-js/pumpdotfun-sdk/src/createAndBuy.js -h -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/images/999.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/src/pumpfunsdk/pumpdotfun-sdk/images/999.jpg -------------------------------------------------------------------------------- /examples/add_liquidity/expected_output1.0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/add_liquidity/expected_output1.0.jpeg -------------------------------------------------------------------------------- /examples/add_liquidity/expected_output1.1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/add_liquidity/expected_output1.1.jpeg -------------------------------------------------------------------------------- /examples/add_liquidity/expected_output2.0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/add_liquidity/expected_output2.0.jpeg -------------------------------------------------------------------------------- /examples/add_liquidity/expected_output2.1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/add_liquidity/expected_output2.1.jpeg -------------------------------------------------------------------------------- /examples/zk_compressed_token/expected-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/zk_compressed_token/expected-output.png -------------------------------------------------------------------------------- /examples/zk_compressed_token/npm-install-cli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/zk_compressed_token/npm-install-cli.png -------------------------------------------------------------------------------- /examples/remove_liquidity/expected_output1.0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/remove_liquidity/expected_output1.0.jpeg -------------------------------------------------------------------------------- /examples/remove_liquidity/expected_output1.1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/remove_liquidity/expected_output1.1.jpeg -------------------------------------------------------------------------------- /examples/remove_liquidity/expected_output2.0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/remove_liquidity/expected_output2.0.jpeg -------------------------------------------------------------------------------- /examples/remove_liquidity/expected_output2.1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/remove_liquidity/expected_output2.1.jpeg -------------------------------------------------------------------------------- /examples/remove_liquidity/expected_output2.2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/remove_liquidity/expected_output2.2.jpeg -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/images/download.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/src/pumpfunsdk/pumpdotfun-sdk/images/download.jpeg -------------------------------------------------------------------------------- /examples/pump_createAndInitialBuy/expected_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/pump_createAndInitialBuy/expected_output.png -------------------------------------------------------------------------------- /examples/zk_compressed_token/cargo-install-photon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/zk_compressed_token/cargo-install-photon.png -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/example/basic/999.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/src/pumpfunsdk/pumpdotfun-sdk/example/basic/999.jpg -------------------------------------------------------------------------------- /examples/zk_compressed_token/run-local-zk-validator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earthskyorg/Solana-Memecoin-CLI/HEAD/examples/zk_compressed_token/run-local-zk-validator.png -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/.gitignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | **/*.rs.bk 5 | node_modules 6 | test-ledger 7 | .yarn 8 | 9 | dist/ 10 | 11 | .keys*/ 12 | .keys*/** 13 | 14 | .env 15 | refs/ -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/IDL/index.js: -------------------------------------------------------------------------------- 1 | // pump-fun.json should be a valid JSON file 2 | const IDL = require("./pump-fun.json"); 3 | const { PumpFun } = require("./pump-fun"); 4 | module.exports = { PumpFun, IDL }; -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/index.js: -------------------------------------------------------------------------------- 1 | // export * from './pumpfun' 2 | // export * from './util' 3 | // export * from './types' 4 | // export * from './events' 5 | // export * from './globalAccount' 6 | // export * from './bondingCurveAccount' 7 | // export * from './amm' 8 | 9 | -------------------------------------------------------------------------------- /examples/boost_volume/doc.txt: -------------------------------------------------------------------------------- 1 | # if you already fill in your private key to src/helpers/.env.copy, 2 | # rename it to .env 3 | 4 | - support only mainnet right now 5 | 6 | example 1: (already set up ur secret key) 7 | node boost_volume --token_address --cluster mainnet --sol_per_order 0.01 -------------------------------------------------------------------------------- /help.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | // Read the contents of the file 4 | fs.readFile("./CLI_Doc.txt", "utf8", (error, data) => { 5 | if (error) { 6 | console.error("❌ Error reading the help file"); 7 | process.exit(1); 8 | } 9 | 10 | console.log(data); // Display the contents of the file 11 | }); 12 | -------------------------------------------------------------------------------- /examples/zk_compressed_token/doc.txt: -------------------------------------------------------------------------------- 1 | make sure you already install 2 | 1. npm install -g @lightprotocol/zk-compression-cli 3 | 2. cargo install photon-indexer --version 0.30.0 --locked 4 | 5 | And simply run 6 | 1. light test-validator 7 | 2. node /Users/{your_user_name}/Desktop/solana-memecoin-cli/src/zk-compression/compressed-token/createAndMint.js -------------------------------------------------------------------------------- /examples/pump_buy/doc.txt: -------------------------------------------------------------------------------- 1 | # if you already fill in your private key to src/helpers/.env.copy, 2 | # rename it to .env 3 | 4 | - support only mainnet right now 5 | 6 | example 1: (already set up ur secret key) 7 | node /Users/chiwangso/Desktop/solana-memecoin-cli/src/pumpfunsdk-js/pumpdotfun-sdk/src/buy.js --token_address wdyfVw7jshftRVsevhPzsNCT2jZJ6p3mFgDsv6Zpump --sol 0.01 -------------------------------------------------------------------------------- /examples/pump_sell/doc.txt: -------------------------------------------------------------------------------- 1 | # if you already fill in your private key to src/helpers/.env.copy, 2 | # rename it to .env 3 | 4 | - support only mainnet right now 5 | 6 | example 1: (already set up ur secret key) 7 | node /Users/chiwangso/Desktop/solana-memecoin-cli/src/pumpfunsdk-js/pumpdotfun-sdk/src/sell.js --token_address wdyfVw7jshftRVsevhPzsNCT2jZJ6p3mFgDsv6Zpump --percentage 100 -------------------------------------------------------------------------------- /examples/pump_createAndInitialBuy/doc.txt: -------------------------------------------------------------------------------- 1 | # if you already fill in your private key to src/helpers/.env.copy, 2 | # rename it to .env 3 | 4 | - support only mainnet right now 5 | 6 | example 1: (already set up ur secret key) 7 | node /Users/chiwangso/Desktop/solana-memecoin-cli/src/pumpfunsdk-js/pumpdotfun-sdk/src/createAndBuy.js --pathToMintKeypair /Users/chiwangso/Desktop/solana-memecoin-cli/src/pumpfunsdk-js/pump-keypair/aNJh1sNPsX1TAPxiqhZxYBkzseuRJZxPpBEcjDBpYnL.json --sol 0.01 --name juiceWrld --symbol JW --description iWillChangeTheWorld --file /Users/chiwangso/Desktop/solana-memecoin-cli/src/pumpfunsdk-js/pumpdotfun-sdk/images/999.jpg 8 | -------------------------------------------------------------------------------- /examples/add_liquidity/add_liq_doc.txt: -------------------------------------------------------------------------------- 1 | # if you already fill in your private key to src/helpers/.env.copy, 2 | # rename it to .env 3 | 4 | - support only mainnet right now 5 | - make sure you are at src/Pool 6 | - cd src/Pool 7 | 8 | example 1: (already set up ur secret key) 9 | node add_pool --token_address kaicqYEgwrSk1GNqiNMcYJVf242YAaaMCmAT6eDjqjW --sol 0.01 --cluster mainnet 10 | 11 | example 2: (use another wallet, in data/payer_keypair/mainnet) (make sure the secret key is in uint8 array format) 12 | node add_pool --payer /Users/{your_user_name}/Desktop/Solana-Memecoin-CLI/data/payer_keypair/mainnet/payer0.json --token_address kaicqYEgwrSk1GNqiNMcYJVf242YAaaMCmAT6eDjqjW --sol 0.01 --cluster mainnet 13 | -------------------------------------------------------------------------------- /examples/buy_token/buy_doc.txt: -------------------------------------------------------------------------------- 1 | # if you already fill in your private key to src/helpers/.env.copy, 2 | # rename it to .env 3 | 4 | - support only mainnet right now 5 | - make sure you are at src/Trading/dex/raydium 6 | - cd src/Trading/dex/raydium 7 | 8 | example 1: (already set up ur secret key) 9 | node buy --token_address EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm --sol 0.001 --cluster mainnet 10 | 11 | example 2: (use another wallet, in data/payer_keypair/mainnet) (make sure the secret key is in uint8 array format) 12 | node buy --token_address EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm --sol 0.001 --cluster mainnet --payer /Users/{your_user_name}/Desktop/Solana-Memecoin-CLI/data/payer_keypair/mainnet/payer0.json -------------------------------------------------------------------------------- /examples/remove_liquidity/remove_liq_doc.txt: -------------------------------------------------------------------------------- 1 | # if you already fill in your private key to src/helpers/.env.copy, 2 | # rename it to .env 3 | 4 | - support only mainnet right now 5 | - make sure you are at src/Pool 6 | - cd src/Pool 7 | 8 | example 1: (already set up ur secret key) 9 | node remove_pool --token_address kaicqYEgwrSk1GNqiNMcYJVf242YAaaMCmAT6eDjqjW --percentage 0.1 --cluster mainnet 10 | 11 | example 2: (use another wallet, in data/payer_keypair/mainnet) (make sure the secret key is in uint8 array format) 12 | node remove_pool --token_address kaicqYEgwrSk1GNqiNMcYJVf242YAaaMCmAT6eDjqjW --percentage 0.1 --cluster mainnet --payer /Users/{your_user_name}/Desktop/Solana-Memecoin-CLI/data/payer_keypair/mainnet/payer0.json -------------------------------------------------------------------------------- /examples/sell_token/sell_doc.txt: -------------------------------------------------------------------------------- 1 | # if you already fill in your private key to src/helpers/.env.copy, 2 | # rename it to .env 3 | 4 | - support only mainnet right now 5 | - make sure you are at src/Trading/dex/raydium 6 | - cd src/Trading/dex/raydium 7 | 8 | example 1: (already set up ur secret key) 9 | node sell --token_address kaicqYEgwrSk1GNqiNMcYJVf242YAaaMCmAT6eDjqjW --percentage 76 --cluster mainnet 10 | 11 | example 2: (use another wallet, in data/payer_keypair/mainnet) (make sure the secret key is in uint8 array format) 12 | node sell --token_address kaicqYEgwrSk1GNqiNMcYJVf242YAaaMCmAT6eDjqjW --percentage 76 --cluster mainnet --payer /Users/{your_user_name}/Desktop/Solana-Memecoin-CLI/data/payer_keypair/mainnet/payer0.json 13 | -------------------------------------------------------------------------------- /examples/burn_token/burn_doc.txt: -------------------------------------------------------------------------------- 1 | # if you already fill in your private key to src/helpers/.env.copy, 2 | # rename it to .env 3 | 4 | - support both devnet and mainnet right now 5 | - make sure you are at src/Token 6 | - cd src/Token 7 | - percentage = 55 => burning 55% of the token 8 | 9 | example 1: (already set up ur secret key) 10 | node burn --token_address --percentage --cluster 11 | 12 | example 2: (use another wallet, in data/payer_keypair/devnet) (make sure the secret key is in uint8 array format) 13 | node burn --payer /Users/{your_user_name}/Desktop/Solana-Memecoin-CLI/data/payer_keypair/devnet/payer.json --token_address --percentage --cluster 14 | 15 | -------------------------------------------------------------------------------- /src/helpers/.env.copy: -------------------------------------------------------------------------------- 1 | ## mainnet (comment the following if you want to switch to devnet) 2 | PRIVATE_KEY = YOUR_PRIVATE_KEY 3 | ## devnet (un-comment the following if you want to switch to devnet) 4 | #PRIVATE_KEY = YOUR_PRIVATE_KEY 5 | 6 | # recommend to use https://dev.helius.xyz/rpcs/my 7 | # or https://shyft.to/dashboard/overview 8 | DEVNET_ENDPOINT = "https://devnet-rpc.shyft.to?api_key=" 9 | MAINNET_ENDPOINT = "https://mainnet.helius-rpc.com/?api-key=" 10 | # please get the api key in https://shyft.to/dashboard/overview 11 | SHYFT_API_KEY = "" 12 | # recommend to use 0.00009 13 | # specify the fee for jito if you want to land your transaction faster 14 | JITO_FEE = "0.001" 15 | TAKE_PROFIT = 0.1 # sell when price up 10% 16 | STOP_LOST = 0.2 # sell when price down 20% -------------------------------------------------------------------------------- /src/Trading/memecoin_trading_strategies/copy_trading/copy-trade.js: -------------------------------------------------------------------------------- 1 | 2 | // use two cores to run the two functions 3 | // 1. copy_sell 4 | // 2. copy_buy 5 | const { fork } = require('child_process'); 6 | const path = require('path'); 7 | const copySellPath = path.join(__dirname, 'copy_sell.js'); 8 | const copyBuyPath = path.join(__dirname, 'copy_buy.js'); 9 | // Run copy_sell in a separate process 10 | const copySellingProcess = fork(copySellPath); 11 | 12 | // Run copy_buy in a separate process 13 | const copyBuyingProcess = fork(copyBuyPath); 14 | 15 | copyBuyingProcess.on('exit', (code) => { 16 | console.log('copy_buy process exited with code:', code); 17 | }); 18 | // Handle the exit event for each child process 19 | copySellingProcess.on('exit', (code) => { 20 | console.log('copy_sell process exited with code:', code); 21 | }); 22 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 15 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/buy.js: -------------------------------------------------------------------------------- 1 | const { PublicKey } = require("@solana/web3.js"); 2 | const {buy} = require("./tools"); 3 | const { program } = require("commander"); 4 | let token_address = null, sol = null; 5 | program 6 | .option("--token_address ", "Specify the token address") 7 | .option("--sol ", "Specify the number of SOL") 8 | .option("-h, --help", "display help for command") 9 | .action((options) => { 10 | if (options.help) { 11 | console.log( 12 | "node buy --token_address --sol " 13 | ); 14 | process.exit(0); 15 | } 16 | if (!options.token_address || !options.sol) { 17 | console.error("❌ Missing required options"); 18 | process.exit(1); 19 | } 20 | token_address = options.token_address; 21 | sol = options.sol; 22 | }); 23 | program.parse(); 24 | 25 | 26 | buy(new PublicKey(token_address), sol); 27 | 28 | -------------------------------------------------------------------------------- /src/Trading/dex/raydium/sell_helper.js: -------------------------------------------------------------------------------- 1 | const { swap } = require("../../../Pool/swap.js"); 2 | 3 | /** 4 | * Sells a specified percentage of a token. 5 | * @param {string} side - The side of the trade (buy or sell). 6 | * @param {string} address - The address of the token. 7 | * @param {number} sell_percentage - The percentage of the token to sell. 8 | * @param {string} payer - The payer of the transaction. 9 | * @returns {Promise} - A promise that resolves when the sell operation is complete. 10 | */ 11 | async function sell(side, address, sell_percentage, payer) { 12 | await swap(side, address, -1, sell_percentage, payer, "trade"); 13 | } 14 | async function get_sell_transaction(side, tokenAddr, payer_wallet) { 15 | const innerTransaction = await swap( 16 | side, 17 | tokenAddr, 18 | -1, 19 | 100, 20 | payer_wallet, 21 | "volume" 22 | ); 23 | return innerTransaction; 24 | } 25 | module.exports = { sell, get_sell_transaction }; 26 | -------------------------------------------------------------------------------- /src/zk-compression/connect-testnet.js: -------------------------------------------------------------------------------- 1 | const stateless = require("@lightprotocol/stateless.js"); 2 | const connection = stateless.createRpc( 3 | "https://zk-testnet.helius.dev:8899", // rpc 4 | "https://zk-testnet.helius.dev:8784", // zk compression rpc 5 | "https://zk-testnet.helius.dev:3001" // prover 6 | ); 7 | 8 | /** 9 | * Main function that retrieves various information from the Solana network. 10 | * @returns {Promise} A promise that resolves when the function completes. 11 | */ 12 | async function main() { 13 | let slot = await connection.getSlot(); 14 | console.log("Slot: ", slot); 15 | 16 | let health = await connection.getIndexerHealth(slot); 17 | console.log("health: ", health); 18 | 19 | let leaderSchedule = await connection.getLeaderSchedule(); 20 | console.log("Current leader schedule: ", leaderSchedule); 21 | 22 | let latestNonVotingSig = await connection.getLatestNonVotingSignatures(); 23 | console.log(latestNonVotingSig); 24 | } 25 | main(); 26 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/sell.js: -------------------------------------------------------------------------------- 1 | const {sell} = require('./tools'); 2 | const { PublicKey } = require("@solana/web3.js"); 3 | const { program } = require("commander"); 4 | let token_address = null, sellPercentage = null; 5 | program 6 | .option("--token_address ", "Specify the token address") 7 | .option("--percentage ", "Specify the percentage of token to sell") 8 | .option("-h, --help", "display help for command") 9 | .action((options) => { 10 | if (options.help) { 11 | console.log( 12 | "node sell --token_address --percentage " 13 | ); 14 | process.exit(0); 15 | } 16 | if (!options.token_address || !options.percentage) { 17 | console.error("❌ Missing required options"); 18 | process.exit(1); 19 | } 20 | token_address = options.token_address; 21 | sellPercentage = options.percentage; 22 | }); 23 | program.parse(); 24 | 25 | 26 | sell(new PublicKey(token_address), sellPercentage/100); -------------------------------------------------------------------------------- /src/Trading/dex/orca/index.js: -------------------------------------------------------------------------------- 1 | const { PublicKey } = require("@solana/web3.js"); 2 | const { AnchorProvider } = require("@coral-xyz/anchor"); 3 | const { DecimalUtil, Percentage } = require("@orca-so/common-sdk"); 4 | const { 5 | WhirlpoolContext, 6 | buildWhirlpoolClient, 7 | ORCA_WHIRLPOOL_PROGRAM_ID, 8 | PDAUtil, 9 | swapQuoteByInputToken, 10 | IGNORE_CACHE, 11 | } = require("@orca-so/whirlpools-sdk"); 12 | const Decimal = require("decimal.js"); 13 | const { 14 | connection, 15 | dev_connection, 16 | wallet, 17 | } = require("../../../helpers/config"); 18 | 19 | async function main() { 20 | const provider = new AnchorProvider(connection, wallet, { 21 | commitment: "confirmed", 22 | }); 23 | const ctx = WhirlpoolContext.withProvider( 24 | provider, 25 | ORCA_WHIRLPOOL_PROGRAM_ID 26 | ); 27 | const client = buildWhirlpoolClient(ctx); 28 | console.log("RPC endpoint: ", ctx.connection.rpcEndpoint); 29 | console.log("Wallet public key: ", ctx.wallet.publicKey.toString()); 30 | } 31 | 32 | main(); 33 | -------------------------------------------------------------------------------- /examples/create_token/create_doc.txt: -------------------------------------------------------------------------------- 1 | # if you already fill in your private key to src/helpers/.env.copy, 2 | # rename it to .env 3 | 4 | - support both devnet and mainnet right now 5 | - make sure you are at src/Token 6 | - cd src/Token 7 | 8 | example 1: (already set up ur secret key) 9 | node create --symbol wif --token_name dogwifhat --supply 69696969 --decimals 9 --metadata /Users/{your_user_name}/Desktop/Solana-Memecoin-CLI/data/metadata_file/metadata.json 10 | --image /Users/{your_user_name}/Desktop/Solana-Memecoin-CLI/data/Image_file/FTW.jpeg --cluster devnet --file_type jpeg 11 | 12 | example 2: (use another wallet, in data/payer_keypair/devnet) (make sure the secret key is in uint8 array format) 13 | node create --payer /Users/{your_user_name}/Desktop/Solana-Memecoin-CLI/data/payer_keypair/devnet/wallet.json --symbol wif --token_name dogwifhat --supply 69696969 --decimals 9 --metadata /Users/{your_user_name}/Desktop/Solana-Memecoin-CLI/data/metadata_file/metadata.json --image /Users/{your_user_name}/Desktop/Solana-Memecoin-CLI/data/Image_file/FTW.jpeg --cluster devnet 14 | -------------------------------------------------------------------------------- /src/Trading/dex/raydium/buy_helper.js: -------------------------------------------------------------------------------- 1 | const { Keypair } = require("@solana/web3.js"); 2 | const { swap } = require("../../../Pool/swap.js"); 3 | /** 4 | * Buys a specified amount of a token using a amount of sol. 5 | * 6 | * @param {string} side - The side of the trade (buy/sell). 7 | * @param {string} address - The address of the token. 8 | * @param {number} no_of_sol - The number of SOL to be used for the trade. 9 | * @param {Keypair} payer - The payer of the transaction. 10 | * @returns {Promise} - A promise that resolves when the trade is completed. 11 | */ 12 | async function buy(side, address, no_of_sol, payer) { 13 | await swap(side, address, no_of_sol, -1, payer, "trade"); 14 | } 15 | 16 | async function get_buy_transaction( 17 | side, 18 | tokenAddr, 19 | buy_AmountOfSol, 20 | payer_wallet 21 | ) { 22 | const innerTransaction = await swap( 23 | side, 24 | tokenAddr, 25 | buy_AmountOfSol, 26 | -1, 27 | payer_wallet, 28 | "volume" 29 | ); 30 | return innerTransaction; 31 | } 32 | 33 | module.exports = { buy, get_buy_transaction }; 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 EarthSkyOrg 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/example/events/index.ts: -------------------------------------------------------------------------------- 1 | import dotenv from "dotenv"; 2 | import { Connection, Keypair } from "@solana/web3.js"; 3 | import { PumpFunSDK } from "../../src"; 4 | import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet"; 5 | import { AnchorProvider } from "@coral-xyz/anchor"; 6 | 7 | const main = async () => { 8 | dotenv.config(); 9 | 10 | if (!process.env.HELIUS_RPC_URL) { 11 | console.error("Please set HELIUS_RPC_URL in .env file"); 12 | console.error( 13 | "Example: HELIUS_RPC_URL=https://mainnet.helius-rpc.com/?api-key=" 14 | ); 15 | console.error("Get one at: https://www.helius.dev"); 16 | return; 17 | } 18 | 19 | let connection = new Connection(process.env.HELIUS_RPC_URL || ""); 20 | 21 | let wallet = new NodeWallet(new Keypair()); //note this is not used 22 | const provider = new AnchorProvider(connection, wallet, { 23 | commitment: "finalized", 24 | }); 25 | 26 | let sdk = new PumpFunSDK(provider); 27 | 28 | let createEvent = sdk.addEventListener("createEvent", (event) => { 29 | console.log("createEvent", event); 30 | }); 31 | console.log("createEvent", createEvent); 32 | 33 | let tradeEvent = sdk.addEventListener("tradeEvent", (event) => { 34 | console.log("tradeEvent", event); 35 | }); 36 | console.log("tradeEvent", tradeEvent); 37 | 38 | let completeEvent = sdk.addEventListener("completeEvent", (event) => { 39 | console.log("completeEvent", event); 40 | }); 41 | console.log("completeEvent", completeEvent); 42 | }; 43 | 44 | main(); 45 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/events.js: -------------------------------------------------------------------------------- 1 | const { PublicKey } =require ("@solana/web3.js"); 2 | 3 | function toCreateEvent(event) { 4 | return { 5 | name: event.name, 6 | symbol: event.symbol, 7 | uri: event.uri, 8 | mint: new PublicKey(event.mint), 9 | bondingCurve: new PublicKey(event.bondingCurve), 10 | user: new PublicKey(event.user), 11 | }; 12 | } 13 | 14 | function toCompleteEvent(event) { 15 | return { 16 | user: new PublicKey(event.user), 17 | mint: new PublicKey(event.mint), 18 | bondingCurve: new PublicKey(event.bondingCurve), 19 | timestamp: event.timestamp, 20 | }; 21 | } 22 | 23 | function toTradeEvent(event) { 24 | return { 25 | mint: new PublicKey(event.mint), 26 | solAmount: BigInt(event.solAmount), 27 | tokenAmount: BigInt(event.tokenAmount), 28 | isBuy: event.isBuy, 29 | user: new PublicKey(event.user), 30 | timestamp: Number(event.timestamp), 31 | virtualSolReserves: BigInt(event.virtualSolReserves), 32 | virtualTokenReserves: BigInt(event.virtualTokenReserves), 33 | realSolReserves: BigInt(event.realSolReserves), 34 | realTokenReserves: BigInt(event.realTokenReserves), 35 | }; 36 | } 37 | 38 | function toSetParamsEvent(event) { 39 | return { 40 | feeRecipient: new PublicKey(event.feeRecipient), 41 | initialVirtualTokenReserves: BigInt(event.initialVirtualTokenReserves), 42 | initialVirtualSolReserves: BigInt(event.initialVirtualSolReserves), 43 | initialRealTokenReserves: BigInt(event.initialRealTokenReserves), 44 | tokenTotalSupply: BigInt(event.tokenTotalSupply), 45 | feeBasisPoints: BigInt(event.feeBasisPoints), 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /src/Transactions/simple_tx_executor.js: -------------------------------------------------------------------------------- 1 | const { 2 | BlockhashWithExpiryBlockHeight, 3 | Connection, 4 | Keypair, 5 | Transaction, 6 | VersionedTransaction, 7 | } = require("@solana/web3.js"); 8 | const { connection } = require("../helpers/config.js"); 9 | 10 | /** 11 | * Executes a transaction and confirms it on the Solana blockchain. 12 | * @param {Transaction} transaction - The transaction to be executed. 13 | * @param {Account} payer - The account that will pay for the transaction fees. 14 | * @param {string} lastestBlockhash - The latest blockhash of the Solana blockchain. 15 | * @returns {Promise} - A promise that resolves to true if the transaction is confirmed, false otherwise. 16 | */ 17 | async function simple_executeAndConfirm(transaction, payer, lastestBlockhash) { 18 | console.log("Executing transaction..."); 19 | const signature = await simple_execute(transaction); 20 | console.log("Transaction executed. Confirming transaction..."); 21 | return simple_confirm(signature, lastestBlockhash); 22 | } 23 | 24 | async function simple_execute(transaction) { 25 | return connection.sendRawTransaction(transaction.serialize(), { 26 | skipPreflight: true, 27 | maxRetries: 0, 28 | }); 29 | } 30 | 31 | async function simple_confirm(signature, latestBlockhash) { 32 | const confirmation = await connection.confirmTransaction( 33 | { 34 | signature, 35 | lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, 36 | blockhash: latestBlockhash.blockhash, 37 | }, 38 | connection.commitment 39 | ); 40 | return { confirmed: !confirmation.value.err, signature }; 41 | } 42 | 43 | module.exports = { simple_executeAndConfirm }; 44 | -------------------------------------------------------------------------------- /src/zk-compression/compressed-token/createAndMint.js: -------------------------------------------------------------------------------- 1 | const { 2 | LightSystemProgram, 3 | Rpc, 4 | confirmTx, 5 | createRpc, 6 | } = require("@lightprotocol/stateless.js"); 7 | const { 8 | createMint, 9 | mintTo, 10 | transfer, 11 | compressToken, 12 | } = require("@lightprotocol/compressed-token"); 13 | const { Keypair } = require("@solana/web3.js"); 14 | const { req } = require("pino-std-serializers"); 15 | 16 | const payer = Keypair.generate(); 17 | const tokenRecipient = Keypair.generate(); 18 | 19 | const connection = createRpc(); 20 | 21 | async function main() { 22 | console.log("Payer: ", payer.publicKey.toBase58()); 23 | console.log("Token recipient: ", tokenRecipient.publicKey.toBase58()); 24 | await confirmTx( 25 | connection, 26 | await connection.requestAirdrop(payer.publicKey, 10e9) 27 | ); 28 | await confirmTx( 29 | connection, 30 | await connection.requestAirdrop(tokenRecipient.publicKey, 1e6) 31 | ); 32 | const { mint, transactionSignature } = await createMint( 33 | // create a mint 34 | connection, 35 | payer, 36 | payer.publicKey, 37 | 9 38 | ); 39 | console.log("Mint created: ", mint.toBase58()); 40 | console.log("create-mint success! Txn signature: ", transactionSignature); 41 | 42 | const mintToTxId = await mintTo( 43 | // mint to your own account 44 | connection, 45 | payer, 46 | mint, 47 | payer.publicKey, 48 | payer, 49 | 1e9 50 | ); 51 | console.log("mint-to success! Txn signature: ", mintToTxId); 52 | 53 | const transferTxId = await transfer( 54 | // transfer to another account 55 | connection, 56 | payer, 57 | mint, 58 | 7e8, 59 | payer, 60 | tokenRecipient.publicKey 61 | ); 62 | console.log("transfer success! Txn signature: ", transferTxId); 63 | } 64 | 65 | main(); 66 | -------------------------------------------------------------------------------- /src/Trading/dex/jupiter/swap/buy-helper.js: -------------------------------------------------------------------------------- 1 | const swap_helper = require("./swap-helper"); 2 | const { PublicKey } = require("@solana/web3.js"); 3 | const { wallet } = require("../../../../helpers/config"); 4 | const { getDecimals } = require("../../../../helpers/util"); 5 | const wsol = "So11111111111111111111111111111111111111112"; 6 | 7 | /** 8 | * Buys a token using the specified parameters. 9 | * 10 | * @param {string} tokenToBuy - The token to be swapped for. 11 | * @param {number} amountTokenOut - The amount of token to be received. 12 | * @param {number} slippage - The slippage tolerance percentage. 13 | * @returns {Promise} - A promise that resolves when the buy operation is completed. 14 | * @throws {Error} - If an error occurs during the buy operation. 15 | */ 16 | async function buy(tokenToBuy, amountTokenOut, slippage) { 17 | try { 18 | const convertedAmountOfTokenOut = await swap_helper.convertToInteger( 19 | amountTokenOut, 20 | 9 21 | ); 22 | const quoteResponse = await swap_helper.getQuote( 23 | wsol, 24 | tokenToBuy, 25 | convertedAmountOfTokenOut, 26 | slippage 27 | ); 28 | console.log(quoteResponse); 29 | const wallet_PubKey = wallet.publicKey.toBase58(); 30 | const swapTransaction = await swap_helper.getSwapTransaction( 31 | quoteResponse, 32 | wallet_PubKey 33 | ); 34 | const { confirmed, signature } = await swap_helper.finalizeTransaction( 35 | swapTransaction 36 | ); 37 | if (confirmed) { 38 | console.log("http://solscan.io/tx/" + signature); 39 | } else { 40 | console.log("Transaction failed"); 41 | console.log("retrying transaction..."); 42 | await buy(tokenToBuy, amountTokenOut, slippage); 43 | } 44 | } catch (error) { 45 | console.error(error); 46 | } 47 | } 48 | 49 | module.exports = { buy }; 50 | -------------------------------------------------------------------------------- /src/Trading/dex/jupiter/swap/sell-helper.js: -------------------------------------------------------------------------------- 1 | const swap_helper = require("./swap-helper"); 2 | const { PublicKey } = require("@solana/web3.js"); 3 | const { wallet } = require("../../../../helpers/config"); 4 | const { getDecimals } = require("../../../../helpers/util"); 5 | const wsol = "So11111111111111111111111111111111111111112"; 6 | 7 | /** 8 | * Sells a specified amount of a token on the DEX. 9 | * @param {string} tokenToSell - The address of the token to sell. 10 | * @param {number} amountOfTokenToSell - The amount of the token to sell. 11 | * @param {number} slippage - The slippage tolerance percentage. 12 | * @returns {Promise} - A promise that resolves when the sell operation is completed. 13 | */ 14 | async function sell(tokenToSell, amountOfTokenToSell, slippage) { 15 | try { 16 | const decimals = await getDecimals(new PublicKey(tokenToSell)); 17 | console.log(decimals); 18 | const convertedAmountOfTokenOut = await swap_helper.convertToInteger( 19 | amountOfTokenToSell, 20 | decimals 21 | ); 22 | console.log(convertedAmountOfTokenOut); 23 | const quoteResponse = await swap_helper.getQuote( 24 | tokenToSell, 25 | wsol, 26 | convertedAmountOfTokenOut, 27 | slippage 28 | ); 29 | const wallet_PubKey = wallet.publicKey.toBase58(); 30 | const swapTransaction = await swap_helper.getSwapTransaction( 31 | quoteResponse, 32 | wallet_PubKey 33 | ); 34 | const { confirmed, signature } = await swap_helper.finalizeTransaction( 35 | swapTransaction 36 | ); 37 | if (confirmed) { 38 | console.log("http://solscan.io/tx/" + signature); 39 | } else { 40 | console.log("Transaction failed"); 41 | console.log("retrying transaction..."); 42 | await sell(tokenToSell, amountOfTokenToSell, slippage); 43 | } 44 | } catch (error) { 45 | console.error(error); 46 | } 47 | } 48 | 49 | module.exports = { sell }; 50 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/pump-events-listener/listeners.js: -------------------------------------------------------------------------------- 1 | const {connection} = require("../../../../helpers/config"); 2 | const { Keypair, Connection } = require("@solana/web3.js"); 3 | const {PumpFunSDK} =require ("pumpdotfun-sdk"); 4 | const { AnchorProvider } = require ("@coral-xyz/anchor"); 5 | 6 | function getProvider(){ 7 | const wallet = Keypair.generate(); 8 | const provider = new AnchorProvider(connection, wallet, { 9 | commitment: "finalized", 10 | }); 11 | return provider; 12 | } 13 | 14 | async function subscribeToCompleteBondingCurveEvent(sdk){ 15 | const completeEventId = sdk.addEventListener("completeEvent", (event, slot, signature) => { 16 | console.log("completeEvent", event, slot, signature); 17 | }); 18 | console.log("Subscribed to completeEvent with ID:", completeEventId); 19 | } 20 | async function subscribeToCreatePumpTokenEvent(sdk){ 21 | const createEventId = sdk.addEventListener("createEvent", (event, slot, signature) => { 22 | console.log("createEvent", event, slot, signature); 23 | console.log("mint pubkey", event.mint.toBase58()) 24 | }); 25 | console.log("Subscribed to createEvent with ID:", createEventId); 26 | } 27 | async function subscribeToTradeEvent(sdk){ 28 | const tradeEventId = sdk.addEventListener("tradeEvent", (event, slot, signature) => { 29 | console.log("tradeEvent", event, slot, signature); 30 | }); 31 | console.log("Subscribed to tradeEvent with ID:", tradeEventId); 32 | } 33 | async function main(){ 34 | try { 35 | const provider = getProvider(); 36 | const sdk = new PumpFunSDK(provider); 37 | 38 | // Set up event listeners 39 | await subscribeToCreatePumpTokenEvent(sdk); 40 | } catch (error) { 41 | console.error("An error occurred:", error); 42 | } 43 | } 44 | main(); 45 | 46 | module.exports = {subscribeToCompleteBondingCurveEvent, subscribeToCreatePumpTokenEvent, subscribeToTradeEvent, getProvider}; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solana-memecoin-cli", 3 | "version": "1.0.0", 4 | "description": "solana memecoin cli", 5 | "main": "help.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": ["solana", "memecoin", "cli", "trading", "copy trading", "pump.fun", "raydium", "orca", "meteora", "jupiter", "jito", "bloXroute", "limit order", "dollar cost average", "stop loss", "take profit"], 10 | "author": "earthskyorg", 11 | "url": "https://github.com/earthskyorg/solana-memecoin-cli/issues", 12 | "homepage": "https://github.com/earthskyorg/solana-memecoin-cli", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@bonfida/spl-name-service": "^2.5.2", 16 | "@coral-xyz/anchor": "^0.30.1", 17 | "@irys/sdk": "^0.2.1", 18 | "@lightprotocol/compressed-token": "^0.3.4", 19 | "@lightprotocol/stateless.js": "^0.4.4", 20 | "@lightprotocol/zk-compression-cli": "^0.4.7", 21 | "@metaplex-foundation/js": "^0.20.1", 22 | "@metaplex-foundation/mpl-candy-machine": "^6.0.1", 23 | "@metaplex-foundation/mpl-token-metadata": "^3.2.1", 24 | "@metaplex-foundation/umi": "^0.9.1", 25 | "@metaplex-foundation/umi-bundle-defaults": "^0.9.1", 26 | "@orca-so/common-sdk": "^0.6.0-alpha.3", 27 | "@orca-so/whirlpools-sdk": "^0.11.8", 28 | "@project-serum/serum": "^0.13.65", 29 | "@raydium-io/raydium-sdk": "^1.3.1-beta.47", 30 | "@raydium-io/raydium-sdk-v2": "^0.1.23-alpha", 31 | "@rollup/plugin-json": "^6.1.0", 32 | "@solana/spl-token": "^0.4.0", 33 | "@solana/web3.js": "^1.89.1", 34 | "axios": "^1.6.8", 35 | "bigint-buffer": "^1.1.5", 36 | "bip39": "^3.1.0", 37 | "bn.js": "^5.2.1", 38 | "bs58": "^5.0.0", 39 | "commander": "^12.1.0", 40 | "decimal.js": "^10.4.3", 41 | "dotenv": "^16.4.5", 42 | "graphql-request": "^4.0.0", 43 | "i": "^0.3.7", 44 | "npm": "^10.5.2", 45 | "pino": "^8.18.0", 46 | "pino-pretty": "^10.3.1", 47 | "pino-std-serializers": "^6.2.2", 48 | "pumpdotfun-sdk": "^1.3.2", 49 | "random-js": "^2.1.0" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/types.js: -------------------------------------------------------------------------------- 1 | const { PublicKey, VersionedTransactionResponse } = require("@solana/web3.js"); 2 | 3 | // export type CreateTokenMetadata = { 4 | // name: string; 5 | // symbol: string; 6 | // description: string; 7 | // file: Blob; 8 | // twitter?: string; 9 | // telegram?: string; 10 | // website?: string; 11 | // }; 12 | 13 | // export type TokenMetadata = { 14 | // name: string; 15 | // symbol: string; 16 | // description: string; 17 | // image: string; 18 | // showName: boolean; 19 | // createdOn: string; 20 | // twitter: string; 21 | // }; 22 | 23 | // export type CreateEvent = { 24 | // name: string; 25 | // symbol: string; 26 | // uri: string; 27 | // mint: PublicKey; 28 | // bondingCurve: PublicKey; 29 | // user: PublicKey; 30 | // }; 31 | 32 | // export type TradeEvent = { 33 | // mint: PublicKey; 34 | // solAmount: bigint; 35 | // tokenAmount: bigint; 36 | // isBuy: boolean; 37 | // user: PublicKey; 38 | // timestamp: number; 39 | // virtualSolReserves: bigint; 40 | // virtualTokenReserves: bigint; 41 | // realSolReserves: bigint; 42 | // realTokenReserves: bigint; 43 | // }; 44 | 45 | // export type CompleteEvent = { 46 | // user: PublicKey; 47 | // mint: PublicKey; 48 | // bondingCurve: PublicKey; 49 | // timestamp: number; 50 | // }; 51 | 52 | // export type SetParamsEvent = { 53 | // feeRecipient: PublicKey; 54 | // initialVirtualTokenReserves: bigint; 55 | // initialVirtualSolReserves: bigint; 56 | // initialRealTokenReserves: bigint; 57 | // tokenTotalSupply: bigint; 58 | // feeBasisPoints: bigint; 59 | // }; 60 | 61 | // export interface PumpFunEventHandlers { 62 | // createEvent: CreateEvent; 63 | // tradeEvent: TradeEvent; 64 | // completeEvent: CompleteEvent; 65 | // setParamsEvent: SetParamsEvent; 66 | // } 67 | 68 | // export type PumpFunEventType = keyof PumpFunEventHandlers; 69 | 70 | // export type PriorityFee = { 71 | // unitLimit: number; 72 | // unitPrice: number; 73 | // }; 74 | 75 | // export type TransactionResult = { 76 | // signature?: string; 77 | // error?: unknown; 78 | // results?: VersionedTransactionResponse; 79 | // success: boolean; 80 | // }; 81 | -------------------------------------------------------------------------------- /src/Trading/dex/raydium/buy.js: -------------------------------------------------------------------------------- 1 | const { swap } = require("../../../Pool/swap.js"); 2 | const { program } = require("commander"); 3 | const { loadOrCreateKeypair_wallet } = require("../../../helpers/util.js"); 4 | const { wallet } = require("../../../helpers/config.js"); 5 | 6 | let payer_keypair = null, 7 | token_address = null, 8 | sol = null, 9 | cluster = null; 10 | program 11 | .option("--payer ", "Specify the path to the secret key") 12 | .option("--token_address ", "Specify the token address") 13 | .option("--sol ", "Specify the number of SOL") 14 | .option("--cluster ", "Specify the cluster") 15 | .option("-h, --help", "display help for command") 16 | .action((options) => { 17 | if (options.help) { 18 | console.log( 19 | "node buy --payer --token_address --sol --cluster " 20 | ); 21 | process.exit(0); 22 | } 23 | if (!options.token_address || !options.sol || !options.cluster) { 24 | console.error("❌ Missing required options"); 25 | process.exit(1); 26 | } 27 | if (options.payer) { 28 | payer_keypair = options.payer; 29 | } 30 | token_address = options.token_address; 31 | sol = options.sol; 32 | cluster = options.cluster; 33 | }); 34 | program.parse(); 35 | 36 | /** 37 | * Buy function to perform a swap on the Raydium DEX. 38 | * 39 | * @param {string} side - The side of the trade (buy/sell). 40 | * @param {string} address - The address of the token to trade. 41 | * @param {number} no_of_sol - The amount of SOL to trade. 42 | * @param {string} payer - The payer's keypair for the transaction. 43 | * @returns {Promise} - A promise that resolves when the swap is completed. 44 | */ 45 | async function buy(side, address, no_of_sol, payer) { 46 | let payer_wallet = null; 47 | if (payer_keypair !== null) { 48 | payer_wallet = await loadOrCreateKeypair_wallet(payer_keypair); 49 | await swap(side, address, no_of_sol, -1, payer_wallet, "trade"); 50 | } else { 51 | await swap(side, address, no_of_sol, -1, wallet, "trade"); 52 | } 53 | } 54 | 55 | buy("buy", token_address, sol, payer_keypair); 56 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/globalAccount.js: -------------------------------------------------------------------------------- 1 | const { PublicKey } =require( "@solana/web3.js"); 2 | const { struct, bool, u64, publicKey, Layout } =require( "@coral-xyz/borsh"); 3 | 4 | class GlobalAccount { 5 | 6 | 7 | constructor( 8 | discriminator, 9 | initialized, 10 | authority, 11 | feeRecipient, 12 | initialVirtualTokenReserves, 13 | initialVirtualSolReserves, 14 | initialRealTokenReserves, 15 | tokenTotalSupply, 16 | feeBasisPoints 17 | ) { 18 | this.discriminator = discriminator; 19 | this.initialized = initialized; 20 | this.authority = authority; 21 | this.feeRecipient = feeRecipient; 22 | this.initialVirtualTokenReserves = initialVirtualTokenReserves; 23 | this.initialVirtualSolReserves = initialVirtualSolReserves; 24 | this.initialRealTokenReserves = initialRealTokenReserves; 25 | this.tokenTotalSupply = tokenTotalSupply; 26 | this.feeBasisPoints = feeBasisPoints; 27 | } 28 | 29 | getInitialBuyPrice(amount) { 30 | if (amount <= 0n) { 31 | return 0n; 32 | } 33 | 34 | let n = this.initialVirtualSolReserves * this.initialVirtualTokenReserves; 35 | let i = this.initialVirtualSolReserves + amount; 36 | let r = n / i + 1n; 37 | let s = this.initialVirtualTokenReserves - r; 38 | return s < this.initialRealTokenReserves 39 | ? s 40 | : this.initialRealTokenReserves; 41 | } 42 | 43 | static fromBuffer(buffer){ 44 | const structure = struct([ 45 | u64("discriminator"), 46 | bool("initialized"), 47 | publicKey("authority"), 48 | publicKey("feeRecipient"), 49 | u64("initialVirtualTokenReserves"), 50 | u64("initialVirtualSolReserves"), 51 | u64("initialRealTokenReserves"), 52 | u64("tokenTotalSupply"), 53 | u64("feeBasisPoints"), 54 | ]); 55 | 56 | let value = structure.decode(buffer); 57 | return new GlobalAccount( 58 | BigInt(value.discriminator), 59 | value.initialized, 60 | value.authority, 61 | value.feeRecipient, 62 | BigInt(value.initialVirtualTokenReserves), 63 | BigInt(value.initialVirtualSolReserves), 64 | BigInt(value.initialRealTokenReserves), 65 | BigInt(value.tokenTotalSupply), 66 | BigInt(value.feeBasisPoints) 67 | ); 68 | } 69 | } 70 | 71 | module.exports = {GlobalAccount}; -------------------------------------------------------------------------------- /CLI_Doc.txt: -------------------------------------------------------------------------------- 1 | 2 | ############ Command Line Tool for Memecoins Projects ################## 3 | 4 | ########## --priority-fee (e.g: 0.000005SOL or 1LAMPORTS) can be used in every command ########### 5 | 6 | ########## --cluster (e.g: mainnet, devnet) can be used in every command ########### 7 | 8 | 1. node create --payer --symbol --token_name --mint --supply --decimals --metadata --image --cluster --priority-fee --file_type 9 | 10 | 2. node burn --payer --token_address --percentage --cluster 11 | 12 | 3. node revoke_authority --payer --mint_address --cluster --mint --freeze 13 | 14 | 4. node transfer --payer --token_address --amount --destination 15 | 16 | 5. node airdrop --payer --token-address --destination-addresses 17 | 18 | 6. node buy --payer --token_address --sol --cluster 19 | 20 | 7. node sell --payer --token_address --percentage --cluster 21 | 22 | 8. node boost_volume --bot --token-address --volume 23 | 24 | 9. node query --token-address 25 | 26 | 10. node add_pool --payer --token_address --pool_id --sol --cluster --priority_fee 27 | 28 | 11. node remove_pool --payer --token_address --percentage --cluster 29 | 30 | 12. node check_pool --pool-id 31 | 32 | 13. node wallet --token-address balance 33 | 13a. node wallet balance # returns us the balance of SOL 34 | 35 | 14. node set_rpc --rpc-url 36 | 14a. node set_rpc public # set the default public mainnet rpc 37 | 38 | Done💰: add_pool, remove_pool, buy, sell, create, burn, revoke_authority 39 | 40 | Not done❌: boost_volume, check_pool, airdrop, set_rpc, wallet, query -------------------------------------------------------------------------------- /src/Trading/dex/raydium/sell.js: -------------------------------------------------------------------------------- 1 | const { swap } = require("../../../Pool/swap.js"); 2 | const { program } = require("commander"); 3 | const { loadOrCreateKeypair_wallet } = require("../../../helpers/util.js"); 4 | const { wallet } = require("../../../helpers/config.js"); 5 | 6 | let payer_keypair = null, 7 | token_address = null, 8 | percentage = null, 9 | cluster = null; 10 | program 11 | .option("--payer ", "Specify the path to the secret key") 12 | .option("--token_address ", "Specify the token address") 13 | .option("--percentage ", "Specify the percentage") 14 | .option("--cluster ", "Specify the cluster") 15 | .option("-h, --help", "display help for command") 16 | .action((options) => { 17 | if (options.help) { 18 | console.log( 19 | "node sell --payer --token_address --percentage --cluster " 20 | ); 21 | process.exit(0); 22 | } 23 | if (!options.token_address || !options.percentage || !options.cluster) { 24 | console.error("❌ Missing required options"); 25 | process.exit(1); 26 | } 27 | if (options.payer) { 28 | payer_keypair = options.payer; 29 | } 30 | token_address = options.token_address; 31 | percentage = options.percentage; 32 | cluster = options.cluster; 33 | }); 34 | program.parse(); 35 | 36 | /** 37 | * Sell function that executes a swap transaction. 38 | * 39 | * @param {string} side - The side of the swap (buy or sell). 40 | * @param {string} address - The address to swap tokens. 41 | * @param {number} sell_percentage - The percentage of tokens to sell. 42 | * @param {string} payer - The payer address for the transaction. 43 | * @returns {Promise} - A promise that resolves when the swap transaction is completed. 44 | */ 45 | async function sell(side, address, sell_percentage, payer) { 46 | await swap(side, address, -1, sell_percentage, payer, "trade"); 47 | } 48 | async function main() { 49 | let payer_wallet = null; 50 | if (payer_keypair !== null) { 51 | payer_wallet = await loadOrCreateKeypair_wallet(payer_keypair); // specified wallet by user in command 52 | sell("sell", token_address, percentage, payer_wallet); 53 | } else { 54 | sell("sell", token_address, percentage, wallet); // default pre-defined wallet 55 | } 56 | } 57 | main(); 58 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/createAndBuy.js: -------------------------------------------------------------------------------- 1 | const {createAndBuy} = require("./tools"); 2 | // command line tool 3 | const {program} = require("commander"); 4 | const fs = require("fs"); 5 | 6 | let sol = null, mintKeypair = null, name = null, symbol = null, description = null, telegram = null, twitter = null, website = null, file = null; 7 | program.option("--pathToMintKeypair ", "Specify the path to your own mint keypair") 8 | .option("--sol ", "Specify the number of SOL you want to buy") 9 | .option("--name ", "Specify the token name") 10 | .option("--symbol ", "Specify the token symbol") 11 | .option("--description ", "Specify the token description") 12 | .option("--telegram ", "Specify the telegram link") 13 | .option("--twitter ", "Specify the twitter link") 14 | .option("--website ", "Specify the website link") 15 | .option("--file ", "Specify the file path") 16 | .option("-h, --help", "display help for command") 17 | .action((options) => { 18 | if (options.help) { 19 | console.log( 20 | "node createAndBuy --pathToMintKeypair --sol --name --symbol --description --telegram --twitter --website --file " 21 | ); 22 | process.exit(0); 23 | } 24 | if (!options.pathToMintKeypair || !options.sol || !options.name || !options.symbol || !options.description || !options.file) { 25 | console.error("❌ Missing required options"); 26 | process.exit(1); 27 | } 28 | mintKeypair = options.pathToMintKeypair; 29 | sol = options.sol; 30 | name = options.name; 31 | symbol = options.symbol; 32 | description = options.description; 33 | telegram = options.telegram; 34 | twitter = options.twitter; 35 | website = options.website; 36 | file = options.file; 37 | }); 38 | program.parse(); 39 | 40 | async function main(){ 41 | let tokenMetadata = { 42 | name: name, 43 | symbol: symbol, 44 | description: description, 45 | telegram: telegram, 46 | twitter: twitter, 47 | website: website, 48 | file: await fs.openAsBlob( 49 | file 50 | ), 51 | }; 52 | createAndBuy(mintKeypair, tokenMetadata, sol); 53 | } 54 | main(); 55 | 56 | -------------------------------------------------------------------------------- /src/helpers/config.js: -------------------------------------------------------------------------------- 1 | const { 2 | Currency, 3 | Token, 4 | ENDPOINT, 5 | MAINNET_PROGRAM_ID, 6 | RAYDIUM_MAINNET, 7 | TxVersion, 8 | LOOKUP_TABLE_CACHE, 9 | TOKEN_PROGRAM_ID, 10 | } = require("@raydium-io/raydium-sdk"); 11 | const { Connection, Keypair, PublicKey } = require("@solana/web3.js"); 12 | const fs = require("fs"); 13 | const dotenv = require("dotenv"); 14 | const bs58 = require("bs58"); 15 | const path = require("path"); 16 | // please specify your own .env path 17 | const envPath = path.join(__dirname, ".env"); 18 | dotenv.config({ 19 | path: envPath, // fill in your .env path 20 | }); 21 | function loadKeypairFromFile(filename) { 22 | const secret = fs.readFileSync(filename, { encoding: "utf8" }); 23 | return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(secret))); 24 | } 25 | const jito_fee = process.env.JITO_FEE; // 0.00009 SOL 26 | const shyft_api_key = process.env.SHYFT_API_KEY; // your shyft api key 27 | const wallet = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY)); // your wallet 28 | const dev_endpoint = process.env.DEVNET_ENDPOINT; // devnet endpoint, if you use devnet 29 | const main_endpoint = process.env.MAINNET_ENDPOINT; // mainnet endpoint 30 | const connection = new Connection(main_endpoint, "confirmed"); // mainnet connection 31 | 32 | const dev_connection = new Connection(dev_endpoint, "confirmed"); // devnet connection 33 | 34 | const PROGRAMIDS = MAINNET_PROGRAM_ID; // raydium mainnet program address 35 | 36 | const RAYDIUM_MAINNET_API = RAYDIUM_MAINNET; // raydium mainnet program's api 37 | 38 | const makeTxVersion = TxVersion.V0; // LEGACY 39 | const _ENDPOINT = ENDPOINT; // raydium mainnet program's base api path 40 | const addLookupTableInfo = LOOKUP_TABLE_CACHE; // only mainnet. other = undefined 41 | 42 | const DEFAULT_TOKEN = { 43 | SOL: new Currency(9, "SOL", "SOL"), 44 | WSOL: new Token( 45 | TOKEN_PROGRAM_ID, 46 | new PublicKey("So11111111111111111111111111111111111111112"), 47 | 9, 48 | "WSOL", 49 | "WSOL" 50 | ), 51 | USDC: new Token( 52 | TOKEN_PROGRAM_ID, 53 | new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), 54 | 6, 55 | "USDC", 56 | "USDC" 57 | ), 58 | }; 59 | 60 | module.exports = { 61 | wallet, 62 | dev_connection, 63 | dev_endpoint, 64 | main_endpoint, 65 | connection, 66 | TOKEN_PROGRAM_ID, 67 | RAYDIUM_MAINNET, 68 | RAYDIUM_MAINNET_API, 69 | PROGRAMIDS, 70 | makeTxVersion, 71 | DEFAULT_TOKEN, 72 | addLookupTableInfo, 73 | _ENDPOINT, 74 | shyft_api_key, 75 | jito_fee, 76 | }; 77 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # personal wallet's private key or file with token data 14 | data/payer_keypair/mainnet 15 | data/payer_keypair/devnet 16 | token_keypair/devnet 17 | token_keypair/mainnet 18 | image_file 19 | metadata_file 20 | config.js 21 | 22 | # Runtime data 23 | pids 24 | *.pid 25 | *.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | lib-cov 30 | 31 | # Coverage directory used by tools like istanbul 32 | coverage 33 | *.lcov 34 | 35 | # nyc test coverage 36 | .nyc_output 37 | 38 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 39 | .grunt 40 | 41 | # Bower dependency directory (https://bower.io/) 42 | bower_components 43 | 44 | # node-waf configuration 45 | .lock-wscript 46 | 47 | # Compiled binary addons (https://nodejs.org/api/addons.html) 48 | build/Release 49 | 50 | # Dependency directories 51 | jspm_packages/ 52 | 53 | # Snowpack dependency directory (https://snowpack.dev/) 54 | web_modules/ 55 | # TypeScript cache 56 | *.tsbuildinfo 57 | 58 | # Optional npm cache directory 59 | .npm 60 | 61 | # Optional eslint cache 62 | .eslintcache 63 | 64 | # Optional stylelint cache 65 | .stylelintcache 66 | 67 | # Microbundle cache 68 | .rpt2_cache/ 69 | .rts2_cache_cjs/ 70 | .rts2_cache_es/ 71 | .rts2_cache_umd/ 72 | 73 | # Optional REPL history 74 | .node_repl_history 75 | 76 | # Output of 'npm pack' 77 | *.tgz 78 | 79 | # Yarn Integrity file 80 | .yarn-integrity 81 | 82 | # dotenv environment variable files 83 | .env 84 | .env.development.local 85 | .env.test.local 86 | .env.production.local 87 | .env.local 88 | 89 | # parcel-bundler cache (https://parceljs.org/) 90 | .cache 91 | .parcel-cache 92 | 93 | # Next.js build output 94 | .next 95 | out 96 | 97 | # Nuxt.js build / generate output 98 | .nuxt 99 | dist 100 | 101 | # Gatsby files 102 | .cache/ 103 | # Comment in the public line in if your project uses Gatsby and not Next.js 104 | # https://nextjs.org/blog/next-9-1#public-directory-support 105 | # public 106 | 107 | # vuepress build output 108 | .vuepress/dist 109 | 110 | # vuepress v2.x temp and cache directory 111 | .temp 112 | .cache 113 | 114 | # Docusaurus cache and generated files 115 | .docusaurus 116 | 117 | # Serverless directories 118 | .serverless/ 119 | 120 | # FuseBox cache 121 | .fusebox/ 122 | 123 | # DynamoDB Local files 124 | .dynamodb/ 125 | 126 | # TernJS port file 127 | .tern-port 128 | 129 | # Stores VSCode versions used for testing VSCode extensions 130 | .vscode-test 131 | 132 | # yarn v2 133 | .yarn/cache 134 | .yarn/unplugged 135 | .yarn/build-state.yml 136 | .yarn/install-state.gz 137 | .pnp.* 138 | node_modules 139 | test-ledger -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/example/util.js: -------------------------------------------------------------------------------- 1 | const { bs58 } =require ("@coral-xyz/anchor/dist/cjs/utils/bytes"); 2 | const { getAssociatedTokenAddressSync } =require ("@solana/spl-token"); 3 | const { 4 | Keypair, 5 | PublicKey, 6 | Connection, 7 | LAMPORTS_PER_SOL, 8 | } =require ("@solana/web3.js"); 9 | const { sha256 } =require ("js-sha256"); 10 | 11 | const fs =require ("fs"); 12 | 13 | function getOrCreateKeypair(dir, keyName) { 14 | if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); 15 | const authorityKey = dir + "/" + keyName + ".json"; 16 | if (fs.existsSync(authorityKey)) { 17 | const data= JSON.parse(fs.readFileSync(authorityKey, "utf-8")); 18 | return Keypair.fromSecretKey(bs58.decode(data.secretKey)); 19 | } else { 20 | const keypair = Keypair.generate(); 21 | keypair.secretKey; 22 | fs.writeFileSync( 23 | authorityKey, 24 | JSON.stringify({ 25 | secretKey: bs58.encode(keypair.secretKey), 26 | publicKey: keypair.publicKey.toBase58(), 27 | }) 28 | ); 29 | return keypair; 30 | } 31 | } 32 | 33 | function getKeypairByJsonPath(jsonPath) { 34 | try { 35 | const keypairJson = fs.readFileSync(jsonPath, "utf-8"); 36 | const data = JSON.parse(keypairJson); 37 | const mintKeypair = Keypair.fromSecretKey(Uint8Array.from(data)); 38 | return mintKeypair 39 | } catch (e) { 40 | console.log(e); 41 | } 42 | } 43 | 44 | async function printSOLBalance ( 45 | connection, 46 | pubKey, 47 | info = "" 48 | ) { 49 | const balance = await connection.getBalance(pubKey); 50 | console.log( 51 | `${info ? info + " " : ""}${pubKey.toBase58()}:`, 52 | balance / LAMPORTS_PER_SOL, 53 | `SOL` 54 | ); 55 | }; 56 | 57 | async function getSPLBalance ( 58 | connection, 59 | mintAddress, 60 | pubKey, 61 | allowOffCurve = false 62 | ) { 63 | try { 64 | let ata = getAssociatedTokenAddressSync(mintAddress, pubKey, allowOffCurve); 65 | const balance = await connection.getTokenAccountBalance(ata, "processed"); 66 | return balance.value.uiAmount; 67 | } catch (e) {} 68 | return null; 69 | }; 70 | 71 | async function printSPLBalance ( 72 | connection, 73 | mintAddress, 74 | user, 75 | info = "" 76 | ) { 77 | const balance = await getSPLBalance(connection, mintAddress, user); 78 | if (balance === null) { 79 | console.log( 80 | `${info ? info + " " : ""}${user.toBase58()}:`, 81 | "No Account Found" 82 | ); 83 | } else { 84 | console.log(`${info ? info + " " : ""}${user.toBase58()}:`, balance); 85 | } 86 | }; 87 | 88 | const baseToValue = (base, decimals) => { 89 | return base * Math.pow(10, decimals); 90 | }; 91 | 92 | const valueToBase = (value, decimal) => { 93 | return value / Math.pow(10, decimals); 94 | }; 95 | 96 | //i.e. account:BondingCurve 97 | function getDiscriminator(name) { 98 | return sha256.digest(name).slice(0, 8); 99 | } 100 | 101 | module.exports = { 102 | getOrCreateKeypair, 103 | getKeypairByJsonPath, 104 | printSOLBalance, 105 | getSPLBalance, 106 | printSPLBalance, 107 | baseToValue, 108 | valueToBase, 109 | getDiscriminator, 110 | }; -------------------------------------------------------------------------------- /src/Trading/volume/boost_volume.js: -------------------------------------------------------------------------------- 1 | const { connection, wallet } = require("../../helpers/config.js"); 2 | const { 3 | simple_executeAndConfirm, 4 | } = require("../../Transactions/simple_tx_executor"); 5 | const { 6 | jito_executeAndConfirm, 7 | } = require("../../Transactions/jito_tips_tx_executor"); 8 | const { buy, get_buy_transaction } = require("../dex/raydium/buy_helper"); 9 | const { sell, get_sell_transaction } = require("../dex/raydium/sell_helper"); 10 | const { program } = require("commander"); 11 | const { loadOrCreateKeypair_wallet, checkTx } = require("../../helpers/util"); 12 | const { 13 | ComputeBudgetProgram, 14 | TransactionMessage, 15 | VersionedTransaction, 16 | } = require("@solana/web3.js"); 17 | const { swapForVolume } = require("../../Pool/swap.js"); 18 | let slippage = null, 19 | tokenAddress = null, 20 | payer = null, 21 | cluster = null, 22 | solPerOrder = null; 23 | 24 | program 25 | .option("--token_address ", "Specify the token address") 26 | .option("--payer ", "Specify the path to the secret key") 27 | .option("--cluster ", "Specify the cluster") 28 | .option( 29 | "--sol_per_order ", 30 | "Specify the number of SOL per order" 31 | ) 32 | .option("-h, --help", "display help for command") 33 | .action((options) => { 34 | if (options.help) { 35 | console.log( 36 | "node boost_volume --token_address --payer --cluster --sol_per_order " 37 | ); 38 | process.exit(0); 39 | } 40 | if (!options.token_address || !options.cluster || !options.sol_per_order) { 41 | console.error("❌ Missing required options"); 42 | process.exit(1); 43 | } 44 | tokenAddress = options.token_address; 45 | if (payer) payer = options.payer; 46 | cluster = options.cluster; 47 | solPerOrder = options.sol_per_order; 48 | }); 49 | program.parse(); 50 | 51 | /** 52 | * Boosts the volume by buying and selling a token in one transaction. 53 | * @async 54 | * @function boost_volume 55 | * @returns {Promise} 56 | */ 57 | async function boost_volume() { 58 | while (true) { 59 | console.log( 60 | `Boosting volume..., buying and selling ${tokenAddress} in one transaction...` 61 | ); 62 | try { 63 | const { confirmed, signature } = await swapForVolume( 64 | tokenAddress, 65 | solPerOrder 66 | ); 67 | await error_handling(signature, confirmed); 68 | } catch (e) { 69 | console.log(e); 70 | console.log("trying to send the transaction again..."); 71 | await new Promise((resolve) => setTimeout(resolve, 2000)); 72 | continue; 73 | } 74 | } 75 | } 76 | 77 | /** 78 | * Handles error for a transaction. 79 | * @param {string} signature - The transaction signature. 80 | * @param {boolean} confirmed - Indicates if the transaction is confirmed. 81 | * @returns {Promise} - A promise that resolves when the error handling is complete. 82 | */ 83 | async function error_handling(signature, confirmed) { 84 | if (confirmed) { 85 | console.log(`https://solscan.io/tx/${signature}?cluster=mainnet`); 86 | return; 87 | } 88 | const response = await checkTx(signature); 89 | if (response) { 90 | console.log(`https://solscan.io/tx/${signature}?cluster=mainnet`); 91 | } else { 92 | console.log("Transaction failed"); 93 | console.log("trying to send the transaction again"); 94 | } 95 | } 96 | boost_volume(); 97 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/amm.js: -------------------------------------------------------------------------------- 1 | const { BondingCurveAccount } =require ("./bondingCurveAccount"); 2 | const { GlobalAccount } =require ("./globalAccount"); 3 | 4 | // type BuyResult = { 5 | // token_amount: bigint; 6 | // sol_amount: bigint; 7 | // }; 8 | 9 | // type SellResult = { 10 | // token_amount: bigint; 11 | // sol_amount: bigint; 12 | // }; 13 | 14 | class AMM { 15 | constructor( 16 | virtualSolReserves, 17 | virtualTokenReserves, 18 | realSolReserves, 19 | realTokenReserves, 20 | initialVirtualTokenReserves 21 | ) {} 22 | 23 | static fromGlobalAccount(global) { 24 | return new AMM( 25 | global.initialVirtualSolReserves, 26 | global.initialVirtualTokenReserves, 27 | 0n, 28 | global.initialRealTokenReserves, 29 | global.initialVirtualTokenReserves 30 | ); 31 | } 32 | 33 | static fromBondingCurveAccount(bonding_curve, initialVirtualTokenReserves) { 34 | return new AMM( 35 | bonding_curve.virtualSolReserves, 36 | bonding_curve.virtualTokenReserves, 37 | bonding_curve.realSolReserves, 38 | bonding_curve.realTokenReserves, 39 | initialVirtualTokenReserves 40 | ); 41 | } 42 | 43 | getBuyPrice(tokens){ 44 | const product_of_reserves = this.virtualSolReserves * this.virtualTokenReserves; 45 | const new_virtual_token_reserves = this.virtualTokenReserves - tokens; 46 | const new_virtual_sol_reserves = product_of_reserves / new_virtual_token_reserves + 1n; 47 | const amount_needed = new_virtual_sol_reserves > this.virtualSolReserves ? new_virtual_sol_reserves - this.virtualSolReserves : 0n; 48 | return amount_needed > 0n ? amount_needed : 0n; 49 | } 50 | 51 | applyBuy(token_amount ) { 52 | const final_token_amount = token_amount > this.realTokenReserves ? this.realTokenReserves : token_amount; 53 | const sol_amount = this.getBuyPrice(final_token_amount); 54 | 55 | this.virtualTokenReserves = this.virtualTokenReserves - final_token_amount; 56 | this.realTokenReserves = this.realTokenReserves - final_token_amount; 57 | 58 | this.virtualSolReserves = this.virtualSolReserves + sol_amount; 59 | this.realSolReserves = this.realSolReserves + sol_amount; 60 | 61 | return { 62 | token_amount: final_token_amount, 63 | sol_amount: sol_amount 64 | } 65 | } 66 | 67 | applySell(token_amount ) { 68 | this.virtualTokenReserves = this.virtualTokenReserves + token_amount; 69 | this.realTokenReserves = this.realTokenReserves + token_amount; 70 | 71 | const sell_price = this.getSellPrice(token_amount); 72 | 73 | this.virtualSolReserves = this.virtualSolReserves - sell_price; 74 | this.realSolReserves = this.realSolReserves - sell_price; 75 | 76 | return { 77 | token_amount: token_amount, 78 | sol_amount: sell_price 79 | } 80 | } 81 | 82 | getSellPrice(tokens ) { 83 | const scaling_factor = this.initialVirtualTokenReserves; 84 | const token_sell_proportion = (tokens * scaling_factor) / this.virtualTokenReserves; 85 | const sol_received = (this.virtualSolReserves * token_sell_proportion) / scaling_factor; 86 | return sol_received < this.realSolReserves ? sol_received : this.realSolReserves; 87 | } 88 | } 89 | module.exports = { 90 | AMM 91 | } -------------------------------------------------------------------------------- /src/helpers/check_balance.js: -------------------------------------------------------------------------------- 1 | const { Connection, LAMPORTS_PER_SOL, PublicKey } = require("@solana/web3.js"); 2 | const { 3 | getDomainKeySync, 4 | NameRegistryState, 5 | } = require("@bonfida/spl-name-service"); 6 | const { main_endpoint, dev_endpoint } = require("./config"); 7 | const connectionDev = new Connection(dev_endpoint, "confirmed"); 8 | const connectionMain = new Connection(main_endpoint); 9 | const { getAssociatedTokenAddressSync } = require("@solana/spl-token"); 10 | 11 | /** 12 | * Retrieves the public key associated with a given .sol domain. 13 | * @param {string} domain - The .sol domain to retrieve the public key for. 14 | * @returns {Promise} The public key associated with the domain. 15 | */ 16 | async function getPublicKeyFromSOLDomain(domain) { 17 | // check if the domain is a .sol domain 18 | // the last four characters should be ".sol" 19 | if (!domain.endsWith(".sol")) { 20 | console.error(`❌ The provided domain is not a .sol domain: ${domain}`); 21 | return; 22 | } 23 | const publicKey = await getDomainKeySync(domain); 24 | const owner = ( 25 | await NameRegistryState.retrieve(connectionMain, publicKey.pubkey) 26 | ).registry.owner.toBase58(); 27 | console.log( 28 | `🔍 Finished! The public key for the domain ${domain} is ${owner}!` 29 | ); 30 | return owner; 31 | } 32 | /** 33 | * Checks the balance of a wallet address. 34 | * @param {string} address - The wallet address to check. 35 | * @param {object} connection - The connection object for interacting with the Solana network. 36 | * @returns {Promise} - A promise that resolves when the balance is checked. 37 | */ 38 | async function checkBalanceByAddress(address, connection) { 39 | // check if the address is valid 40 | // check the domain name of the address 41 | 42 | try { 43 | new PublicKey(address); 44 | } catch (error) { 45 | console.error(`❌ The provided address is invalid: ${address}`); 46 | return; 47 | } 48 | 49 | const publicKey = new PublicKey(address); 50 | const balanceInLamports = await connection.getBalance(publicKey); 51 | const balanceInSOL = balanceInLamports / LAMPORTS_PER_SOL; 52 | console.log( 53 | `💰 Finished! The balance for the wallet at address ${address} is ${balanceInSOL}!` 54 | ); 55 | return balanceInSOL; 56 | } 57 | /** 58 | * Retrieves the balance of an SPL token associated with a given token account. 59 | * @param {Connection} connection - The connection object for interacting with the Solana network. 60 | * @param {PublicKey} tokenAccount - The public key of the token account. 61 | * @param {PublicKey} payerPubKey - The public key of the payer account. 62 | * @returns {Promise} The balance of the SPL token. 63 | * @throws {Error} If no balance is found. 64 | */ 65 | async function getSPLTokenBalance(connection, tokenAccount, payerPubKey) { 66 | const address = getAssociatedTokenAddressSync(tokenAccount, payerPubKey); 67 | console.log("Associated token address: ", address.toBase58()); 68 | const info = await connection.getTokenAccountBalance(address); 69 | if (info.value.uiAmount == null) throw new Error("No balance found"); 70 | return info.value.uiAmount; 71 | } 72 | /** 73 | * Checks the balance of a wallet associated with a given domain. 74 | * @param {string} domain - The domain associated with the wallet. 75 | * @param {object} connection - The connection object for interacting with the Solana network. 76 | * @returns {Promise} - A promise that resolves once the balance is checked. 77 | */ 78 | async function checkBalanceByDomain(domain, connection) { 79 | // get the public key from the domain 80 | 81 | const owner = await getPublicKeyFromSOLDomain(domain); 82 | 83 | const balanceInLamports = await connection.getBalance(new PublicKey(owner)); 84 | const balanceInSOL = balanceInLamports / LAMPORTS_PER_SOL; 85 | console.log( 86 | `💰 Finished! The balance for the wallet at domain ${domain} is ${balanceInSOL}!` 87 | ); 88 | } 89 | module.exports = { checkBalanceByAddress, getSPLTokenBalance }; 90 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/bondingCurveAccount.js: -------------------------------------------------------------------------------- 1 | const { struct, bool, u64, Layout } =require ("@coral-xyz/borsh"); 2 | 3 | class BondingCurveAccount { 4 | 5 | 6 | constructor( 7 | discriminator, 8 | virtualTokenReserves, 9 | virtualSolReserves, 10 | realTokenReserves, 11 | realSolReserves, 12 | tokenTotalSupply, 13 | complete 14 | ) { 15 | this.discriminator = discriminator; 16 | this.virtualTokenReserves = virtualTokenReserves; 17 | this.virtualSolReserves = virtualSolReserves; 18 | this.realTokenReserves = realTokenReserves; 19 | this.realSolReserves = realSolReserves; 20 | this.tokenTotalSupply = tokenTotalSupply; 21 | this.complete = complete; 22 | } 23 | 24 | getBuyPrice(amount) { 25 | if (this.complete) { 26 | throw new Error("Curve is complete"); 27 | } 28 | 29 | if (amount <= 0n) { 30 | return 0n; 31 | } 32 | 33 | // Calculate the product of virtual reserves 34 | let n = this.virtualSolReserves * this.virtualTokenReserves; 35 | 36 | // Calculate the new virtual sol reserves after the purchase 37 | let i = this.virtualSolReserves + amount; 38 | 39 | // Calculate the new virtual token reserves after the purchase 40 | let r = n / i + 1n; 41 | 42 | // Calculate the amount of tokens to be purchased 43 | let s = this.virtualTokenReserves - r; 44 | 45 | // Return the minimum of the calculated tokens and real token reserves 46 | return s < this.realTokenReserves ? s : this.realTokenReserves; 47 | } 48 | 49 | getSellPrice(amount , feeBasisPoints ) { 50 | if (this.complete) { 51 | throw new Error("Curve is complete"); 52 | } 53 | 54 | if (amount <= 0n) { 55 | return 0n; 56 | } 57 | 58 | // Calculate the proportional amount of virtual sol reserves to be received 59 | let n = 60 | (amount * this.virtualSolReserves) / (this.virtualTokenReserves + amount); 61 | 62 | // Calculate the fee amount in the same units 63 | let a = (n * feeBasisPoints) / 10000n; 64 | 65 | // Return the net amount after deducting the fee 66 | return n - a; 67 | } 68 | 69 | getMarketCapSOL() { 70 | if (this.virtualTokenReserves === 0n) { 71 | return 0n; 72 | } 73 | 74 | return ( 75 | (this.tokenTotalSupply * this.virtualSolReserves) / 76 | this.virtualTokenReserves 77 | ); 78 | } 79 | 80 | getFinalMarketCapSOL(feeBasisPoints){ 81 | let totalSellValue = this.getBuyOutPrice( 82 | this.realTokenReserves, 83 | feeBasisPoints 84 | ); 85 | let totalVirtualValue = this.virtualSolReserves + totalSellValue; 86 | let totalVirtualTokens = this.virtualTokenReserves - this.realTokenReserves; 87 | 88 | if (totalVirtualTokens === 0n) { 89 | return 0n; 90 | } 91 | 92 | return (this.tokenTotalSupply * totalVirtualValue) / totalVirtualTokens; 93 | } 94 | 95 | getBuyOutPrice(amount, feeBasisPoints) { 96 | let solTokens = 97 | amount < this.realSolReserves ? this.realSolReserves : amount; 98 | let totalSellValue = 99 | (solTokens * this.virtualSolReserves) / 100 | (this.virtualTokenReserves - solTokens) + 101 | 1n; 102 | let fee = (totalSellValue * feeBasisPoints) / 10000n; 103 | return totalSellValue + fee; 104 | } 105 | 106 | static fromBuffer(buffer) { 107 | const structure = struct([ 108 | u64("discriminator"), 109 | u64("virtualTokenReserves"), 110 | u64("virtualSolReserves"), 111 | u64("realTokenReserves"), 112 | u64("realSolReserves"), 113 | u64("tokenTotalSupply"), 114 | bool("complete"), 115 | ]); 116 | 117 | let value = structure.decode(buffer); 118 | return new BondingCurveAccount( 119 | BigInt(value.discriminator), 120 | BigInt(value.virtualTokenReserves), 121 | BigInt(value.virtualSolReserves), 122 | BigInt(value.realTokenReserves), 123 | BigInt(value.realSolReserves), 124 | BigInt(value.tokenTotalSupply), 125 | value.complete 126 | ); 127 | } 128 | } 129 | 130 | module.exports = {BondingCurveAccount}; -------------------------------------------------------------------------------- /src/Trading/memecoin_trading_strategies/copy_trading/copy-sell.js: -------------------------------------------------------------------------------- 1 | const { 2 | PublicKey, 3 | } = require("@solana/web3.js"); 4 | const { 5 | TOKEN_PROGRAM_ID, 6 | AccountLayout, 7 | } = require("@solana/spl-token"); 8 | const fs = require('fs'); 9 | const path = require('path'); 10 | const { wallet, second_connection, smart_money_wallet } = require("../../../helpers/config"); 11 | //const { buy } = require("../../dex/jupiter/swap/buy-helper"); 12 | //const { sell } = require("../../dex/jupiter/swap/sell-helper"); 13 | const {sell} = require("../../dex/raydium/sell_helper") 14 | 15 | //const {swap} = require("../../../Pool/swap") 16 | var current_trader_wallet_state = {}; 17 | var current_our_wallet_state = {}; 18 | // [usdc, sol, usdt, wsol] 19 | const wsol = "So11111111111111111111111111111111111111112" 20 | const quoteToken = [ 21 | "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", 22 | "SOL", 23 | "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", 24 | wsol, 25 | ]; 26 | const boughtTokensPath = path.join(__dirname, 'bought-tokens.json'); 27 | let boughtTokens = JSON.parse(fs.readFileSync(boughtTokensPath, 'utf8')); 28 | console.log(boughtTokens); 29 | function saveToJson() { 30 | fs.writeFileSync(boughtTokensPath, JSON.stringify(boughtTokens, null, 2)); 31 | } 32 | /** 33 | * Retrieves the state of a wallet by querying the Solana blockchain. 34 | * @param {string} wallet_address - The address of the wallet to retrieve the state for. 35 | * @returns {Object} - An object containing the token balances of the wallet and the SOL balance. 36 | */ 37 | async function retriveWalletState(wallet_address) { 38 | const filters = [ 39 | { 40 | dataSize: 165, //size of account (bytes) 41 | }, 42 | { 43 | memcmp: { 44 | offset: 32, //location of our query in the account (bytes) 45 | bytes: wallet_address, //our search criteria, a base58 encoded string 46 | }, 47 | }, 48 | ]; 49 | const accounts = await second_connection.getParsedProgramAccounts( 50 | TOKEN_PROGRAM_ID, //new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") 51 | { filters: filters } 52 | ); 53 | let results = {}; 54 | const solBalance = await second_connection.getBalance(new PublicKey(wallet_address)); 55 | accounts.forEach((account, i) => { 56 | //Parse the account data 57 | const parsedAccountInfo = account.account.data; 58 | const mintAddress = parsedAccountInfo["parsed"]["info"]["mint"]; 59 | const tokenBalance = 60 | parsedAccountInfo["parsed"]["info"]["tokenAmount"]["uiAmount"]; 61 | 62 | results[mintAddress] = tokenBalance; 63 | results["SOL"] = solBalance / 10 ** 9; 64 | }); 65 | return results; 66 | } 67 | async function copy_sell(address){ 68 | // 400 ms to check the wallet state 69 | // if token we have but trader doesn't have, sell it 70 | // that's it 71 | let soldTokens = []; 72 | let flag = false; 73 | let possible_cant_sell_token = null 74 | try{ 75 | if(boughtTokens.length > 0){ 76 | for(let i=0; i !soldTokens.includes(token)); 97 | // Save the updated list back to the JSON file 98 | saveToJson(); 99 | 100 | } 101 | 102 | } 103 | async function main(){ 104 | while(true){ 105 | boughtTokens = JSON.parse(fs.readFileSync(boughtTokensPath, 'utf8')); 106 | console.log(boughtTokens); 107 | await copy_sell(smart_money_wallet); 108 | 109 | await new Promise((resolve) => setTimeout(resolve, 2500)); 110 | } 111 | } 112 | main(); 113 | module.exports = {copy_sell} 114 | -------------------------------------------------------------------------------- /src/Token/revoke_authority.js: -------------------------------------------------------------------------------- 1 | const { AuthorityType, setAuthority } = require("@solana/spl-token"); 2 | const bs58 = require("bs58"); 3 | const fs = require("fs"); 4 | const { Connection, PublicKey, Keypair } = require("@solana/web3.js"); 5 | const { program } = require("commander"); 6 | const { connection, dev_connection } = require("../helpers/config"); 7 | const { loadOrCreateKeypair_wallet } = require("../helpers/util"); 8 | const { wallet } = require("../helpers/config"); 9 | 10 | let newConnection = null; 11 | let payer_keypair_path = null, 12 | token_address = null, 13 | mint = false, 14 | freeze = false; 15 | program 16 | .option("--payer ", "Specify the path to the secret key") 17 | .option("--token_address ", "Specify the token address") 18 | .option("--cluster ", "Specify the cluster") 19 | .option("-m, --mint", "Specify the mint") 20 | .option("-f, --freeze", "Specify the freeze") 21 | .option("-h, --help", "display help for command") 22 | .action((options) => { 23 | if (options.help) { 24 | console.log( 25 | "node revoke_authority --payer --mint_address --cluster --mint --freeze" 26 | ); 27 | process.exit(0); 28 | } 29 | if (!options.token_address || !options.cluster) { 30 | console.error("❌ Missing required options"); 31 | process.exit(1); 32 | } 33 | if (options.payer) { 34 | payer_keypair_path = options.payer; 35 | } 36 | token_address = options.token_address; 37 | if (options.mint) { 38 | mint = true; 39 | } 40 | if (options.freeze) { 41 | freeze = true; 42 | } 43 | cluster = options.cluster; 44 | if (cluster === "devnet") { 45 | newConnection = connection; 46 | } else if (cluster === "mainnet") { 47 | newConnection = dev_connection; 48 | } else { 49 | console.error("❌ Cluster not supported"); 50 | process.exit(1); 51 | } 52 | }); 53 | program.parse(); 54 | 55 | /** 56 | * Revokes the mint authority for a given mint. 57 | * @param {string} mint - The mint address. 58 | * @param {string} payer - The payer address. 59 | * @param {string} owner - The owner address. 60 | * @returns {Promise} - A promise that resolves when the mint authority is revoked. 61 | */ 62 | async function revokeMint(mint, payer, owner) { 63 | console.log("Disabling the mint authority..."); 64 | await setAuthority( 65 | newConnection, 66 | payer, 67 | mint, 68 | owner, 69 | AuthorityType.MintTokens, 70 | null 71 | ).catch((error) => { 72 | console.error(error); 73 | console.log("Error: try again..."); 74 | revokeMint(mint, payer, owner); 75 | }); 76 | } 77 | /** 78 | * Disables the freeze authority for a given mint and owner. 79 | * @param {string} mint - The mint address. 80 | * @param {string} payer - The payer address. 81 | * @param {string} owner - The owner address. 82 | * @returns {Promise} - A promise that resolves when the freeze authority is disabled. 83 | */ 84 | async function revokeFreeze(mint, payer, owner) { 85 | console.log("Disabling the freeze authority..."); 86 | await setAuthority( 87 | newConnection, 88 | payer, 89 | mint, 90 | owner, 91 | AuthorityType.FreezeAccount, 92 | null 93 | ).catch((error) => { 94 | console.error(error); 95 | console.log("Error: try again..."); 96 | revokeFreeze(mint, payer, owner); 97 | }); 98 | } 99 | 100 | /** 101 | * Revoke authority for a token. 102 | * @async 103 | * @function revokeAuthority 104 | * @returns {Promise} 105 | */ 106 | async function revokeAuthority() { 107 | // let payer_wallet = null; 108 | // if (payer_keypair !== null) { 109 | // payer_wallet = await loadOrCreateKeypair_wallet(payer_keypair); 110 | // await swap(side, address, no_of_sol, -1, payer_wallet); 111 | // } else { 112 | // await swap(side, address, no_of_sol, -1, wallet); 113 | // } 114 | let payer_wallet = null; 115 | const token_mint = new PublicKey(token_address); 116 | if (payer_keypair_path !== null) { 117 | payer_wallet = await loadOrCreateKeypair_wallet(payer_keypair_path); 118 | if (mint) { 119 | await revokeMint(token_mint, payer_wallet, payer_wallet); 120 | } 121 | if (freeze) { 122 | await revokeFreeze(token_mint, payer_wallet, payer_wallet); 123 | } 124 | } else { 125 | if (mint) { 126 | await revokeMint(token_mint, payer_wallet, wallet); 127 | } 128 | if (freeze) { 129 | await revokeFreeze(token_mint, payer_wallet, wallet); 130 | } 131 | } 132 | } 133 | 134 | revokeAuthority(); 135 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/example/basic/index.ts: -------------------------------------------------------------------------------- 1 | import dotenv from "dotenv"; 2 | import fs from "fs"; 3 | import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js"; 4 | import { DEFAULT_DECIMALS, PumpFunSDK } from "../../src"; 5 | import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet"; 6 | import { AnchorProvider } from "@coral-xyz/anchor"; 7 | import { 8 | getOrCreateKeypair, 9 | getSPLBalance, 10 | printSOLBalance, 11 | printSPLBalance, 12 | } from "../util"; 13 | 14 | const KEYS_FOLDER = __dirname + "/.keys";s 15 | const SLIPPAGE_BASIS_POINTS = 100n; 16 | 17 | //create token example: 18 | //https://solscan.io/tx/bok9NgPeoJPtYQHoDqJZyRDmY88tHbPcAk1CJJsKV3XEhHpaTZhUCG3mA9EQNXcaUfNSgfPkuVbEsKMp6H7D9NY 19 | //devnet faucet 20 | //https://faucet.solana.com/ 21 | 22 | const main = async () => { 23 | dotenv.config(); 24 | 25 | if (!process.env.HELIUS_RPC_URL) { 26 | console.error("Please set HELIUS_RPC_URL in .env file"); 27 | console.error( 28 | "Example: HELIUS_RPC_URL=https://mainnet.helius-rpc.com/?api-key=" 29 | ); 30 | console.error("Get one at: https://www.helius.dev"); 31 | return; 32 | } 33 | 34 | let connection = new Connection(process.env.HELIUS_RPC_URL || ""); 35 | 36 | let wallet = new NodeWallet(new Keypair()); //note this is not used 37 | const provider = new AnchorProvider(connection, wallet, { 38 | commitment: "finalized", 39 | }); 40 | 41 | const testAccount = getOrCreateKeypair(KEYS_FOLDER, "test-account"); 42 | const mint = getOrCreateKeypair(KEYS_FOLDER, "mint"); 43 | 44 | await printSOLBalance( 45 | connection, 46 | testAccount.publicKey, 47 | "Test Account keypair" 48 | ); 49 | 50 | let sdk = new PumpFunSDK(provider); 51 | 52 | let globalAccount = await sdk.getGlobalAccount(); 53 | console.log(globalAccount); 54 | 55 | let currentSolBalance = await connection.getBalance(testAccount.publicKey); 56 | if (currentSolBalance == 0) { 57 | console.log( 58 | "Please send some SOL to the test-account:", 59 | testAccount.publicKey.toBase58() 60 | ); 61 | return; 62 | } 63 | 64 | console.log(await sdk.getGlobalAccount()); 65 | 66 | //Check if mint already exists 67 | let boundingCurveAccount = await sdk.getBondingCurveAccount(mint.publicKey); 68 | if (!boundingCurveAccount) { 69 | let tokenMetadata = { 70 | name: "TST-7", 71 | symbol: "TST-7", 72 | description: "TST-7: This is a test token", 73 | file: await fs.openAsBlob("example/basic/random.png"), 74 | }; 75 | 76 | let createResults = await sdk.createAndBuy( 77 | testAccount, 78 | mint, 79 | tokenMetadata, 80 | BigInt(0.0001 * LAMPORTS_PER_SOL), 81 | SLIPPAGE_BASIS_POINTS, 82 | { 83 | unitLimit: 250000, 84 | unitPrice: 250000, 85 | }, 86 | ); 87 | 88 | if (createResults.success) { 89 | console.log("Success:", `https://pump.fun/${mint.publicKey.toBase58()}`); 90 | boundingCurveAccount = await sdk.getBondingCurveAccount(mint.publicKey); 91 | console.log("Bonding curve after create and buy", boundingCurveAccount); 92 | printSPLBalance(connection, mint.publicKey, testAccount.publicKey); 93 | } 94 | } else { 95 | console.log("boundingCurveAccount", boundingCurveAccount); 96 | console.log("Success:", `https://pump.fun/${mint.publicKey.toBase58()}`); 97 | printSPLBalance(connection, mint.publicKey, testAccount.publicKey); 98 | } 99 | 100 | if (boundingCurveAccount) { 101 | //buy 0.0001 SOL worth of tokens 102 | let buyResults = await sdk.buy( 103 | testAccount, 104 | mint.publicKey, 105 | BigInt(0.0001 * LAMPORTS_PER_SOL), 106 | SLIPPAGE_BASIS_POINTS, 107 | { 108 | unitLimit: 250000, 109 | unitPrice: 250000, 110 | }, 111 | ); 112 | 113 | if (buyResults.success) { 114 | printSPLBalance(connection, mint.publicKey, testAccount.publicKey); 115 | console.log("Bonding curve after buy", await sdk.getBondingCurveAccount(mint.publicKey)); 116 | } else { 117 | console.log("Buy failed"); 118 | } 119 | 120 | //sell all tokens 121 | let currentSPLBalance = await getSPLBalance( 122 | connection, 123 | mint.publicKey, 124 | testAccount.publicKey 125 | ); 126 | console.log("currentSPLBalance", currentSPLBalance); 127 | if (currentSPLBalance) { 128 | let sellResults = await sdk.sell( 129 | testAccount, 130 | mint.publicKey, 131 | BigInt(currentSPLBalance * Math.pow(10, DEFAULT_DECIMALS)), 132 | SLIPPAGE_BASIS_POINTS, 133 | { 134 | unitLimit: 250000, 135 | unitPrice: 250000, 136 | }, 137 | ); 138 | if (sellResults.success) { 139 | await printSOLBalance( 140 | connection, 141 | testAccount.publicKey, 142 | "Test Account keypair" 143 | ); 144 | 145 | printSPLBalance(connection, mint.publicKey, testAccount.publicKey, "After SPL sell all"); 146 | console.log("Bonding curve after sell", await sdk.getBondingCurveAccount(mint.publicKey)); 147 | } else { 148 | console.log("Sell failed"); 149 | } 150 | } 151 | } 152 | }; 153 | 154 | main(); 155 | -------------------------------------------------------------------------------- /src/Pool/formatAmmKeysById.js: -------------------------------------------------------------------------------- 1 | const { 2 | LIQUIDITY_STATE_LAYOUT_V4, 3 | MARKET_STATE_LAYOUT_V3, 4 | SPL_MINT_LAYOUT, 5 | Liquidity, 6 | Market, 7 | MAINNET_PROGRAM_ID, 8 | publicKey, 9 | struct, 10 | } = require("@raydium-io/raydium-sdk"); 11 | const { PublicKey } = require("@solana/web3.js"); 12 | const MINIMAL_MARKET_STATE_LAYOUT_V3 = struct([ 13 | publicKey("eventQueue"), 14 | publicKey("bids"), 15 | publicKey("asks"), 16 | ]); 17 | const { connection } = require("../helpers/config.js"); 18 | 19 | // Promise 20 | /** 21 | * Formats AMM keys by ID. 22 | * @param {string} id - The ID of the AMM. 23 | * @returns {Object} - The formatted AMM keys. 24 | * @throws {Error} - If there is an error retrieving the account information. 25 | */ 26 | async function formatAmmKeysById_swap(id) { 27 | const account = await connection.getAccountInfo(id); 28 | if (account === null) throw Error(" get id info error "); 29 | const info = LIQUIDITY_STATE_LAYOUT_V4.decode(account.data); 30 | 31 | const marketId = info.marketId; 32 | const marketAccount_minimal = await connection.getAccountInfo(marketId, { 33 | commitment: "confirmed", 34 | dataSlice: { 35 | offset: MARKET_STATE_LAYOUT_V3.offsetOf("eventQueue"), 36 | length: 32 * 3, 37 | }, 38 | }); 39 | const marketAccount = await connection.getAccountInfo(marketId); 40 | if (marketAccount === null || marketAccount_minimal === null) 41 | throw Error(" get market info error"); 42 | const marketInfo_minimal = MINIMAL_MARKET_STATE_LAYOUT_V3.decode( 43 | marketAccount_minimal.data 44 | ); 45 | const marketInfo = MARKET_STATE_LAYOUT_V3.decode(marketAccount.data); 46 | const lpMint = info.lpMint; 47 | const lpMintAccount = await connection.getAccountInfo(lpMint); 48 | if (lpMintAccount === null) throw Error(" get lp mint info error"); 49 | const lpMintInfo = SPL_MINT_LAYOUT.decode(lpMintAccount.data); 50 | 51 | return { 52 | id, 53 | baseMint: info.baseMint, 54 | quoteMint: info.quoteMint, 55 | lpMint: info.lpMint, 56 | baseDecimals: info.baseDecimal.toNumber(), 57 | quoteDecimals: info.quoteDecimal.toNumber(), 58 | lpDecimals: 5, 59 | version: 4, 60 | programId: MAINNET_PROGRAM_ID.AmmV4, 61 | authority: Liquidity.getAssociatedAuthority({ 62 | programId: MAINNET_PROGRAM_ID.AmmV4, 63 | }).publicKey, 64 | openOrders: info.openOrders, 65 | targetOrders: info.targetOrders, 66 | baseVault: info.baseVault, 67 | quoteVault: info.quoteVault, 68 | marketVersion: 3, 69 | marketProgramId: info.marketProgramId, 70 | marketId: info.marketId, 71 | marketAuthority: Market.getAssociatedAuthority({ 72 | programId: info.marketProgramId, 73 | marketId: info.marketId, 74 | }).publicKey, 75 | marketBaseVault: marketInfo.baseVault, 76 | marketQuoteVault: marketInfo.quoteVault, 77 | marketBids: marketInfo_minimal.bids, 78 | marketAsks: marketInfo_minimal.asks, 79 | marketEventQueue: marketInfo_minimal.eventQueue, 80 | withdrawQueue: info.withdrawQueue, 81 | lpVault: info.lpVault, 82 | lookupTableAccount: PublicKey.default, 83 | }; 84 | } 85 | 86 | async function formatAmmKeysById_pool(id) { 87 | const account = await connection.getAccountInfo(id); 88 | if (account === null) throw Error(" get id info error "); 89 | const info = LIQUIDITY_STATE_LAYOUT_V4.decode(account.data); 90 | 91 | const marketId = info.marketId; 92 | const marketAccount = await connection.getAccountInfo(marketId); 93 | if (marketAccount === null) throw Error(" get market info error"); 94 | const marketInfo = MARKET_STATE_LAYOUT_V3.decode(marketAccount.data); 95 | 96 | const lpMint = info.lpMint; 97 | const lpMintAccount = await connection.getAccountInfo(lpMint); 98 | if (lpMintAccount === null) throw Error(" get lp mint info error"); 99 | const lpMintInfo = SPL_MINT_LAYOUT.decode(lpMintAccount.data); 100 | 101 | return { 102 | id, 103 | baseMint: info.baseMint.toString(), 104 | quoteMint: info.quoteMint.toString(), 105 | lpMint: info.lpMint.toString(), 106 | baseDecimals: info.baseDecimal.toNumber(), 107 | quoteDecimals: info.quoteDecimal.toNumber(), 108 | lpDecimals: lpMintInfo.decimals, 109 | version: 4, 110 | programId: account.owner.toString(), 111 | authority: Liquidity.getAssociatedAuthority({ 112 | programId: account.owner, 113 | }).publicKey.toString(), 114 | openOrders: info.openOrders.toString(), 115 | targetOrders: info.targetOrders.toString(), 116 | baseVault: info.baseVault.toString(), 117 | quoteVault: info.quoteVault.toString(), 118 | withdrawQueue: info.withdrawQueue.toString(), 119 | lpVault: info.lpVault.toString(), 120 | marketVersion: 3, 121 | marketProgramId: info.marketProgramId.toString(), 122 | marketId: info.marketId.toString(), 123 | marketAuthority: Market.getAssociatedAuthority({ 124 | programId: info.marketProgramId, 125 | marketId: info.marketId, 126 | }).publicKey.toString(), 127 | marketBaseVault: marketInfo.baseVault.toString(), 128 | marketQuoteVault: marketInfo.quoteVault.toString(), 129 | marketBids: marketInfo.bids.toString(), 130 | marketAsks: marketInfo.asks.toString(), 131 | marketEventQueue: marketInfo.eventQueue.toString(), 132 | lookupTableAccount: PublicKey.default.toString(), 133 | }; 134 | } 135 | 136 | module.exports = { formatAmmKeysById_swap, formatAmmKeysById_pool }; 137 | -------------------------------------------------------------------------------- /src/Transactions/jito_tips_tx_executor.js: -------------------------------------------------------------------------------- 1 | const { 2 | BlockhashWithExpiryBlockHeight, 3 | Keypair, 4 | PublicKey, 5 | SystemProgram, 6 | Connection, 7 | TransactionMessage, 8 | VersionedTransaction, 9 | } = require("@solana/web3.js"); 10 | const axios = require("axios"); 11 | const bs58 = require("bs58"); 12 | const { Currency, CurrencyAmount } = require("@raydium-io/raydium-sdk"); 13 | const { connection } = require("../helpers/config"); 14 | const jito_Validators = [ 15 | "DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh", 16 | "ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt", 17 | "3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT", 18 | "HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe", 19 | "ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49", 20 | "Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY", 21 | "DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL", 22 | "96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5", 23 | ]; 24 | const endpoints = [ // TODO: Choose a jito endpoint which is closest to your location, and uncomment others 25 | "https://mainnet.block-engine.jito.wtf/api/v1/bundles", 26 | "https://amsterdam.mainnet.block-engine.jito.wtf/api/v1/bundles", 27 | "https://frankfurt.mainnet.block-engine.jito.wtf/api/v1/bundles", 28 | "https://ny.mainnet.block-engine.jito.wtf/api/v1/bundles", 29 | "https://tokyo.mainnet.block-engine.jito.wtf/api/v1/bundles", 30 | ]; 31 | 32 | /** 33 | * Generates a random validator from the list of jito_Validators. 34 | * @returns {PublicKey} A new PublicKey representing the random validator. 35 | */ 36 | async function getRandomValidator() { 37 | const res = 38 | jito_Validators[Math.floor(Math.random() * jito_Validators.length)]; 39 | return new PublicKey(res); 40 | } 41 | /** 42 | * Executes and confirms a Jito transaction. 43 | * @param {Transaction} transaction - The transaction to be executed and confirmed. 44 | * @param {Account} payer - The payer account for the transaction. 45 | * @param {Blockhash} lastestBlockhash - The latest blockhash. 46 | * @param {number} jitofee - The fee for the Jito transaction. 47 | * @returns {Promise<{ confirmed: boolean, signature: string | null }>} - A promise that resolves to an object containing the confirmation status and the transaction signature. 48 | */ 49 | async function jito_executeAndConfirm( 50 | transaction, 51 | payer, 52 | lastestBlockhash, 53 | jitofee 54 | ) { 55 | console.log("Executing transaction (jito)..."); 56 | const jito_validator_wallet = await getRandomValidator(); 57 | console.log("Selected Jito Validator: ", jito_validator_wallet.toBase58()); 58 | try { 59 | const fee = new CurrencyAmount(Currency.SOL, jitofee, false).raw.toNumber(); 60 | console.log(`Jito Fee: ${fee / 10 ** 9} sol`); 61 | const jitoFee_message = new TransactionMessage({ 62 | payerKey: payer.publicKey, 63 | recentBlockhash: lastestBlockhash.blockhash, 64 | instructions: [ 65 | SystemProgram.transfer({ 66 | fromPubkey: payer.publicKey, 67 | toPubkey: jito_validator_wallet, 68 | lamports: fee, 69 | }), 70 | ], 71 | }).compileToV0Message(); 72 | const jitoFee_transaction = new VersionedTransaction(jitoFee_message); 73 | jitoFee_transaction.sign([payer]); 74 | const jitoTxSignature = bs58.encode(jitoFee_transaction.signatures[0]); 75 | const serializedJitoFeeTransaction = bs58.encode( 76 | jitoFee_transaction.serialize() 77 | ); 78 | const serializedTransaction = bs58.encode(transaction.serialize()); 79 | const final_transaction = [ 80 | serializedJitoFeeTransaction, 81 | serializedTransaction, 82 | ]; 83 | const requests = endpoints.map((url) => 84 | axios.post(url, { 85 | jsonrpc: "2.0", 86 | id: 1, 87 | method: "sendBundle", 88 | params: [final_transaction], 89 | }) 90 | ); 91 | console.log("Sending tx to Jito validators..."); 92 | const res = await Promise.all(requests.map((p) => p.catch((e) => e))); 93 | const success_res = res.filter((r) => !(r instanceof Error)); 94 | if (success_res.length > 0) { 95 | console.log("Jito validator accepted the tx"); 96 | return await jito_confirm(jitoTxSignature, lastestBlockhash); 97 | } else { 98 | console.log("No Jito validators accepted the tx"); 99 | return { confirmed: false, signature: jitoTxSignature }; 100 | } 101 | } catch (e) { 102 | if (e instanceof axios.AxiosError) { 103 | console.log("Failed to execute the jito transaction"); 104 | } else { 105 | console.log("Error during jito transaction execution: ", e); 106 | } 107 | return { confirmed: false, signature: null }; 108 | } 109 | } 110 | 111 | /** 112 | * Confirms a transaction on the Solana blockchain. 113 | * @param {string} signature - The signature of the transaction. 114 | * @param {object} latestBlockhash - The latest blockhash information. 115 | * @returns {object} - An object containing the confirmation status and the transaction signature. 116 | */ 117 | async function jito_confirm(signature, latestBlockhash) { 118 | console.log("Confirming the jito transaction..."); 119 | const confirmation = await connection.confirmTransaction( 120 | { 121 | signature, 122 | lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, 123 | blockhash: latestBlockhash.blockhash, 124 | }, 125 | "confirmed" 126 | ); 127 | return { confirmed: !confirmation.value.err, signature }; 128 | } 129 | 130 | module.exports = { jito_executeAndConfirm }; 131 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/transactions/jito-tx-executor.js: -------------------------------------------------------------------------------- 1 | const { 2 | BlockhashWithExpiryBlockHeight, 3 | Keypair, 4 | PublicKey, 5 | SystemProgram, 6 | Connection, 7 | TransactionMessage, 8 | VersionedTransaction, 9 | } = require("@solana/web3.js"); 10 | const axios = require("axios"); 11 | const bs58 = require("bs58"); 12 | const { Currency, CurrencyAmount } = require("@raydium-io/raydium-sdk"); 13 | const { connection } = require("../../../../helpers/config"); 14 | const jito_Validators = [ 15 | "DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh", 16 | "ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt", 17 | "3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT", 18 | "HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe", 19 | "ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49", 20 | "Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY", 21 | "DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL", 22 | "96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5", 23 | ]; 24 | const endpoints = [ // TODO: Choose a jito endpoint which is closest to your location, and uncomment others 25 | //"https://mainnet.block-engine.jito.wtf/api/v1/bundles", 26 | //"https://amsterdam.mainnet.block-engine.jito.wtf/api/v1/bundles", 27 | //"https://frankfurt.mainnet.block-engine.jito.wtf/api/v1/bundles", 28 | //"https://ny.mainnet.block-engine.jito.wtf/api/v1/bundles", 29 | "https://tokyo.mainnet.block-engine.jito.wtf/api/v1/bundles", 30 | ]; 31 | async function getRandomValidator() { 32 | const res = 33 | jito_Validators[Math.floor(Math.random() * jito_Validators.length)]; 34 | return new PublicKey(res); 35 | } 36 | /** 37 | * Executes and confirms a Jito transaction. 38 | * @param {Transaction} transaction - The transaction to be executed and confirmed. 39 | * @param {Account} payer - The payer account for the transaction. 40 | * @param {Blockhash} lastestBlockhash - The latest blockhash. 41 | * @param {number} jitofee - The fee for the Jito transaction. 42 | * @returns {Promise<{ confirmed: boolean, signature: string | null }>} - A promise that resolves to an object containing the confirmation status and the transaction signature. 43 | */ 44 | async function jito_executeAndConfirm( 45 | transaction, 46 | payer, 47 | lastestBlockhash, 48 | jitofee 49 | ){ 50 | const jito_validator_wallet = await getRandomValidator(); 51 | console.log("Executing transaction (jito)..."); 52 | console.log("Selected Jito Validator: ", jito_validator_wallet.toBase58()); 53 | try { 54 | const fee = new CurrencyAmount(Currency.SOL, jitofee, false).raw.toNumber(); 55 | console.log(`Jito Fee: ${fee / 10 ** 9} sol`); 56 | const jitoFee_message = new TransactionMessage({ 57 | payerKey: payer.publicKey, 58 | recentBlockhash: lastestBlockhash.blockhash, 59 | instructions: [ 60 | SystemProgram.transfer({ 61 | fromPubkey: payer.publicKey, 62 | toPubkey: jito_validator_wallet, 63 | lamports: fee, 64 | }), 65 | ], 66 | }).compileToV0Message(); 67 | const jitoFee_transaction = new VersionedTransaction(jitoFee_message); 68 | jitoFee_transaction.sign([payer]); 69 | const jitoTxSignature = bs58.encode(jitoFee_transaction.signatures[0]); 70 | const serializedJitoFeeTransaction = bs58.encode( 71 | jitoFee_transaction.serialize() 72 | ); 73 | const serializedTransaction = bs58.encode(transaction.serialize()); 74 | const final_transaction = [ 75 | serializedJitoFeeTransaction, 76 | serializedTransaction, 77 | ]; 78 | const requests = endpoints.map((url) => 79 | axios.post(url, { 80 | jsonrpc: "2.0", 81 | id: 1, 82 | method: "sendBundle", 83 | params: [final_transaction], 84 | }) 85 | ); 86 | console.log("Sending tx to Jito validators..."); 87 | const res = await Promise.all(requests.map((p) => p.catch((e) => e))); 88 | const success_res = res.filter((r) => !(r instanceof Error)); 89 | if (success_res.length > 0) { 90 | console.log("Jito validator accepted the tx"); 91 | return await jito_confirm(jitoTxSignature, lastestBlockhash); 92 | } else { 93 | console.log("No Jito validators accepted the tx"); 94 | return { confirmed: false, signature: jitoTxSignature }; 95 | } 96 | } catch (e) { 97 | if (e instanceof axios.AxiosError) { 98 | console.log("Failed to execute the jito transaction"); 99 | } else { 100 | console.log("Error during jito transaction execution: ", e); 101 | } 102 | return { confirmed: false, signature: null }; 103 | } 104 | } 105 | 106 | /** 107 | * Confirms a transaction on the Solana blockchain. 108 | * @param {string} signature - The signature of the transaction. 109 | * @param {object} latestBlockhash - The latest blockhash information. 110 | * @returns {object} - An object containing the confirmation status and the transaction signature. 111 | */ 112 | async function jito_confirm(signature, latestBlockhash) { 113 | console.log("Confirming the jito transaction..."); 114 | const confirmation = await connection.confirmTransaction( 115 | { 116 | signature, 117 | lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, 118 | blockhash: latestBlockhash.blockhash, 119 | }, 120 | "confirmed" 121 | ); 122 | return { confirmed: !confirmation.value.err, signature: signature }; 123 | } 124 | 125 | 126 | module.exports = { jito_executeAndConfirm, jito_confirm }; -------------------------------------------------------------------------------- /src/Trading/dex/jupiter/swap/swap-helper.js: -------------------------------------------------------------------------------- 1 | const { VersionedTransaction, PublicKey } = require("@solana/web3.js"); 2 | const fetch = require("cross-fetch"); 3 | const { connection, wallet, jito_fee } = require("../../../../helpers/config"); 4 | const { 5 | jito_executeAndConfirm, 6 | } = require("../../../../Transactions/jito_tips_tx_executor"); 7 | const { getDecimals } = require("../../../../helpers/util"); 8 | /** 9 | * Retrieves a quote for swapping tokens. 10 | * 11 | * @param {string} tokenToSell - The output token's mint address. 12 | * @param {string} tokenToBuy - The input token's mint address. 13 | * @param {number} convertedAmountOfTokenOut - The amount of output token to be converted. 14 | * @param {number} slippage - The allowed slippage in basis points. 15 | * @returns {Promise} - The quote object containing swap details. 16 | */ 17 | async function getQuote( 18 | tokenToSell, 19 | tokenToBuy, 20 | convertedAmountOfTokenOut, 21 | slippage 22 | ) { 23 | const url = `https://quote-api.jup.ag/v6/quote?inputMint=${tokenToSell}&outputMint=${tokenToBuy}&amount=${convertedAmountOfTokenOut}&slippageBps=${slippage}`; 24 | const response = await fetch(url); 25 | const quote = await response.json(); 26 | return quote; 27 | } 28 | 29 | /** 30 | * Retrieves the swap transaction from the quote API. 31 | * @param {Object} quoteResponse - The quote response object. 32 | * @param {string} wallet_pubKey - The public key of the user's wallet. 33 | * @returns {Promise} - The swap transaction. 34 | * @throws {Error} - If an error occurs during the process. 35 | */ 36 | async function getSwapTransaction(quoteResponse, wallet_pubKey) { 37 | try { 38 | let body = null; 39 | body = { 40 | quoteResponse, 41 | userPublicKey: wallet_pubKey, 42 | wrapAndUnwrapSol: true, 43 | dynamicComputeUnitLimit: true, // allow dynamic compute limit instead of max 1,400,000 44 | prioritizationFeeLamports: 4211970, // prioritization fee 45 | prioritizationFeeLamports: { 46 | autoMultiplier: 2, 47 | }, 48 | }; 49 | const resp = await fetch("https://quote-api.jup.ag/v6/swap", { 50 | method: "POST", 51 | headers: { 52 | "Content-Type": "application/json", 53 | }, 54 | body: JSON.stringify(body), 55 | }); 56 | const swapResponse = await resp.json(); 57 | return swapResponse.swapTransaction; 58 | } catch (error) { 59 | throw new Error(error); 60 | } 61 | } 62 | /** 63 | * Converts the given amount to an integer by multiplying it with 10 raised to the power of decimals. 64 | * @param {number} amount - The amount to be converted. 65 | * @param {number} decimals - The number of decimal places. 66 | * @returns {Promise} The converted integer value. 67 | */ 68 | async function convertToInteger(amount, decimals) { 69 | return Math.floor(amount * 10 ** decimals); 70 | } 71 | 72 | /** 73 | * Finalizes a swap transaction by deserializing, signing, and executing the transaction. 74 | * @param {string} swapTransaction - The base64 encoded swap transaction. 75 | * @returns {Promise<{ confirmed: boolean, signature: string }>} - A promise that resolves to an object containing the confirmation status and transaction signature. 76 | * @throws {Error} - If an error occurs during the transaction finalization process. 77 | */ 78 | async function finalizeTransaction(swapTransaction) { 79 | try { 80 | let confirmed = null, 81 | signature = null; 82 | // deserialize the transaction 83 | const swapTransactionBuf = Buffer.from(swapTransaction, "base64"); 84 | let transaction = VersionedTransaction.deserialize(swapTransactionBuf); 85 | // sign the transaction 86 | transaction.sign([wallet]); 87 | 88 | const latestBlockhash = await connection.getLatestBlockhash("processed"); 89 | res = await jito_executeAndConfirm( 90 | transaction, 91 | wallet, 92 | latestBlockhash, 93 | jito_fee 94 | ); 95 | confirmed = res.confirmed; 96 | signature = res.signature; 97 | return { confirmed, signature }; 98 | } catch (error) { 99 | throw new Error(error); 100 | } 101 | return { confirmed: false, signature: null }; 102 | } 103 | /** 104 | * Performs a token swap transaction. 105 | * 106 | * @param {string} tokenToSell - The token to sell. 107 | * @param {string} tokenToBuy - The token to buy. 108 | * @param {number} amountTokenOut - The amount of token to receive. 109 | * @param {number} slippage - The allowed slippage percentage. 110 | * @returns {Promise} - A promise that resolves when the swap transaction is completed. 111 | */ 112 | async function swap(tokenToSell, tokenToBuy, amountTokenOut, slippage) { 113 | try { 114 | const decimals = await getDecimals(new PublicKey(tokenToSell)); 115 | const convertedAmountOfTokenOut = await convertToInteger( 116 | amountTokenOut, 117 | decimals 118 | ); 119 | const quoteResponse = await getQuote( 120 | tokenToSell, 121 | tokenToBuy, 122 | convertedAmountOfTokenOut, 123 | slippage 124 | ); 125 | const wallet_PubKey = wallet.publicKey.toBase58(); 126 | const swapTransaction = await getSwapTransaction( 127 | quoteResponse, 128 | wallet_PubKey 129 | ); 130 | const { confirmed, signature } = await finalizeTransaction(swapTransaction); 131 | if (confirmed) { 132 | console.log("http://solscan.io/tx/" + signature); 133 | } else { 134 | console.log("Transaction failed"); 135 | console.log("retrying transaction..."); 136 | await swap(tokenToSell, tokenToBuy, amountTokenOut, slippage); 137 | } 138 | } catch (error) { 139 | console.error(error); 140 | } 141 | } 142 | module.exports = { 143 | getQuote, 144 | getSwapTransaction, 145 | finalizeTransaction, 146 | convertToInteger, 147 | swap, 148 | }; 149 | -------------------------------------------------------------------------------- /src/Token/burn.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const { 3 | Connection, 4 | PublicKey, 5 | Keypair, 6 | TransactionMessage, 7 | VersionedTransaction, 8 | } = require("@solana/web3.js"); 9 | const { program } = require("commander"); 10 | const { 11 | getAccount, 12 | getMint, 13 | getAssociatedTokenAddress, 14 | createBurnCheckedInstruction, 15 | } = require("@solana/spl-token"); 16 | const { connection, dev_connection } = require("../helpers/config"); 17 | const { wallet } = require("../helpers/config"); 18 | 19 | let payer_keypair_path = null, 20 | token_address = null, 21 | percentage = null, 22 | decimals = null, 23 | cluster = null, 24 | payerKeypair = null, 25 | newConnection = null; 26 | program 27 | .option("--payer ", "Specify the path to the secret key") 28 | .option("--token_address ", "Specify the token address") 29 | .option("--percentage ", "Specify the percentage to burn") 30 | .option("--cluster ", "Specify the cluster") 31 | .option("-h, --help", "display help for command") 32 | .action((options) => { 33 | if (options.help) { 34 | console.log( 35 | "node burn --payer --token_address --percentage --cluster " 36 | ); 37 | process.exit(0); 38 | } 39 | if (!options.token_address || !options.cluster || !options.percentage) { 40 | console.error("❌ Missing required options"); 41 | process.exit(1); 42 | } 43 | if (options.payer) { 44 | payer_keypair_path = options.payer; 45 | } 46 | token_address = new PublicKey(options.token_address); 47 | percentage = options.percentage; 48 | cluster = options.cluster; 49 | }); 50 | program.parse(); 51 | if (cluster === "devnet") { 52 | newConnection = dev_connection; 53 | } else if (cluster === "mainnet") { 54 | newConnection = connection; 55 | } 56 | /** 57 | * Loads or creates a keypair from the specified file path. 58 | * @param {string} filepath - The path to the keypair file. 59 | * @returns {Uint8Array} - The loaded or created keypair. 60 | */ 61 | function loadOrCreateKeypair(filepath) { 62 | try { 63 | const keypairStringArr = fs.readFileSync(filepath, { 64 | encoding: "utf8", 65 | }); 66 | const res = Uint8Array.from(JSON.parse(keypairStringArr)); 67 | return res; 68 | } catch (error) { 69 | console.log(error); 70 | console.log(`File ${filepath} not Found!`); 71 | process.exit(1); 72 | } 73 | } 74 | /** 75 | * Retrieves the token balance for a given token account. 76 | * @param {string} tokenAccount - The token account address. 77 | * @returns {number} The token balance. 78 | */ 79 | async function getTokenBalance(tokenAccount) { 80 | const info = await getAccount(newConnection, tokenAccount); // token account right here 81 | const amount = Number(info.amount); 82 | const mint = await getMint(newConnection, info.mint); 83 | const decimals = mint.decimals; 84 | const balance = amount / 10 ** decimals; 85 | return balance; 86 | } 87 | 88 | /** 89 | * Retrieves the decimal value of a token. 90 | * @param {string} tokenAddress - The address of the token. 91 | * @returns {Promise} The decimal value of the token. 92 | */ 93 | async function getTokenDecimal(tokenAddress) { 94 | const mint = await getMint(newConnection, tokenAddress); 95 | return mint.decimals; 96 | } 97 | /** 98 | * Burns a specified percentage of tokens from a given token address. 99 | * @param {string} tokenAddress - The address of the token to burn. 100 | * @param {object} payer - The payer's public key and associated token address. 101 | * @param {number} percentage - The percentage of tokens to burn. 102 | * @returns {Promise} - A promise that resolves when the burning process is complete. 103 | */ 104 | async function burnToken(tokenAddress, payer, percentage) { 105 | try { 106 | decimals = await getTokenDecimal(tokenAddress); 107 | console.log("Decimals: ", decimals); 108 | const account = await getAssociatedTokenAddress( 109 | tokenAddress, 110 | payer.publicKey 111 | ); 112 | const amtToBurn = Math.floor( 113 | (await getTokenBalance(account)) * (percentage / 100) 114 | ); 115 | console.log("Will burn: ", amtToBurn); 116 | // 1: fetch token account 117 | // 2: create burn instruction 118 | const burnInstruction = createBurnCheckedInstruction( 119 | account, 120 | tokenAddress, 121 | payer.publicKey, 122 | amtToBurn * 10 ** decimals, 123 | decimals 124 | ); 125 | // 3: fetch the latest blockhash 126 | const { blockhash, lastValidBlockHeight } = 127 | await newConnection.getLatestBlockhash("finalized"); 128 | // 4: assemble the transaction 129 | const messageV0 = new TransactionMessage({ 130 | payerKey: payer.publicKey, 131 | recentBlockhash: blockhash, 132 | instructions: [burnInstruction], 133 | }).compileToV0Message(); 134 | const transaction = new VersionedTransaction(messageV0); 135 | // 5: sign the transaction 136 | transaction.sign([payer]); 137 | console.log("🔥 Burning Token..."); 138 | // 6: execute and confirm the transaction (sending to Solana blockchain) 139 | const txid = await newConnection.sendTransaction(transaction); 140 | const confirmation = await newConnection.confirmTransaction({ 141 | signature: txid, 142 | blockhash, 143 | lastValidBlockHeight, 144 | }); 145 | if (confirmation.value.err) { 146 | console.error("❌ Transaction failed"); 147 | process.exit(1); 148 | } 149 | console.log( 150 | "✅ Transaction confirmed, https://explorer.solana.com/tx/" + txid 151 | ); 152 | } catch (e) { 153 | console.log(e); 154 | console.log("❌ Burn failed"); 155 | console.log("Maybe the network is congested, trying again..."); 156 | burnToken(tokenAddress, payer, percentage); 157 | } 158 | } 159 | 160 | if (payer_keypair_path) { 161 | payerKeypair = Keypair.fromSecretKey(loadOrCreateKeypair(payer_keypair_path)); 162 | } else { 163 | payerKeypair = Keypair.fromSecretKey(wallet.secretKey); 164 | } 165 | 166 | burnToken(token_address, payerKeypair, percentage); 167 | -------------------------------------------------------------------------------- /src/Pool/remove_pool.js: -------------------------------------------------------------------------------- 1 | const assert = require("assert"); 2 | 3 | const { 4 | jsonInfo2PoolKeys, 5 | Liquidity, 6 | TokenAmount, 7 | Token, 8 | TOKEN_PROGRAM_ID, 9 | } = require("@raydium-io/raydium-sdk"); 10 | 11 | const { Keypair, PublicKey } = require("@solana/web3.js"); 12 | const { Decimal } = require("decimal.js"); 13 | const { 14 | connection, 15 | makeTxVersion, 16 | wallet, 17 | } = require("../helpers/config.js"); 18 | const { 19 | formatAmmKeysById_pool, 20 | formatAmmKeysById_swap, 21 | } = require("./formatAmmKeysById.js"); 22 | const { 23 | buildAndSendTx, 24 | getWalletTokenAccount, 25 | loadOrCreateKeypair_wallet, 26 | checkTx, 27 | } = require("../helpers/util.js"); 28 | const { 29 | getPoolId, 30 | getPoolIdByPair, 31 | queryLpByToken, 32 | queryLpPair, 33 | } = require("./query_pool.js"); 34 | const { getSPLTokenBalance } = require("../helpers/check_balance.js"); 35 | const { getDecimals, getTokenMetadata } = require("../helpers/util.js"); 36 | const { BN } = require("@project-serum/anchor"); 37 | const { program } = require("commander"); 38 | 39 | let payer_keypair = null, 40 | tokenAddress = null, 41 | percentage = null, 42 | cluster = null; 43 | program 44 | .option("--payer ", "Specify the path to the secret key") 45 | .option("--token_address ", "Specify the token address") 46 | .option( 47 | "--percentage ", 48 | "Specify the percentage of LP token to remove" 49 | ) 50 | .option("--cluster ", "Specify the cluster") 51 | .option("-h, --help", "display help for command") 52 | .action((options) => { 53 | if (options.help) { 54 | console.log( 55 | "node remove_pool --payer --token_address --percentage --cluster " 56 | ); 57 | process.exit(0); 58 | } 59 | if (!options.token_address || !options.percentage || !options.cluster) { 60 | console.error("❌ Missing required options"); 61 | process.exit(1); 62 | } 63 | if (options.payer) { 64 | payer_keypair = options.payer; 65 | } 66 | tokenAddress = new PublicKey(options.token_address); 67 | percentage = options.percentage; 68 | cluster = options.cluster; 69 | }); 70 | program.parse(); 71 | /** 72 | * Removes liquidity from a target pool. 73 | * @param {Object} input - The input parameters. 74 | * @param {string} input.targetPool - The ID of the target pool. 75 | * @param {Object} input.wallet - The wallet object. 76 | * @param {string} input.wallet.publicKey - The public key of the wallet. 77 | * @param {Array} input.walletTokenAccounts - The token accounts of the wallet. 78 | * @param {number} input.removeLpTokenAmount - The amount of LP tokens to remove. 79 | * @param {number} makeTxVersion - The transaction version. 80 | * @returns {Object} - The transaction IDs. 81 | */ 82 | async function ammRemoveLiquidity(input) { 83 | try { 84 | // -------- pre-action: fetch basic info -------- 85 | const targetPoolInfo = await formatAmmKeysById_pool(input.targetPool); 86 | assert(targetPoolInfo, "cannot find the target pool"); 87 | 88 | // -------- step 1: make instructions -------- 89 | const poolKeys = jsonInfo2PoolKeys(targetPoolInfo); 90 | const removeLiquidityInstructionResponse = 91 | await Liquidity.makeRemoveLiquidityInstructionSimple({ 92 | connection, 93 | poolKeys, 94 | userKeys: { 95 | owner: input.wallet.publicKey, 96 | payer: input.wallet.publicKey, 97 | tokenAccounts: input.walletTokenAccounts, 98 | }, 99 | amountIn: input.removeLpTokenAmount, 100 | makeTxVersion, 101 | }); 102 | 103 | return { 104 | txids: await buildAndSendTx( 105 | removeLiquidityInstructionResponse.innerTransactions, 106 | { 107 | preflightCommitment: "confirmed", 108 | } 109 | ), 110 | }; 111 | } catch (err) { 112 | console.log(err); 113 | return { 114 | txids: await buildAndSendTx( 115 | removeLiquidityInstructionResponse.innerTransactions, 116 | { 117 | preflightCommitment: "confirmed", 118 | } 119 | ), 120 | }; 121 | } 122 | } 123 | 124 | /** 125 | * Finds the LP token address for a given token address. 126 | * @param {string} tokenAddress - The token address. 127 | * @returns {string} - The LP token address. 128 | */ 129 | async function findLPTokenAddress(tokenAddress) { 130 | const response = await queryLpByToken(tokenAddress); 131 | console.log(response); 132 | console.log(response.Raydium_LiquidityPoolv4[0].lpMint); 133 | return response.Raydium_LiquidityPoolv4[0].lpMint; 134 | } 135 | 136 | /** 137 | * Helper function for removing liquidity from an AMM pool that retries the transaction if it fails. 138 | * @param {Object} input - The input parameters for removing liquidity. 139 | * @returns {Promise} - A promise that resolves when the liquidity is removed. 140 | */ 141 | async function ammRemoveLiquidityHelper(input) { 142 | const { txids } = await ammRemoveLiquidity(input); 143 | console.log("txids:", txids); 144 | const response = await checkTx(txids[0]); 145 | if (response) { 146 | console.log(`https://explorer.solana.com/tx/${txids}?cluster=mainnet`); 147 | } else { 148 | console.log("Transaction failed"); 149 | console.log("trying to send the transaction again"); 150 | ammRemoveLiquidityHelper(input); 151 | } 152 | } 153 | /** 154 | * Main function for removing a pool's liquidity. 155 | * @returns {Promise} A promise that resolves when the pool removal is complete. 156 | */ 157 | async function main() { 158 | if (payer_keypair !== null) { 159 | payer_keypair = await loadOrCreateKeypair_wallet(payer_keypair); 160 | } else { 161 | payer_keypair = Keypair.fromSecretKey(wallet.secretKey); 162 | } 163 | 164 | const lpTokenAddress = await findLPTokenAddress(tokenAddress); 165 | const lpTokenAccount = new PublicKey(lpTokenAddress); 166 | const lpTokenBalance = await getSPLTokenBalance( 167 | connection, 168 | lpTokenAccount, 169 | payer_keypair.publicKey 170 | ); 171 | console.log("lpTokenBalance", lpTokenBalance); 172 | const decimals = await getDecimals(lpTokenAccount); 173 | console.log("decimals", decimals); 174 | const { tokenName, tokenSymbol } = await getTokenMetadata(lpTokenAddress); 175 | 176 | const lpToken = new Token( 177 | TOKEN_PROGRAM_ID, 178 | new PublicKey(lpTokenAddress), 179 | decimals, 180 | tokenSymbol, 181 | tokenName 182 | ); 183 | 184 | const percentageOfLpToken = percentage / 100; 185 | const inputTokenAmount = new Decimal(lpTokenBalance * percentageOfLpToken); 186 | 187 | const removeLpTokenAmount = new TokenAmount( 188 | lpToken, 189 | new BN(inputTokenAmount.mul(10 ** lpToken.decimals).toFixed(0)) 190 | ); 191 | const targetPool = await getPoolIdByPair(tokenAddress); 192 | if (targetPool === null) { 193 | console.log( 194 | "Pool not found or raydium is not supported for this token. Exiting..." 195 | ); 196 | return; 197 | } 198 | const walletTokenAccounts = await getWalletTokenAccount( 199 | connection, 200 | payer_keypair.publicKey 201 | ); 202 | 203 | await ammRemoveLiquidityHelper({ 204 | removeLpTokenAmount, 205 | targetPool, 206 | walletTokenAccounts, 207 | wallet: payer_keypair, 208 | }); 209 | } 210 | 211 | main(); 212 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/tools.js: -------------------------------------------------------------------------------- 1 | const { AnchorProvider } = require("@coral-xyz/anchor"); 2 | const { PumpFunSDK, DEFAULT_DECIMALS } = require("./pumpfun.js"); 3 | const { 4 | sendTxToJito, 5 | DEFAULT_COMMITMENT, 6 | generateWalletsAndDropSOL, 7 | solCollector, 8 | } = require("./util.js"); 9 | const { wallet, connection } = require("../../../helpers/config.js"); 10 | const { 11 | getOrCreateKeypair, 12 | getSPLBalance, 13 | printSOLBalance, 14 | printSPLBalance, 15 | getKeypairByJsonPath, 16 | } = require("../example/util.js"); 17 | const fs = require("fs"); 18 | const { promises } = require("dns"); 19 | const { 20 | Keypair, 21 | PublicKey, 22 | SystemProgram, 23 | Transaction, 24 | LAMPORTS_PER_SOL, 25 | } = require("@solana/web3.js"); 26 | const { bs58 } = require("@coral-xyz/anchor/dist/cjs/utils/bytes"); 27 | const { 28 | calculateWithSlippageBuy, 29 | sendTx, 30 | getOurWallet, 31 | getOtherTradersWallet, 32 | readCSVFile, 33 | extractPrivateKeyAndSolana, 34 | } = require("./util.js"); 35 | const { 36 | jito_executeAndConfirm, 37 | } = require("./transactions/jito-tx-executor.js"); 38 | const path = require("path"); 39 | const { get } = require("http"); 40 | const SLIPPAGE_BASIS_POINTS = 100n; 41 | 42 | /** 43 | * Creates and buys a token using the provided parameters. 44 | * @param {string} pathToMintKeypair - The path to the mint keypair JSON file. 45 | * @param {object} tokenMetadata - The metadata of the token. 46 | * @param {number} initialBuySolAmount - The initial amount of SOL to buy the token with. 47 | * @returns {Promise} - A promise that resolves when the token creation and purchase is complete. 48 | */ 49 | async function createAndBuy(pathToMintKeypair, tokenMetadata, initialBuySolAmount) { 50 | const provider = new AnchorProvider(connection, wallet, { 51 | commitment: "finalized", 52 | }); 53 | 54 | const sdk = new PumpFunSDK(provider); 55 | const mintKeypair = getKeypairByJsonPath(pathToMintKeypair); 56 | console.log(mintKeypair.publicKey); 57 | await printSOLBalance(connection, wallet.publicKey, "Master wallet keypair"); 58 | let globalAccount = await sdk.getGlobalAccount(); 59 | let bondingCurveAccount = await sdk.getBondingCurveAccount( 60 | mintKeypair.publicKey 61 | ); 62 | if (!bondingCurveAccount) { 63 | // the mint is not exist in pump.fun yet 64 | 65 | let createResults = await sdk.createAndBuy( 66 | wallet, 67 | mintKeypair, 68 | tokenMetadata, 69 | BigInt(initialBuySolAmount * LAMPORTS_PER_SOL), 70 | SLIPPAGE_BASIS_POINTS, 71 | { 72 | unitLimit: 250000, 73 | unitPrice: 170000, // can be ignored if using jito tips 74 | } 75 | ); 76 | if (createResults) { 77 | console.log( 78 | "Success:", 79 | `https://pump.fun/${mintKeypair.publicKey.toBase58()}` 80 | ); 81 | bondingCurveAccount = await sdk.getBondingCurveAccount( 82 | mintKeypair.publicKey 83 | ); 84 | console.log("Bonding curve after create and buy", bondingCurveAccount); 85 | printSPLBalance(connection, mintKeypair.publicKey, wallet.publicKey); 86 | } 87 | } else { 88 | console.log("boundingCurveAccount", bondingCurveAccount); 89 | console.log( 90 | "Success:", 91 | `https://pump.fun/${mintKeypair.publicKey.toBase58()}` 92 | ); 93 | printSPLBalance(connection, mintKeypair.publicKey, wallet.publicKey); 94 | } 95 | } 96 | 97 | /** 98 | * Sells a specified percentage of tokens. 99 | * @param {string} mintPubKey - The public key of the token mint. 100 | * @param {number} sellPercentage - The percentage of tokens to sell. 101 | * @returns {Promise} - A promise that resolves when the sell operation is complete. 102 | */ 103 | async function sell(mintPubKey, sellPercentage) { 104 | const provider = new AnchorProvider(connection, wallet, { 105 | commitment: "finalized", 106 | }); 107 | 108 | const sdk = new PumpFunSDK(provider); 109 | let currentTokenBalance = await getSPLBalance( 110 | connection, 111 | mintPubKey, 112 | wallet.publicKey 113 | ); 114 | console.log("currentTokenBalance", currentTokenBalance); 115 | if (currentTokenBalance) { 116 | let sellResults = await sdk.sell( 117 | wallet, 118 | mintPubKey, 119 | BigInt( 120 | currentTokenBalance * Math.pow(10, DEFAULT_DECIMALS) * sellPercentage 121 | ), 122 | SLIPPAGE_BASIS_POINTS, 123 | { 124 | unitLimit: 250000, 125 | unitPrice: 250000, 126 | } 127 | ); 128 | if (sellResults.success) { 129 | await printSPLBalance(connection, mintPubKey, wallet.publicKey); 130 | console.log( 131 | "Bonding curve after sell", 132 | await sdk.getBondingCurveAccount(mintPubKey) 133 | ); 134 | } else { 135 | console.log("Sell failed"); 136 | } 137 | } 138 | } 139 | 140 | /** 141 | * Buys tokens from the bonding curve. 142 | * @param {string} mintPubKey - The public key of the token mint. 143 | * @param {number} solPerOrder - The amount of SOL to spend per order. 144 | * @returns {Promise} - A promise that resolves when the buy operation is complete. 145 | */ 146 | async function buy(mintPubKey, solPerOrder) { 147 | const provider = new AnchorProvider(connection, wallet, { 148 | commitment: "finalized", 149 | }); 150 | 151 | const sdk = new PumpFunSDK(provider); 152 | let buyResults = await sdk.buy( 153 | wallet, 154 | mintPubKey, 155 | BigInt(solPerOrder * LAMPORTS_PER_SOL), 156 | SLIPPAGE_BASIS_POINTS, 157 | { 158 | unitLimit: 250000, 159 | unitPrice: 250000, 160 | } 161 | ); 162 | if (buyResults.success) { 163 | printSPLBalance(connection, mintPubKey, wallet.publicKey); 164 | console.log( 165 | "Bonding curve after buy", 166 | await sdk.getBondingCurveAccount(mintPubKey) 167 | ); 168 | } else { 169 | console.log("Buy failed"); 170 | } 171 | } 172 | 173 | 174 | 175 | async function run() { 176 | 177 | // Please change your own path 178 | const pathToSnipersPrivateKey = 179 | "/Users/chiwangso/Desktop/beta-memecoin-cli/src/pump.fun/pumpdotfun-sdk/src/WalletKeypairs/privateKeys.json"; 180 | const pathToMintKeypair = 181 | "/Users/chiwangso/Desktop/beta-memecoin-cli/src/pump.fun/pump-keypair/token_address.json"; 182 | const tokenAddress = new PublicKey( 183 | "token_address" 184 | ); 185 | 186 | //console.log(wallet.publicKey.toBase58()); 187 | // buy token with 0.01 SOL 188 | // await buy(tokenAddress, 0.01); 189 | // sell token with 100% of the balance 190 | // await sell(tokenAddress, 1); 191 | 192 | // bundle buy with 3 buyers, it will help to generate three wallets, 193 | // if you don't have private keys in pathToSnipersPrivateKey, 194 | // if you have, it look for the first 3 private keys in pathToSnipersPrivateKey 195 | //await bundleBuys(5, pathToSnipersPrivateKey, tokenAddress, 0.005, wallet); 196 | 197 | // bundle sell with 3 sellers, it will look for the first 3 private keys in pathToSnipersPrivateKey 198 | // with 100 percentage of the balance of these mfers, use master to pay the fee 199 | // await bundleSells(pathToSnipersPrivateKey, tokenAddress, 3, 1, connection, wallet) 200 | 201 | 202 | // collet the sol from those mfers to the master wallet 203 | // await solCollector(connection, wallet, 6, pathToSnipersPrivateKey) 204 | 205 | // create the token and initial buy with 0.01 sol 206 | // createAndBuy(pathToMintKeypair, tokenMetadata, 0.01); 207 | 208 | 209 | 210 | 211 | } 212 | 213 | //run(); 214 | 215 | module.exports = {buy, sell, createAndBuy} -------------------------------------------------------------------------------- /src/Pool/add_pool.js: -------------------------------------------------------------------------------- 1 | const assert = require("assert"); 2 | const { 3 | jsonInfo2PoolKeys, 4 | Liquidity, 5 | Token, 6 | TOKEN_PROGRAM_ID, 7 | TokenAmount, 8 | Percent, 9 | } = require("@raydium-io/raydium-sdk"); 10 | const { PublicKey, Keypair } = require("@solana/web3.js"); 11 | const { getPoolId, getPoolIdByPair } = require("./query_pool.js"); 12 | const Decimal = require("decimal.js"); 13 | 14 | const { 15 | connection, 16 | DEFAULT_TOKEN, 17 | makeTxVersion, 18 | dev_connection, 19 | wallet, 20 | } = require("../helpers/config.js"); 21 | const { formatAmmKeysById_pool } = require("./formatAmmKeysById.js"); 22 | const { 23 | buildAndSendTx, 24 | getWalletTokenAccount, 25 | loadOrCreateKeypair_wallet, 26 | getDecimals, 27 | getTokenMetadata, 28 | checkTx, 29 | } = require("../helpers/util.js"); 30 | const BN = require("bn.js"); 31 | const { program } = require("commander"); 32 | 33 | let payer_keypair = null, 34 | token_address = null, 35 | pool_id = null, 36 | sol = null, 37 | cluster = null, 38 | priority_fee = null, 39 | connection_sol = connection; 40 | program 41 | .option("--payer ", "Specify the path to the secret key") 42 | .option("--token_address ", "Specify the token address") 43 | .option("--pool_id ", "Specify the pool id") 44 | .option("--sol ", "Specify the number of SOL") 45 | .option("--cluster ", "Specify the cluster") 46 | .option("--priority_fee ", "Specify the priority fee") 47 | .option("-h, --help", "display help for command") 48 | .action((options) => { 49 | if (options.help) { 50 | console.log( 51 | "node add_pool --payer --token_address --pool_id --sol --cluster --priority_fee " 52 | ); 53 | process.exit(0); 54 | } 55 | 56 | if (!options.token_address || !options.sol || !options.cluster) { 57 | console.log( 58 | "Please provide the required param's value, except the pool id and the priority fee." 59 | ); 60 | process.exit(1); 61 | } 62 | if (options.payer) { 63 | payer_keypair = options.payer; 64 | } 65 | token_address = new PublicKey(options.token_address); 66 | pool_id = options.pool_id; 67 | sol = options.sol; 68 | cluster = options.cluster; 69 | priority_fee = options.priority_fee; 70 | 71 | // Handle the logic for the create command 72 | }); 73 | program.parse(); 74 | /** 75 | * Adds liquidity to a target pool. 76 | * @param {Object} input - The input parameters. 77 | * @param {string} input.targetPool - The ID of the target pool. 78 | * @param {number} input.Amount - The amount of liquidity to add. 79 | * @param {string} input.quoteToken - The quote token for the liquidity. 80 | * @param {number} input.slippage - The slippage for the liquidity. 81 | * @param {Object} input.wallet - The wallet information. 82 | * @param {string} input.wallet.publicKey - The public key of the wallet. 83 | * @param {string} input.walletTokenAccounts - The token accounts of the wallet. 84 | * @returns {Object} - The transaction IDs and the amount of another currency. 85 | */ 86 | async function ammAddLiquidity(input) { 87 | try { 88 | const targetPoolInfo = await formatAmmKeysById_pool(input.targetPool); 89 | assert(targetPoolInfo, "cannot find the target pool"); 90 | 91 | // -------- step 1: compute another amount -------- 92 | 93 | const poolKeys = jsonInfo2PoolKeys(targetPoolInfo); 94 | const extraPoolInfo = await Liquidity.fetchInfo({ 95 | connection, 96 | poolKeys, 97 | }); 98 | const { maxAnotherAmount, anotherAmount, liquidity } = 99 | Liquidity.computeAnotherAmount({ 100 | poolKeys, 101 | poolInfo: { ...targetPoolInfo, ...extraPoolInfo }, 102 | amount: input.Amount, 103 | anotherCurrency: input.quoteToken, 104 | slippage: input.slippage, 105 | }); 106 | 107 | console.log("will add liquidity info", { 108 | liquidity: liquidity.toString(), 109 | liquidityD: new Decimal(liquidity.toString()).div( 110 | 10 ** extraPoolInfo.lpDecimals 111 | ), 112 | }); 113 | 114 | // -------- step 2: make instructions -------- 115 | const addLiquidityInstructionResponse = 116 | await Liquidity.makeAddLiquidityInstructionSimple({ 117 | connection, 118 | poolKeys, 119 | userKeys: { 120 | owner: input.wallet.publicKey, 121 | payer: input.wallet.publicKey, 122 | tokenAccounts: input.walletTokenAccounts, 123 | }, 124 | amountInA: input.Amount, 125 | amountInB: maxAnotherAmount, 126 | fixedSide: "a", 127 | makeTxVersion, 128 | }); 129 | console.log( 130 | "addLiquidityInstructionResponse: ", 131 | addLiquidityInstructionResponse 132 | ); 133 | 134 | return { 135 | txids: await buildAndSendTx( 136 | addLiquidityInstructionResponse.innerTransactions 137 | ), 138 | anotherAmount, 139 | }; 140 | } catch (e) { 141 | console.log(e); 142 | return { 143 | txids: await buildAndSendTx( 144 | addLiquidityInstructionResponse.innerTransactions 145 | ), 146 | anotherAmount, 147 | }; 148 | } 149 | } 150 | /** 151 | * Helper function for adding liquidity to an AMM pool that retries the transaction if it fails. 152 | * @param {Object} input - The input parameters for adding liquidity. 153 | * @returns {Promise} - A promise that resolves when the liquidity is added. 154 | */ 155 | async function ammAddLiquidityHelper(input) { 156 | const { txids, amount } = await ammAddLiquidity(input); 157 | console.log("txids:", txids); 158 | const response = await checkTx(txids[0]); 159 | if (response) { 160 | console.log(`https://explorer.solana.com/tx/${txids}?cluster=mainnet`); 161 | } else { 162 | console.log("Transaction failed"); 163 | console.log("trying to send the transaction again"); 164 | ammAddLiquidityHelper(input); 165 | } 166 | } 167 | 168 | /** 169 | * Main function for adding liquidity to a pool. 170 | * @returns {Promise} A promise that resolves when liquidity is added. 171 | */ 172 | async function main() { 173 | if (payer_keypair !== null) { 174 | payer_keypair = await loadOrCreateKeypair_wallet(payer_keypair); 175 | } else { 176 | payer_keypair = Keypair.fromSecretKey(wallet.secretKey); 177 | } 178 | const baseToken = DEFAULT_TOKEN.WSOL; 179 | const { tokenName, tokenSymbol } = await getTokenMetadata(token_address); 180 | console.log("token symbol: ", tokenSymbol); 181 | const quoteToken = new Token( 182 | TOKEN_PROGRAM_ID, 183 | token_address, 184 | await getDecimals(token_address), 185 | tokenSymbol, 186 | tokenName 187 | ); 188 | let targetPool = null; 189 | if (pool_id != null) { 190 | targetPool = pool_id; 191 | } else targetPool = await getPoolIdByPair(quoteToken.mint.toBase58()); 192 | if (targetPool === null) { 193 | console.log( 194 | "Pool not found or raydium is not supported for this token. Exiting..." 195 | ); 196 | process.exit(1); 197 | } 198 | console.log("targetPool: ", targetPool); 199 | const inputTokenAmount = new Decimal(sol); 200 | const Amount = new TokenAmount( 201 | baseToken, 202 | new BN(inputTokenAmount.mul(10 ** baseToken.decimals).toFixed(0)) 203 | ); 204 | const slippage = new Percent(5, 1000); 205 | const walletTokenAccounts = await getWalletTokenAccount( 206 | connection, 207 | payer_keypair.publicKey 208 | ); 209 | 210 | await ammAddLiquidityHelper({ 211 | baseToken, 212 | quoteToken, 213 | targetPool, 214 | Amount, 215 | slippage, 216 | walletTokenAccounts, 217 | wallet: payer_keypair, 218 | }); 219 | } 220 | 221 | main(); 222 | -------------------------------------------------------------------------------- /src/helpers/util.js: -------------------------------------------------------------------------------- 1 | const { 2 | TOKEN_PROGRAM_ID, 3 | SPL_ACCOUNT_LAYOUT, 4 | buildSimpleTransaction, 5 | } = require("@raydium-io/raydium-sdk"); 6 | const { PublicKey, VersionedTransaction, Keypair } = require("@solana/web3.js"); 7 | const { 8 | addLookupTableInfo, 9 | connection, 10 | makeTxVersion, 11 | wallet, 12 | } = require("./config.js"); 13 | const { Metaplex } = require("@metaplex-foundation/js"); 14 | const fs = require("fs"); 15 | const { 16 | Connection, 17 | LAMPORTS_PER_SOL, 18 | SystemProgram, 19 | TransactionInstruction, 20 | TransactionMessage, 21 | Transaction, 22 | ComputeBudgetProgram, 23 | } = require("@solana/web3.js"); 24 | 25 | /** 26 | * Retrieves the number of decimals for a given mint address. 27 | * @param {PublicKey} mintAddress - The address of the mint. 28 | * @returns {Promise} The number of decimals. 29 | */ 30 | async function getDecimals(mintAddress) { 31 | const info = await connection.getParsedAccountInfo(mintAddress); 32 | const result = (info.value?.data).parsed.info.decimals || 0; 33 | return result; 34 | } 35 | /** 36 | * Retrieves the metadata of a token based on its address. 37 | * @param {string} address - The address of the token. 38 | * @returns {Promise<{ tokenName: string, tokenSymbol: string }>} The token metadata, including the token name and symbol. 39 | */ 40 | async function getTokenMetadata(address) { 41 | const metaplex = Metaplex.make(connection); 42 | 43 | const mintAddress = new PublicKey(address); 44 | 45 | let tokenName; 46 | let tokenSymbol; 47 | 48 | const metadataAccount = metaplex 49 | .nfts() 50 | .pdas() 51 | .metadata({ mint: mintAddress }); 52 | 53 | const metadataAccountInfo = await connection.getAccountInfo(metadataAccount); 54 | 55 | if (metadataAccountInfo) { 56 | const token = await metaplex 57 | .nfts() 58 | .findByMint({ mintAddress: mintAddress }); 59 | tokenName = token.name; 60 | tokenSymbol = token.symbol; 61 | } 62 | return { tokenName, tokenSymbol }; 63 | } 64 | /** 65 | * Sends multiple transactions to the Solana blockchain. 66 | * @param {Connection} connection - The Solana connection object. 67 | * @param {Account} payer - The payer account for signing the transactions. 68 | * @param {Array} txs - An array of transactions to be sent. 69 | * @param {TransactionSendOptions} options - The options for sending the transactions. 70 | * @returns {Promise>} - A promise that resolves to an array of transaction IDs. 71 | */ 72 | async function sendTx(connection, payer, txs, options) { 73 | const txids = []; 74 | try { 75 | for (const iTx of txs) { 76 | if (iTx instanceof VersionedTransaction) { 77 | iTx.sign([payer]); 78 | 79 | txids.push( 80 | await connection.sendRawTransaction(iTx.serialize(), options) 81 | ); 82 | } else { 83 | txids.push(await connection.sendTransaction(iTx, [payer], options)); 84 | } 85 | } 86 | } catch (e) { 87 | console.log(e); 88 | return txids; 89 | } 90 | return txids; 91 | } 92 | 93 | /** 94 | * Retrieves the token account associated with a wallet. 95 | * @param {Connection} localconnection - The connection object. 96 | * @param {Wallet} localwallet - The wallet object. 97 | * @returns {Array} An array of token account objects. 98 | */ 99 | async function getWalletTokenAccount(localconnection, localwallet) { 100 | const walletTokenAccount = await localconnection.getTokenAccountsByOwner( 101 | localwallet, 102 | { 103 | programId: TOKEN_PROGRAM_ID, 104 | } 105 | ); 106 | return walletTokenAccount.value.map((i) => ({ 107 | pubkey: i.pubkey, 108 | programId: i.account.owner, 109 | accountInfo: SPL_ACCOUNT_LAYOUT.decode(i.account.data), 110 | })); 111 | } 112 | 113 | /** 114 | * Builds and sends a transaction using the provided innerSimpleV0Transaction and options. 115 | * @param {Object} innerSimpleV0Transaction - The inner transaction object. 116 | * @param {Object} options - The options for the transaction. 117 | * @returns {Promise} - A promise that resolves with the result of the transaction. 118 | */ 119 | async function buildAndSendTx(innerSimpleV0Transaction, options) { 120 | try { 121 | const recentBlockhash = await connection.getLatestBlockhash("confirmed"); 122 | const priority_fee_arr = [ 123 | ComputeBudgetProgram.setComputeUnitLimit({ 124 | units: 101337, 125 | }), 126 | ComputeBudgetProgram.setComputeUnitPrice({ 127 | microLamports: 421197, 128 | }), 129 | ]; 130 | console.log(innerSimpleV0Transaction); 131 | const original_inner_instructions = 132 | innerSimpleV0Transaction[0].instructions; 133 | innerSimpleV0Transaction[0].instructions = [ 134 | ...priority_fee_arr, 135 | ...original_inner_instructions, 136 | ]; 137 | console.log("innerSimpleV0Transaction: ", innerSimpleV0Transaction); 138 | const willSendTx = await buildSimpleTransaction({ 139 | connection: connection, 140 | makeTxVersion: makeTxVersion, 141 | payer: wallet.publicKey, 142 | innerTransactions: innerSimpleV0Transaction, 143 | addLookupTableInfo: addLookupTableInfo, 144 | }); 145 | console.log("willSendTx", willSendTx); 146 | 147 | return await sendTx(connection, wallet, willSendTx, options); 148 | } catch (e) { 149 | console.log(e); 150 | } 151 | } 152 | 153 | /** 154 | * Sleeps for a specified amount of time. 155 | * @param {number} ms - The duration to sleep in milliseconds. 156 | * @returns {Promise} - A promise that resolves after the specified duration. 157 | */ 158 | async function sleepTime(ms) { 159 | console.log(new Date().toLocaleString(), "sleepTime", ms); 160 | return new Promise((resolve) => setTimeout(resolve, ms)); 161 | } 162 | 163 | /** 164 | * Loads or creates a Solana keypair from a file. 165 | * If the file exists, it reads the keypair from the file and returns it. 166 | * If the file does not exist, it generates a new keypair, saves it to the file, and returns it. 167 | * 168 | * @param {string} filepath - The path to the file where the keypair is stored or will be stored. 169 | * @returns {Promise} The loaded or newly created keypair. 170 | */ 171 | async function loadOrCreateKeypair_wallet(filepath) { 172 | try { 173 | const keypairString = fs.readFileSync(filepath, { encoding: "utf8" }); 174 | return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(keypairString))); 175 | } catch (error) { 176 | const newKeypair = Keypair.generate(); 177 | fs.writeFileSync( 178 | filepath, 179 | JSON.stringify(Array.from(newKeypair.secretKey)) 180 | ); 181 | console.log(`New keypair created and saved to ${filepath}`); 182 | return newKeypair; 183 | } 184 | } 185 | async function isBlockhashExpired(lastValidBlockHeight) { 186 | let currentBlockHeight = await connection.getBlockHeight("finalized"); 187 | console.log(" "); 188 | console.log("Current Block height: ", currentBlockHeight); 189 | console.log( 190 | "Last Valid Block height - 150: ", 191 | lastValidBlockHeight - 150 192 | ); 193 | console.log("--------------------------------------------"); 194 | console.log( 195 | "Difference: ", 196 | currentBlockHeight - (lastValidBlockHeight - 150) 197 | ); // If Difference is positive, blockhash has expired. 198 | console.log(" "); 199 | 200 | return currentBlockHeight > lastValidBlockHeight - 150; 201 | } 202 | const sleep = (ms) => { 203 | return new Promise((resolve) => setTimeout(resolve, ms)); 204 | }; 205 | async function checkTx(txId) { 206 | const blockhashResponse = await connection.getLatestBlockhashAndContext( 207 | "finalized" 208 | ); 209 | const lastValidHeight = blockhashResponse.value.lastValidBlockHeight; 210 | console.log("Last Valid Height: ", lastValidHeight); 211 | const START_TIME = new Date(); 212 | // Check transaction status and blockhash status until the transaction succeeds or blockhash expires 213 | let hashExpired = false; 214 | let txSuccess = false; 215 | while (!hashExpired && !txSuccess) { 216 | const { value: status } = await connection.getSignatureStatus(txId); 217 | 218 | // Break loop if transaction has succeeded 219 | if ( 220 | status && 221 | (status.confirmationStatus === "confirmed" || 222 | status.confirmationStatus === "finalized") 223 | ) { 224 | txSuccess = true; 225 | const endTime = new Date(); 226 | const elapsed = (endTime.getTime() - START_TIME.getTime()) / 1000; 227 | console.log(`Transaction Success. Elapsed time: ${elapsed} seconds.`); 228 | return true; 229 | } 230 | 231 | hashExpired = await isBlockhashExpired(lastValidHeight); 232 | 233 | // Break loop if blockhash has expired 234 | if (hashExpired) { 235 | const endTime = new Date(); 236 | const elapsed = (endTime.getTime() - START_TIME.getTime()) / 1000; 237 | console.log(`Blockhash has expired. Elapsed time: ${elapsed} seconds.`); 238 | return false; 239 | } 240 | 241 | // Check again after 2.5 sec 242 | await sleep(2500); 243 | } 244 | } 245 | 246 | module.exports = { 247 | getDecimals, 248 | getTokenMetadata, 249 | getWalletTokenAccount, 250 | sendTx, 251 | buildAndSendTx, 252 | sleepTime, 253 | loadOrCreateKeypair_wallet, 254 | checkTx, 255 | }; 256 | -------------------------------------------------------------------------------- /src/Trading/memecoin_trading_strategies/copy_trading/copy-buy.js: -------------------------------------------------------------------------------- 1 | const { 2 | PublicKey, 3 | } = require("@solana/web3.js"); 4 | const { 5 | TOKEN_PROGRAM_ID, 6 | AccountLayout, 7 | } = require("@solana/spl-token"); 8 | const { connection, wallet, smart_money_wallet } = require("../../../helpers/config"); 9 | //const { buy } = require("../../dex/jupiter/swap/buy-helper"); 10 | //const { sell } = require("../../dex/jupiter/swap/sell-helper"); 11 | const path = require('path'); 12 | const { swap } = require("../../dex/jupiter/swap/swap-helper"); 13 | const {buy} = require("../../dex/raydium/buy_helper") 14 | const {sell} = require("../../dex/raydium/sell_helper") 15 | const fs = require('fs'); 16 | const boughtTokensPath = path.join(__dirname, 'bought-tokens.json'); 17 | //const {swap} = require("../../../Pool/swap") 18 | let walletsToListen = []; 19 | var previous_trader_wallet_state = {}; 20 | var previous_our_wallet_state = {}; 21 | // [usdc, sol, usdt, wsol] 22 | const wsol = "So11111111111111111111111111111111111111112" 23 | const quoteToken = [ 24 | "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", 25 | "SOL", 26 | "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", 27 | wsol, 28 | ]; 29 | let boughtTokens = JSON.parse(fs.readFileSync(boughtTokensPath, 'utf8')); 30 | 31 | async function saveToJson(token) { 32 | boughtTokens.push(token); 33 | fs.writeFileSync(boughtTokensPath, JSON.stringify(boughtTokens, null, 2)); 34 | } 35 | 36 | 37 | /** 38 | * Listens to changes in multiple wallets and performs trading actions based on the changes. 39 | * @returns {Promise} A promise that resolves once the wallet listening is set up. 40 | */ 41 | async function listenToWallets(address) { 42 | try{ 43 | 44 | 45 | connection.onProgramAccountChange( 46 | TOKEN_PROGRAM_ID, 47 | async (data) => { 48 | const changedMint = AccountLayout.decode(data.accountInfo.data).mint.toBase58(); 49 | console.log("changed mint: ", changedMint); 50 | // realize in smart money wallet there is a token's balance changed 51 | // then we look at trader's portfolio 52 | console.log("Wallet state changed"); 53 | const current_trader_wallet_state = await retriveWalletState( 54 | address.toBase58() 55 | ); 56 | const current_our_wallet_state = await retriveWalletState( 57 | wallet.publicKey.toBase58() 58 | ); 59 | if((changedMint in current_trader_wallet_state || current_trader_wallet_state[changedMint] > 0) && current_trader_wallet_state["SOL"] < previous_trader_wallet_state["SOL"]){ 60 | console.log(`buying ${changedMint}...`) 61 | if (!current_our_wallet_state[wsol]) { 62 | console.log("We don't have enough SOL to swap"); 63 | throw new Error("We don't have enough SOL to swap"); 64 | } 65 | const buy_percentage = Math.abs((current_trader_wallet_state["SOL"] - previous_trader_wallet_state["SOL"]) / previous_trader_wallet_state["SOL"]); 66 | const amountOut = current_our_wallet_state[wsol] * buy_percentage; 67 | console.log("amountOut: ", amountOut); 68 | buy("buy", changedMint, amountOut, wallet) 69 | saveToJson(changedMint); 70 | previous_our_wallet_state = await retriveWalletState(wallet.publicKey.toBase58()); 71 | previous_trader_wallet_state = await retriveWalletState(address.toBase58()); 72 | return; 73 | } 74 | else if((!(changedMint in current_trader_wallet_state) || current_trader_wallet_state[changedMint] <= previous_trader_wallet_state[changedMint] ) && current_trader_wallet_state["SOL"] > previous_trader_wallet_state["SOL"]){ 75 | console.log(`selling ${changedMint}...`) 76 | if (!current_our_wallet_state[wsol]) { 77 | console.log("We don't have enough SOL to swap"); 78 | throw new Error("We don't have enough SOL to swap"); 79 | } 80 | if(!changedMint in current_trader_wallet_state){ 81 | current_trader_wallet_state[changedMint] = 0; 82 | } 83 | const sell_percentage = Math.abs((current_trader_wallet_state[changedMint] - previous_trader_wallet_state[changedMint]) / previous_trader_wallet_state[changedMint]); 84 | const amountOut = current_our_wallet_state[changedMint] * sell_percentage; 85 | console.log("amountOut: ", amountOut); 86 | sell("sell", changedMint, amountOut*100, wallet); 87 | previous_our_wallet_state = await retriveWalletState(wallet.publicKey.toBase58()); 88 | previous_trader_wallet_state = await retriveWalletState(address.toBase58()); 89 | return; 90 | } 91 | // changed mint might dissapear in the current trader state if they sold all of it before 92 | // so we need to add it to the state with 0 balance 93 | // Compare the current wallet state with the previous state 94 | // to determine if the trader is buying or selling 95 | // trader's wallet state 96 | const prevState = previous_trader_wallet_state; 97 | const currentState = current_trader_wallet_state; 98 | let res_case = 0; 99 | // Check if there is one token that decreased and one token that increased 100 | let increasedToken = null, decreasedToken = null, increasedTokenPercentage = 0, decreasedTokenPercentage = 0; 101 | for (const mint in currentState) { 102 | if (increasedToken && decreasedToken) { 103 | break; 104 | } 105 | const prevBalance = prevState[mint] || 0; 106 | const currentBalance = currentState[mint]; 107 | 108 | if (currentBalance > prevBalance) { 109 | increasedToken = mint; 110 | increasedTokenPercentage = 111 | (currentBalance - prevBalance) / prevBalance; 112 | } else if (currentBalance < prevBalance) { 113 | decreasedToken = mint; 114 | decreasedTokenPercentage = 115 | (currentBalance - prevBalance) / prevBalance; 116 | } 117 | } 118 | // the Trader is trading 119 | if (increasedToken && decreasedToken) { 120 | if ( 121 | !quoteToken.includes(increasedToken) && 122 | !quoteToken.includes(decreasedToken) 123 | ) { 124 | console.log( 125 | `case1: The trader is swapping ${decreasedToken} to ${increasedToken}` 126 | ); 127 | 128 | if (!current_our_wallet_state[wsol]) { 129 | console.log("We don't have enough SOL to swap"); 130 | throw new Error("We don't have enough SOL to swap"); 131 | } 132 | res_case = 1; 133 | // swap directly it if we have decreased token and balance > 0 134 | if ( 135 | decreasedToken in current_our_wallet_state && 136 | current_our_wallet_state[decreasedToken] 137 | ) { 138 | const buy_percentage = Math.abs(decreasedTokenPercentage); 139 | const amountOut = 140 | current_our_wallet_state[decreasedToken] * buy_percentage; 141 | 142 | swap(decreasedToken, increasedToken, amountOut, 5); 143 | 144 | } else if (current_our_wallet_state[wsol]) { 145 | // use sol to buy it if we don't have decreased token 146 | const buy_percentage = Math.abs(decreasedTokenPercentage); 147 | const amountOut = current_our_wallet_state[wsol] * buy_percentage; 148 | 149 | buy("buy", increasedToken, amountOut, wallet) 150 | saveToJson(increasedToken); 151 | } 152 | } else { 153 | // when the trader is swapping usdt to usdc, ignore it 154 | } 155 | } else { 156 | 157 | // someone send token to the wallet 158 | // wallet send token to someone 159 | // wallet send some token to limit order program or DCA program 160 | // ignore it for now, we only focus on trading for now 161 | } 162 | previous_our_wallet_state = await retriveWalletState(wallet.publicKey.toBase58()); 163 | previous_trader_wallet_state = await retriveWalletState(address.toBase58()); 164 | }, 165 | "confirmed", 166 | [ 167 | { 168 | dataSize: 165, 169 | }, 170 | { 171 | memcmp: { 172 | offset: 32, 173 | bytes: address.toBase58(), 174 | }, 175 | }, 176 | ] 177 | );} 178 | catch(e){ 179 | console.log(e) 180 | } 181 | } 182 | 183 | /** 184 | * Retrieves the state of a wallet by querying the Solana blockchain. 185 | * @param {string} wallet_address - The address of the wallet to retrieve the state for. 186 | * @returns {Object} - An object containing the token balances of the wallet and the SOL balance. 187 | */ 188 | async function retriveWalletState(wallet_address) { 189 | try{ 190 | const filters = [ 191 | { 192 | dataSize: 165, //size of account (bytes) 193 | }, 194 | { 195 | memcmp: { 196 | offset: 32, //location of our query in the account (bytes) 197 | bytes: wallet_address, //our search criteria, a base58 encoded string 198 | }, 199 | }, 200 | ]; 201 | const accounts = await connection.getParsedProgramAccounts( 202 | TOKEN_PROGRAM_ID, //new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") 203 | { filters: filters } 204 | ); 205 | let results = {}; 206 | const solBalance = await connection.getBalance(new PublicKey(wallet_address)); 207 | accounts.forEach((account, i) => { 208 | //Parse the account data 209 | const parsedAccountInfo = account.account.data; 210 | const mintAddress = parsedAccountInfo["parsed"]["info"]["mint"]; 211 | const tokenBalance = 212 | parsedAccountInfo["parsed"]["info"]["tokenAmount"]["uiAmount"]; 213 | 214 | results[mintAddress] = tokenBalance; 215 | results["SOL"] = solBalance / 10 ** 9; 216 | }); 217 | return results; 218 | }catch(e){ 219 | console.log(e) 220 | } 221 | } 222 | 223 | /** 224 | * Copies trades based on predefined parameters. 225 | * @returns {Promise} A promise that resolves when the trade copying is complete. 226 | */ 227 | async function copy_buy() { 228 | // smart money wallet address 229 | let smart_money_address = smart_money_wallet; 230 | // our wallet address 231 | let our_wallet_address = wallet.publicKey.toBase58(); 232 | previous_trader_wallet_state = await retriveWalletState(smart_money_address); 233 | previous_our_wallet_state = await retriveWalletState(our_wallet_address); 234 | console.log("Our wallet state: ", previous_our_wallet_state); 235 | // subscribe to the smart money wallet 236 | // walletsToListen.push(new PublicKey(smart_money_address)); 237 | await listenToWallets(new PublicKey(smart_money_address)); 238 | } 239 | 240 | copy_buy(); 241 | module.exports = { 242 | copy_buy, 243 | listenToWallets, 244 | retriveWalletState, 245 | }; 246 | -------------------------------------------------------------------------------- /src/Pool/query_pool.js: -------------------------------------------------------------------------------- 1 | const { Connection, PublicKey } = require("@solana/web3.js"); 2 | const { OpenOrders } = require("@project-serum/serum"); 3 | const { gql, GraphQLClient } = require("graphql-request"); 4 | const { shyft_api_key } = require("../helpers/config"); 5 | const {Liquidity} = require("@raydium-io/raydium-sdk"); 6 | const { token } = require("@metaplex-foundation/js"); 7 | const {getDecimals} = require( 8 | "../helpers/util" 9 | ) 10 | const graphQLEndpoint = `https://programs.shyft.to/v0/graphql/?api_key=${shyft_api_key}`; 11 | const rpcEndpoint = `https://rpc.shyft.to/?api_key=${shyft_api_key}`; 12 | 13 | 14 | 15 | async function generateV4PoolInfo(tokenAddress) { 16 | // RAY-USDC 17 | const poolInfo = Liquidity.getAssociatedPoolKeys({ 18 | version: 4, 19 | marketVersion: 3, 20 | baseMint: new PublicKey('So11111111111111111111111111111111111111112'), 21 | quoteMint: new PublicKey(tokenAddress), 22 | baseDecimals: await getDecimals(new PublicKey(tokenAddress)), 23 | quoteDecimals: 9, 24 | programId: new PublicKey('675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8'), 25 | 26 | marketId: new PublicKey('DZjbn4XC8qoHKikZqzmhemykVzmossoayV9ffbsUqxVj'), 27 | marketProgramId: new PublicKey('srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX'), 28 | }) 29 | console.log(poolInfo) 30 | return { poolInfo } 31 | } 32 | 33 | async function howToUse() { 34 | generateV4PoolInfo().then(({ poolInfo }) => { 35 | console.log('poolInfo: ', poolInfo) 36 | }) 37 | } 38 | const graphQLClient = new GraphQLClient(graphQLEndpoint, { 39 | method: `POST`, 40 | jsonSerializer: { 41 | parse: JSON.parse, 42 | stringify: JSON.stringify, 43 | }, 44 | }); 45 | // Get Pools By Token Address 46 | /** 47 | * Queries the liquidity pool by token. 48 | * @param {string} token - The token to query the liquidity pool for. 49 | * @returns {Promise} - The response object containing the liquidity pool information. 50 | */ 51 | async function queryLpByToken(token) { 52 | // Get all proposalsV2 accounts 53 | const query = gql` 54 | query MyQuery( 55 | $where: Raydium_LiquidityPoolv4_bool_exp 56 | $order_by: [Raydium_LiquidityPoolv4_order_by!] 57 | ) { 58 | Raydium_LiquidityPoolv4(where: $where, order_by: $order_by) { 59 | _updatedAt 60 | amountWaveRatio 61 | baseDecimal 62 | baseLotSize 63 | baseMint 64 | baseNeedTakePnl 65 | baseTotalPnl 66 | baseVault 67 | depth 68 | lpMint 69 | lpReserve 70 | lpVault 71 | marketId 72 | marketProgramId 73 | maxOrder 74 | maxPriceMultiplier 75 | minPriceMultiplier 76 | minSeparateDenominator 77 | minSeparateNumerator 78 | minSize 79 | nonce 80 | openOrders 81 | orderbookToInitTime 82 | owner 83 | pnlDenominator 84 | pnlNumerator 85 | poolOpenTime 86 | punishCoinAmount 87 | punishPcAmount 88 | quoteDecimal 89 | quoteLotSize 90 | quoteMint 91 | quoteNeedTakePnl 92 | quoteTotalPnl 93 | quoteVault 94 | resetFlag 95 | state 96 | status 97 | swapBase2QuoteFee 98 | swapBaseInAmount 99 | swapBaseOutAmount 100 | swapFeeDenominator 101 | swapFeeNumerator 102 | swapQuote2BaseFee 103 | swapQuoteInAmount 104 | swapQuoteOutAmount 105 | systemDecimalValue 106 | targetOrders 107 | tradeFeeDenominator 108 | tradeFeeNumerator 109 | volMaxCutRatio 110 | withdrawQueue 111 | pubkey 112 | } 113 | } 114 | `; 115 | 116 | const variables = { 117 | where: { 118 | baseMint: { 119 | _eq: token, 120 | }, 121 | }, 122 | order_by: [ 123 | { 124 | lpReserve: "desc", 125 | }, 126 | ], 127 | }; 128 | 129 | const response = await graphQLClient.request(query, variables); 130 | return response; 131 | } 132 | // Get Token Supply Percentage In Pool 133 | /** 134 | * Queries a liquidity pool by address. 135 | * @param {string} address - The address of the liquidity pool. 136 | * @returns {Promise} - The result of the GraphQL query. 137 | */ 138 | async function queryLpByAddress(address) { 139 | // We only fetch fields necessary for us 140 | const query = gql` 141 | query MyQuery($where: Raydium_LiquidityPoolv4_bool_exp) { 142 | Raydium_LiquidityPoolv4( 143 | where: {pubkey: {_eq: ${JSON.stringify(address)}}} 144 | ) { 145 | baseDecimal 146 | baseMint 147 | baseNeedTakePnl 148 | baseVault 149 | marketId 150 | marketProgramId 151 | openOrders 152 | quoteDecimal 153 | quoteMint 154 | quoteNeedTakePnl 155 | quoteVault 156 | } 157 | }`; 158 | 159 | return await graphQLClient.request(query); 160 | } 161 | 162 | //We have to check how much tokens are present in openbook market as well 163 | /** 164 | * Parses the pool information and calculates various metrics related to the pool. 165 | * @param {Object} poolInfo - The pool information object. 166 | * @returns {Promise} - A promise that resolves once the pool information is parsed. 167 | */ 168 | async function parsePoolInfo(poolInfo) { 169 | const OPENBOOK_PROGRAM_ID = new PublicKey( 170 | "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX" 171 | ); 172 | 173 | //to load openOorders from openbook 174 | const connection = new Connection(rpcEndpoint, "confirmed"); 175 | 176 | const openOrders = await OpenOrders.load( 177 | connection, 178 | new PublicKey(poolInfo.openOrders), 179 | OPENBOOK_PROGRAM_ID 180 | ); 181 | 182 | const baseDecimal = 10 ** poolInfo.baseDecimal; // e.g. 10 ^ 6 183 | const quoteDecimal = 10 ** poolInfo.quoteDecimal; 184 | console.log("baseToken: ", poolInfo.baseMint); 185 | console.log("quoteToken: ", poolInfo.quoteMint); 186 | 187 | const baseTokenAmount = await connection.getTokenAccountBalance( 188 | new PublicKey(poolInfo.baseVault) 189 | ); 190 | const quoteTokenAmount = await connection.getTokenAccountBalance( 191 | new PublicKey(poolInfo.quoteVault) 192 | ); 193 | 194 | const basePnl = poolInfo.baseNeedTakePnl / baseDecimal; 195 | const quotePnl = poolInfo.quoteNeedTakePnl / quoteDecimal; 196 | 197 | const openOrdersBaseTokenTotal = openOrders.baseTokenTotal / baseDecimal; 198 | const openOrdersQuoteTokenTotal = openOrders.quoteTokenTotal / quoteDecimal; 199 | 200 | const base = 201 | (baseTokenAmount.value?.uiAmount || 0) + openOrdersBaseTokenTotal - basePnl; 202 | //You can do the same for quote tokens also. This doesnt work for SOL. 203 | const quote = 204 | (quoteTokenAmount.value?.uiAmount || 0) + 205 | openOrdersQuoteTokenTotal - 206 | quotePnl; 207 | 208 | //We get the current token supply through RPC and find the percentage 209 | const baseSupply = await connection.getTokenSupply( 210 | new PublicKey(poolInfo.baseMint) 211 | ); 212 | console.log(`Total Base tokens: ${baseSupply.value.uiAmount}`); 213 | console.log(`Base tokens in Pool: ${base}`); 214 | console.log( 215 | `Pecentage of total base tokens in Pool: ${ 216 | (base / baseSupply?.value?.uiAmount) * 100 217 | } %` 218 | ); 219 | } 220 | 221 | // Sort Liquidity Pools 222 | /** 223 | * Queries the liquidity pool for a given pair of tokens. 224 | * @param {string} tokenOne - The first token of the pair. 225 | * @param {string} tokenTwo - The second token of the pair. 226 | * @returns {Promise} - The response object containing the liquidity pool data. 227 | */ 228 | async function queryLpPair(tokenOne, tokenTwo) { 229 | const query = gql` 230 | query MyQuery( 231 | $where: Raydium_LiquidityPoolv4_bool_exp 232 | $order_by: [Raydium_LiquidityPoolv4_order_by!] 233 | ) { 234 | Raydium_LiquidityPoolv4(where: $where, order_by: $order_by) { 235 | amountWaveRatio 236 | baseDecimal 237 | baseLotSize 238 | baseMint 239 | baseNeedTakePnl 240 | baseTotalPnl 241 | baseVault 242 | depth 243 | lpMint 244 | lpReserve 245 | lpVault 246 | marketId 247 | marketProgramId 248 | maxOrder 249 | maxPriceMultiplier 250 | minPriceMultiplier 251 | minSeparateDenominator 252 | minSeparateNumerator 253 | minSize 254 | nonce 255 | openOrders 256 | orderbookToInitTime 257 | owner 258 | pnlDenominator 259 | pnlNumerator 260 | poolOpenTime 261 | punishCoinAmount 262 | punishPcAmount 263 | quoteDecimal 264 | quoteLotSize 265 | quoteMint 266 | quoteNeedTakePnl 267 | quoteTotalPnl 268 | quoteVault 269 | resetFlag 270 | state 271 | status 272 | swapBase2QuoteFee 273 | swapBaseInAmount 274 | swapBaseOutAmount 275 | swapFeeDenominator 276 | swapFeeNumerator 277 | swapQuote2BaseFee 278 | swapQuoteInAmount 279 | swapQuoteOutAmount 280 | systemDecimalValue 281 | targetOrders 282 | tradeFeeDenominator 283 | tradeFeeNumerator 284 | volMaxCutRatio 285 | withdrawQueue 286 | pubkey 287 | } 288 | } 289 | `; 290 | 291 | const variables = { 292 | where: { 293 | baseMint: { 294 | _eq: tokenOne, 295 | }, 296 | quoteMint: { 297 | _eq: tokenTwo, 298 | }, 299 | }, 300 | order_by: [ 301 | { 302 | lpReserve: "desc", 303 | }, 304 | ], 305 | }; 306 | 307 | const response = await graphQLClient.request(query, variables); 308 | return response; 309 | } 310 | /** 311 | * Retrieves the pool ID associated with the given token. 312 | * @param {string} token - The token to query the pool ID for. 313 | * @returns {Promise} The pool ID if found, or null if no pool is found. 314 | */ 315 | async function getPoolId(token) { 316 | const poolId = await queryLpByToken(token); 317 | if (poolId.Raydium_LiquidityPoolv4.length === 0) { 318 | console.log(`Cannot find any liquidity pool related to ${token}`); 319 | return null; 320 | } 321 | 322 | return poolId.Raydium_LiquidityPoolv4[0].pubkey; 323 | } 324 | 325 | /** 326 | * Retrieves the pool ID for a given base token. 327 | * @param {string} baseToken - The base token. 328 | * @returns {string|null} - The pool ID if found, otherwise null. 329 | */ 330 | async function getPoolIdByPair(baseToken) { 331 | // token/SOL pair 332 | const quoteToken = "So11111111111111111111111111111111111111112"; 333 | const poolId = await queryLpPair(baseToken, quoteToken); 334 | if (poolId.Raydium_LiquidityPoolv4.length === 0) { 335 | console.log( 336 | `Cannot find any liquidity pool related to ${baseToken}/${quoteToken}` 337 | ); 338 | console.log(`It may be a token launched on pump.fun, we try to find ${quoteToken}/${baseToken}`) 339 | const poolIdByPair = await queryLpPair(quoteToken, baseToken); 340 | if (poolIdByPair.Raydium_LiquidityPoolv4.length === 0) { 341 | console.log( 342 | `Cannot find any liquidity pool related to ${quoteToken}/${baseToken}` 343 | ); 344 | throw new Error(`Cannot find any liquidity pool related to ${quoteToken}`); 345 | return null; 346 | }else{ 347 | return poolIdByPair.Raydium_LiquidityPoolv4[0].pubkey; 348 | } 349 | return null; 350 | } 351 | return poolId.Raydium_LiquidityPoolv4[0].pubkey; 352 | } 353 | async function main() { 354 | // getting the pool address for npch 355 | //const poolId = await getPoolIdByPair("token_address") 356 | //console.log(poolId) 357 | // get token supply by token address 358 | // const poolInfo: any = await queryLpByAddress('TOKEN_ADDRESS'); 359 | // await parsePoolInfo(poolInfo.Raydium_LiquidityPoolv4[0]); 360 | // get the pair of liquidity pool of two tokens 361 | // like sol/slerf 362 | // const poolIdByPair = await getPoolIdByPair( 363 | // 'TOKEN_ADDRESS', 364 | // 'So11111111111111111111111111111111111111112', 365 | // ); 366 | // console.log(poolIdByPair); 367 | await howToUse(); 368 | } 369 | main().catch(console.error); 370 | module.exports = { 371 | getPoolIdByPair, 372 | queryLpByToken, 373 | queryLpByAddress, 374 | parsePoolInfo, 375 | queryLpPair, 376 | getPoolId, 377 | }; 378 | -------------------------------------------------------------------------------- /src/Pool/swap.js: -------------------------------------------------------------------------------- 1 | const assert = require("assert"); 2 | 3 | const { 4 | Liquidity, 5 | Percent, 6 | Token, 7 | TOKEN_PROGRAM_ID, 8 | TokenAmount, 9 | } = require("@raydium-io/raydium-sdk"); 10 | const { 11 | PublicKey, 12 | TransactionMessage, 13 | ComputeBudgetProgram, 14 | VersionedTransaction, 15 | LAMPORTS_PER_SOL 16 | } = require("@solana/web3.js"); 17 | const { Decimal } = require("decimal.js"); 18 | const { BN } = require("@project-serum/anchor"); 19 | const { getSPLTokenBalance } = require("../helpers/check_balance.js"); 20 | const { 21 | connection, 22 | DEFAULT_TOKEN, 23 | makeTxVersion, 24 | RAYDIUM_MAINNET_API, 25 | _ENDPOINT, 26 | wallet, 27 | jito_fee 28 | } = require("../helpers/config.js"); 29 | const { 30 | getDecimals, 31 | getTokenMetadata, 32 | checkTx, 33 | } = require("../helpers/util.js"); 34 | const { getPoolId, getPoolIdByPair } = require("./query_pool.js"); 35 | const { 36 | getAssociatedTokenAddress, 37 | getAssociatedTokenAddressSync, 38 | createAssociatedTokenAccountIdempotentInstruction, 39 | createCloseAccountInstruction, 40 | } = require("@solana/spl-token"); 41 | const { mint } = require("@metaplex-foundation/mpl-candy-machine"); 42 | const { formatAmmKeysById_swap } = require("./formatAmmKeysById.js"); 43 | const { 44 | simple_executeAndConfirm, 45 | } = require("../Transactions/simple_tx_executor.js"); 46 | const { 47 | jito_executeAndConfirm, 48 | } = require("../Transactions/jito_tips_tx_executor.js"); 49 | 50 | let tokenToPoolIdMap = { 51 | 52 | }; 53 | 54 | 55 | /** 56 | * Performs a swap transaction using an Automated Market Maker (AMM) pool. 57 | * @param {Object} input - The input parameters for the swap transaction. 58 | * @param {string} input.targetPool - The target pool address. 59 | * @param {string} input.inputTokenAmount - The amount of input token to swap. 60 | * @param {string} input.outputToken - The output token to receive. 61 | * @param {number} input.slippage - The slippage tolerance percentage. 62 | * @param {string} input.ataIn - The associated token account for the input token. 63 | * @param {string} input.ataOut - The associated token account for the output token. 64 | * @param {string} input.usage - The usage type of the transaction (e.g., "volume"). 65 | * @param {string} input.side - The side of the swap transaction (e.g., "buy"). 66 | * @returns {Object} - The transaction ID if successful, otherwise null. 67 | */ 68 | async function swapOnlyAmm(input) { 69 | // -------- pre-action: get pool info --------\ 70 | 71 | const poolKeys = await formatAmmKeysById_swap( 72 | new PublicKey(input.targetPool) 73 | ); 74 | assert(poolKeys, "cannot find the target pool"); 75 | const poolInfo = await Liquidity.fetchInfo({ 76 | connection: connection, 77 | poolKeys: poolKeys, 78 | }); 79 | // -------- step 1: coumpute amount out -------- 80 | const { amountOut, minAmountOut } = Liquidity.computeAmountOut({ 81 | poolKeys: poolKeys, 82 | poolInfo: poolInfo, 83 | amountIn: input.inputTokenAmount, 84 | currencyOut: input.outputToken, 85 | slippage: input.slippage, 86 | }); 87 | // -------- step 2: create instructions by SDK function -------- 88 | const { innerTransaction } = await Liquidity.makeSwapFixedInInstruction( 89 | { 90 | poolKeys: poolKeys, 91 | userKeys: { 92 | tokenAccountIn: input.ataIn, 93 | tokenAccountOut: input.ataOut, 94 | owner: wallet.publicKey, 95 | }, 96 | amountIn: input.inputTokenAmount.raw, 97 | minAmountOut: minAmountOut.raw, 98 | }, 99 | poolKeys.version 100 | ); 101 | if (input.usage == "volume") return innerTransaction; 102 | let latestBlockhash = await connection.getLatestBlockhash(); 103 | const messageV0 = new TransactionMessage({ 104 | payerKey: wallet.publicKey, 105 | recentBlockhash: latestBlockhash.blockhash, 106 | instructions: [ 107 | 108 | ...[ 109 | ComputeBudgetProgram.setComputeUnitPrice({ 110 | microLamports: 3052900, 111 | }), 112 | ComputeBudgetProgram.setComputeUnitLimit({ 113 | units: 3127500, 114 | }), 115 | ], 116 | ...(input.side === "buy" 117 | ? [ 118 | createAssociatedTokenAccountIdempotentInstruction( 119 | wallet.publicKey, 120 | input.ataOut, 121 | wallet.publicKey, 122 | input.outputToken.mint 123 | ), 124 | ] 125 | : []), 126 | ...innerTransaction.instructions, 127 | ], 128 | }).compileToV0Message(); 129 | 130 | const transaction = new VersionedTransaction(messageV0); 131 | transaction.sign([wallet, ...innerTransaction.signers]); 132 | let attempts = 0; 133 | const maxAttempts = 3; 134 | 135 | while (attempts < maxAttempts) { 136 | attempts++; 137 | try { 138 | const res = await jito_executeAndConfirm(transaction, wallet, latestBlockhash, jito_fee); 139 | const signature = res.signature; 140 | const confirmed = res.confirmed; 141 | 142 | if (signature) { 143 | return { txid: signature }; 144 | } else { 145 | console.log("jito fee transaction failed"); 146 | console.log(`Retry attempt ${attempts}`); 147 | } 148 | } catch (e) { 149 | console.log(e); 150 | if (e.signature) { 151 | return { txid: e.signature }; 152 | } 153 | } 154 | latestBlockhash = await connection.getLatestBlockhash(); 155 | } 156 | 157 | console.log("Transaction failed after maximum retry attempts"); 158 | return { txid: null }; 159 | } 160 | 161 | 162 | /** 163 | * Swaps tokens for a specified volume. 164 | * @param {string} tokenAddr - The address of the token to swap. 165 | * @param {number} sol_per_order - The price of SOL per order. 166 | * @returns {Promise<{ confirmed: boolean, txid: string }>} The confirmation status and transaction ID. 167 | */ 168 | async function swapForVolume(tokenAddr, sol_per_order) { 169 | const buy_instruction = await swap( 170 | "buy", 171 | tokenAddr, 172 | sol_per_order, 173 | -1, 174 | wallet, 175 | "volume" 176 | ); 177 | const sell_instruction = await swap( 178 | "sell", 179 | tokenAddr, 180 | -1, 181 | 100, 182 | wallet, 183 | "volume" 184 | ); 185 | const latestBlockhash = await connection.getLatestBlockhash(); 186 | const messageV0 = new TransactionMessage({ 187 | payerKey: wallet.publicKey, 188 | recentBlockhash: latestBlockhash.blockhash, 189 | instructions: [ 190 | ...[ 191 | ComputeBudgetProgram.setComputeUnitLimit({ 192 | units: 70000, 193 | }), 194 | ComputeBudgetProgram.setComputeUnitPrice({ 195 | microLamports: 90000, 196 | }), 197 | ], 198 | ...sell_instruction.instructions, 199 | ...buy_instruction.instructions, 200 | ], 201 | }); 202 | 203 | const transaction = new VersionedTransaction(messageV0.compileToV0Message()); 204 | transaction.sign([ 205 | wallet, 206 | ...buy_instruction.signers, 207 | ...sell_instruction.signers, 208 | ]); 209 | let signature = null, 210 | confirmed = null; 211 | try { 212 | const res = simple_executeAndConfirm( 213 | transaction, 214 | wallet, 215 | latestBlockhash 216 | ); 217 | signature = res.signature; 218 | confirmed = res.confirmed; 219 | } catch (e) { 220 | console.log(e); 221 | return { confirmed: confirmed, txid: e.signature }; 222 | } 223 | return { confirmed: confirmed, txid: signature }; 224 | } 225 | 226 | 227 | 228 | /** 229 | * Helper function for swapping tokens using the AMM protocol. 230 | * @param {Object} input - The input object containing the necessary parameters for the swap. 231 | * @returns {Promise} - A promise that resolves when the swap is completed. 232 | */ 233 | async function swapOnlyAmmHelper(input) { 234 | const { txid } = await swapOnlyAmm(input); 235 | console.log("txids:", txid); 236 | const response = await checkTx(txid); 237 | if (response) { 238 | if (input.side === "buy") { 239 | console.log( 240 | `https://dexscreener.com/solana/${input.targetPool}?maker=${wallet.publicKey}` 241 | ); 242 | } else { 243 | console.log( 244 | `https://dexscreener.com/solana/${input.targetPool}?maker=${wallet.publicKey}` 245 | ); 246 | } 247 | console.log(`https://solscan.io/tx/${txid}?cluster=mainnet`); 248 | } else { 249 | console.log("Transaction failed"); 250 | 251 | } 252 | } 253 | /** 254 | * Performs a swap operation. 255 | * 256 | * @param {string} side - The side of the swap operation ("buy" or "sell"). 257 | * @param {string} tokenAddr - The address of the token involved in the swap. 258 | * @param {number} buy_AmountOfSol - The amount of SOL to buy (only applicable for "buy" side). 259 | * @param {number} sell_PercentageOfToken - The percentage of the token to sell (only applicable for "sell" side). 260 | * @param {object} payer_wallet - The payer's wallet object. 261 | * @returns {Promise} - A promise that resolves when the swap operation is completed. 262 | */ 263 | async function swap( 264 | side, 265 | tokenAddr, 266 | buy_AmountOfSol, 267 | sell_PercentageOfToken, 268 | payer_wallet, 269 | usage 270 | ) { 271 | const tokenAddress = tokenAddr; 272 | const tokenAccount = new PublicKey(tokenAddress); 273 | const mintAta = await getAssociatedTokenAddress( 274 | tokenAccount, 275 | wallet.publicKey 276 | ); 277 | const quoteAta = await getAssociatedTokenAddressSync( 278 | Token.WSOL.mint, 279 | wallet.publicKey 280 | ); 281 | if (side === "buy") { 282 | 283 | const outputToken = new Token( 284 | TOKEN_PROGRAM_ID, 285 | tokenAccount, 286 | await getDecimals(tokenAccount) 287 | ); 288 | const inputToken = DEFAULT_TOKEN.WSOL; // SOL 289 | let targetPool = null; 290 | if(!(tokenAddress in tokenToPoolIdMap)){ 291 | targetPool = await getPoolIdByPair(tokenAddress); 292 | tokenToPoolIdMap[tokenAddress] = targetPool; 293 | }else targetPool = tokenToPoolIdMap[tokenAddress]; 294 | 295 | if (targetPool === null) { 296 | console.log( 297 | "Pool not found or raydium is not supported for this token. Exiting..." 298 | ); 299 | return; 300 | } 301 | const amountOfSol = new Decimal(buy_AmountOfSol); 302 | const inputTokenAmount = new TokenAmount( 303 | inputToken, 304 | new BN(amountOfSol.mul(10 ** inputToken.decimals).toFixed(0)) 305 | ); 306 | const slippage = new Percent(3, 100); 307 | const input = { 308 | outputToken, 309 | targetPool, 310 | inputTokenAmount, 311 | slippage, 312 | ataIn: quoteAta, 313 | ataOut: mintAta, 314 | side, 315 | usage, 316 | }; 317 | if (usage == "volume") { 318 | return await swapOnlyAmm(input); 319 | } 320 | swapOnlyAmmHelper(input); 321 | } else { 322 | // sell 323 | const { tokenName, tokenSymbol } = await getTokenMetadata(tokenAddress); 324 | const inputToken = new Token( 325 | TOKEN_PROGRAM_ID, 326 | tokenAccount, 327 | await getDecimals(tokenAccount), 328 | tokenSymbol, 329 | tokenName 330 | ); 331 | const outputToken = DEFAULT_TOKEN.WSOL; // SOL 332 | let targetPool = null; 333 | if(!(tokenAddress in tokenToPoolIdMap)){ 334 | targetPool = await getPoolIdByPair(tokenAddress); 335 | tokenToPoolIdMap[tokenAddress] = targetPool; 336 | }else targetPool = tokenToPoolIdMap[tokenAddress]; 337 | 338 | if (targetPool === null) { 339 | console.log( 340 | "Pool not found or raydium is not supported for this token. Exiting..." 341 | ); 342 | return; 343 | } 344 | 345 | const balnaceOfToken = await getSPLTokenBalance( 346 | connection, 347 | tokenAccount, 348 | wallet.publicKey 349 | ); 350 | const percentage = sell_PercentageOfToken / 100; 351 | const amount = new Decimal(percentage * balnaceOfToken); 352 | const slippage = new Percent(3, 100); 353 | const inputTokenAmount = new TokenAmount( 354 | inputToken, 355 | new BN(amount.mul(10 ** inputToken.decimals).toFixed(0)) 356 | ); 357 | const input = { 358 | outputToken, 359 | sell_PercentageOfToken, 360 | targetPool, 361 | inputTokenAmount, 362 | slippage, 363 | wallet: payer_wallet, 364 | ataIn: mintAta, 365 | ataOut: quoteAta, 366 | side, 367 | usage, 368 | tokenAddress: tokenAddress 369 | }; 370 | if (usage == "volume") { 371 | return await swapOnlyAmm(input); 372 | } 373 | swapOnlyAmmHelper(input); 374 | } 375 | } 376 | 377 | module.exports = { swap, swapForVolume }; 378 | -------------------------------------------------------------------------------- /src/pumpfunsdk/pumpdotfun-sdk/src/pumpfun.js: -------------------------------------------------------------------------------- 1 | const { 2 | Commitment, 3 | Connection, 4 | Finality, 5 | Keypair, 6 | PublicKey, 7 | Transaction, 8 | } =require ("@solana/web3.js"); 9 | const { Program, Provider } =require ("@coral-xyz/anchor"); 10 | const { GlobalAccount } =require ("./globalAccount.js"); 11 | const { 12 | toCompleteEvent, 13 | toCreateEvent, 14 | toSetParamsEvent, 15 | toTradeEvent, 16 | } =require ("./events.js"); 17 | const { 18 | createAssociatedTokenAccountInstruction, 19 | getAccount, 20 | getAssociatedTokenAddress, 21 | getOrCreateAssociatedTokenAccount, 22 | } =require ("@solana/spl-token"); 23 | const { BondingCurveAccount } =require ("./bondingCurveAccount.js"); 24 | const { BN } =require ("bn.js"); 25 | const { 26 | DEFAULT_COMMITMENT, 27 | DEFAULT_FINALITY, 28 | calculateWithSlippageBuy, 29 | calculateWithSlippageSell, 30 | sendTx, 31 | sendTxToJito, 32 | } =require ("./util.js"); 33 | const { PumpFun, IDL } =require ("./IDL/index.js"); 34 | const {wallet} = require("../../../helpers/config.js") 35 | const PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"; 36 | const MPL_TOKEN_METADATA_PROGRAM_ID = 37 | "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"; 38 | 39 | const GLOBAL_ACCOUNT_SEED = "global"; 40 | const MINT_AUTHORITY_SEED = "mint-authority"; 41 | const BONDING_CURVE_SEED = "bonding-curve"; 42 | const METADATA_SEED = "metadata"; 43 | 44 | const DEFAULT_DECIMALS = 6; 45 | 46 | class PumpFunSDK { 47 | 48 | constructor(provider) { 49 | this.program = new Program(IDL, provider); 50 | this.connection = this.program.provider.connection; 51 | } 52 | async bundleBuys( creator, 53 | mint, 54 | createTokenMetadata, 55 | buyAmountSol, 56 | buyersWallets, 57 | slippageBasisPoints = 500n, 58 | priorityFees, 59 | commitment = DEFAULT_COMMITMENT, 60 | finality = DEFAULT_FINALITY, 61 | ){ 62 | let tokenMetadata = await this.createTokenMetadata(createTokenMetadata); 63 | let createTx = await this.getCreateInstructions( 64 | creator.publicKey, 65 | createTokenMetadata.name, 66 | createTokenMetadata.symbol, 67 | tokenMetadata.metadataUri, 68 | mint 69 | ); 70 | let final_tx = new Transaction().add(createTx); 71 | const globalAccount = await this.getGlobalAccount(commitment); 72 | const buyAmount = globalAccount.getInitialBuyPrice(buyAmountSol); 73 | const buyAmountWithSlippage = calculateWithSlippageBuy( 74 | buyAmountSol, 75 | slippageBasisPoints 76 | ); 77 | final_tx.add( 78 | await this.getBuyInstructions( 79 | creator.publicKey, 80 | mint.publicKey, 81 | globalAccount.feeRecipient, 82 | buyAmount, 83 | buyAmountWithSlippage 84 | ) 85 | ); 86 | 87 | for(let i=0; i 0) { 132 | const globalAccount = await this.getGlobalAccount(commitment); 133 | const buyAmount = globalAccount.getInitialBuyPrice(buyAmountSol); 134 | const buyAmountWithSlippage = calculateWithSlippageBuy( 135 | buyAmountSol, 136 | slippageBasisPoints 137 | ); 138 | 139 | const buyTx = await this.getBuyInstructions( 140 | creator.publicKey, 141 | mint.publicKey, 142 | globalAccount.feeRecipient, 143 | buyAmount, 144 | buyAmountWithSlippage 145 | ); 146 | 147 | newTx.add(buyTx); 148 | } 149 | // using jito 150 | const res = await sendTxToJito( 151 | this.connection, 152 | newTx, 153 | creator, 154 | [creator, mint], 155 | 0.00003 156 | ); 157 | // with jito 158 | // let createResults = await sendTx( 159 | // this.connection, 160 | // newTx, 161 | // creator.publicKey, 162 | // [creator, mint], 163 | // priorityFees, 164 | // commitment, 165 | // finality 166 | // ); 167 | 168 | return res.success; 169 | } 170 | 171 | async buy( 172 | buyer, 173 | mint, 174 | buyAmountSol, 175 | slippageBasisPoints = 500n, 176 | priorityFees, 177 | commitment = DEFAULT_COMMITMENT, 178 | finality = DEFAULT_FINALITY 179 | ) { 180 | let buyTx = await this.getBuyInstructionsBySolAmount( 181 | buyer.publicKey, 182 | mint, 183 | buyAmountSol, 184 | slippageBasisPoints, 185 | commitment 186 | ); 187 | 188 | // let buyResults = await sendTx( 189 | // this.connection, 190 | // buyTx, 191 | // buyer.publicKey, 192 | // [buyer], 193 | // priorityFees, 194 | // commitment, 195 | // finality 196 | // ); 197 | let buyResults = await sendTxToJito( 198 | this.connection, 199 | buyTx, 200 | buyer, 201 | [buyer], 202 | 0.00001 203 | ) 204 | return buyResults; 205 | } 206 | 207 | async sell( 208 | seller, 209 | mint, 210 | sellTokenAmount, 211 | slippageBasisPoints = 500n, 212 | priorityFees, 213 | commitment = DEFAULT_COMMITMENT, 214 | finality = DEFAULT_FINALITY 215 | ) { 216 | let sellTx = await this.getSellInstructionsByTokenAmount( 217 | seller.publicKey, 218 | mint, 219 | sellTokenAmount, 220 | slippageBasisPoints, 221 | commitment 222 | ); 223 | 224 | // let sellResults = await sendTx( 225 | // this.connection, 226 | // sellTx, 227 | // seller.publicKey, 228 | // [seller], 229 | // priorityFees, 230 | // commitment, 231 | // finality 232 | // ); 233 | let sellResults = await sendTxToJito( 234 | this.connection, 235 | sellTx, 236 | seller, 237 | [seller], 238 | 0.00001 239 | ) 240 | return sellResults; 241 | } 242 | 243 | //create token instructions 244 | async getCreateInstructions( 245 | creator, 246 | name, 247 | symbol, 248 | uri, 249 | mint 250 | ) { 251 | const mplTokenMetadata = new PublicKey(MPL_TOKEN_METADATA_PROGRAM_ID); 252 | 253 | const [metadataPDA] = PublicKey.findProgramAddressSync( 254 | [ 255 | Buffer.from(METADATA_SEED), 256 | mplTokenMetadata.toBuffer(), 257 | mint.publicKey.toBuffer(), 258 | ], 259 | mplTokenMetadata 260 | ); 261 | 262 | const associatedBondingCurve = await getAssociatedTokenAddress( 263 | mint.publicKey, 264 | this.getBondingCurvePDA(mint.publicKey), 265 | true 266 | ); 267 | 268 | return this.program.methods 269 | .create(name, symbol, uri) 270 | .accounts({ 271 | mint: mint.publicKey, 272 | associatedBondingCurve: associatedBondingCurve, 273 | metadata: metadataPDA, 274 | user: creator, 275 | }) 276 | .signers([mint]) 277 | .transaction(); 278 | } 279 | 280 | async getBuyInstructionsBySolAmount( 281 | buyer, 282 | mint, 283 | buyAmountSol, 284 | slippageBasisPoints = 500n, 285 | commitment = DEFAULT_COMMITMENT 286 | ) { 287 | let bondingCurveAccount = await this.getBondingCurveAccount( 288 | mint, 289 | commitment 290 | ); 291 | if (!bondingCurveAccount) { 292 | throw new Error(`Bonding curve account not found: ${mint.toBase58()}`); 293 | } 294 | 295 | let buyAmount = bondingCurveAccount.getBuyPrice(buyAmountSol); 296 | let buyAmountWithSlippage = calculateWithSlippageBuy( 297 | buyAmountSol, 298 | slippageBasisPoints 299 | ); 300 | 301 | let globalAccount = await this.getGlobalAccount(commitment); 302 | 303 | return await this.getBuyInstructions( 304 | buyer, 305 | mint, 306 | globalAccount.feeRecipient, 307 | buyAmount, 308 | buyAmountWithSlippage 309 | ); 310 | } 311 | async getAssoBondingCurve( 312 | mint, 313 | ){ 314 | const associatedBondingCurve = await getAssociatedTokenAddress( 315 | mint, 316 | this.getBondingCurvePDA(mint), 317 | true 318 | ); 319 | console.log(associatedBondingCurve) 320 | return associatedBondingCurve; 321 | } 322 | //buy 323 | async getBuyInstructions( 324 | buyer, 325 | mint, 326 | feeRecipient, 327 | amount, 328 | solAmount, 329 | commitment = DEFAULT_COMMITMENT 330 | ) { 331 | const associatedBondingCurve = await getAssociatedTokenAddress( 332 | mint, 333 | this.getBondingCurvePDA(mint), 334 | true 335 | ); 336 | 337 | const associatedUser = await getAssociatedTokenAddress(mint, buyer, true); 338 | //const associatedUser = await getOrCreateAssociatedTokenAccount(this.connection, wallet, mint, buyer, false); 339 | 340 | let transaction = new Transaction(); 341 | 342 | try { 343 | await getAccount(this.connection, associatedUser, commitment); 344 | } catch (e) { 345 | transaction.add( 346 | createAssociatedTokenAccountInstruction( 347 | buyer, 348 | associatedUser, 349 | buyer, 350 | mint 351 | ) 352 | ); 353 | } 354 | 355 | transaction.add( 356 | await this.program.methods 357 | .buy(new BN(amount.toString()), new BN(solAmount.toString())) 358 | .accounts({ 359 | feeRecipient: feeRecipient, 360 | mint: mint, 361 | associatedBondingCurve: associatedBondingCurve, 362 | associatedUser: associatedUser, 363 | user: buyer, 364 | }) 365 | .transaction() 366 | ); 367 | 368 | return transaction; 369 | } 370 | 371 | //sell 372 | async getSellInstructionsByTokenAmount( 373 | seller, 374 | mint, 375 | sellTokenAmount, 376 | slippageBasisPoints = 500n, 377 | commitment = DEFAULT_COMMITMENT 378 | ) { 379 | let bondingCurveAccount = await this.getBondingCurveAccount( 380 | mint, 381 | commitment 382 | ); 383 | if (!bondingCurveAccount) { 384 | throw new Error(`Bonding curve account not found: ${mint.toBase58()}`); 385 | } 386 | 387 | let globalAccount = await this.getGlobalAccount(commitment); 388 | 389 | let minSolOutput = bondingCurveAccount.getSellPrice( 390 | sellTokenAmount, 391 | globalAccount.feeBasisPoints 392 | ); 393 | 394 | let sellAmountWithSlippage = calculateWithSlippageSell( 395 | minSolOutput, 396 | slippageBasisPoints 397 | ); 398 | 399 | return await this.getSellInstructions( 400 | seller, 401 | mint, 402 | globalAccount.feeRecipient, 403 | sellTokenAmount, 404 | sellAmountWithSlippage 405 | ); 406 | } 407 | 408 | async getSellInstructions( 409 | seller, 410 | mint, 411 | feeRecipient, 412 | amount, 413 | minSolOutput 414 | ) { 415 | const associatedBondingCurve = await getAssociatedTokenAddress( 416 | mint, 417 | this.getBondingCurvePDA(mint), 418 | true 419 | ); 420 | 421 | const associatedUser = await getAssociatedTokenAddress(mint, seller, false); 422 | 423 | let transaction = new Transaction(); 424 | 425 | transaction.add( 426 | await this.program.methods 427 | .sell(new BN(amount.toString()), new BN(minSolOutput.toString())) 428 | .accounts({ 429 | feeRecipient: feeRecipient, 430 | mint: mint, 431 | associatedBondingCurve: associatedBondingCurve, 432 | associatedUser: associatedUser, 433 | user: seller, 434 | }) 435 | .transaction() 436 | ); 437 | 438 | return transaction; 439 | } 440 | 441 | async getBondingCurveAccount( 442 | mint, 443 | commitment = DEFAULT_COMMITMENT 444 | ) { 445 | const tokenAccount = await this.connection.getAccountInfo( 446 | this.getBondingCurvePDA(mint), 447 | commitment 448 | ); 449 | if (!tokenAccount) { 450 | return null; 451 | } 452 | return BondingCurveAccount.fromBuffer(tokenAccount.data); 453 | } 454 | 455 | async getGlobalAccount(commitment = DEFAULT_COMMITMENT) { 456 | const [globalAccountPDA] = PublicKey.findProgramAddressSync( 457 | [Buffer.from(GLOBAL_ACCOUNT_SEED)], 458 | new PublicKey(PROGRAM_ID) 459 | ); 460 | 461 | const tokenAccount = await this.connection.getAccountInfo( 462 | globalAccountPDA, 463 | commitment 464 | ); 465 | 466 | return GlobalAccount.fromBuffer(tokenAccount.data); 467 | } 468 | 469 | getBondingCurvePDA(mint) { 470 | return PublicKey.findProgramAddressSync( 471 | [Buffer.from(BONDING_CURVE_SEED), mint.toBuffer()], 472 | this.program.programId 473 | )[0]; 474 | } 475 | 476 | async createTokenMetadata(create) { 477 | let formData = new FormData(); 478 | formData.append("file", create.file), 479 | formData.append("name", create.name), 480 | formData.append("symbol", create.symbol), 481 | formData.append("description", create.description), 482 | formData.append("twitter", create.twitter || ""), 483 | formData.append("telegram", create.telegram || ""), 484 | formData.append("website", create.website || ""), 485 | formData.append("showName", "true"); 486 | let request = await fetch("https://pump.fun/api/ipfs", { 487 | method: "POST", 488 | body: formData, 489 | }); 490 | return request.json(); 491 | } 492 | //EVENTS 493 | addEventListener( 494 | eventType, 495 | callback 496 | ) { 497 | return this.program.addEventListener( 498 | eventType, 499 | (event, slot, signature) => { 500 | let processedEvent; 501 | switch (eventType) { 502 | case "createEvent": 503 | processedEvent = toCreateEvent(event); 504 | callback( 505 | processedEvent, 506 | slot, 507 | signature 508 | ); 509 | break; 510 | case "tradeEvent": 511 | processedEvent = toTradeEvent(event); 512 | callback( 513 | processedEvent, 514 | slot, 515 | signature 516 | ); 517 | break; 518 | case "completeEvent": 519 | processedEvent = toCompleteEvent(event); 520 | callback( 521 | processedEvent , 522 | slot, 523 | signature 524 | ); 525 | console.log("completeEvent", event, slot, signature); 526 | break; 527 | case "setParamsEvent": 528 | processedEvent = toSetParamsEvent(event ); 529 | callback( 530 | processedEvent, 531 | slot, 532 | signature 533 | ); 534 | break; 535 | default: 536 | console.error("Unhandled event type:", eventType); 537 | } 538 | } 539 | ); 540 | } 541 | 542 | removeEventListener(eventId) { 543 | this.program.removeEventListener(eventId); 544 | } 545 | } 546 | 547 | module.exports = { PumpFunSDK, PROGRAM_ID, GLOBAL_ACCOUNT_SEED, MINT_AUTHORITY_SEED, BONDING_CURVE_SEED, METADATA_SEED, DEFAULT_DECIMALS }; --------------------------------------------------------------------------------